{"version":3,"file":"nmr-processing.js","sources":["../node_modules/gyromagnetic-ratio/lib-esm/index.js","../lib-esm/constants/impurities.js","../lib-esm/constants/couplingPatterns.js","../lib-esm/peaks/peaksFilterImpurities.js","../node_modules/ml-peak-shape-generator/lib-esm/util/constants.js","../node_modules/ml-peak-shape-generator/lib-esm/util/erfinv.js","../node_modules/ml-peak-shape-generator/lib-esm/shapes/1d/gaussian/Gaussian.js","../node_modules/ml-peak-shape-generator/lib-esm/shapes/1d/lorentzian/Lorentzian.js","../node_modules/ml-peak-shape-generator/lib-esm/shapes/1d/pseudoVoigt/PseudoVoigt.js","../node_modules/ml-peak-shape-generator/lib-esm/shapes/2d/gaussian2D/Gaussian2D.js","../node_modules/ml-peak-shape-generator/lib-esm/shapes/1d/getShape1D.js","../node_modules/ml-peak-shape-generator/lib-esm/shapes/2d/getShape2D.js","../node_modules/spectrum-generator/lib-esm/util/addBaseline.js","../node_modules/d3-array/build/d3-array.js","../node_modules/spline-interpolator/index.js","../node_modules/ml-spectra-processing/lib-esm/utils/createFromToArray.js","../node_modules/ml-spectra-processing/lib-esm/x/erfcinv.js","../node_modules/ml-spectra-processing/lib-esm/x/rayleighCdf.js","../node_modules/ml-spectra-processing/lib-esm/x/xNoiseSanPlot.js","../node_modules/ml-spectra-processing/lib-esm/x/xAbsolute.js","../node_modules/is-any-array/lib-esm/index.js","../node_modules/median-quickselect/lib/median-quickselect.min.js","../node_modules/ml-spectra-processing/lib-esm/x/xMedian.js","../node_modules/ml-spectra-processing/lib-esm/x/xAbsoluteMedian.js","../node_modules/ml-spectra-processing/lib-esm/x/xAdd.js","../node_modules/ml-spectra-processing/lib-esm/x/xCheck.js","../node_modules/ml-spectra-processing/lib-esm/x/xFindClosestIndex.js","../node_modules/ml-spectra-processing/lib-esm/x/xGetFromToIndex.js","../node_modules/ml-spectra-processing/lib-esm/x/xMaxValue.js","../node_modules/ml-spectra-processing/lib-esm/x/xMinValue.js","../node_modules/ml-spectra-processing/lib-esm/x/xIsEquallySpaced.js","../node_modules/ml-spectra-processing/lib-esm/x/xIsMonotoneIncreasing.js","../node_modules/ml-spectra-processing/lib-esm/x/xMedianAbsoluteDeviation.js","../node_modules/ml-spectra-processing/lib-esm/x/xMinMaxValues.js","../node_modules/ml-spectra-processing/lib-esm/x/xNoiseStandardDeviation.js","../node_modules/ml-spectra-processing/lib-esm/x/xNorm.js","../node_modules/ml-spectra-processing/lib-esm/x/xSequentialFill.js","../node_modules/ml-spectra-processing/lib-esm/xy/xyCheck.js","../node_modules/ml-spectra-processing/lib-esm/xy/xyFindClosestPoint.js","../node_modules/ml-spectra-processing/lib-esm/zones/zonesNormalize.js","../node_modules/ml-spectra-processing/lib-esm/xy/xyExtract.js","../node_modules/ml-spectra-processing/lib-esm/xy/xyIntegration.js","../node_modules/ml-spectra-processing/lib-esm/matrix/matrixCheck.js","../node_modules/ml-spectra-processing/lib-esm/matrix/matrixMinMaxZ.js","../node_modules/ml-array-max/lib-es6/index.js","../node_modules/ml-array-min/lib-es6/index.js","../node_modules/ml-array-rescale/lib-es6/index.js","../node_modules/ml-matrix/src/inspect.js","../node_modules/ml-matrix/src/mathOperations.js","../node_modules/ml-matrix/src/util.js","../node_modules/ml-matrix/src/stat.js","../node_modules/ml-matrix/src/matrix.js","../node_modules/ml-matrix/src/wrap/WrapperMatrix2D.js","../node_modules/ml-matrix/src/dc/lu.js","../node_modules/ml-matrix/src/dc/util.js","../node_modules/ml-matrix/src/dc/qr.js","../node_modules/ml-matrix/src/dc/svd.js","../node_modules/ml-matrix/src/decompositions.js","../node_modules/ml-matrix/src/dc/evd.js","../node_modules/ml-xsadd/lib-es6/xsadd.js","../node_modules/ml-spectra-processing/lib-esm/utils/createRandomArray.js","../node_modules/spectrum-generator/lib-esm/util/addNoise.js","../node_modules/spectrum-generator/lib-esm/SpectrumGenerator.js","../node_modules/spectrum-generator/lib-esm/Spectrum2DGenerator.js","../lib-esm/utilities/hasProperty.js","../lib-esm/peaks/util/convertWidth.js","../lib-esm/peaks/util/convertWidthToPPM.js","../lib-esm/peaks/peaksToXY.js","../node_modules/@lukeed/uuid/dist/index.mjs","../node_modules/ml-savitzky-golay-generalized/lib-esm/index.js","../node_modules/ml-gsd/lib-esm/utils/optimizeTop.js","../node_modules/ml-gsd/lib-esm/gsd.js","../node_modules/ml-spectra-fitting/lib-esm/shapes/getSumOfShapes.js","../node_modules/ml-spectra-fitting/lib-esm/util/assert.js","../node_modules/ml-spectra-fitting/lib-esm/util/internalPeaks/DefaultParameters.js","../node_modules/ml-spectra-fitting/lib-esm/util/internalPeaks/getInternalPeaks.js","../node_modules/ml-levenberg-marquardt/lib-esm/checkOptions.js","../node_modules/ml-levenberg-marquardt/lib-esm/errorCalculation.js","../node_modules/ml-levenberg-marquardt/lib-esm/gradientFunction.js","../node_modules/ml-levenberg-marquardt/lib-esm/step.js","../node_modules/ml-levenberg-marquardt/lib-esm/index.js","../node_modules/ml-direct/src/util/antiLowerConvexHull.js","../node_modules/ml-direct/src/index.js","../node_modules/ml-spectra-fitting/lib-esm/util/wrappers/directOptimization.js","../node_modules/ml-spectra-fitting/lib-esm/util/selectMethod.js","../node_modules/ml-spectra-fitting/lib-esm/index.js","../node_modules/ml-gsd/lib-esm/utils/addMissingShape.js","../node_modules/ml-gsd/lib-esm/utils/groupPeaks.js","../node_modules/ml-gsd/lib-esm/post/optimizePeaksWithLogs.js","../node_modules/ml-gsd/lib-esm/post/optimizePeaks.js","../node_modules/ml-gsd/lib-esm/utils/addMissingIDs.js","../node_modules/ml-gsd/lib-esm/post/joinBroadPeaks.js","../node_modules/ml-gsd/lib-esm/utils/setShape.js","../lib-esm/peaks/peakToXY.js","../node_modules/cross-fetch/dist/browser-ponyfill.js","../node_modules/form-data/lib/browser.js","../node_modules/openchemlib-utils/src/util/tagAtom.js","../node_modules/openchemlib-utils/src/diastereotopic/addDiastereotopicMissingChirality.js","../node_modules/openchemlib-utils/src/util/makeRacemic.js","../node_modules/openchemlib-utils/src/diastereotopic/getDiastereotopicAtomIDs.js","../node_modules/openchemlib-utils/src/diastereotopic/groupDiastereotopicAtomIDs.js","../node_modules/openchemlib-utils/src/diastereotopic/getGroupedDiastereotopicAtomIDs.js","../node_modules/openchemlib-utils/src/util/isCsp3.js","../node_modules/openchemlib-utils/src/hose/getHoseCodesForAtoms.js","../node_modules/openchemlib-utils/src/hose/getHoseCodesForAtom.js","../node_modules/openchemlib-utils/src/hose/getHoseCodesFromDiastereotopicID.js","../node_modules/openchemlib-utils/src/hose/getHoseCodesForPath.js","../node_modules/openchemlib-utils/src/util/getAtomsInfo.js","../node_modules/ml-floyd-warshall/src/index.js","../node_modules/openchemlib-utils/src/util/getConnectivityMatrix.js","../node_modules/openchemlib-utils/src/path/getPathAndTorsion.js","../node_modules/openchemlib-utils/src/path/getPathsInfo.js","../node_modules/ml-array-sum/lib-es6/index.js","../node_modules/ml-array-mean/lib-es6/index.js","../lib-esm/constants/couplingValues.js","../lib-esm/utilities/joinPatterns.js","../lib-esm/signal/signalJoinCouplings.js","../lib-esm/signals/signalsJoin.js","../lib-esm/utilities/rangeFromSignal.js","../lib-esm/signals/signalsToRanges.js","../lib-esm/prediction/predictProton.js","../lib-esm/peaks/util/setIDs.js","../lib-esm/prediction/utils/fetchPrediction.js","../lib-esm/prediction/utils/getFilteredIDiaIDs.js","../lib-esm/prediction/utils/queryByHOSE.js","../lib-esm/prediction/predictCarbon.js","../node_modules/ml-distance-euclidean/lib-es6/euclidean.js","../node_modules/ml-distance-matrix/src/index.js","../node_modules/heap/lib/heap.js","../node_modules/heap/index.js","../node_modules/ml-hclust/src/Cluster.js","../node_modules/ml-hclust/src/agnes.js","../lib-esm/prediction/utils/getNuclei.js","../lib-esm/prediction/utils/getPredictions.js","../lib-esm/prediction/utils/predict2D.js","../lib-esm/prediction/predictCOSY.js","../lib-esm/prediction/predictHSQC.js","../lib-esm/prediction/predictHMBC.js","../lib-esm/prediction/predictAll.js","../lib-esm/signals/signals2DToZ.js","../node_modules/ml-simple-clustering/src/index.js","../lib-esm/signals/simulation/signalsToSpinSystem.js","../node_modules/binary-search/index.js","../node_modules/num-sort/index.js","../node_modules/ml-hash-table/src/primeFinder.js","../node_modules/ml-hash-table/src/HashTable.js","../node_modules/ml-sparse-matrix/src/index.js","../lib-esm/signals/simulation/getPauliMatrix.js","../lib-esm/signals/simulation/simulateXYPeaks.js","../lib-esm/signals/simulation/simulate1D.js","../lib-esm/signals/simulation/splitSpinSystem.js","../lib-esm/signals/signalsToXY.js","../lib-esm/utilities/getFrequency.js","../lib-esm/prediction/predictAllSpectra.js","../node_modules/ml-tree-set/src/index.js","../lib-esm/assignment/utils/createMapPossibleAssignments.js","../lib-esm/assignment/utils/partialScore.js","../lib-esm/assignment/utils/exploreTreeRec.js","../lib-esm/assignment/utils/buildAssignments.js","../lib-esm/assignment/get1HAssignments.js","../lib-esm/assignment/get13CAssignments.js","../node_modules/nmr-correlation/lib-esm/utilities/general/getAtomCounts.js","../node_modules/nmr-correlation/lib-esm/utilities/general/getCorrelationIndex.js","../node_modules/nmr-correlation/lib-esm/utilities/general/getCorrelationsByAtomType.js","../node_modules/nmr-correlation/lib-esm/utilities/build/buildState.js","../node_modules/lodash/isArray.js","../node_modules/lodash/_freeGlobal.js","../node_modules/lodash/_root.js","../node_modules/lodash/_Symbol.js","../node_modules/lodash/_getRawTag.js","../node_modules/lodash/_objectToString.js","../node_modules/lodash/_baseGetTag.js","../node_modules/lodash/isObjectLike.js","../node_modules/lodash/isSymbol.js","../node_modules/lodash/_isKey.js","../node_modules/lodash/isObject.js","../node_modules/lodash/isFunction.js","../node_modules/lodash/_coreJsData.js","../node_modules/lodash/_isMasked.js","../node_modules/lodash/_toSource.js","../node_modules/lodash/_baseIsNative.js","../node_modules/lodash/_getValue.js","../node_modules/lodash/_getNative.js","../node_modules/lodash/_nativeCreate.js","../node_modules/lodash/_hashClear.js","../node_modules/lodash/_hashDelete.js","../node_modules/lodash/_hashGet.js","../node_modules/lodash/_hashHas.js","../node_modules/lodash/_hashSet.js","../node_modules/lodash/_Hash.js","../node_modules/lodash/_listCacheClear.js","../node_modules/lodash/eq.js","../node_modules/lodash/_assocIndexOf.js","../node_modules/lodash/_listCacheDelete.js","../node_modules/lodash/_listCacheGet.js","../node_modules/lodash/_listCacheHas.js","../node_modules/lodash/_listCacheSet.js","../node_modules/lodash/_ListCache.js","../node_modules/lodash/_Map.js","../node_modules/lodash/_mapCacheClear.js","../node_modules/lodash/_isKeyable.js","../node_modules/lodash/_getMapData.js","../node_modules/lodash/_mapCacheDelete.js","../node_modules/lodash/_mapCacheGet.js","../node_modules/lodash/_mapCacheHas.js","../node_modules/lodash/_mapCacheSet.js","../node_modules/lodash/_MapCache.js","../node_modules/lodash/memoize.js","../node_modules/lodash/_memoizeCapped.js","../node_modules/lodash/_stringToPath.js","../node_modules/lodash/_arrayMap.js","../node_modules/lodash/_baseToString.js","../node_modules/lodash/toString.js","../node_modules/lodash/_castPath.js","../node_modules/lodash/_toKey.js","../node_modules/lodash/_baseGet.js","../node_modules/lodash/get.js","../node_modules/nmr-correlation/lib-esm/utilities/general/checkMatch.js","../node_modules/nmr-correlation/lib-esm/utilities/general/getLinkDim.js","../node_modules/nmr-correlation/lib-esm/utilities/general/getLinkDelta.js","../node_modules/nmr-correlation/lib-esm/utilities/general/getCorrelationDelta.js","../node_modules/nmr-correlation/lib-esm/utilities/protonsCount/setProtonsCount.js","../node_modules/nmr-correlation/lib-esm/utilities/protonsCount/setProtonsCountFromDEPT.js","../node_modules/nmr-correlation/lib-esm/utilities/protonsCount/setProtonsCountFromEditedHSQC.js","../node_modules/nmr-correlation/lib-esm/utilities/protonsCount/setProtonsCountFromData.js","../node_modules/nmr-correlation/lib-esm/utilities/experiment/getExperiments.js","../node_modules/nmr-correlation/lib-esm/utilities/general/getAtomTypeFromNucleus.js","../node_modules/nmr-correlation/lib-esm/utilities/experiment/addToExperiments.js","../node_modules/nmr-correlation/lib-esm/utilities/experiment/getExperiments1D.js","../node_modules/nmr-correlation/lib-esm/utilities/experiment/getExperiments1DExtra.js","../node_modules/nmr-correlation/lib-esm/utilities/experiment/getExperiments2D.js","../node_modules/nmr-correlation/lib-esm/constants/allowedSignalKinds.js","../node_modules/nmr-correlation/lib-esm/utilities/signals/getSignals1D.js","../node_modules/lodash/_stackClear.js","../node_modules/lodash/_stackDelete.js","../node_modules/lodash/_stackGet.js","../node_modules/lodash/_stackHas.js","../node_modules/lodash/_stackSet.js","../node_modules/lodash/_Stack.js","../node_modules/lodash/_arrayEach.js","../node_modules/lodash/_defineProperty.js","../node_modules/lodash/_baseAssignValue.js","../node_modules/lodash/_assignValue.js","../node_modules/lodash/_copyObject.js","../node_modules/lodash/_baseTimes.js","../node_modules/lodash/_baseIsArguments.js","../node_modules/lodash/isArguments.js","../node_modules/lodash/stubFalse.js","../node_modules/lodash/isBuffer.js","../node_modules/lodash/_isIndex.js","../node_modules/lodash/isLength.js","../node_modules/lodash/_baseIsTypedArray.js","../node_modules/lodash/_baseUnary.js","../node_modules/lodash/_nodeUtil.js","../node_modules/lodash/isTypedArray.js","../node_modules/lodash/_arrayLikeKeys.js","../node_modules/lodash/_isPrototype.js","../node_modules/lodash/_overArg.js","../node_modules/lodash/_nativeKeys.js","../node_modules/lodash/_baseKeys.js","../node_modules/lodash/isArrayLike.js","../node_modules/lodash/keys.js","../node_modules/lodash/_baseAssign.js","../node_modules/lodash/_nativeKeysIn.js","../node_modules/lodash/_baseKeysIn.js","../node_modules/lodash/keysIn.js","../node_modules/lodash/_baseAssignIn.js","../node_modules/lodash/_cloneBuffer.js","../node_modules/lodash/_copyArray.js","../node_modules/lodash/_arrayFilter.js","../node_modules/lodash/stubArray.js","../node_modules/lodash/_getSymbols.js","../node_modules/lodash/_copySymbols.js","../node_modules/lodash/_arrayPush.js","../node_modules/lodash/_getPrototype.js","../node_modules/lodash/_getSymbolsIn.js","../node_modules/lodash/_copySymbolsIn.js","../node_modules/lodash/_baseGetAllKeys.js","../node_modules/lodash/_getAllKeys.js","../node_modules/lodash/_getAllKeysIn.js","../node_modules/lodash/_DataView.js","../node_modules/lodash/_Promise.js","../node_modules/lodash/_Set.js","../node_modules/lodash/_WeakMap.js","../node_modules/lodash/_getTag.js","../node_modules/lodash/_initCloneArray.js","../node_modules/lodash/_Uint8Array.js","../node_modules/lodash/_cloneArrayBuffer.js","../node_modules/lodash/_cloneDataView.js","../node_modules/lodash/_cloneRegExp.js","../node_modules/lodash/_cloneSymbol.js","../node_modules/lodash/_cloneTypedArray.js","../node_modules/lodash/_initCloneByTag.js","../node_modules/lodash/_baseCreate.js","../node_modules/lodash/_initCloneObject.js","../node_modules/lodash/_baseIsMap.js","../node_modules/lodash/isMap.js","../node_modules/lodash/_baseIsSet.js","../node_modules/lodash/isSet.js","../node_modules/lodash/_baseClone.js","../node_modules/lodash/cloneDeep.js","../node_modules/lodash/_setCacheAdd.js","../node_modules/lodash/_setCacheHas.js","../node_modules/lodash/_SetCache.js","../node_modules/lodash/_arraySome.js","../node_modules/lodash/_cacheHas.js","../node_modules/lodash/_equalArrays.js","../node_modules/lodash/_mapToArray.js","../node_modules/lodash/_setToArray.js","../node_modules/lodash/_equalByTag.js","../node_modules/lodash/_equalObjects.js","../node_modules/lodash/_baseIsEqualDeep.js","../node_modules/lodash/_baseIsEqual.js","../node_modules/lodash/isEqual.js","../node_modules/nmr-correlation/lib-esm/utilities/general/isEditedHSQC.js","../node_modules/nmr-correlation/lib-esm/utilities/signals/getSignals2D.js","../node_modules/nmr-correlation/lib-esm/utilities/signals/getSignalsDEPT.js","../node_modules/nmr-correlation/lib-esm/utilities/signals/getSignals.js","../node_modules/nmr-correlation/lib-esm/utilities/general/generateID.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/buildLink.js","../node_modules/nmr-correlation/lib-esm/utilities/general/findLinkedCorrelationsBySignalID.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/containsLink.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/hasLinks.js","../node_modules/nmr-correlation/lib-esm/utilities/build/addSignal.js","../node_modules/nmr-correlation/lib-esm/utilities/build/addFromData.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/buildCorrelation.js","../node_modules/nmr-correlation/lib-esm/utilities/build/pseudo/addPseudoCorrelations.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/removeLink.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/removeMatch.js","../node_modules/nmr-correlation/lib-esm/utilities/build/pseudo/checkPseudoCorrelations.js","../node_modules/nmr-correlation/lib-esm/utilities/build/pseudo/replacePseudoCorrelationsByEquivalences.js","../node_modules/nmr-correlation/lib-esm/utilities/build/pseudo/updatePseudoCorrelations.js","../node_modules/nmr-correlation/lib-esm/utilities/build/removeObsoleteLinksAndNotLinkedCorrelations.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/hasAttachmentAtomType.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/addAttachmentAtomType.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/addAttachment.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/removeAttachments.js","../node_modules/nmr-correlation/lib-esm/utilities/build/setAttachmentsAndProtonEquivalences.js","../node_modules/nmr-correlation/lib-esm/utilities/build/setLabels.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/addMatch.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/removeMatches.js","../node_modules/nmr-correlation/lib-esm/utilities/build/setMatches.js","../node_modules/nmr-correlation/lib-esm/utilities/build/sortCorrelations.js","../node_modules/nmr-correlation/lib-esm/utilities/build/buildValues.js","../node_modules/nmr-correlation/lib-esm/build/buildCorrelationData.js","../node_modules/nmr-correlation/lib-esm/utilities/correlation/addLink.js","../lib-esm/assignment/utils/getAssignment/createMapPossibleAssignment.js","../lib-esm/assignment/utils/getAssignment/groupCarbonTargetByIntegrationZone.js","../lib-esm/assignment/utils/getAssignment/partialScore.js","../lib-esm/assignment/utils/getAssignment/exploreTree.js","../lib-esm/assignment/utils/getAssignment/isSpectraData1D.js","../lib-esm/assignment/utils/getAssignment/searchIndices.js","../lib-esm/assignment/utils/getAssignment/buildAssignments.js","../lib-esm/assignment/utils/getAssignment/checkIDs.js","../lib-esm/assignment/utils/getAssignment/formatData.js","../lib-esm/assignment/utils/getAssignment/getIntegrationOfAttachedProtons.js","../lib-esm/assignment/utils/getAssignment/getTargetsAndCorrelations.js","../lib-esm/assignment/utils/getAssignment/getWorkFlow.js","../lib-esm/assignment/getAssignments.js","../lib-esm/signal/signalMultiplicityPattern.js","../lib-esm/ranges/rangesToACS.js","../lib-esm/signals/addDummySignals.js","../lib-esm/signals/hackSignalsToXY.js","../lib-esm/ranges/rangesToXY.js","../lib-esm/signals/optimization/directOptimization.js","../lib-esm/signals/optimization/defaultParameters.js","../lib-esm/signals/optimization/signalsToPointXY.js","../lib-esm/signals/optimization/getInternalSignals.js","../lib-esm/signals/optimization/getSumOfShapes.js","../lib-esm/signals/optimizeSignals.js","../lib-esm/apodization/applyWindow.js","../lib-esm/apodization/shapes/exponential.js","../lib-esm/apodization/shapes/lorentzToGauss.js","../lib-esm/apodization/getFunction.js","../lib-esm/apodization/utils/getData.js","../lib-esm/apodization/compose.js","../lib-esm/apodization/apodization.js","../lib-esm/signals/signalsToFID.js","../lib-esm/utilities/splitParenthesis.js","../lib-esm/utilities/splitPatterns.js","../lib-esm/utilities/resurrectRange.js","../lib-esm/utilities/resurrect.js","../lib-esm/peaks/util/convertWidthToHz.js","../lib-esm/xy/xyAutoPeaksPicking.js","../lib-esm/ranges/utils/joinRanges.js","../lib-esm/signals/utils/jAnalyzer.js","../lib-esm/peaks/peaksToRanges.js","../lib-esm/xy/xyAutoRangesPicking.js","../lib-esm/xy/xyPeaksOptimization.js","../node_modules/ml-fft/src/fftlib.js","../node_modules/ml-fft/src/FFTUtils.js","../node_modules/ml-fft/src/index.js","../node_modules/ml-matrix-convolution/src/util/matrix2Array.js","../node_modules/ml-matrix-convolution/src/convolutionFFT.js","../node_modules/ml-matrix-convolution/src/convolutionDirect.js","../node_modules/ml-disjoint-set/src/DisjointSet.js","../node_modules/ml-matrix-peaks-finder/src/drainLabelling.js","../node_modules/ml-matrix-peaks-finder/src/floodFillLabelling.js","../node_modules/ml-matrix-peaks-finder/src/index.js","../lib-esm/peaks/util/addMissingIDs.js","../lib-esm/peaks/util/determineRealTop.js","../lib-esm/peaks/util/getKernel.js","../lib-esm/peaks/util/peakOptimizer.js","../lib-esm/xyz/util/formatZone.js","../lib-esm/xyz/xyzAutoZonesPicking.js","../lib-esm/xyz/xyzJResAnalyzer.js","../lib-esm/databases/getDatabase.js","../lib-esm/databases/carbonImpurities.js","../lib-esm/databases/protonImpurities.js","../node_modules/linear-sum-assignment/lib-esm/getShortestPath.js","../node_modules/linear-sum-assignment/lib-esm/index.js","../lib-esm/utilities/clone.js","../lib-esm/peaks/solventSuppression.js","../lib-esm/ranges/markSolventSignal.js"],"sourcesContent":["export const gyromagneticRatio = {\n    '1H': 267.52218744e6,\n    '2H': 41.065e6,\n    '3H': 285.3508e6,\n    '3He': -203.789e6,\n    '7Li': 103.962e6,\n    '13C': 67.28284e6,\n    '14N': 19.331e6,\n    '15N': -27.116e6,\n    '17O': -36.264e6,\n    '19F': 251.662e6,\n    '23Na': 70.761e6,\n    '27Al': 69.763e6,\n    '29Si': -53.19e6,\n    '31P': 108.291e6,\n    '57Fe': 8.681e6,\n    '63Cu': 71.118e6,\n    '67Zn': 16.767e6,\n    '129Xe': -73.997e6,\n};\n//# sourceMappingURL=index.js.map","/* eslint-disable camelcase */\nexport const impurities = {\n    cdcl3: {\n        tms: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: '',\n                shift: 0,\n            },\n        ],\n        solvent: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: 'ds',\n                shift: 7.26,\n            },\n        ],\n        h2o: [\n            {\n                proton: 'H2O',\n                coupling: 0,\n                multiplicity: 'bs',\n                shift: 1.56,\n            },\n        ],\n        acetic_acid: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.1,\n            },\n        ],\n        acetone: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.17,\n            },\n        ],\n        acetonitrile: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.1,\n            },\n        ],\n        benzene: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.36,\n            },\n        ],\n        'tert-butyl_alcohol': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.28,\n            },\n        ],\n        'tert-butyl_methyl_ether': [\n            {\n                proton: 'CCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.19,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.22,\n            },\n        ],\n        bhtb: [\n            {\n                proton: 'ArH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 6.98,\n            },\n            {\n                proton: 'OHc',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 5.01,\n            },\n            {\n                proton: 'ArCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.27,\n            },\n            {\n                proton: 'ArC(CH3)3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.43,\n            },\n        ],\n        chloroform: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.26,\n            },\n        ],\n        cyclohexane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.43,\n            },\n        ],\n        '1,2-dichloroethane': [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.73,\n            },\n        ],\n        dichloromethane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 5.3,\n            },\n        ],\n        diethyl_ether: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.21,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.48,\n            },\n        ],\n        diglyme: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.65,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.57,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.39,\n            },\n        ],\n        '1,2-dimethoxyethane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.4,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.55,\n            },\n        ],\n        dimethylacetamide: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.09,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.02,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.94,\n            },\n        ],\n        dimethylformamide: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 8.02,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.96,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.88,\n            },\n        ],\n        dimethyl_sulfoxide: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.62,\n            },\n        ],\n        dioxane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.71,\n            },\n        ],\n        ethanol: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.25,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.72,\n            },\n            {\n                proton: 'OH',\n                coupling: 5,\n                multiplicity: 's,t',\n                shift: 1.32,\n            },\n        ],\n        ethyl_acetate: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.05,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 4.12,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.26,\n            },\n        ],\n        ethyl_methyl_ketone: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.14,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 2.46,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.06,\n            },\n        ],\n        ethylene_glycol: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.76,\n            },\n        ],\n        'grease^f': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 0.86,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'br_s',\n                shift: 1.26,\n            },\n        ],\n        'n-hexane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 't',\n                shift: 0.88,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.26,\n            },\n        ],\n        hmpag: [\n            {\n                proton: 'CH3',\n                coupling: 9.5,\n                multiplicity: 'd',\n                shift: 2.65,\n            },\n        ],\n        methanol: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.49,\n            },\n            {\n                proton: 'OH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.09,\n            },\n        ],\n        nitromethane: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 4.33,\n            },\n        ],\n        'n-pentane': [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 7,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.27,\n            },\n        ],\n        '2-propanol': [\n            {\n                proton: 'CH3',\n                coupling: 6,\n                multiplicity: 'd',\n                shift: 1.22,\n            },\n            {\n                proton: 'CH',\n                coupling: 6,\n                multiplicity: 'sep',\n                shift: 4.04,\n            },\n        ],\n        pyridine: [\n            {\n                proton: 'CH(2)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 8.62,\n            },\n            {\n                proton: 'CH(3)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.29,\n            },\n            {\n                proton: 'CH(4)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.68,\n            },\n        ],\n        silicone_greasei: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 0.07,\n            },\n        ],\n        tetrahydrofuran: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.85,\n            },\n            {\n                proton: 'CH2O',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.76,\n            },\n        ],\n        toluene: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.36,\n            },\n            {\n                proton: 'CH(o/p)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.17,\n            },\n            {\n                proton: 'CH(m)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.25,\n            },\n        ],\n        triethylamine: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.03,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 2.53,\n            },\n        ],\n    },\n    '(cd3)2co': {\n        tms: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: '',\n                shift: 0,\n            },\n        ],\n        solvent: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: '',\n                shift: 2.05,\n            },\n        ],\n        h2o: [\n            {\n                proton: 'H2O',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.84,\n            },\n        ],\n        acetic_acid: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.96,\n            },\n        ],\n        acetone: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.09,\n            },\n        ],\n        acetonitrile: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.05,\n            },\n        ],\n        benzene: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.36,\n            },\n        ],\n        'tert-butyl_alcohol': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.18,\n            },\n        ],\n        'tert-butyl_methyl_ether': [\n            {\n                proton: 'CCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.13,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.13,\n            },\n        ],\n        bhtb: [\n            {\n                proton: 'ArH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 6.96,\n            },\n            {\n                proton: 'ArCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.22,\n            },\n            {\n                proton: 'ArC(CH3)3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.41,\n            },\n        ],\n        chloroform: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 8.02,\n            },\n        ],\n        cyclohexane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.43,\n            },\n        ],\n        '1,2-dichloroethane': [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.87,\n            },\n        ],\n        dichloromethane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 5.63,\n            },\n        ],\n        diethyl_ether: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.11,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.41,\n            },\n        ],\n        diglyme: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.56,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.47,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.28,\n            },\n        ],\n        '1,2-dimethoxyethane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.28,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.46,\n            },\n        ],\n        dimethylacetamide: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.97,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.83,\n            },\n        ],\n        dimethylformamide: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.96,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.94,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.78,\n            },\n        ],\n        dimethyl_sulfoxide: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.52,\n            },\n        ],\n        dioxane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.59,\n            },\n        ],\n        ethanol: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.12,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.57,\n            },\n            {\n                proton: 'OH',\n                coupling: 5,\n                multiplicity: 's,t',\n                shift: 3.39,\n            },\n        ],\n        ethyl_acetate: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.97,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 4.05,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.2,\n            },\n        ],\n        ethyl_methyl_ketone: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.07,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 2.45,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.96,\n            },\n        ],\n        ethylene_glycol: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.28,\n            },\n        ],\n        'grease^f': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 0.87,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'br_s',\n                shift: 1.29,\n            },\n        ],\n        'n-hexane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 't',\n                shift: 0.88,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.28,\n            },\n        ],\n        hmpag: [\n            {\n                proton: 'CH3',\n                coupling: 9.5,\n                multiplicity: 'd',\n                shift: 2.59,\n            },\n        ],\n        methanol: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.31,\n            },\n            {\n                proton: 'OH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.12,\n            },\n        ],\n        nitromethane: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 4.43,\n            },\n        ],\n        'n-pentane': [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.88,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.27,\n            },\n        ],\n        '2-propanol': [\n            {\n                proton: 'CH3',\n                coupling: 6,\n                multiplicity: 'd',\n                shift: 1.1,\n            },\n            {\n                proton: 'CH',\n                coupling: 6,\n                multiplicity: 'sep',\n                shift: 3.9,\n            },\n        ],\n        pyridine: [\n            {\n                proton: 'CH(2)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 8.58,\n            },\n            {\n                proton: 'CH(3)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.35,\n            },\n            {\n                proton: 'CH(4)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.76,\n            },\n        ],\n        silicone_greasei: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 0.13,\n            },\n        ],\n        tetrahydrofuran: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.79,\n            },\n            {\n                proton: 'CH2O',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.63,\n            },\n        ],\n        toluene: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.32,\n            },\n            {\n                proton: 'CH(o/p)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.5,\n            },\n            {\n                proton: 'CH(m)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.5,\n            },\n        ],\n        triethylamine: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.96,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 2.45,\n            },\n        ],\n    },\n    dmso: {\n        tms: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: '',\n                shift: 0,\n            },\n        ],\n        solvent: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: 'quint',\n                shift: 2.5,\n            },\n        ],\n        h2o: [\n            {\n                proton: 'H2O',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.33,\n            },\n        ],\n        acetic_acid: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.91,\n            },\n        ],\n        acetone: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.09,\n            },\n        ],\n        acetonitrile: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.07,\n            },\n        ],\n        benzene: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.37,\n            },\n        ],\n        'tert-butyl_alcohol': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.11,\n            },\n            {\n                proton: 'OHc',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 4.19,\n            },\n        ],\n        'tert-butyl_methyl_ether': [\n            {\n                proton: 'CCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.11,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.08,\n            },\n        ],\n        bhtb: [\n            {\n                proton: 'ArH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 6.87,\n            },\n            {\n                proton: 'OHc',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 6.65,\n            },\n            {\n                proton: 'ArCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.18,\n            },\n            {\n                proton: 'ArC(CH3)3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.36,\n            },\n        ],\n        chloroform: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 8.32,\n            },\n        ],\n        cyclohexane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.4,\n            },\n        ],\n        '1,2-dichloroethane': [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.9,\n            },\n        ],\n        dichloromethane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 5.76,\n            },\n        ],\n        diethyl_ether: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.09,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.38,\n            },\n        ],\n        diglyme: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.51,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.38,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.24,\n            },\n        ],\n        '1,2-dimethoxyethane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.24,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.43,\n            },\n        ],\n        dimethylacetamide: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.96,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.94,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.78,\n            },\n        ],\n        dimethylformamide: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.95,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.89,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.73,\n            },\n        ],\n        dimethyl_sulfoxide: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.54,\n            },\n        ],\n        dioxane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.57,\n            },\n        ],\n        ethanol: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.06,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.44,\n            },\n            {\n                proton: 'OH',\n                coupling: 5,\n                multiplicity: 's,t',\n                shift: 4.63,\n            },\n        ],\n        ethyl_acetate: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.99,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 4.03,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.17,\n            },\n        ],\n        ethyl_methyl_ketone: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.07,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 2.43,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.91,\n            },\n        ],\n        ethylene_glycol: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.34,\n            },\n        ],\n        'grease^f': [],\n        'n-hexane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 't',\n                shift: 0.86,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.25,\n            },\n        ],\n        hmpag: [\n            {\n                proton: 'CH3',\n                coupling: 9.5,\n                multiplicity: 'd',\n                shift: 2.53,\n            },\n        ],\n        methanol: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.16,\n            },\n            {\n                proton: 'OH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 4.01,\n            },\n        ],\n        nitromethane: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 4.42,\n            },\n        ],\n        'n-pentane': [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.88,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.27,\n            },\n        ],\n        '2-propanol': [\n            {\n                proton: 'CH3',\n                coupling: 6,\n                multiplicity: 'd',\n                shift: 1.04,\n            },\n            {\n                proton: 'CH',\n                coupling: 6,\n                multiplicity: 'sep',\n                shift: 3.78,\n            },\n        ],\n        pyridine: [\n            {\n                proton: 'CH(2)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 8.58,\n            },\n            {\n                proton: 'CH(3)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.39,\n            },\n            {\n                proton: 'CH(4)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.79,\n            },\n        ],\n        silicone_greasei: [],\n        tetrahydrofuran: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.76,\n            },\n            {\n                proton: 'CH2O',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.6,\n            },\n        ],\n        toluene: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.3,\n            },\n            {\n                proton: 'CH(o/p)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.18,\n            },\n            {\n                proton: 'CH(m)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.25,\n            },\n        ],\n        triethylamine: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.93,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 2.43,\n            },\n        ],\n    },\n    c6d6: {\n        tms: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: '',\n                shift: 0,\n            },\n        ],\n        solvent: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: '',\n                shift: 7.16,\n            },\n        ],\n        h2o: [\n            {\n                proton: 'H2O',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 0.4,\n            },\n        ],\n        acetic_acid: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.55,\n            },\n        ],\n        acetone: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.55,\n            },\n        ],\n        acetonitrile: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.55,\n            },\n        ],\n        benzene: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.15,\n            },\n        ],\n        'tert-butyl_alcohol': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.05,\n            },\n            {\n                proton: 'OHc',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.55,\n            },\n        ],\n        'tert-butyl_methyl_ether': [\n            {\n                proton: 'CCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.07,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.04,\n            },\n        ],\n        bhtb: [\n            {\n                proton: 'ArH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.05,\n            },\n            {\n                proton: 'OHc',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 4.79,\n            },\n            {\n                proton: 'ArCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.24,\n            },\n            {\n                proton: 'ArC(CH3)3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.38,\n            },\n        ],\n        chloroform: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 6.15,\n            },\n        ],\n        cyclohexane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.4,\n            },\n        ],\n        '1,2-dichloroethane': [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.9,\n            },\n        ],\n        dichloromethane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 4.27,\n            },\n        ],\n        diethyl_ether: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.11,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.26,\n            },\n        ],\n        diglyme: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.46,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.34,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.11,\n            },\n        ],\n        '1,2-dimethoxyethane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.12,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.33,\n            },\n        ],\n        dimethylacetamide: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.6,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.57,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.05,\n            },\n        ],\n        dimethylformamide: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.63,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.36,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.86,\n            },\n        ],\n        dimethyl_sulfoxide: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.68,\n            },\n        ],\n        dioxane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.35,\n            },\n        ],\n        ethanol: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.96,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.34,\n            },\n        ],\n        ethyl_acetate: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.65,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.89,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.92,\n            },\n        ],\n        ethyl_methyl_ketone: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.58,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 1.81,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.85,\n            },\n        ],\n        ethylene_glycol: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.41,\n            },\n        ],\n        'grease^f': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 0.92,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'br_s',\n                shift: 1.36,\n            },\n        ],\n        'n-hexane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 't',\n                shift: 0.89,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.24,\n            },\n        ],\n        hmpag: [\n            {\n                proton: 'CH3',\n                coupling: 9.5,\n                multiplicity: 'd',\n                shift: 2.4,\n            },\n        ],\n        methanol: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.07,\n            },\n        ],\n        nitromethane: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.94,\n            },\n        ],\n        'n-pentane': [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.86,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.23,\n            },\n        ],\n        '2-propanol': [\n            {\n                proton: 'CH3',\n                coupling: 6,\n                multiplicity: 'd',\n                shift: 0.95,\n            },\n            {\n                proton: 'CH',\n                coupling: 6,\n                multiplicity: 'sep',\n                shift: 3.67,\n            },\n        ],\n        pyridine: [\n            {\n                proton: 'CH(2)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 8.53,\n            },\n            {\n                proton: 'CH(3)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 6.66,\n            },\n            {\n                proton: 'CH(4)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 6.98,\n            },\n        ],\n        silicone_greasei: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 0.29,\n            },\n        ],\n        tetrahydrofuran: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.4,\n            },\n            {\n                proton: 'CH2O',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.57,\n            },\n        ],\n        toluene: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.11,\n            },\n            {\n                proton: 'CH(o/p)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.02,\n            },\n            {\n                proton: 'CH(m)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.13,\n            },\n        ],\n        triethylamine: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.96,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 2.4,\n            },\n        ],\n    },\n    cd3cn: {\n        tms: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: '',\n                shift: 0,\n            },\n        ],\n        solvent: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: '',\n                shift: 1.94,\n            },\n        ],\n        h2o: [\n            {\n                proton: 'H2O',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.13,\n            },\n        ],\n        acetic_acid: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.96,\n            },\n        ],\n        acetone: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.08,\n            },\n        ],\n        acetonitrile: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.96,\n            },\n        ],\n        benzene: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.37,\n            },\n        ],\n        'tert-butyl_alcohol': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.16,\n            },\n            {\n                proton: 'OHc',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.18,\n            },\n        ],\n        'tert-butyl_methyl_ether': [\n            {\n                proton: 'CCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.14,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.13,\n            },\n        ],\n        bhtb: [\n            {\n                proton: 'ArH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 6.97,\n            },\n            {\n                proton: 'OHc',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 5.2,\n            },\n            {\n                proton: 'ArCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.22,\n            },\n            {\n                proton: 'ArC(CH3)3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.39,\n            },\n        ],\n        chloroform: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.58,\n            },\n        ],\n        cyclohexane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.44,\n            },\n        ],\n        '1,2-dichloroethane': [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.81,\n            },\n        ],\n        dichloromethane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 5.44,\n            },\n        ],\n        diethyl_ether: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.12,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.42,\n            },\n        ],\n        diglyme: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.53,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.45,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.29,\n            },\n        ],\n        '1,2-dimethoxyethane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.28,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.45,\n            },\n        ],\n        dimethylacetamide: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.97,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.96,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.83,\n            },\n        ],\n        dimethylformamide: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.92,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.89,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.77,\n            },\n        ],\n        dimethyl_sulfoxide: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.5,\n            },\n        ],\n        dioxane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.6,\n            },\n        ],\n        ethanol: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.12,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.54,\n            },\n            {\n                proton: 'OH',\n                coupling: 5,\n                multiplicity: 's,t',\n                shift: 2.47,\n            },\n        ],\n        ethyl_acetate: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.97,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 4.06,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.2,\n            },\n        ],\n        ethyl_methyl_ketone: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.06,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 2.43,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.96,\n            },\n        ],\n        ethylene_glycol: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.51,\n            },\n        ],\n        'grease^f': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 0.86,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'br_s',\n                shift: 1.27,\n            },\n        ],\n        'n-hexane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 't',\n                shift: 0.89,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.28,\n            },\n        ],\n        hmpag: [\n            {\n                proton: 'CH3',\n                coupling: 9.5,\n                multiplicity: 'd',\n                shift: 2.57,\n            },\n        ],\n        methanol: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.28,\n            },\n            {\n                proton: 'OH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.16,\n            },\n        ],\n        nitromethane: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 4.31,\n            },\n        ],\n        'n-pentane': [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.87,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.29,\n            },\n        ],\n        '2-propanol': [\n            {\n                proton: 'CH3',\n                coupling: 6,\n                multiplicity: 'd',\n                shift: 1.09,\n            },\n            {\n                proton: 'CH',\n                coupling: 6,\n                multiplicity: 'sep',\n                shift: 3.87,\n            },\n        ],\n        pyridine: [\n            {\n                proton: 'CH(2)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 8.57,\n            },\n            {\n                proton: 'CH(3)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.33,\n            },\n            {\n                proton: 'CH(4)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.73,\n            },\n        ],\n        silicone_greasei: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 0.08,\n            },\n        ],\n        tetrahydrofuran: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.8,\n            },\n            {\n                proton: 'CH2O',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.64,\n            },\n        ],\n        toluene: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.33,\n            },\n            {\n                proton: 'CH(o/p)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.2,\n            },\n            {\n                proton: 'CH(m)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.2,\n            },\n        ],\n        triethylamine: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.96,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 2.45,\n            },\n        ],\n    },\n    cd3od: {\n        tms: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: '',\n                shift: 0,\n            },\n        ],\n        solvent: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: '',\n                shift: 3.31,\n            },\n        ],\n        h2o: [\n            {\n                proton: 'H2O',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 4.87,\n            },\n        ],\n        acetic_acid: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.99,\n            },\n        ],\n        acetone: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.15,\n            },\n        ],\n        acetonitrile: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.03,\n            },\n        ],\n        benzene: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.33,\n            },\n        ],\n        'tert-butyl_alcohol': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.4,\n            },\n        ],\n        'tert-butyl_methyl_ether': [\n            {\n                proton: 'CCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.15,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.2,\n            },\n        ],\n        bhtb: [\n            {\n                proton: 'ArH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 6.92,\n            },\n            {\n                proton: 'ArCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.21,\n            },\n            {\n                proton: 'ArC(CH3)3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.4,\n            },\n        ],\n        chloroform: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.9,\n            },\n        ],\n        cyclohexane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.45,\n            },\n        ],\n        '1,2-dichloroethane': [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.78,\n            },\n        ],\n        dichloromethane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 5.49,\n            },\n        ],\n        diethyl_ether: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.18,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.49,\n            },\n        ],\n        diglyme: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.61,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.58,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.35,\n            },\n        ],\n        '1,2-dimethoxyethane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.35,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.52,\n            },\n        ],\n        dimethylacetamide: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.07,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.31,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.92,\n            },\n        ],\n        dimethylformamide: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.97,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.99,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.86,\n            },\n        ],\n        dimethyl_sulfoxide: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.65,\n            },\n        ],\n        dioxane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.66,\n            },\n        ],\n        ethanol: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.19,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.6,\n            },\n        ],\n        ethyl_acetate: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.01,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 4.09,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.24,\n            },\n        ],\n        ethyl_methyl_ketone: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.12,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 2.5,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.01,\n            },\n        ],\n        ethylene_glycol: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.59,\n            },\n        ],\n        'grease^f': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 0.88,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'br_s',\n                shift: 1.29,\n            },\n        ],\n        'n-hexane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 't',\n                shift: 0.9,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.29,\n            },\n        ],\n        hmpag: [\n            {\n                proton: 'CH3',\n                coupling: 9.5,\n                multiplicity: 'd',\n                shift: 2.64,\n            },\n        ],\n        methanol: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.34,\n            },\n        ],\n        nitromethane: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 4.34,\n            },\n        ],\n        'n-pentane': [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.89,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.29,\n            },\n        ],\n        '2-propanol': [\n            {\n                proton: 'CH3',\n                coupling: 6,\n                multiplicity: 'd',\n                shift: 1.5,\n            },\n            {\n                proton: 'CH',\n                coupling: 6,\n                multiplicity: 'sep',\n                shift: 3.92,\n            },\n        ],\n        pyridine: [\n            {\n                proton: 'CH(2)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 8.53,\n            },\n            {\n                proton: 'CH(3)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.44,\n            },\n            {\n                proton: 'CH(4)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.85,\n            },\n        ],\n        silicone_greasei: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 0.1,\n            },\n        ],\n        tetrahydrofuran: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.87,\n            },\n            {\n                proton: 'CH2O',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.71,\n            },\n        ],\n        toluene: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.32,\n            },\n            {\n                proton: 'CH(o/p)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.16,\n            },\n            {\n                proton: 'CH(m)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.16,\n            },\n        ],\n        triethylamine: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.05,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 2.58,\n            },\n        ],\n    },\n    d2o: {\n        tms: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: '',\n                shift: 0,\n            },\n        ],\n        solvent: [\n            {\n                proton: 'X',\n                coupling: 0,\n                multiplicity: '',\n                shift: 4.79,\n            },\n        ],\n        h2o: [],\n        acetic_acid: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.08,\n            },\n        ],\n        acetone: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.22,\n            },\n        ],\n        acetonitrile: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.06,\n            },\n        ],\n        benzene: [],\n        'tert-butyl_alcohol': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.24,\n            },\n        ],\n        'tert-butyl_methyl_ether': [\n            {\n                proton: 'CCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 1.21,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.22,\n            },\n        ],\n        bhtb: [],\n        chloroform: [],\n        cyclohexane: [],\n        '1,2-dichloroethane': [],\n        dichloromethane: [],\n        diethyl_ether: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.17,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.56,\n            },\n        ],\n        diglyme: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.67,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.61,\n            },\n            {\n                proton: 'OCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.37,\n            },\n        ],\n        '1,2-dimethoxyethane': [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.37,\n            },\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.6,\n            },\n        ],\n        dimethylacetamide: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.08,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.06,\n            },\n            {\n                proton: 'NCH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.9,\n            },\n        ],\n        dimethylformamide: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 7.92,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.01,\n            },\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.85,\n            },\n        ],\n        dimethyl_sulfoxide: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.71,\n            },\n        ],\n        dioxane: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.75,\n            },\n        ],\n        ethanol: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.17,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.65,\n            },\n        ],\n        ethyl_acetate: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.07,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 4.14,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.24,\n            },\n        ],\n        ethyl_methyl_ketone: [\n            {\n                proton: 'CH3CO',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 2.19,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 3.18,\n            },\n            {\n                proton: 'CH2CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 1.26,\n            },\n        ],\n        ethylene_glycol: [\n            {\n                proton: 'CH',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.65,\n            },\n        ],\n        'grease^f': [],\n        'n-hexane': [],\n        hmpag: [\n            {\n                proton: 'CH3',\n                coupling: 9.5,\n                multiplicity: 'd',\n                shift: 2.61,\n            },\n        ],\n        methanol: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 3.34,\n            },\n        ],\n        nitromethane: [\n            {\n                proton: 'CH3',\n                coupling: 0,\n                multiplicity: 's',\n                shift: 4.4,\n            },\n        ],\n        'n-pentane': [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.9,\n            },\n        ],\n        '2-propanol': [\n            {\n                proton: 'CH3',\n                coupling: 6,\n                multiplicity: 'd',\n                shift: 1.17,\n            },\n            {\n                proton: 'CH',\n                coupling: 6,\n                multiplicity: 'sep',\n                shift: 4.02,\n            },\n        ],\n        pyridine: [\n            {\n                proton: 'CH(2)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 8.52,\n            },\n            {\n                proton: 'CH(3)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.45,\n            },\n            {\n                proton: 'CH(4)',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 7.87,\n            },\n        ],\n        silicone_greasei: [],\n        tetrahydrofuran: [\n            {\n                proton: 'CH2',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 1.88,\n            },\n            {\n                proton: 'CH2O',\n                coupling: 0,\n                multiplicity: 'm',\n                shift: 3.74,\n            },\n        ],\n        toluene: [],\n        triethylamine: [\n            {\n                proton: 'CH3',\n                coupling: 7,\n                multiplicity: 't',\n                shift: 0.99,\n            },\n            {\n                proton: 'CH2',\n                coupling: 7,\n                multiplicity: 'q',\n                shift: 2.57,\n            },\n        ],\n    },\n};\n//# sourceMappingURL=impurities.js.map","export const couplingPatterns = [\n    's',\n    'd',\n    't',\n    'q',\n    'quint',\n    'h',\n    'sept',\n    'o',\n    'n',\n];\n//# sourceMappingURL=couplingPatterns.js.map","import { impurities } from '../constants/impurities';\nconst toCheck = ['solvent', 'h2o', 'tms'];\n/**\n * Try to remove peaks of impurities.\n */\nexport function peaksFilterImpurities(peakList, options = {}) {\n    let { solvent, error = 0.025, remove = false } = options;\n    if (solvent) {\n        if (solvent === '(cd3)2so')\n            solvent = 'dmso';\n        if (solvent === 'meod')\n            solvent = 'cd3od';\n        let solventImpurities = impurities[solvent];\n        for (let impurity of toCheck) {\n            let impurityShifts = solventImpurities[impurity];\n            checkImpurity(peakList, impurityShifts, {\n                error,\n                remove,\n                name: impurity,\n            });\n        }\n    }\n    return peakList;\n}\nfunction checkImpurity(peakList, impurity, options) {\n    let { name, error, remove } = options;\n    let j, tolerance, difference;\n    let i = impurity.length;\n    while (i--) {\n        j = peakList.length;\n        while (j--) {\n            tolerance = error + peakList[j].width;\n            difference = Math.abs(impurity[i].shift - peakList[j].x);\n            if (difference < tolerance) {\n                // && (impurity[i].multiplicity === '' || (impurity[i].multiplicity.indexOf(peakList[j].multiplicity)) { // some impurities has multiplicities like 'bs' but at presents it is unsupported\n                if (remove) {\n                    peakList.splice(j, 1);\n                }\n                else {\n                    peakList[j].kind = name;\n                }\n            }\n        }\n    }\n}\n//# sourceMappingURL=peaksFilterImpurities.js.map","export const GAUSSIAN_EXP_FACTOR = -4 * Math.LN2;\nexport const ROOT_PI_OVER_LN2 = Math.sqrt(Math.PI / Math.LN2);\nexport const ROOT_THREE = Math.sqrt(3);\nexport const ROOT_2LN2 = Math.sqrt(2 * Math.LN2);\nexport const ROOT_2LN2_MINUS_ONE = Math.sqrt(2 * Math.LN2) - 1;\n//# sourceMappingURL=constants.js.map","// https://en.wikipedia.org/wiki/Error_function#Inverse_functions\n// This code yields to a good approximation\n// If needed a better implementation using polynomial can be found on https://en.wikipedia.org/wiki/Error_function#Inverse_functions\nexport default function erfinv(x) {\n    let a = 0.147;\n    if (x === 0)\n        return 0;\n    let ln1MinusXSqrd = Math.log(1 - x * x);\n    let lnEtcBy2Plus2 = ln1MinusXSqrd / 2 + 2 / (Math.PI * a);\n    let firstSqrt = Math.sqrt(lnEtcBy2Plus2 ** 2 - ln1MinusXSqrd / a);\n    let secondSqrt = Math.sqrt(firstSqrt - lnEtcBy2Plus2);\n    return secondSqrt * (x > 0 ? 1 : -1);\n}\n//# sourceMappingURL=erfinv.js.map","import { ROOT_2LN2, GAUSSIAN_EXP_FACTOR, ROOT_PI_OVER_LN2, } from '../../../util/constants';\nimport erfinv from '../../../util/erfinv';\nexport class Gaussian {\n    constructor(options = {}) {\n        const { fwhm = 500, sd } = options;\n        this.fwhm = sd ? gaussianWidthToFWHM(2 * sd) : fwhm;\n    }\n    fwhmToWidth(fwhm = this.fwhm) {\n        return gaussianFwhmToWidth(fwhm);\n    }\n    widthToFWHM(width) {\n        return gaussianWidthToFWHM(width);\n    }\n    fct(x) {\n        return gaussianFct(x, this.fwhm);\n    }\n    getArea(height = calculateGaussianHeight({ fwhm: this.fwhm })) {\n        return getGaussianArea({ fwhm: this.fwhm, height });\n    }\n    getFactor(area) {\n        return getGaussianFactor(area);\n    }\n    getData(options = {}) {\n        return getGaussianData(this, options);\n    }\n    calculateHeight(area = 1) {\n        return calculateGaussianHeight({ fwhm: this.fwhm, area });\n    }\n    getParameters() {\n        return ['fwhm'];\n    }\n}\nexport function calculateGaussianHeight(options) {\n    let { fwhm = 500, area = 1, sd } = options;\n    if (sd)\n        fwhm = gaussianWidthToFWHM(2 * sd);\n    return (2 * area) / ROOT_PI_OVER_LN2 / fwhm;\n}\n/**\n * Calculate the height of the gaussian function of a specific width (fwhm) at a speicifc\n * x position (the gaussian is centered on x=0)\n * @param x\n * @param fwhm\n * @returns y\n */\nexport function gaussianFct(x, fwhm) {\n    return Math.exp(GAUSSIAN_EXP_FACTOR * Math.pow(x / fwhm, 2));\n}\nexport function gaussianWidthToFWHM(width) {\n    return width * ROOT_2LN2;\n}\nexport function gaussianFwhmToWidth(fwhm) {\n    return fwhm / ROOT_2LN2;\n}\nexport function getGaussianArea(options) {\n    let { fwhm = 500, sd, height = 1 } = options;\n    if (sd)\n        fwhm = gaussianWidthToFWHM(2 * sd);\n    return (height * ROOT_PI_OVER_LN2 * fwhm) / 2;\n}\nexport function getGaussianFactor(area = 0.9999) {\n    return Math.sqrt(2) * erfinv(area);\n}\nexport function getGaussianData(shape = {}, options = {}) {\n    let { fwhm = 500, sd } = shape;\n    if (sd)\n        fwhm = gaussianWidthToFWHM(2 * sd);\n    let { length, factor = getGaussianFactor(), height = calculateGaussianHeight({ fwhm }), } = options;\n    if (!length) {\n        length = Math.min(Math.ceil(fwhm * factor), Math.pow(2, 25) - 1);\n        if (length % 2 === 0)\n            length++;\n    }\n    const center = (length - 1) / 2;\n    const data = new Float64Array(length);\n    for (let i = 0; i <= center; i++) {\n        data[i] = gaussianFct(i - center, fwhm) * height;\n        data[length - 1 - i] = data[i];\n    }\n    return data;\n}\n//# sourceMappingURL=Gaussian.js.map","import { ROOT_THREE } from '../../../util/constants';\nexport class Lorentzian {\n    constructor(options = {}) {\n        const { fwhm = 500 } = options;\n        this.fwhm = fwhm;\n    }\n    fwhmToWidth(fwhm = this.fwhm) {\n        return lorentzianFwhmToWidth(fwhm);\n    }\n    widthToFWHM(width) {\n        return lorentzianWidthToFWHM(width);\n    }\n    fct(x) {\n        return lorentzianFct(x, this.fwhm);\n    }\n    getArea(height = 1) {\n        return getLorentzianArea({ fwhm: this.fwhm, height });\n    }\n    getFactor(area) {\n        return getLorentzianFactor(area);\n    }\n    getData(options = {}) {\n        return getLorentzianData(this, options);\n    }\n    calculateHeight(area = 1) {\n        return calculateLorentzianHeight({ fwhm: this.fwhm, area });\n    }\n    getParameters() {\n        return ['fwhm'];\n    }\n}\nexport const calculateLorentzianHeight = ({ fwhm = 1, area = 1 }) => {\n    return (2 * area) / Math.PI / fwhm;\n};\nexport const getLorentzianArea = (options) => {\n    const { fwhm = 500, height = 1 } = options;\n    return (height * Math.PI * fwhm) / 2;\n};\nexport const lorentzianFct = (x, fwhm) => {\n    return fwhm ** 2 / (4 * x ** 2 + fwhm ** 2);\n};\nexport const lorentzianWidthToFWHM = (width) => {\n    return width * ROOT_THREE;\n};\nexport const lorentzianFwhmToWidth = (fwhm) => {\n    return fwhm / ROOT_THREE;\n};\nexport const getLorentzianFactor = (area = 0.9999) => {\n    if (area >= 1) {\n        throw new Error('area should be (0 - 1)');\n    }\n    const halfResidual = (1 - area) * 0.5;\n    const quantileFunction = (p) => Math.tan(Math.PI * (p - 0.5));\n    return ((quantileFunction(1 - halfResidual) - quantileFunction(halfResidual)) / 2);\n};\nexport const getLorentzianData = (shape = {}, options = {}) => {\n    let { fwhm = 500 } = shape;\n    let { length, factor = getLorentzianFactor(), height = calculateLorentzianHeight({ fwhm, area: 1 }), } = options;\n    if (!length) {\n        length = Math.min(Math.ceil(fwhm * factor), Math.pow(2, 25) - 1);\n        if (length % 2 === 0)\n            length++;\n    }\n    const center = (length - 1) / 2;\n    const data = new Float64Array(length);\n    for (let i = 0; i <= center; i++) {\n        data[i] = lorentzianFct(i - center, fwhm) * height;\n        data[length - 1 - i] = data[i];\n    }\n    return data;\n};\n//# sourceMappingURL=Lorentzian.js.map","import { GAUSSIAN_EXP_FACTOR, ROOT_2LN2_MINUS_ONE, ROOT_PI_OVER_LN2, } from '../../../util/constants';\nimport { gaussianFct, getGaussianFactor } from '../gaussian/Gaussian';\nimport { lorentzianFct, getLorentzianFactor } from '../lorentzian/Lorentzian';\nexport class PseudoVoigt {\n    constructor(options = {}) {\n        const { fwhm = 500, mu = 0.5 } = options;\n        this.mu = mu;\n        this.fwhm = fwhm;\n    }\n    fwhmToWidth(fwhm = this.fwhm, mu = this.mu) {\n        return pseudoVoigtFwhmToWidth(fwhm, mu);\n    }\n    widthToFWHM(width, mu = this.mu) {\n        return pseudoVoigtWidthToFWHM(width, mu);\n    }\n    fct(x) {\n        return pseudoVoigtFct(x, this.fwhm, this.mu);\n    }\n    getArea(height = 1) {\n        return getPseudoVoigtArea({ fwhm: this.fwhm, height, mu: this.mu });\n    }\n    getFactor(area) {\n        return getPseudoVoigtFactor(area);\n    }\n    getData(options = {}) {\n        const { length, factor, height = calculatePseudoVoigtHeight({\n            fwhm: this.fwhm,\n            mu: this.mu,\n            area: 1,\n        }), } = options;\n        return getPseudoVoigtData(this, { factor, length, height });\n    }\n    calculateHeight(area = 1) {\n        return calculatePseudoVoigtHeight({ fwhm: this.fwhm, mu: this.mu, area });\n    }\n    getParameters() {\n        return ['fwhm', 'mu'];\n    }\n}\nexport const calculatePseudoVoigtHeight = (options = {}) => {\n    let { fwhm = 1, mu = 0.5, area = 1 } = options;\n    return (2 * area) / (fwhm * (mu * ROOT_PI_OVER_LN2 + (1 - mu) * Math.PI));\n};\nexport const pseudoVoigtFct = (x, fwhm, mu) => {\n    return (1 - mu) * lorentzianFct(x, fwhm) + mu * gaussianFct(x, fwhm);\n};\nexport const pseudoVoigtWidthToFWHM = (width, mu = 0.5) => {\n    return width * (mu * ROOT_2LN2_MINUS_ONE + 1);\n};\nexport const pseudoVoigtFwhmToWidth = (fwhm, mu = 0.5) => {\n    return fwhm / (mu * ROOT_2LN2_MINUS_ONE + 1);\n};\nexport const getPseudoVoigtArea = (options) => {\n    const { fwhm = 500, height = 1, mu = 0.5 } = options;\n    return (fwhm * height * (mu * ROOT_PI_OVER_LN2 + (1 - mu) * Math.PI)) / 2;\n};\nexport const getPseudoVoigtFactor = (area = 0.9999, mu = 0.5) => {\n    return mu < 1 ? getLorentzianFactor(area) : getGaussianFactor(area);\n};\nexport const getPseudoVoigtData = (shape = {}, options = {}) => {\n    let { fwhm = 500, mu = 0.5 } = shape;\n    let { length, factor = getPseudoVoigtFactor(0.999, mu), height = calculatePseudoVoigtHeight({ fwhm, mu, area: 1 }), } = options;\n    if (!height) {\n        height =\n            1 /\n                ((mu / Math.sqrt(-GAUSSIAN_EXP_FACTOR / Math.PI)) * fwhm +\n                    ((1 - mu) * fwhm * Math.PI) / 2);\n    }\n    if (!length) {\n        length = Math.min(Math.ceil(fwhm * factor), Math.pow(2, 25) - 1);\n        if (length % 2 === 0)\n            length++;\n    }\n    const center = (length - 1) / 2;\n    const data = new Float64Array(length);\n    for (let i = 0; i <= center; i++) {\n        data[i] = pseudoVoigtFct(i - center, fwhm, mu) * height;\n        data[length - 1 - i] = data[i];\n    }\n    return data;\n};\n//# sourceMappingURL=PseudoVoigt.js.map","import { GAUSSIAN_EXP_FACTOR } from '../../../util/constants';\nimport { getGaussianFactor, gaussianFwhmToWidth, gaussianWidthToFWHM, } from '../../1d/gaussian/Gaussian';\nexport class Gaussian2D {\n    constructor(options = {}) {\n        let { fwhm = 20, sd } = options;\n        fwhm = ensureFWHM2D(fwhm, sd);\n        this.fwhmX = fwhm.x;\n        this.fwhmY = fwhm.y;\n    }\n    fct(x, y) {\n        return gaussian2DFct(x, y, this.fwhmX, this.fwhmY);\n    }\n    getData(options = {}) {\n        return getGaussian2DData({\n            fwhm: { x: this.fwhmX, y: this.fwhmY },\n        }, options);\n    }\n    getFactor(volume = 1) {\n        return getGaussianFactor(volume);\n    }\n    getVolume(height = calculateGaussian2DHeight({\n        fwhm: { x: this.fwhmX, y: this.fwhmY },\n        volume: 1,\n    })) {\n        return getGaussian2DVolume({\n            fwhm: { x: this.fwhmX, y: this.fwhmY },\n            height,\n        });\n    }\n    widthToFWHM(width) {\n        return gaussianWidthToFWHM(width);\n    }\n    fwhmToWidth(fwhm) {\n        return gaussianFwhmToWidth(fwhm);\n    }\n    calculateHeight(volume = 1) {\n        return calculateGaussian2DHeight({\n            volume,\n            fwhm: { x: this.fwhmX, y: this.fwhmY },\n        });\n    }\n    set fwhm(fwhm) {\n        fwhm = ensureXYNumber(fwhm);\n        this.fwhmX = fwhm.x;\n        this.fwhmY = fwhm.y;\n    }\n}\nexport const gaussian2DFct = (x, y, xFWHM, yFWHM) => {\n    return Math.exp(GAUSSIAN_EXP_FACTOR * (Math.pow(x / xFWHM, 2) + Math.pow(y / yFWHM, 2)));\n};\nexport const getGaussian2DData = (shape, options = {}) => {\n    let { fwhm = 50, sd } = shape;\n    fwhm = ensureFWHM2D(fwhm, sd);\n    let { factor = getGaussianFactor(), length = { x: 0, y: 0 }, height = calculateGaussian2DHeight({ fwhm, volume: 1 }), } = options;\n    factor = ensureXYNumber(factor);\n    length = ensureXYNumber(length);\n    for (const axis of ['x', 'y']) {\n        if (!length[axis]) {\n            length[axis] = Math.min(Math.ceil(fwhm[axis] * factor[axis]), Math.pow(2, 25) - 1);\n            if (length[axis] % 2 === 0)\n                length[axis]++;\n        }\n    }\n    const xCenter = (length.x - 1) / 2;\n    const yCenter = (length.y - 1) / 2;\n    const data = new Array(length.x);\n    for (let i = 0; i < length.x; i++) {\n        data[i] = new Float64Array(length.y);\n    }\n    for (let i = 0; i < length.x; i++) {\n        for (let j = 0; j < length.y; j++) {\n            data[i][j] =\n                gaussian2DFct(i - xCenter, j - yCenter, fwhm.x, fwhm.y) * height;\n        }\n    }\n    return data;\n};\nexport const calculateGaussian2DHeight = (options = {}) => {\n    let { volume = 1, fwhm = 50, sd } = options;\n    fwhm = ensureFWHM2D(fwhm, sd);\n    return (volume * Math.LN2 * 4) / (Math.PI * fwhm.y * fwhm.x);\n};\nexport const getGaussian2DVolume = (options = {}) => {\n    let { fwhm = 50, height = 1, sd } = options;\n    fwhm = ensureFWHM2D(fwhm, sd);\n    return (height * Math.PI * fwhm.y * fwhm.x) / Math.LN2 / 4;\n};\nfunction ensureXYNumber(input) {\n    return typeof input !== 'object' ? { x: input, y: input } : { ...input };\n}\nfunction ensureFWHM2D(fwhm, sd) {\n    if (sd !== undefined) {\n        let sdObject = ensureXYNumber(sd);\n        return {\n            x: gaussianWidthToFWHM(2 * sdObject.x),\n            y: gaussianWidthToFWHM(2 * sdObject.y),\n        };\n    }\n    else if (fwhm !== undefined) {\n        return ensureXYNumber(fwhm);\n    }\n    else {\n        throw new Error('ensureFWHM2D must have either fwhm or sd defined');\n    }\n}\n//# sourceMappingURL=Gaussian2D.js.map","import { Gaussian } from './gaussian/Gaussian';\nimport { Lorentzian } from './lorentzian/Lorentzian';\nimport { PseudoVoigt } from './pseudoVoigt/PseudoVoigt';\n/**\n * Generate a instance of a specific kind of shape.\n */\nexport function getShape1D(shape) {\n    const { kind } = shape;\n    switch (kind) {\n        case 'gaussian':\n            return new Gaussian(shape);\n        case 'lorentzian':\n            return new Lorentzian(shape);\n        case 'pseudoVoigt':\n            return new PseudoVoigt(shape);\n        default: {\n            throw Error(`Unknown distribution ${kind}`);\n        }\n    }\n}\n//# sourceMappingURL=getShape1D.js.map","import { Gaussian2D } from './gaussian2D/Gaussian2D';\n/**\n * Generate a instance of a specific kind of shape.\n */\nexport function getShape2D(shape) {\n    const { kind } = shape;\n    switch (kind) {\n        case 'gaussian':\n            return new Gaussian2D(shape);\n        default: {\n            const unHandled = kind;\n            // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n            throw Error(`Unknown distribution ${unHandled}`);\n        }\n    }\n}\n//# sourceMappingURL=getShape2D.js.map","export default function addBaseline(data, baselineFct) {\n    if (!baselineFct)\n        return data;\n    let xs = data.x;\n    let ys = data.y;\n    for (let i = 0; i < xs.length; i++) {\n        ys[i] += baselineFct(xs[i]);\n    }\n    return data;\n}\n//# sourceMappingURL=addBaseline.js.map","(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n  typeof define === 'function' && define.amd ? define(['exports'], factory) :\n  (factory((global.d3_array = {})));\n}(this, function (exports) { 'use strict';\n\n  function ascending(a, b) {\n    return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;\n  }\n\n  function bisector(compare) {\n    if (compare.length === 1) compare = ascendingComparator(compare);\n    return {\n      left: function(a, x, lo, hi) {\n        if (lo == null) lo = 0;\n        if (hi == null) hi = a.length;\n        while (lo < hi) {\n          var mid = lo + hi >>> 1;\n          if (compare(a[mid], x) < 0) lo = mid + 1;\n          else hi = mid;\n        }\n        return lo;\n      },\n      right: function(a, x, lo, hi) {\n        if (lo == null) lo = 0;\n        if (hi == null) hi = a.length;\n        while (lo < hi) {\n          var mid = lo + hi >>> 1;\n          if (compare(a[mid], x) > 0) hi = mid;\n          else lo = mid + 1;\n        }\n        return lo;\n      }\n    };\n  }\n\n  function ascendingComparator(f) {\n    return function(d, x) {\n      return ascending(f(d), x);\n    };\n  }\n\n  var ascendingBisect = bisector(ascending);\n  var bisectRight = ascendingBisect.right;\n  var bisectLeft = ascendingBisect.left;\n\n  function descending(a, b) {\n    return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;\n  }\n\n  function number$1(x) {\n    return x === null ? NaN : +x;\n  }\n\n  function variance(array, f) {\n    var n = array.length,\n        m = 0,\n        a,\n        d,\n        s = 0,\n        i = -1,\n        j = 0;\n\n    if (f == null) {\n      while (++i < n) {\n        if (!isNaN(a = number$1(array[i]))) {\n          d = a - m;\n          m += d / ++j;\n          s += d * (a - m);\n        }\n      }\n    }\n\n    else {\n      while (++i < n) {\n        if (!isNaN(a = number$1(f(array[i], i, array)))) {\n          d = a - m;\n          m += d / ++j;\n          s += d * (a - m);\n        }\n      }\n    }\n\n    if (j > 1) return s / (j - 1);\n  }\n\n  function deviation(array, f) {\n    var v = variance(array, f);\n    return v ? Math.sqrt(v) : v;\n  }\n\n  function extent(array, f) {\n    var i = -1,\n        n = array.length,\n        a,\n        b,\n        c;\n\n    if (f == null) {\n      while (++i < n) if ((b = array[i]) != null && b >= b) { a = c = b; break; }\n      while (++i < n) if ((b = array[i]) != null) {\n        if (a > b) a = b;\n        if (c < b) c = b;\n      }\n    }\n\n    else {\n      while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = c = b; break; }\n      while (++i < n) if ((b = f(array[i], i, array)) != null) {\n        if (a > b) a = b;\n        if (c < b) c = b;\n      }\n    }\n\n    return [a, c];\n  }\n\n  function constant(x) {\n    return function() {\n      return x;\n    };\n  }\n\n  function identity(x) {\n    return x;\n  }\n\n  function range(start, stop, step) {\n    start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;\n\n    var i = -1,\n        n = Math.max(0, Math.ceil((stop - start) / step)) | 0,\n        range = new Array(n);\n\n    while (++i < n) {\n      range[i] = start + i * step;\n    }\n\n    return range;\n  }\n\n  var e10 = Math.sqrt(50);\n  var e5 = Math.sqrt(10);\n  var e2 = Math.sqrt(2);\n  function ticks(start, stop, count) {\n    var step = tickStep(start, stop, count);\n    return range(\n      Math.ceil(start / step) * step,\n      Math.floor(stop / step) * step + step / 2, // inclusive\n      step\n    );\n  }\n\n  function tickStep(start, stop, count) {\n    var step0 = Math.abs(stop - start) / Math.max(0, count),\n        step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),\n        error = step0 / step1;\n    if (error >= e10) step1 *= 10;\n    else if (error >= e5) step1 *= 5;\n    else if (error >= e2) step1 *= 2;\n    return stop < start ? -step1 : step1;\n  }\n\n  function sturges(values) {\n    return Math.ceil(Math.log(values.length) / Math.LN2) + 1;\n  }\n\n  function number(x) {\n    return +x;\n  }\n\n  function histogram() {\n    var value = identity,\n        domain = extent,\n        threshold = sturges;\n\n    function histogram(data) {\n      var i,\n          n = data.length,\n          x,\n          values = new Array(n);\n\n      // Coerce values to numbers.\n      for (i = 0; i < n; ++i) {\n        values[i] = +value(data[i], i, data);\n      }\n\n      var xz = domain(values),\n          x0 = +xz[0],\n          x1 = +xz[1],\n          tz = threshold(values, x0, x1);\n\n      // Convert number of thresholds into uniform thresholds.\n      if (!Array.isArray(tz)) tz = ticks(x0, x1, +tz);\n\n      // Coerce thresholds to numbers, ignoring any outside the domain.\n      var m = tz.length;\n      for (i = 0; i < m; ++i) tz[i] = +tz[i];\n      while (tz[0] <= x0) tz.shift(), --m;\n      while (tz[m - 1] >= x1) tz.pop(), --m;\n\n      var bins = new Array(m + 1),\n          bin;\n\n      // Initialize bins.\n      for (i = 0; i <= m; ++i) {\n        bin = bins[i] = [];\n        bin.x0 = i > 0 ? tz[i - 1] : x0;\n        bin.x1 = i < m ? tz[i] : x1;\n      }\n\n      // Assign data to bins by value, ignoring any outside the domain.\n      for (i = 0; i < n; ++i) {\n        x = values[i];\n        if (x0 <= x && x <= x1) {\n          bins[bisectRight(tz, x, 0, m)].push(data[i]);\n        }\n      }\n\n      return bins;\n    }\n\n    histogram.value = function(_) {\n      return arguments.length ? (value = typeof _ === \"function\" ? _ : constant(+_), histogram) : value;\n    };\n\n    histogram.domain = function(_) {\n      return arguments.length ? (domain = typeof _ === \"function\" ? _ : constant([+_[0], +_[1]]), histogram) : domain;\n    };\n\n    histogram.thresholds = function(_) {\n      if (!arguments.length) return threshold;\n      threshold = typeof _ === \"function\" ? _\n          : Array.isArray(_) ? constant(Array.prototype.map.call(_, number))\n          : constant(+_);\n      return histogram;\n    };\n\n    return histogram;\n  }\n\n  function quantile(array, p, f) {\n    if (f == null) f = number$1;\n    if (!(n = array.length)) return;\n    if ((p = +p) <= 0 || n < 2) return +f(array[0], 0, array);\n    if (p >= 1) return +f(array[n - 1], n - 1, array);\n    var n,\n        h = (n - 1) * p,\n        i = Math.floor(h),\n        a = +f(array[i], i, array),\n        b = +f(array[i + 1], i + 1, array);\n    return a + (b - a) * (h - i);\n  }\n\n  function freedmanDiaconis(values, min, max) {\n    values.sort(ascending);\n    return Math.ceil((max - min) / (2 * (quantile(values, 0.75) - quantile(values, 0.25)) * Math.pow(values.length, -1 / 3)));\n  }\n\n  function scott(values, min, max) {\n    return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3)));\n  }\n\n  function max(array, f) {\n    var i = -1,\n        n = array.length,\n        a,\n        b;\n\n    if (f == null) {\n      while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }\n      while (++i < n) if ((b = array[i]) != null && b > a) a = b;\n    }\n\n    else {\n      while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = b; break; }\n      while (++i < n) if ((b = f(array[i], i, array)) != null && b > a) a = b;\n    }\n\n    return a;\n  }\n\n  function mean(array, f) {\n    var s = 0,\n        n = array.length,\n        a,\n        i = -1,\n        j = n;\n\n    if (f == null) {\n      while (++i < n) if (!isNaN(a = number$1(array[i]))) s += a; else --j;\n    }\n\n    else {\n      while (++i < n) if (!isNaN(a = number$1(f(array[i], i, array)))) s += a; else --j;\n    }\n\n    if (j) return s / j;\n  }\n\n  function median(array, f) {\n    var numbers = [],\n        n = array.length,\n        a,\n        i = -1;\n\n    if (f == null) {\n      while (++i < n) if (!isNaN(a = number$1(array[i]))) numbers.push(a);\n    }\n\n    else {\n      while (++i < n) if (!isNaN(a = number$1(f(array[i], i, array)))) numbers.push(a);\n    }\n\n    return quantile(numbers.sort(ascending), 0.5);\n  }\n\n  function merge(arrays) {\n    var n = arrays.length,\n        m,\n        i = -1,\n        j = 0,\n        merged,\n        array;\n\n    while (++i < n) j += arrays[i].length;\n    merged = new Array(j);\n\n    while (--n >= 0) {\n      array = arrays[n];\n      m = array.length;\n      while (--m >= 0) {\n        merged[--j] = array[m];\n      }\n    }\n\n    return merged;\n  }\n\n  function min(array, f) {\n    var i = -1,\n        n = array.length,\n        a,\n        b;\n\n    if (f == null) {\n      while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }\n      while (++i < n) if ((b = array[i]) != null && a > b) a = b;\n    }\n\n    else {\n      while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = b; break; }\n      while (++i < n) if ((b = f(array[i], i, array)) != null && a > b) a = b;\n    }\n\n    return a;\n  }\n\n  function pairs(array) {\n    var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n);\n    while (i < n) pairs[i] = [p, p = array[++i]];\n    return pairs;\n  }\n\n  function permute(array, indexes) {\n    var i = indexes.length, permutes = new Array(i);\n    while (i--) permutes[i] = array[indexes[i]];\n    return permutes;\n  }\n\n  function scan(array, compare) {\n    if (!(n = array.length)) return;\n    var i = 0,\n        n,\n        j = 0,\n        xi,\n        xj = array[j];\n\n    if (!compare) compare = ascending;\n\n    while (++i < n) if (compare(xi = array[i], xj) < 0 || compare(xj, xj) !== 0) xj = xi, j = i;\n\n    if (compare(xj, xj) === 0) return j;\n  }\n\n  function shuffle(array, i0, i1) {\n    var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0),\n        t,\n        i;\n\n    while (m) {\n      i = Math.random() * m-- | 0;\n      t = array[m + i0];\n      array[m + i0] = array[i + i0];\n      array[i + i0] = t;\n    }\n\n    return array;\n  }\n\n  function sum(array, f) {\n    var s = 0,\n        n = array.length,\n        a,\n        i = -1;\n\n    if (f == null) {\n      while (++i < n) if (a = +array[i]) s += a; // Note: zero and null are equivalent.\n    }\n\n    else {\n      while (++i < n) if (a = +f(array[i], i, array)) s += a;\n    }\n\n    return s;\n  }\n\n  function transpose(matrix) {\n    if (!(n = matrix.length)) return [];\n    for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) {\n      for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) {\n        row[j] = matrix[j][i];\n      }\n    }\n    return transpose;\n  }\n\n  function length(d) {\n    return d.length;\n  }\n\n  function zip() {\n    return transpose(arguments);\n  }\n\n  var version = \"0.7.1\";\n\n  exports.version = version;\n  exports.bisect = bisectRight;\n  exports.bisectRight = bisectRight;\n  exports.bisectLeft = bisectLeft;\n  exports.ascending = ascending;\n  exports.bisector = bisector;\n  exports.descending = descending;\n  exports.deviation = deviation;\n  exports.extent = extent;\n  exports.histogram = histogram;\n  exports.thresholdFreedmanDiaconis = freedmanDiaconis;\n  exports.thresholdScott = scott;\n  exports.thresholdSturges = sturges;\n  exports.max = max;\n  exports.mean = mean;\n  exports.median = median;\n  exports.merge = merge;\n  exports.min = min;\n  exports.pairs = pairs;\n  exports.permute = permute;\n  exports.quantile = quantile;\n  exports.range = range;\n  exports.scan = scan;\n  exports.shuffle = shuffle;\n  exports.sum = sum;\n  exports.ticks = ticks;\n  exports.tickStep = tickStep;\n  exports.transpose = transpose;\n  exports.variance = variance;\n  exports.zip = zip;\n\n}));","const {bisectRight} = require('d3-array')\n\nconst quincunx = (u, v, w, q) => {\n  const n = u.length - 1\n\n  u[0] = 0\n  v[0] = 0\n  w[0] = 0\n  v[1] = v[1] / u[1]\n  w[1] = w[1] / u[1]\n  for (let i = 2; i < n; ++i) {\n    u[i] = u[i] - u[i - 2] * w[i - 2] * w[i - 2] - u[i - 1] * v[i - 1] * v[i - 1]\n    v[i] = (v[i] - u[i - 1] * v[i - 1] * w[i - 1]) / u[i]\n    w[i] = w[i] / u[i]\n  }\n\n  for (let i = 2; i < n; ++i) {\n    q[i] = q[i] - v[i - 1] * q[i - 1] - w[i - 2] * q[i - 2]\n  }\n  for (let i = 1; i < n; ++i) {\n    q[i] = q[i] / u[i]\n  }\n\n  q[n - 2] = q[n - 2] - v[n - 2] * q[n - 1]\n  for (let i = n - 3; i > 0; --i) {\n    q[i] = q[i] - v[i] * q[i + 1] - w[i] * q[i + 2]\n  }\n}\n\nconst smoothingSpline = (x, y, sigma, lambda) => {\n  const n = x.length - 1\n  const h = new Array(n + 1)\n  const r = new Array(n + 1)\n  const f = new Array(n + 1)\n  const p = new Array(n + 1)\n  const q = new Array(n + 1)\n  const u = new Array(n + 1)\n  const v = new Array(n + 1)\n  const w = new Array(n + 1)\n  const params = x.map(() => [0, 0, 0, 0])\n  params.pop()\n\n  const mu = 2 * (1 - lambda) / (3 * lambda)\n  for (let i = 0; i < n; ++i) {\n    h[i] = x[i + 1] - x[i]\n    r[i] = 3 / h[i]\n  }\n  q[0] = 0\n  for (let i = 1; i < n; ++i) {\n    f[i] = -(r[i - 1] + r[i])\n    p[i] = 2 * (x[i + 1] - x[i - 1])\n    q[i] = 3 * (y[i + 1] - y[i]) / h[i] - 3 * (y[i] - y[i - 1]) / h[i - 1]\n  }\n  q[n] = 0\n\n  for (let i = 1; i < n; ++i) {\n    u[i] = r[i - 1] * r[i - 1] * sigma[i - 1] + f[i] * f[i] * sigma[i] + r[i] * r[i] * sigma[i + 1]\n    u[i] = mu * u[i] + p[i]\n  }\n  for (let i = 1; i < n - 1; ++i) {\n    v[i] = f[i] * r[i] * sigma[i] + r[i] * f[i + 1] * sigma[i + 1]\n    v[i] = mu * v[i] + h[i]\n  }\n  for (let i = 1; i < n - 2; ++i) {\n    w[i] = mu * r[i] * r[i + 1] * sigma[i + 1]\n  }\n\n  quincunx(u, v, w, q)\n\n  params[0][3] = y[0] - mu * r[0] * q[1] * sigma[0]\n  params[1][3] = y[1] - mu * (f[1] * q[1] + r[1] * q[2]) * sigma[0]\n  params[0][0] = q[1] / (3 * h[0])\n  params[0][1] = 0\n  params[0][2] = (params[1][3] - params[0][3]) / h[0] - q[1] * h[0] / 3\n  r[0] = 0\n  for (let i = 1; i < n; ++i) {\n    params[i][0] = (q[i + 1] - q[i]) / (3 * h[i])\n    params[i][1] = q[i]\n    params[i][2] = (q[i] + q[i - 1]) * h[i - 1] + params[i - 1][2]\n    params[i][3] = r[i - 1] * q[i - 1] + f[i] * q[i] + r[i] * q[i + 1]\n    params[i][3] = y[i] - mu * params[i][3] * sigma[i]\n  }\n  return params\n}\n\nclass SplineInterpolator {\n  constructor (xIn, yIn, lambda = 1) {\n    const indices = xIn.map((_, i) => i)\n    indices.sort((i, j) => xIn[i] - xIn[j])\n    const x = indices.map((i) => xIn[i])\n    const y = indices.map((i) => yIn[i])\n    const n = indices.length\n    const sigma = indices.map(() => 1)\n    this.n = n\n    this.x = x\n    this.y = y\n    this.params = smoothingSpline(x, y, sigma, lambda)\n  }\n\n  interpolate (v) {\n    if (v === this.x[this.n - 1]) {\n      return this.y[this.n - 1]\n    }\n    const i = Math.min(Math.max(0, bisectRight(this.x, v) - 1), this.n - 2)\n    const [a, b, c, d] = this.params[i]\n    v = v - this.x[i]\n    return a * v * v * v + b * v * v + c * v + d\n  }\n\n  max (step = 100) {\n    const xStart = this.x[0]\n    const xStop = this.x[this.n - 1]\n    const delta = (xStop - xStart) / step\n    let maxValue = -Infinity\n    for (let i = 0, x = xStart; i < step; ++i, x += delta) {\n      const y = this.interpolate(x)\n      if (y > maxValue) {\n        maxValue = y\n      }\n    }\n    return maxValue\n  }\n\n  min (step = 100) {\n    const xStart = this.x[0]\n    const xStop = this.x[this.n - 1]\n    const delta = (xStop - xStart) / step\n    let minValue = Infinity\n    for (let i = 0, x = xStart; i < step; ++i, x += delta) {\n      const y = this.interpolate(x)\n      if (y < minValue) {\n        minValue = y\n      }\n    }\n    return minValue\n  }\n\n  domain () {\n    return [this.x[0], this.x[this.x.length - 1]]\n  }\n\n  range () {\n    return [this.min(), this.max()]\n  }\n\n  curve (nInterval, domain = null) {\n    domain = domain || this.domain()\n    const delta = (domain[1] - domain[0]) / (nInterval - 1)\n    const vals = new Array(nInterval)\n    for (let i = 0; i < nInterval; ++i) {\n      const x = delta * i + domain[0]\n      vals[i] = [x, this.interpolate(x)]\n    }\n    return vals\n  }\n}\n\nmodule.exports = SplineInterpolator\n","/**\n * Create an array with numbers between \"from\" and \"to\" of length \"length\"\n *\n * @param options - options\n * @return - array of distributed numbers between \"from\" and \"to\"\n */\nexport function createFromToArray(options = {}) {\n    let { from = 0, to = 1, length = 1000, includeFrom = true, includeTo = true, distribution = 'uniform', } = options;\n    const array = new Float64Array(length);\n    let div = length;\n    if (includeFrom && includeTo) {\n        div = length - 1;\n    }\n    else if ((!includeFrom && includeTo) || (includeFrom && !includeTo)) {\n        div = length;\n    }\n    else if (!includeFrom && !includeTo) {\n        div = length + 1;\n    }\n    let delta = (to - from) / div;\n    if (distribution === 'uniform') {\n        if (includeFrom) {\n            let index = 0;\n            while (index < length) {\n                array[index] = from + delta * index;\n                index++;\n            }\n        }\n        else {\n            let index = 0;\n            while (index < length) {\n                array[index] = from + delta * (index + 1);\n                index++;\n            }\n        }\n    }\n    else if (distribution === 'log') {\n        let base = (to / from) ** (1 / div);\n        let firstExponent = Math.log(from) / Math.log(base);\n        if (includeFrom) {\n            let index = 0;\n            while (index < length) {\n                array[index] = base ** (firstExponent + index);\n                index++;\n            }\n        }\n        else {\n            let index = 0;\n            while (index < length) {\n                array[index] = base ** (firstExponent + index + 1);\n                index++;\n            }\n        }\n    }\n    else {\n        throw new Error('Please choose for the distribution either uniform or log. By default the distribution chosen is uniform.');\n    }\n    return array;\n}\n//# sourceMappingURL=createFromToArray.js.map","/* eslint-disable @typescript-eslint/no-loss-of-precision */\n/*\nAdapted from: https://github.com/compute-io/erfcinv/blob/aa116e23883839359e310ad41a7c42f72815fc1e/lib/number.js\n\nThe MIT License (MIT)\n\nCopyright (c) 2014-2015 The Compute.io Authors. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n\nBoost Software License - Version 1.0 - August 17th, 2003\n\nPermission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the \"Software\") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following:\n\nThe copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n// Coefficients for erfcinv on [0, 0.5]:\nconst Y1 = 8.91314744949340820313e-2;\nconst P1 = [\n    -5.38772965071242932965e-3, 8.22687874676915743155e-3,\n    2.19878681111168899165e-2, -3.65637971411762664006e-2,\n    -1.26926147662974029034e-2, 3.34806625409744615033e-2,\n    -8.36874819741736770379e-3, -5.08781949658280665617e-4,\n];\nconst Q1 = [\n    8.86216390456424707504e-4, -2.33393759374190016776e-3,\n    7.95283687341571680018e-2, -5.27396382340099713954e-2,\n    -7.1228902341542847553e-1, 6.62328840472002992063e-1, 1.56221558398423026363,\n    -1.56574558234175846809, -9.70005043303290640362e-1, 1,\n];\n// Coefficients for erfcinv for 0.5 > 1-x >= 0:\nconst Y2 = 2.249481201171875;\nconst P2 = [\n    -3.67192254707729348546, 2.11294655448340526258e1, 1.7445385985570866523e1,\n    -4.46382324441786960818e1, -1.88510648058714251895e1,\n    1.76447298408374015486e1, 8.37050328343119927838, 1.05264680699391713268e-1,\n    -2.02433508355938759655e-1,\n];\nconst Q2 = [\n    1.72114765761200282724, -2.26436933413139721736e1, 1.08268667355460159008e1,\n    4.85609213108739935468e1, -2.01432634680485188801e1,\n    -2.86608180499800029974e1, 3.9713437953343869095, 6.24264124854247537712, 1,\n];\n// Coefficients for erfcinv for sqrt( -log(1-x)):\nconst Y3 = 8.07220458984375e-1;\nconst P3 = [\n    -6.81149956853776992068e-10, 2.85225331782217055858e-8,\n    -6.79465575181126350155e-7, 2.14558995388805277169e-3,\n    2.90157910005329060432e-2, 1.42869534408157156766e-1,\n    3.37785538912035898924e-1, 3.87079738972604337464e-1,\n    1.17030156341995252019e-1, -1.63794047193317060787e-1,\n    -1.31102781679951906451e-1,\n];\nconst Q3 = [\n    1.105924229346489121e-2, 1.52264338295331783612e-1, 8.48854343457902036425e-1,\n    2.59301921623620271374, 4.77846592945843778382, 5.38168345707006855425,\n    3.46625407242567245975, 1,\n];\nconst Y4 = 9.3995571136474609375e-1;\nconst P4 = [\n    2.66339227425782031962e-12, -2.30404776911882601748e-10,\n    4.60469890584317994083e-6, 1.57544617424960554631e-4,\n    1.87123492819559223345e-3, 9.50804701325919603619e-3,\n    1.85573306514231072324e-2, -2.22426529213447927281e-3,\n    -3.50353787183177984712e-2,\n];\nconst Q4 = [\n    7.64675292302794483503e-5, 2.63861676657015992959e-3,\n    3.41589143670947727934e-2, 2.20091105764131249824e-1,\n    7.62059164553623404043e-1, 1.3653349817554063097, 1,\n];\nconst Y5 = 9.8362827301025390625e-1;\nconst P5 = [\n    9.9055709973310326855e-17, -2.81128735628831791805e-14,\n    4.62596163522878599135e-9, 4.49696789927706453732e-7,\n    1.49624783758342370182e-5, 2.09386317487588078668e-4,\n    1.05628862152492910091e-3, -1.12951438745580278863e-3,\n    -1.67431005076633737133e-2,\n];\nconst Q5 = [\n    2.82243172016108031869e-7, 2.75335474764726041141e-5,\n    9.64011807005165528527e-4, 1.60746087093676504695e-2,\n    1.38151865749083321638e-1, 5.91429344886417493481e-1, 1,\n];\n/**\n * Polyval.\n *\n * @param c - Array of Number.\n * @param x - Number.\n * @returns Number.\n */\nfunction polyval(c, x) {\n    let p = 0;\n    for (const coef of c) {\n        p = p * x + coef;\n    }\n    return p;\n}\n/**\n * Calculates a rational approximation.\n *\n * @private\n * @param x - Number.\n * @param v - Number.\n * @param P - Array of polynomial coefficients.\n * @param Q - Array of polynomial coefficients.\n * @param Y - Number.\n * @returns Rational approximation.\n */\nfunction calc(x, v, P, Q, Y) {\n    const s = x - v;\n    const r = polyval(P, s) / polyval(Q, s);\n    return Y * x + r * x;\n}\n/**\n * Evaluates the complementary inverse error function for an input value.\n *\n * @private\n * @param x - Input value.\n * @returns Evaluated complementary inverse error function.\n */\nexport default function erfcinv(x) {\n    let sign = false;\n    let val;\n    let q;\n    let g;\n    let r;\n    // [1] Special cases...\n    // NaN:\n    if (Number.isNaN(x)) {\n        return Number.NaN;\n    }\n    // x not on the interval: [0,2]\n    if (x < 0 || x > 2) {\n        throw new RangeError(`erfcinv()::invalid input argument. Value must be on the interval [0,2]. Value: \\`${x}\\`.`);\n    }\n    if (x === 0) {\n        return Number.POSITIVE_INFINITY;\n    }\n    if (x === 2) {\n        return Number.NEGATIVE_INFINITY;\n    }\n    if (x === 1) {\n        return 0;\n    }\n    // [2] Get the sign and make use of `erfc` reflection formula: `erfc(-z)=2 - erfc(z)`...\n    if (x > 1) {\n        q = 2 - x;\n        x = 1 - q;\n        sign = true;\n    }\n    else {\n        q = x;\n        x = 1 - x;\n    }\n    // [3] |x| <= 0.5\n    if (x <= 0.5) {\n        g = x * (x + 10);\n        r = polyval(P1, x) / polyval(Q1, x);\n        val = g * Y1 + g * r;\n        return sign ? -val : val;\n    }\n    // [4] 1-|x| >= 0.25\n    if (q >= 0.25) {\n        g = Math.sqrt(-2 * Math.log(q));\n        q = q - 0.25;\n        r = polyval(P2, q) / polyval(Q2, q);\n        val = g / (Y2 + r);\n        return sign ? -val : val;\n    }\n    q = Math.sqrt(-Math.log(q));\n    // [5] q < 3\n    if (q < 3) {\n        return calc(q, 1.125, P3, Q3, Y3);\n    }\n    // [6] q < 6\n    if (q < 6) {\n        return calc(q, 3, P4, Q4, Y4);\n    }\n    // Note that the smallest number in JavaScript is 5e-324. Math.sqrt( -Math.log( 5e-324 ) ) ~27.2844\n    return calc(q, 6, P5, Q5, Y5);\n    // Note that in the boost library, they are able to go to much smaller values, as 128 bit long doubles support ~1e-5000; something which JavaScript does not natively support.\n}\n//# sourceMappingURL=erfcinv.js.map","/**\n * RayleighCdf.\n *\n * @param x - data\n * @param sigma - standard deviation\n * @returns - rayleigh cdf\n */\nexport default function rayleighCdf(x, sigma = 1) {\n    if (x < 0) {\n        return 0;\n    }\n    return -Math.expm1(-Math.pow(x, 2) / (2 * Math.pow(sigma, 2)));\n}\n//# sourceMappingURL=rayleighCdf.js.map","import SplineInterpolator from 'spline-interpolator';\nimport { createFromToArray } from '../utils/createFromToArray';\nimport erfcinv from './erfcinv';\nimport rayleighCdf from './rayleighCdf';\n/**\n * Determine noise level by san plot methodology (https://doi.org/10.1002/mrc.4882)\n *\n * @param array - real or magnitude spectra data.\n * @param options - options\n * @returns noise level\n */\nexport function xNoiseSanPlot(array, options = {}) {\n    const { mask, cutOff, refine = true, magnitudeMode = false, scaleFactor = 1, factorStd = 5, fixOffset = true, } = options;\n    let input;\n    if (Array.isArray(mask) && mask.length === array.length) {\n        input = new Float64Array(array.filter((_e, i) => !mask[i]));\n    }\n    else {\n        input = new Float64Array(array);\n    }\n    if (scaleFactor > 1) {\n        for (let i = 0; i < input.length; i++) {\n            input[i] *= scaleFactor;\n        }\n    }\n    input = input.sort().reverse();\n    if (fixOffset && !magnitudeMode) {\n        let medianIndex = Math.floor(input.length / 2);\n        let median = 0.5 * (input[medianIndex] + input[medianIndex + 1]);\n        for (let i = 0; i < input.length; i++) {\n            input[i] -= median;\n        }\n    }\n    let firstNegativeValueIndex = input[input.length - 1] >= 0 ? input.length : input.findIndex((e) => e < 0);\n    let lastPositiveValueIndex = firstNegativeValueIndex - 1;\n    for (let i = lastPositiveValueIndex; i >= 0; i--) {\n        if (input[i] > 0) {\n            lastPositiveValueIndex = i;\n            break;\n        }\n    }\n    let signPositive = input.slice(0, lastPositiveValueIndex + 1);\n    let signNegative = input.slice(firstNegativeValueIndex);\n    let cutOffDist = cutOff || determineCutOff(signPositive, { magnitudeMode });\n    let pIndex = Math.floor(signPositive.length * cutOffDist);\n    let initialNoiseLevelPositive = signPositive[pIndex];\n    let skyPoint = signPositive[0];\n    let initialNoiseLevelNegative;\n    if (signNegative.length > 0) {\n        let nIndex = Math.floor(signNegative.length * (1 - cutOffDist));\n        initialNoiseLevelNegative = -1 * signNegative[nIndex];\n    }\n    else {\n        initialNoiseLevelNegative = 0;\n    }\n    let noiseLevelPositive = initialNoiseLevelPositive;\n    let noiseLevelNegative = initialNoiseLevelNegative;\n    let cloneSignPositive = signPositive.slice();\n    let cloneSignNegative = signNegative.slice();\n    let cutOffSignalsIndexPlus = 0;\n    let cutOffSignalsIndexNeg = 2;\n    if (refine) {\n        let cutOffSignals = noiseLevelPositive * factorStd;\n        cutOffSignalsIndexPlus = signPositive.findIndex((e) => e < cutOffSignals);\n        if (cutOffSignalsIndexPlus > -1) {\n            cloneSignPositive = signPositive.slice(cutOffSignalsIndexPlus);\n            noiseLevelPositive =\n                cloneSignPositive[Math.floor(cloneSignPositive.length * cutOffDist)];\n        }\n        cutOffSignals = noiseLevelNegative * factorStd;\n        cutOffSignalsIndexNeg = signNegative.findIndex((e) => e < cutOffSignals);\n        if (cutOffSignalsIndexNeg > -1) {\n            cloneSignNegative = signNegative.slice(cutOffSignalsIndexNeg);\n            noiseLevelNegative =\n                cloneSignPositive[Math.floor(cloneSignNegative.length * (1 - cutOffDist))];\n        }\n    }\n    let correctionFactor = -simpleNormInv(cutOffDist / 2, { magnitudeMode });\n    initialNoiseLevelPositive = initialNoiseLevelPositive / correctionFactor;\n    initialNoiseLevelNegative = initialNoiseLevelNegative / correctionFactor;\n    let effectiveCutOffDist, refinedCorrectionFactor;\n    if (refine && cutOffSignalsIndexPlus > -1) {\n        effectiveCutOffDist =\n            (cutOffDist * cloneSignPositive.length + cutOffSignalsIndexPlus) /\n                (cloneSignPositive.length + cutOffSignalsIndexPlus);\n        refinedCorrectionFactor =\n            -1 *\n                simpleNormInv(effectiveCutOffDist / 2, { magnitudeMode });\n        noiseLevelPositive /= refinedCorrectionFactor;\n        if (cutOffSignalsIndexNeg > -1) {\n            effectiveCutOffDist =\n                (cutOffDist * cloneSignNegative.length + cutOffSignalsIndexNeg) /\n                    (cloneSignNegative.length + cutOffSignalsIndexNeg);\n            refinedCorrectionFactor =\n                -1 *\n                    simpleNormInv(effectiveCutOffDist / 2, { magnitudeMode });\n            if (noiseLevelNegative !== 0) {\n                noiseLevelNegative /= refinedCorrectionFactor;\n            }\n        }\n    }\n    else {\n        noiseLevelPositive /= correctionFactor;\n        noiseLevelNegative /= correctionFactor;\n    }\n    return {\n        positive: noiseLevelPositive,\n        negative: noiseLevelNegative,\n        snr: skyPoint / noiseLevelPositive,\n        sanplot: generateSanPlot(input, {\n            fromTo: {\n                positive: { from: 0, to: lastPositiveValueIndex },\n                negative: { from: firstNegativeValueIndex, to: input.length },\n            },\n        }),\n    };\n}\n/**\n * DetermineCutOff.\n *\n * @param signPositive - Array of numbers.\n * @param [options = {}] - Options.\n * @param [options.mask] - Boolean array to filter data, if the i-th element is true then the i-th element of the distribution will be ignored.\n * @param [options.scaleFactor=1] - Factor to scale the data input[i]*=scaleFactor.\n * @param [options.cutOff] - Percent of positive signal distribution where the noise level will be determined, if it is not defined the program calculate it.\n * @param [options.factorStd=5] - Factor times std to determine what will be marked as signals.\n * @param [options.refine=true] - If true the noise level will be recalculated get out the signals using factorStd.\n * @param [options.fixOffset=true] - If the baseline is correct, the midpoint of distribution should be zero. If true, the distribution will be centered.\n * @param [options.logBaseY=2] - Log scale to apply in the intensity axis in order to avoid big numbers.\n * @param options.magnitudeMode -\n * @param options.considerList -\n * @param options.considerList.from -\n * @param options.considerList.step -\n * @param options.considerList.to -\n * @param options.fromTo -\n * @returns Result.\n */\nfunction determineCutOff(signPositive, options = {}) {\n    let { magnitudeMode = false, considerList = { from: 0.5, step: 0.1, to: 0.9 }, } = options;\n    //generate a list of values for\n    let cutOff = [];\n    let indexMax = signPositive.length - 1;\n    for (let i = 0.01; i <= 0.99; i += 0.01) {\n        let index = Math.round(indexMax * i);\n        let value = -signPositive[index] /\n            simpleNormInv([i / 2], { magnitudeMode });\n        cutOff.push([i, value]);\n    }\n    let minKi = Number.MAX_SAFE_INTEGER;\n    let { from, to, step } = considerList;\n    let delta = step / 2;\n    let whereToCutStat = 0.5;\n    for (let i = from; i <= to; i += step) {\n        let floor = i - delta;\n        let top = i + delta;\n        let elementsOfCutOff = cutOff.filter((e) => e[0] < top && e[0] > floor);\n        let averageValue = elementsOfCutOff.reduce((a, b) => a + Math.abs(b[1]), 0);\n        let kiSqrt = 0;\n        for (const element of elementsOfCutOff) {\n            kiSqrt += Math.pow(element[1] - averageValue, 2);\n        }\n        if (kiSqrt < minKi) {\n            minKi = kiSqrt;\n            whereToCutStat = i;\n        }\n    }\n    return whereToCutStat;\n}\n/**\n * SimpleNormInvs.\n *\n * @param data - Data array.\n * @param [options = {}] - Options.\n * @param [options.mask] - Boolean array to filter data, if the i-th element is true then the i-th element of the distribution will be ignored.\n * @param [options.scaleFactor=1] - Factor to scale the data input[i]*=scaleFactor.\n * @param [options.cutOff] - Percent of positive signal distribution where the noise level will be determined, if it is not defined the program calculate it.\n * @param [options.factorStd=5] - Factor times std to determine what will be marked as signals.\n * @param [options.refine=true] - If true the noise level will be recalculated get out the signals using factorStd.\n * @param [options.fixOffset=true] - If the baseline is correct, the midpoint of distribution should be zero. If true, the distribution will be centered.\n * @param [options.logBaseY=2] - Log scale to apply in the intensity axis in order to avoid big numbers.\n * @param options.magnitudeMode -\n * @param options.considerList -\n * @param options.considerList.from -\n * @param options.considerList.step -\n * @param options.considerList.to -\n * @param options.fromTo -\n * @returns Result.\n */\nfunction simpleNormInv(data, options = {}) {\n    const { magnitudeMode = false } = options;\n    if (!Array.isArray(data))\n        data = [data];\n    let from = 0;\n    let to = 2;\n    let step = 0.01;\n    let xTraining = Array.from(createArray(from, to, step));\n    let result = new Float64Array(data.length);\n    let yTraining = new Float64Array(xTraining.length);\n    if (magnitudeMode) {\n        let factor = 1;\n        for (let i = 0; i < yTraining.length; i++) {\n            let finalInput = xTraining[i] * factor;\n            yTraining[i] = 1 - rayleighCdf(finalInput);\n        }\n        let interp = new SplineInterpolator(xTraining, yTraining);\n        for (let i = 0; i < result.length; i++) {\n            let yValue = 2 * data[i];\n            result[i] = -1 * interp.interpolate(yValue);\n        }\n    }\n    else {\n        for (let i = 0; i < result.length; i++) {\n            result[i] = -1 * Math.SQRT2 * erfcinv(2 * data[i]);\n        }\n    }\n    return result.length === 1 ? result[0] : result;\n}\n/**\n * CreateArray.\n *\n * @param from - From.\n * @param to - To.\n * @param step - Step.\n * @returns Array of results.\n */\nfunction createArray(from, to, step) {\n    // Changed Array to Float64Array\n    let result = new Float64Array(Math.abs((from - to) / step + 1));\n    for (let i = 0; i < result.length; i++) {\n        result[i] = from + i * step;\n    }\n    return result;\n}\n/**\n * GenerateSanPlot.\n *\n * @param array - Array.\n * @param [options = {}] - Options.\n * @param [options.mask] - Boolean array to filter data, if the i-th element is true then the i-th element of the distribution will be ignored.\n * @param [options.scaleFactor=1] - Factor to scale the data input[i]*=scaleFactor.\n * @param [options.cutOff] - Percent of positive signal distribution where the noise level will be determined, if it is not defined the program calculate it.\n * @param [options.factorStd=5] - Factor times std to determine what will be marked as signals.\n * @param [options.refine=true] - If true the noise level will be recalculated get out the signals using factorStd.\n * @param [options.fixOffset=true] - If the baseline is correct, the midpoint of distribution should be zero. If true, the distribution will be centered.\n * @param [options.logBaseY=2] - Log scale to apply in the intensity axis in order to avoid big numbers.\n * @param options.magnitudeMode -\n * @param options.considerList -\n * @param options.considerList.from -\n * @param options.considerList.step -\n * @param options.considerList.to -\n * @param options.fromTo -\n * @returns Results.\n */\nfunction generateSanPlot(array, options = {}) {\n    const { fromTo, logBaseY = 2 } = options;\n    let sanplot = {};\n    for (let key in fromTo) {\n        let { from, to } = fromTo[key];\n        sanplot[key] =\n            from !== to\n                ? scale(array.slice(from, to), {\n                    logBaseY,\n                })\n                : { x: [], y: [] };\n        if (key === 'negative') {\n            sanplot[key].y.reverse();\n        }\n    }\n    return sanplot;\n}\n/**\n * Scale.\n *\n * @param array - Array.\n * @param [options = {}] - Options.\n * @param [options.mask] - Boolean array to filter data, if the i-th element is true then the i-th element of the distribution will be ignored.\n * @param [options.scaleFactor=1] - Factor to scale the data input[i]*=scaleFactor.\n * @param [options.cutOff] - Percent of positive signal distribution where the noise level will be determined, if it is not defined the program calculate it.\n * @param [options.factorStd=5] - Factor times std to determine what will be marked as signals.\n * @param [options.refine=true] - If true the noise level will be recalculated get out the signals using factorStd.\n * @param [options.fixOffset=true] - If the baseline is correct, the midpoint of distribution should be zero. If true, the distribution will be centered.\n * @param [options.logBaseY=2] - Log scale to apply in the intensity axis in order to avoid big numbers.\n * @param options.magnitudeMode -\n * @param options.considerList -\n * @param options.considerList.from -\n * @param options.considerList.step -\n * @param options.considerList.to -\n * @param options.fromTo -\n * @returns Results.\n */\nfunction scale(array, options = {}) {\n    const { log10, abs } = Math;\n    const { logBaseY } = options;\n    if (logBaseY) {\n        array = array.slice();\n        const logOfBase = log10(logBaseY);\n        for (let i = 0; i < array.length; i++) {\n            array[i] = log10(abs(array[i])) / logOfBase;\n        }\n    }\n    const xAxis = createFromToArray({\n        from: 0,\n        to: array.length - 1,\n        length: array.length,\n    });\n    return { x: xAxis, y: array };\n}\n//# sourceMappingURL=xNoiseSanPlot.js.map","/**\n * This function returns an array with absolute values\n *\n * @param array - array of data\n * @returns - array with absolute values\n */\nexport function xAbsolute(array) {\n    let tmpArray = array.slice();\n    for (let i = 0; i < tmpArray.length; i++) {\n        if (tmpArray[i] < 0)\n            tmpArray[i] *= -1;\n    }\n    return tmpArray;\n}\n//# sourceMappingURL=xAbsolute.js.map","const toString = Object.prototype.toString;\n/**\n * Checks if an object is an instance of an Array (array or typed array).\n *\n * @param {any} value - Object to check.\n * @returns {boolean} True if the object is an array.\n */\nexport function isAnyArray(value) {\n    return toString.call(value).endsWith('Array]');\n}\n//# sourceMappingURL=index.js.map","(function(){function a(d){for(var e=0,f=d.length-1,g=void 0,h=void 0,i=void 0,j=c(e,f);!0;){if(f<=e)return d[j];if(f==e+1)return d[e]>d[f]&&b(d,e,f),d[j];for(g=c(e,f),d[g]>d[f]&&b(d,g,f),d[e]>d[f]&&b(d,e,f),d[g]>d[e]&&b(d,g,e),b(d,g,e+1),h=e+1,i=f;!0;){do h++;while(d[e]>d[h]);do i--;while(d[i]>d[e]);if(i<h)break;b(d,h,i)}b(d,e,i),i<=j&&(e=h),i>=j&&(f=i-1)}}var b=function b(d,e,f){var _ref;return _ref=[d[f],d[e]],d[e]=_ref[0],d[f]=_ref[1],_ref},c=function c(d,e){return~~((d+e)/2)};'undefined'!=typeof module&&module.exports?module.exports=a:window.median=a})();\n","import { isAnyArray } from 'is-any-array';\nimport quickSelectMedian from 'median-quickselect';\n/**\n * Calculates the median of an array\n *\n * @param input - Array containing values\n * @returns - median\n */\nexport function xMedian(input) {\n    if (!isAnyArray(input)) {\n        throw new TypeError('input must be an array');\n    }\n    if (input.length === 0) {\n        throw new TypeError('input must not be empty');\n    }\n    // we need to slice because the order of elements is changed in the quickselect\n    // https://github.com/mad-gooze/median-quickselect\n    return quickSelectMedian(input.slice());\n}\n//# sourceMappingURL=xMedian.js.map","import { xAbsolute } from './xAbsolute';\nimport { xMedian } from './xMedian';\n/**\n * This function calculates the median after taking the reimAbsolute values of the points\n *\n * @param array - the array for which we want to calculate the absolute value\n * @returns - median\n */\nexport function xAbsoluteMedian(array) {\n    return xMedian(xAbsolute(array));\n}\n//# sourceMappingURL=xAbsoluteMedian.js.map","import { isAnyArray } from 'is-any-array';\n/**\n * This function xAdd the first array by the second array or a constant value to each element of the first array\n *\n * @param array1 - the first array\n * @param array2 - the second array or number\n */\nexport function xAdd(array1, array2) {\n    let isConstant = false;\n    let constant = 0;\n    if (isAnyArray(array2)) {\n        if (array1.length !== array2.length) {\n            throw new Error('xAdd: size of array1 and array2 must be identical');\n        }\n    }\n    else {\n        isConstant = true;\n        constant = array2;\n    }\n    let array3 = new Float64Array(array1.length);\n    if (isConstant) {\n        for (let i = 0; i < array1.length; i++) {\n            array3[i] = array1[i] + constant;\n        }\n    }\n    else {\n        for (let i = 0; i < array1.length; i++) {\n            array3[i] = array1[i] + array2[i];\n        }\n    }\n    return array3;\n}\n//# sourceMappingURL=xAdd.js.map","import { isAnyArray } from 'is-any-array';\n/**\n * Checks if input is of type array\n *\n * @param input - input\n */\nexport function xCheck(input) {\n    if (!isAnyArray(input)) {\n        throw new TypeError('input must be an array');\n    }\n    if (input.length === 0) {\n        throw new TypeError('input must not be empty');\n    }\n}\n//# sourceMappingURL=xCheck.js.map","/**\n * Returns the closest index of a `target`\n *\n * @param array - array of numbers\n * @param target - target\n * @returns - closest index\n */\nexport function xFindClosestIndex(array, target, options = {}) {\n    const { sorted = true } = options;\n    if (sorted) {\n        let low = 0;\n        let high = array.length - 1;\n        let middle = 0;\n        while (high - low > 1) {\n            middle = low + ((high - low) >> 1);\n            if (array[middle] < target) {\n                low = middle;\n            }\n            else if (array[middle] > target) {\n                high = middle;\n            }\n            else {\n                return middle;\n            }\n        }\n        if (low < array.length - 1) {\n            if (Math.abs(target - array[low]) < Math.abs(array[low + 1] - target)) {\n                return low;\n            }\n            else {\n                return low + 1;\n            }\n        }\n        else {\n            return low;\n        }\n    }\n    else {\n        let index = 0;\n        let diff = Number.POSITIVE_INFINITY;\n        for (let i = 0; i < array.length; i++) {\n            const currentDiff = Math.abs(array[i] - target);\n            if (currentDiff < diff) {\n                diff = currentDiff;\n                index = i;\n            }\n        }\n        return index;\n    }\n}\n//# sourceMappingURL=xFindClosestIndex.js.map","import { xFindClosestIndex } from './xFindClosestIndex';\n/**\n * Returns an object with {fromIndex, toIndex} for a specific from / to\n *\n * @param x - array of numbers\n * @param options - Options\n */\nexport function xGetFromToIndex(x, options = {}) {\n    let { fromIndex, toIndex, from, to } = options;\n    if (fromIndex === undefined) {\n        if (from !== undefined) {\n            fromIndex = xFindClosestIndex(x, from);\n        }\n        else {\n            fromIndex = 0;\n        }\n    }\n    if (toIndex === undefined) {\n        if (to !== undefined) {\n            toIndex = xFindClosestIndex(x, to);\n        }\n        else {\n            toIndex = x.length - 1;\n        }\n    }\n    if (fromIndex < 0)\n        fromIndex = 0;\n    if (toIndex < 0)\n        toIndex = 0;\n    if (fromIndex >= x.length)\n        fromIndex = x.length - 1;\n    if (toIndex >= x.length)\n        toIndex = x.length - 1;\n    if (fromIndex > toIndex)\n        [fromIndex, toIndex] = [toIndex, fromIndex];\n    return { fromIndex, toIndex };\n}\n//# sourceMappingURL=xGetFromToIndex.js.map","import { xCheck } from './xCheck';\nimport { xGetFromToIndex } from './xGetFromToIndex';\n/**\n * Computes the maximal value of an array of values\n *\n * @param array - array of numbers\n * @param options - options\n */\nexport function xMaxValue(array, options = {}) {\n    xCheck(array);\n    const { fromIndex, toIndex } = xGetFromToIndex(array, options);\n    let maxValue = array[fromIndex];\n    for (let i = fromIndex + 1; i <= toIndex; i++) {\n        if (array[i] > maxValue) {\n            maxValue = array[i];\n        }\n    }\n    return maxValue;\n}\n//# sourceMappingURL=xMaxValue.js.map","import { xCheck } from './xCheck';\nimport { xGetFromToIndex } from './xGetFromToIndex';\n/**\n * Computes the minimal value of an array of values\n *\n * @param array - array of numbers\n * @param options - options\n */\nexport function xMinValue(array, options = {}) {\n    xCheck(array);\n    const { fromIndex, toIndex } = xGetFromToIndex(array, options);\n    let minValue = array[fromIndex];\n    for (let i = fromIndex + 1; i <= toIndex; i++) {\n        if (array[i] < minValue) {\n            minValue = array[i];\n        }\n    }\n    return minValue;\n}\n//# sourceMappingURL=xMinValue.js.map","/**\n * Check if the values are separated always by the same difference\n *\n * @param array - Monotone growing array of number\n */\nexport function xIsEquallySpaced(array, options = {}) {\n    if (array.length < 3)\n        return true;\n    const { tolerance = 0.05 } = options;\n    let maxDx = 0;\n    let minDx = Number.MAX_SAFE_INTEGER;\n    for (let i = 0; i < array.length - 1; ++i) {\n        let absoluteDifference = array[i + 1] - array[i];\n        if (absoluteDifference < minDx) {\n            minDx = absoluteDifference;\n        }\n        if (absoluteDifference > maxDx) {\n            maxDx = absoluteDifference;\n        }\n    }\n    return (maxDx - minDx) / maxDx < tolerance;\n}\n//# sourceMappingURL=xIsEquallySpaced.js.map","/**\n * Returns true if x is monotone\n *\n * @param array - array of numbers\n */\nexport function xIsMonotoneIncreasing(array) {\n    if (array.length < 2) {\n        return true;\n    }\n    for (let i = 0; i < array.length - 1; i++) {\n        if (array[i] >= array[i + 1])\n            return false;\n    }\n    return true;\n}\n//# sourceMappingURL=xIsMonotoneIncreasing.js.map","import { xMedian } from './xMedian';\n/**\n * This function calculates the median absolute deviation (MAD)\n * https://en.wikipedia.org/wiki/Median_absolute_deviation\n * @param array\n */\nexport function xMedianAbsoluteDeviation(array) {\n    const median = xMedian(array);\n    const averageDeviations = new Float64Array(array.length);\n    for (let i = 0; i < array.length; i++) {\n        averageDeviations[i] = Math.abs(array[i] - median);\n    }\n    return {\n        median,\n        mad: xMedian(averageDeviations),\n    };\n}\n//# sourceMappingURL=xMedianAbsoluteDeviation.js.map","import { xCheck } from './xCheck';\n/**\n * Return min and max values of an array\n *\n * @param array - array of number\n * @returns - Object with 2 properties, min and max\n */\nexport function xMinMaxValues(array) {\n    xCheck(array);\n    let min = array[0];\n    let max = array[0];\n    for (let value of array) {\n        if (value < min)\n            min = value;\n        if (value > max)\n            max = value;\n    }\n    return { min, max };\n}\n//# sourceMappingURL=xMinMaxValues.js.map","import { xMedianAbsoluteDeviation } from '..';\n/**\n * Determine noise level using MAD https://en.wikipedia.org/wiki/Median_absolute_deviation\n * Constant to convert mad to sd calculated using https://www.wolframalpha.com/input?i=sqrt%282%29+inverse+erf%280.5%29\n * This assumes a gaussian distribution of the noise\n * @param array\n * @returns noise level corresponding to one standard deviation\n */\nexport function xNoiseStandardDeviation(array) {\n    const { mad, median } = xMedianAbsoluteDeviation(array);\n    return { sd: mad / 0.6744897501960817, mad, median };\n}\n//# sourceMappingURL=xNoiseStandardDeviation.js.map","/**\n * This function calculate the norm of a vector\n *\n * @example xNorm([3, 4]) -> 5\n * @param array - array\n * @returns - calculated norm\n */\nexport function xNorm(array) {\n    let result = 0;\n    for (const element of array) {\n        result += element ** 2;\n    }\n    return Math.sqrt(result);\n}\n//# sourceMappingURL=xNorm.js.map","import { isAnyArray } from 'is-any-array';\n/** Fill an array with sequential numbers\n *\n * @param input - optional destination array (if not provided a new array will be created)\n * @param options - options\n * @return array with sequential numbers\n */\nexport function xSequentialFill(input = [], options = {}) {\n    if (typeof input === 'object' && !isAnyArray(input)) {\n        options = input;\n        input = [];\n    }\n    if (!isAnyArray(input)) {\n        throw new TypeError('input must be an array');\n    }\n    // maybe should not specify default step and size\n    let { from = 0, to = 10, size = Array.isArray(input) ||\n        input.constructor === Float64Array ||\n        input.constructor === Uint16Array\n        ? input.length\n        : 0, step = null, } = options;\n    if (!size) {\n        if (step) {\n            size = Math.floor((to - from) / step) + 1;\n        }\n        else {\n            size = to - from + 1;\n        }\n    }\n    if (!step && size) {\n        step = (to - from) / (size - 1);\n    }\n    if (Array.isArray(input)) {\n        // only works with normal array\n        input.length = 0;\n        for (let i = 0; i < size; i++) {\n            input.push(from);\n            if (step)\n                from += step;\n        }\n    }\n    else {\n        if (Array.isArray(input) ||\n            input.constructor === Float64Array ||\n            (input.constructor === Uint16Array && input.length !== size)) {\n            throw new Error('sequentialFill typed array must have the correct length');\n        }\n        for (let i = 0; i < size; i++) {\n            if (Array.isArray(input) ||\n                input.constructor === Float64Array ||\n                input.constructor === Uint16Array) {\n                input[i] = from;\n            }\n            if (step) {\n                from += step;\n            }\n        }\n    }\n    return Array.isArray(input) ||\n        input.constructor === Float64Array ||\n        input.constructor === Uint16Array\n        ? Array.from(input)\n        : [];\n}\n//# sourceMappingURL=xSequentialFill.js.map","import { isAnyArray } from 'is-any-array';\n/**\n * Throw an error in no an object of x,y arrays\n *\n * @param data - array of points {x,y,z}\n */\nexport function xyCheck(data, options = {}) {\n    const { minLength } = options;\n    if (typeof data !== 'object' || !isAnyArray(data.x) || !isAnyArray(data.y)) {\n        throw new Error('Data must be an object of x and y arrays');\n    }\n    if (data.x.length !== data.y.length) {\n        throw new Error('The x and y arrays must have the same length');\n    }\n    if (minLength && data.x.length < minLength) {\n        throw new Error(`data.x must have a length of at least ${minLength}`);\n    }\n}\n//# sourceMappingURL=xyCheck.js.map","import { xFindClosestIndex } from '../x/xFindClosestIndex';\n/**\n * Finds the closest point\n *\n * @param data - x array should be sorted and ascending\n * @param target - target to search\n * @returns - closest point\n */\nexport function xyFindClosestPoint(\n/** points */\ndata, target) {\n    const { x, y } = data;\n    const index = xFindClosestIndex(x, target);\n    return {\n        x: x[index],\n        y: y[index],\n    };\n}\n//# sourceMappingURL=xyFindClosestPoint.js.map","/**\n * Normalize an array of zones:\n * - ensure than from < to\n * - merge overlapping zones\n * - deal with exclusions zones\n * - if no zones is specified add one between -Infinity and +Infinity\n * @param zones - array of zones\n * @param options - options\n * @returns array of zones\n */\nexport function zonesNormalize(zones = [], options = {}) {\n    let { from = Number.NEGATIVE_INFINITY, to = Number.POSITIVE_INFINITY, exclusions = [], } = options;\n    if (from > to)\n        [from, to] = [to, from];\n    zones = JSON.parse(JSON.stringify(zones)).map((zone) => zone.from > zone.to ? { from: zone.to, to: zone.from } : zone);\n    zones = zones.sort((a, b) => {\n        if (a.from !== b.from)\n            return a.from - b.from;\n        return a.to - b.to;\n    });\n    if (zones.length === 0) {\n        zones.push({ from, to });\n    }\n    for (const zone of zones) {\n        if (from > zone.from)\n            zone.from = from;\n        if (to < zone.to)\n            zone.to = to;\n    }\n    zones = zones.filter((zone) => zone.from <= zone.to);\n    if (zones.length === 0)\n        return [];\n    let currentZone = zones[0];\n    let beforeExclusionsZones = [currentZone];\n    for (let i = 1; i < zones.length; i++) {\n        let zone = zones[i];\n        if (zone.from <= currentZone.to) {\n            if (currentZone.to < zone.to) {\n                currentZone.to = zone.to;\n            }\n        }\n        else {\n            currentZone = zone;\n            beforeExclusionsZones.push(currentZone);\n        }\n    }\n    if (exclusions.length === 0)\n        return beforeExclusionsZones;\n    const normalizedExclusions = zonesNormalize(exclusions);\n    let currentExclusionIndex = 0;\n    const results = [];\n    let counter = 0;\n    for (let zoneIndex = 0; zoneIndex < beforeExclusionsZones.length; zoneIndex++) {\n        if (counter++ > 5)\n            break;\n        const zone = beforeExclusionsZones[zoneIndex];\n        if (currentExclusionIndex === normalizedExclusions.length) {\n            // we analysed all the exclusion zones\n            results.push(zone);\n            continue;\n        }\n        while (currentExclusionIndex < normalizedExclusions.length &&\n            normalizedExclusions[currentExclusionIndex].to <= zone.from) {\n            currentExclusionIndex++;\n        }\n        if (currentExclusionIndex === normalizedExclusions.length) {\n            // we analysed all the exclusion zones\n            results.push(zone);\n            continue;\n        }\n        if (zone.to < normalizedExclusions[currentExclusionIndex].from) {\n            // no problems, not yet in exclusion\n            results.push(zone);\n            continue;\n        }\n        if (normalizedExclusions[currentExclusionIndex].to >= zone.to) {\n            // could be totally excluded\n            if (normalizedExclusions[currentExclusionIndex].from <= zone.from) {\n                continue;\n            }\n            results.push({\n                from: normalizedExclusions[currentExclusionIndex].to,\n                to: zone.to,\n            });\n        }\n        // we cut in the middle, we need to create more zones, annoying !\n        if (normalizedExclusions[currentExclusionIndex].from > zone.from) {\n            results.push({\n                from: zone.from,\n                to: normalizedExclusions[currentExclusionIndex].from,\n            });\n        }\n        zone.from = normalizedExclusions[currentExclusionIndex].to;\n        zoneIndex--;\n    }\n    return results;\n}\n//# sourceMappingURL=zonesNormalize.js.map","import { zonesNormalize } from '../zones/zonesNormalize';\nimport { xyCheck } from './xyCheck';\n/**\n * XyExtract zones from a XY data\n *\n * @param data - Object that contains property x (an ordered increasing array) and y (an array)\n * @param options - options\n * @returns - Array of points\n */\nexport function xyExtract(data, options = {}) {\n    xyCheck(data);\n    const { x, y } = data;\n    let { zones } = options;\n    zones = zonesNormalize(zones);\n    if (x === undefined ||\n        y === undefined ||\n        !Array.isArray(zones) ||\n        zones.length === 0) {\n        return data;\n    }\n    let newX = [];\n    let newY = [];\n    let currentZone = zones[0];\n    let position = 0;\n    loop: for (let i = 0; i < x.length; i++) {\n        while (currentZone.to < x[i]) {\n            position++;\n            currentZone = zones[position];\n            if (!currentZone) {\n                i = x.length;\n                break loop;\n            }\n        }\n        if (x[i] >= currentZone.from) {\n            newX.push(x[i]);\n            newY.push(y[i]);\n        }\n    }\n    return { x: newX, y: newY };\n}\n//# sourceMappingURL=xyExtract.js.map","import { xGetFromToIndex } from '../x/xGetFromToIndex';\nimport { xyCheck } from './xyCheck';\n/**\n * Calculate integration\n *\n * @param data - Object that contains property x (an ordered increasing array) and y (an array)\n * @param options - Options\n * @returns - xyIntegration value on the specified range\n */\nexport function xyIntegration(data, options = {}) {\n    xyCheck(data, { minLength: 1 });\n    const { x, y } = data;\n    if (x.length === 1)\n        return 0;\n    const { fromIndex, toIndex } = xGetFromToIndex(x, options);\n    let currentxyIntegration = 0;\n    for (let i = fromIndex; i < toIndex; i++) {\n        currentxyIntegration += ((x[i + 1] - x[i]) * (y[i + 1] + y[i])) / 2;\n    }\n    return currentxyIntegration;\n}\n//# sourceMappingURL=xyIntegration.js.map","export function matrixCheck(data) {\n    if (data.length === 0 || data[0].length === 0) {\n        throw new RangeError('matrix should contain data');\n    }\n    const firstLength = data[0].length;\n    for (let i = 1; i < data.length; i++) {\n        if (data[i].length !== firstLength) {\n            throw new RangeError('All rows should has the same length');\n        }\n    }\n}\n//# sourceMappingURL=matrixCheck.js.map","import { matrixCheck } from './matrixCheck';\n/**\n * Get min and max Z\n *\n * @param matrix - matrix [rows][cols].\n */\nexport function matrixMinMaxZ(matrix) {\n    matrixCheck(matrix);\n    const nbRows = matrix.length;\n    const nbColumns = matrix[0].length;\n    let min = matrix[0][0];\n    let max = matrix[0][0];\n    for (let column = 0; column < nbColumns; column++) {\n        for (let row = 0; row < nbRows; row++) {\n            if (matrix[row][column] < min)\n                min = matrix[row][column];\n            if (matrix[row][column] > max)\n                max = matrix[row][column];\n        }\n    }\n    return { min, max };\n}\n//# sourceMappingURL=matrixMinMaxZ.js.map","import { isAnyArray } from 'is-any-array';\n\nfunction max(input) {\n  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n  if (!isAnyArray(input)) {\n    throw new TypeError('input must be an array');\n  }\n\n  if (input.length === 0) {\n    throw new TypeError('input must not be empty');\n  }\n\n  var _options$fromIndex = options.fromIndex,\n      fromIndex = _options$fromIndex === void 0 ? 0 : _options$fromIndex,\n      _options$toIndex = options.toIndex,\n      toIndex = _options$toIndex === void 0 ? input.length : _options$toIndex;\n\n  if (fromIndex < 0 || fromIndex >= input.length || !Number.isInteger(fromIndex)) {\n    throw new Error('fromIndex must be a positive integer smaller than length');\n  }\n\n  if (toIndex <= fromIndex || toIndex > input.length || !Number.isInteger(toIndex)) {\n    throw new Error('toIndex must be an integer greater than fromIndex and at most equal to length');\n  }\n\n  var maxValue = input[fromIndex];\n\n  for (var i = fromIndex + 1; i < toIndex; i++) {\n    if (input[i] > maxValue) maxValue = input[i];\n  }\n\n  return maxValue;\n}\n\nexport { max as default };\n","import { isAnyArray } from 'is-any-array';\n\nfunction min(input) {\n  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n  if (!isAnyArray(input)) {\n    throw new TypeError('input must be an array');\n  }\n\n  if (input.length === 0) {\n    throw new TypeError('input must not be empty');\n  }\n\n  var _options$fromIndex = options.fromIndex,\n      fromIndex = _options$fromIndex === void 0 ? 0 : _options$fromIndex,\n      _options$toIndex = options.toIndex,\n      toIndex = _options$toIndex === void 0 ? input.length : _options$toIndex;\n\n  if (fromIndex < 0 || fromIndex >= input.length || !Number.isInteger(fromIndex)) {\n    throw new Error('fromIndex must be a positive integer smaller than length');\n  }\n\n  if (toIndex <= fromIndex || toIndex > input.length || !Number.isInteger(toIndex)) {\n    throw new Error('toIndex must be an integer greater than fromIndex and at most equal to length');\n  }\n\n  var minValue = input[fromIndex];\n\n  for (var i = fromIndex + 1; i < toIndex; i++) {\n    if (input[i] < minValue) minValue = input[i];\n  }\n\n  return minValue;\n}\n\nexport { min as default };\n","import { isAnyArray } from 'is-any-array';\nimport max from 'ml-array-max';\nimport min from 'ml-array-min';\n\nfunction rescale(input) {\n  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n  if (!isAnyArray(input)) {\n    throw new TypeError('input must be an array');\n  } else if (input.length === 0) {\n    throw new TypeError('input must not be empty');\n  }\n\n  var output;\n\n  if (options.output !== undefined) {\n    if (!isAnyArray(options.output)) {\n      throw new TypeError('output option must be an array if specified');\n    }\n\n    output = options.output;\n  } else {\n    output = new Array(input.length);\n  }\n\n  var currentMin = min(input);\n  var currentMax = max(input);\n\n  if (currentMin === currentMax) {\n    throw new RangeError('minimum and maximum input values are equal. Cannot rescale a constant array');\n  }\n\n  var _options$min = options.min,\n      minValue = _options$min === void 0 ? options.autoMinMax ? currentMin : 0 : _options$min,\n      _options$max = options.max,\n      maxValue = _options$max === void 0 ? options.autoMinMax ? currentMax : 1 : _options$max;\n\n  if (minValue >= maxValue) {\n    throw new RangeError('min option must be smaller than max option');\n  }\n\n  var factor = (maxValue - minValue) / (currentMax - currentMin);\n\n  for (var i = 0; i < input.length; i++) {\n    output[i] = (input[i] - currentMin) * factor + minValue;\n  }\n\n  return output;\n}\n\nexport { rescale as default };\n","const indent = ' '.repeat(2);\nconst indentData = ' '.repeat(4);\n\nexport function inspectMatrix() {\n  return inspectMatrixWithOptions(this);\n}\n\nexport function inspectMatrixWithOptions(matrix, options = {}) {\n  const {\n    maxRows = 15,\n    maxColumns = 10,\n    maxNumSize = 8,\n    padMinus = 'auto',\n  } = options;\n  return `${matrix.constructor.name} {\n${indent}[\n${indentData}${inspectData(matrix, maxRows, maxColumns, maxNumSize, padMinus)}\n${indent}]\n${indent}rows: ${matrix.rows}\n${indent}columns: ${matrix.columns}\n}`;\n}\n\nfunction inspectData(matrix, maxRows, maxColumns, maxNumSize, padMinus) {\n  const { rows, columns } = matrix;\n  const maxI = Math.min(rows, maxRows);\n  const maxJ = Math.min(columns, maxColumns);\n  const result = [];\n\n  if (padMinus === 'auto') {\n    padMinus = false;\n    loop: for (let i = 0; i < maxI; i++) {\n      for (let j = 0; j < maxJ; j++) {\n        if (matrix.get(i, j) < 0) {\n          padMinus = true;\n          break loop;\n        }\n      }\n    }\n  }\n\n  for (let i = 0; i < maxI; i++) {\n    let line = [];\n    for (let j = 0; j < maxJ; j++) {\n      line.push(formatNumber(matrix.get(i, j), maxNumSize, padMinus));\n    }\n    result.push(`${line.join(' ')}`);\n  }\n  if (maxJ !== columns) {\n    result[result.length - 1] += ` ... ${columns - maxColumns} more columns`;\n  }\n  if (maxI !== rows) {\n    result.push(`... ${rows - maxRows} more rows`);\n  }\n  return result.join(`\\n${indentData}`);\n}\n\nfunction formatNumber(num, maxNumSize, padMinus) {\n  return (\n    num >= 0 && padMinus\n      ? ` ${formatNumber2(num, maxNumSize - 1)}`\n      : formatNumber2(num, maxNumSize)\n  ).padEnd(maxNumSize);\n}\n\nfunction formatNumber2(num, len) {\n  // small.length numbers should be as is\n  let str = num.toString();\n  if (str.length <= len) return str;\n\n  // (7)'0.00123' is better then (7)'1.23e-2'\n  // (8)'0.000123' is worse then (7)'1.23e-3',\n  let fix = num.toFixed(len);\n  if (fix.length > len) {\n    fix = num.toFixed(Math.max(0, len - (fix.length - len)));\n  }\n  if (\n    fix.length <= len &&\n    !fix.startsWith('0.000') &&\n    !fix.startsWith('-0.000')\n  ) {\n    return fix;\n  }\n\n  // well, if it's still too long the user should've used longer numbers\n  let exp = num.toExponential(len);\n  if (exp.length > len) {\n    exp = num.toExponential(Math.max(0, len - (exp.length - len)));\n  }\n  return exp.slice(0);\n}\n","export function installMathOperations(AbstractMatrix, Matrix) {\n  AbstractMatrix.prototype.add = function add(value) {\n    if (typeof value === 'number') return this.addS(value);\n    return this.addM(value);\n  };\n\n  AbstractMatrix.prototype.addS = function addS(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) + value);\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.prototype.addM = function addM(matrix) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (this.rows !== matrix.rows ||\n      this.columns !== matrix.columns) {\n      throw new RangeError('Matrices dimensions must be equal');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) + matrix.get(i, j));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.add = function add(matrix, value) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.add(value);\n  };\n\n  AbstractMatrix.prototype.sub = function sub(value) {\n    if (typeof value === 'number') return this.subS(value);\n    return this.subM(value);\n  };\n\n  AbstractMatrix.prototype.subS = function subS(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) - value);\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.prototype.subM = function subM(matrix) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (this.rows !== matrix.rows ||\n      this.columns !== matrix.columns) {\n      throw new RangeError('Matrices dimensions must be equal');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) - matrix.get(i, j));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.sub = function sub(matrix, value) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.sub(value);\n  };\n  AbstractMatrix.prototype.subtract = AbstractMatrix.prototype.sub;\n  AbstractMatrix.prototype.subtractS = AbstractMatrix.prototype.subS;\n  AbstractMatrix.prototype.subtractM = AbstractMatrix.prototype.subM;\n  AbstractMatrix.subtract = AbstractMatrix.sub;\n\n  AbstractMatrix.prototype.mul = function mul(value) {\n    if (typeof value === 'number') return this.mulS(value);\n    return this.mulM(value);\n  };\n\n  AbstractMatrix.prototype.mulS = function mulS(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) * value);\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.prototype.mulM = function mulM(matrix) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (this.rows !== matrix.rows ||\n      this.columns !== matrix.columns) {\n      throw new RangeError('Matrices dimensions must be equal');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) * matrix.get(i, j));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.mul = function mul(matrix, value) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.mul(value);\n  };\n  AbstractMatrix.prototype.multiply = AbstractMatrix.prototype.mul;\n  AbstractMatrix.prototype.multiplyS = AbstractMatrix.prototype.mulS;\n  AbstractMatrix.prototype.multiplyM = AbstractMatrix.prototype.mulM;\n  AbstractMatrix.multiply = AbstractMatrix.mul;\n\n  AbstractMatrix.prototype.div = function div(value) {\n    if (typeof value === 'number') return this.divS(value);\n    return this.divM(value);\n  };\n\n  AbstractMatrix.prototype.divS = function divS(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) / value);\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.prototype.divM = function divM(matrix) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (this.rows !== matrix.rows ||\n      this.columns !== matrix.columns) {\n      throw new RangeError('Matrices dimensions must be equal');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) / matrix.get(i, j));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.div = function div(matrix, value) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.div(value);\n  };\n  AbstractMatrix.prototype.divide = AbstractMatrix.prototype.div;\n  AbstractMatrix.prototype.divideS = AbstractMatrix.prototype.divS;\n  AbstractMatrix.prototype.divideM = AbstractMatrix.prototype.divM;\n  AbstractMatrix.divide = AbstractMatrix.div;\n\n  AbstractMatrix.prototype.mod = function mod(value) {\n    if (typeof value === 'number') return this.modS(value);\n    return this.modM(value);\n  };\n\n  AbstractMatrix.prototype.modS = function modS(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) % value);\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.prototype.modM = function modM(matrix) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (this.rows !== matrix.rows ||\n      this.columns !== matrix.columns) {\n      throw new RangeError('Matrices dimensions must be equal');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) % matrix.get(i, j));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.mod = function mod(matrix, value) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.mod(value);\n  };\n  AbstractMatrix.prototype.modulus = AbstractMatrix.prototype.mod;\n  AbstractMatrix.prototype.modulusS = AbstractMatrix.prototype.modS;\n  AbstractMatrix.prototype.modulusM = AbstractMatrix.prototype.modM;\n  AbstractMatrix.modulus = AbstractMatrix.mod;\n\n  AbstractMatrix.prototype.and = function and(value) {\n    if (typeof value === 'number') return this.andS(value);\n    return this.andM(value);\n  };\n\n  AbstractMatrix.prototype.andS = function andS(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) & value);\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.prototype.andM = function andM(matrix) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (this.rows !== matrix.rows ||\n      this.columns !== matrix.columns) {\n      throw new RangeError('Matrices dimensions must be equal');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) & matrix.get(i, j));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.and = function and(matrix, value) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.and(value);\n  };\n\n  AbstractMatrix.prototype.or = function or(value) {\n    if (typeof value === 'number') return this.orS(value);\n    return this.orM(value);\n  };\n\n  AbstractMatrix.prototype.orS = function orS(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) | value);\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.prototype.orM = function orM(matrix) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (this.rows !== matrix.rows ||\n      this.columns !== matrix.columns) {\n      throw new RangeError('Matrices dimensions must be equal');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) | matrix.get(i, j));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.or = function or(matrix, value) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.or(value);\n  };\n\n  AbstractMatrix.prototype.xor = function xor(value) {\n    if (typeof value === 'number') return this.xorS(value);\n    return this.xorM(value);\n  };\n\n  AbstractMatrix.prototype.xorS = function xorS(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) ^ value);\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.prototype.xorM = function xorM(matrix) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (this.rows !== matrix.rows ||\n      this.columns !== matrix.columns) {\n      throw new RangeError('Matrices dimensions must be equal');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) ^ matrix.get(i, j));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.xor = function xor(matrix, value) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.xor(value);\n  };\n\n  AbstractMatrix.prototype.leftShift = function leftShift(value) {\n    if (typeof value === 'number') return this.leftShiftS(value);\n    return this.leftShiftM(value);\n  };\n\n  AbstractMatrix.prototype.leftShiftS = function leftShiftS(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) << value);\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.prototype.leftShiftM = function leftShiftM(matrix) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (this.rows !== matrix.rows ||\n      this.columns !== matrix.columns) {\n      throw new RangeError('Matrices dimensions must be equal');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) << matrix.get(i, j));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.leftShift = function leftShift(matrix, value) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.leftShift(value);\n  };\n\n  AbstractMatrix.prototype.signPropagatingRightShift = function signPropagatingRightShift(value) {\n    if (typeof value === 'number') return this.signPropagatingRightShiftS(value);\n    return this.signPropagatingRightShiftM(value);\n  };\n\n  AbstractMatrix.prototype.signPropagatingRightShiftS = function signPropagatingRightShiftS(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) >> value);\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.prototype.signPropagatingRightShiftM = function signPropagatingRightShiftM(matrix) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (this.rows !== matrix.rows ||\n      this.columns !== matrix.columns) {\n      throw new RangeError('Matrices dimensions must be equal');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) >> matrix.get(i, j));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.signPropagatingRightShift = function signPropagatingRightShift(matrix, value) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.signPropagatingRightShift(value);\n  };\n\n  AbstractMatrix.prototype.rightShift = function rightShift(value) {\n    if (typeof value === 'number') return this.rightShiftS(value);\n    return this.rightShiftM(value);\n  };\n\n  AbstractMatrix.prototype.rightShiftS = function rightShiftS(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) >>> value);\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.prototype.rightShiftM = function rightShiftM(matrix) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (this.rows !== matrix.rows ||\n      this.columns !== matrix.columns) {\n      throw new RangeError('Matrices dimensions must be equal');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) >>> matrix.get(i, j));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.rightShift = function rightShift(matrix, value) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.rightShift(value);\n  };\n  AbstractMatrix.prototype.zeroFillRightShift = AbstractMatrix.prototype.rightShift;\n  AbstractMatrix.prototype.zeroFillRightShiftS = AbstractMatrix.prototype.rightShiftS;\n  AbstractMatrix.prototype.zeroFillRightShiftM = AbstractMatrix.prototype.rightShiftM;\n  AbstractMatrix.zeroFillRightShift = AbstractMatrix.rightShift;\n\n  AbstractMatrix.prototype.not = function not() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, ~(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.not = function not(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.not();\n  };\n\n  AbstractMatrix.prototype.abs = function abs() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.abs(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.abs = function abs(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.abs();\n  };\n\n  AbstractMatrix.prototype.acos = function acos() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.acos(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.acos = function acos(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.acos();\n  };\n\n  AbstractMatrix.prototype.acosh = function acosh() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.acosh(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.acosh = function acosh(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.acosh();\n  };\n\n  AbstractMatrix.prototype.asin = function asin() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.asin(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.asin = function asin(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.asin();\n  };\n\n  AbstractMatrix.prototype.asinh = function asinh() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.asinh(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.asinh = function asinh(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.asinh();\n  };\n\n  AbstractMatrix.prototype.atan = function atan() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.atan(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.atan = function atan(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.atan();\n  };\n\n  AbstractMatrix.prototype.atanh = function atanh() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.atanh(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.atanh = function atanh(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.atanh();\n  };\n\n  AbstractMatrix.prototype.cbrt = function cbrt() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.cbrt(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.cbrt = function cbrt(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.cbrt();\n  };\n\n  AbstractMatrix.prototype.ceil = function ceil() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.ceil(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.ceil = function ceil(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.ceil();\n  };\n\n  AbstractMatrix.prototype.clz32 = function clz32() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.clz32(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.clz32 = function clz32(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.clz32();\n  };\n\n  AbstractMatrix.prototype.cos = function cos() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.cos(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.cos = function cos(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.cos();\n  };\n\n  AbstractMatrix.prototype.cosh = function cosh() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.cosh(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.cosh = function cosh(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.cosh();\n  };\n\n  AbstractMatrix.prototype.exp = function exp() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.exp(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.exp = function exp(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.exp();\n  };\n\n  AbstractMatrix.prototype.expm1 = function expm1() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.expm1(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.expm1 = function expm1(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.expm1();\n  };\n\n  AbstractMatrix.prototype.floor = function floor() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.floor(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.floor = function floor(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.floor();\n  };\n\n  AbstractMatrix.prototype.fround = function fround() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.fround(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.fround = function fround(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.fround();\n  };\n\n  AbstractMatrix.prototype.log = function log() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.log(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.log = function log(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.log();\n  };\n\n  AbstractMatrix.prototype.log1p = function log1p() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.log1p(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.log1p = function log1p(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.log1p();\n  };\n\n  AbstractMatrix.prototype.log10 = function log10() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.log10(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.log10 = function log10(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.log10();\n  };\n\n  AbstractMatrix.prototype.log2 = function log2() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.log2(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.log2 = function log2(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.log2();\n  };\n\n  AbstractMatrix.prototype.round = function round() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.round(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.round = function round(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.round();\n  };\n\n  AbstractMatrix.prototype.sign = function sign() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.sign(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.sign = function sign(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.sign();\n  };\n\n  AbstractMatrix.prototype.sin = function sin() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.sin(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.sin = function sin(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.sin();\n  };\n\n  AbstractMatrix.prototype.sinh = function sinh() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.sinh(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.sinh = function sinh(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.sinh();\n  };\n\n  AbstractMatrix.prototype.sqrt = function sqrt() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.sqrt(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.sqrt = function sqrt(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.sqrt();\n  };\n\n  AbstractMatrix.prototype.tan = function tan() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.tan(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.tan = function tan(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.tan();\n  };\n\n  AbstractMatrix.prototype.tanh = function tanh() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.tanh(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.tanh = function tanh(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.tanh();\n  };\n\n  AbstractMatrix.prototype.trunc = function trunc() {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.trunc(this.get(i, j)));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.trunc = function trunc(matrix) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.trunc();\n  };\n\n  AbstractMatrix.pow = function pow(matrix, arg0) {\n    const newMatrix = new Matrix(matrix);\n    return newMatrix.pow(arg0);\n  };\n\n  AbstractMatrix.prototype.pow = function pow(value) {\n    if (typeof value === 'number') return this.powS(value);\n    return this.powM(value);\n  };\n\n  AbstractMatrix.prototype.powS = function powS(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.pow(this.get(i, j), value));\n      }\n    }\n    return this;\n  };\n\n  AbstractMatrix.prototype.powM = function powM(matrix) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (this.rows !== matrix.rows ||\n      this.columns !== matrix.columns) {\n      throw new RangeError('Matrices dimensions must be equal');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, Math.pow(this.get(i, j), matrix.get(i, j)));\n      }\n    }\n    return this;\n  };\n}\n","import { isAnyArray } from 'is-any-array';\n\n/**\n * @private\n * Check that a row index is not out of bounds\n * @param {Matrix} matrix\n * @param {number} index\n * @param {boolean} [outer]\n */\nexport function checkRowIndex(matrix, index, outer) {\n  let max = outer ? matrix.rows : matrix.rows - 1;\n  if (index < 0 || index > max) {\n    throw new RangeError('Row index out of range');\n  }\n}\n\n/**\n * @private\n * Check that a column index is not out of bounds\n * @param {Matrix} matrix\n * @param {number} index\n * @param {boolean} [outer]\n */\nexport function checkColumnIndex(matrix, index, outer) {\n  let max = outer ? matrix.columns : matrix.columns - 1;\n  if (index < 0 || index > max) {\n    throw new RangeError('Column index out of range');\n  }\n}\n\n/**\n * @private\n * Check that the provided vector is an array with the right length\n * @param {Matrix} matrix\n * @param {Array|Matrix} vector\n * @return {Array}\n * @throws {RangeError}\n */\nexport function checkRowVector(matrix, vector) {\n  if (vector.to1DArray) {\n    vector = vector.to1DArray();\n  }\n  if (vector.length !== matrix.columns) {\n    throw new RangeError(\n      'vector size must be the same as the number of columns',\n    );\n  }\n  return vector;\n}\n\n/**\n * @private\n * Check that the provided vector is an array with the right length\n * @param {Matrix} matrix\n * @param {Array|Matrix} vector\n * @return {Array}\n * @throws {RangeError}\n */\nexport function checkColumnVector(matrix, vector) {\n  if (vector.to1DArray) {\n    vector = vector.to1DArray();\n  }\n  if (vector.length !== matrix.rows) {\n    throw new RangeError('vector size must be the same as the number of rows');\n  }\n  return vector;\n}\n\nexport function checkRowIndices(matrix, rowIndices) {\n  if (!isAnyArray(rowIndices)) {\n    throw new TypeError('row indices must be an array');\n  }\n\n  for (let i = 0; i < rowIndices.length; i++) {\n    if (rowIndices[i] < 0 || rowIndices[i] >= matrix.rows) {\n      throw new RangeError('row indices are out of range');\n    }\n  }\n}\n\nexport function checkColumnIndices(matrix, columnIndices) {\n  if (!isAnyArray(columnIndices)) {\n    throw new TypeError('column indices must be an array');\n  }\n\n  for (let i = 0; i < columnIndices.length; i++) {\n    if (columnIndices[i] < 0 || columnIndices[i] >= matrix.columns) {\n      throw new RangeError('column indices are out of range');\n    }\n  }\n}\n\nexport function checkRange(matrix, startRow, endRow, startColumn, endColumn) {\n  if (arguments.length !== 5) {\n    throw new RangeError('expected 4 arguments');\n  }\n  checkNumber('startRow', startRow);\n  checkNumber('endRow', endRow);\n  checkNumber('startColumn', startColumn);\n  checkNumber('endColumn', endColumn);\n  if (\n    startRow > endRow ||\n    startColumn > endColumn ||\n    startRow < 0 ||\n    startRow >= matrix.rows ||\n    endRow < 0 ||\n    endRow >= matrix.rows ||\n    startColumn < 0 ||\n    startColumn >= matrix.columns ||\n    endColumn < 0 ||\n    endColumn >= matrix.columns\n  ) {\n    throw new RangeError('Submatrix indices are out of range');\n  }\n}\n\nexport function newArray(length, value = 0) {\n  let array = [];\n  for (let i = 0; i < length; i++) {\n    array.push(value);\n  }\n  return array;\n}\n\nfunction checkNumber(name, value) {\n  if (typeof value !== 'number') {\n    throw new TypeError(`${name} must be a number`);\n  }\n}\n\nexport function checkNonEmpty(matrix) {\n  if (matrix.isEmpty()) {\n    throw new Error('Empty matrix has no elements to index');\n  }\n}\n","import { newArray } from './util';\n\nexport function sumByRow(matrix) {\n  let sum = newArray(matrix.rows);\n  for (let i = 0; i < matrix.rows; ++i) {\n    for (let j = 0; j < matrix.columns; ++j) {\n      sum[i] += matrix.get(i, j);\n    }\n  }\n  return sum;\n}\n\nexport function sumByColumn(matrix) {\n  let sum = newArray(matrix.columns);\n  for (let i = 0; i < matrix.rows; ++i) {\n    for (let j = 0; j < matrix.columns; ++j) {\n      sum[j] += matrix.get(i, j);\n    }\n  }\n  return sum;\n}\n\nexport function sumAll(matrix) {\n  let v = 0;\n  for (let i = 0; i < matrix.rows; i++) {\n    for (let j = 0; j < matrix.columns; j++) {\n      v += matrix.get(i, j);\n    }\n  }\n  return v;\n}\n\nexport function productByRow(matrix) {\n  let sum = newArray(matrix.rows, 1);\n  for (let i = 0; i < matrix.rows; ++i) {\n    for (let j = 0; j < matrix.columns; ++j) {\n      sum[i] *= matrix.get(i, j);\n    }\n  }\n  return sum;\n}\n\nexport function productByColumn(matrix) {\n  let sum = newArray(matrix.columns, 1);\n  for (let i = 0; i < matrix.rows; ++i) {\n    for (let j = 0; j < matrix.columns; ++j) {\n      sum[j] *= matrix.get(i, j);\n    }\n  }\n  return sum;\n}\n\nexport function productAll(matrix) {\n  let v = 1;\n  for (let i = 0; i < matrix.rows; i++) {\n    for (let j = 0; j < matrix.columns; j++) {\n      v *= matrix.get(i, j);\n    }\n  }\n  return v;\n}\n\nexport function varianceByRow(matrix, unbiased, mean) {\n  const rows = matrix.rows;\n  const cols = matrix.columns;\n  const variance = [];\n\n  for (let i = 0; i < rows; i++) {\n    let sum1 = 0;\n    let sum2 = 0;\n    let x = 0;\n    for (let j = 0; j < cols; j++) {\n      x = matrix.get(i, j) - mean[i];\n      sum1 += x;\n      sum2 += x * x;\n    }\n    if (unbiased) {\n      variance.push((sum2 - (sum1 * sum1) / cols) / (cols - 1));\n    } else {\n      variance.push((sum2 - (sum1 * sum1) / cols) / cols);\n    }\n  }\n  return variance;\n}\n\nexport function varianceByColumn(matrix, unbiased, mean) {\n  const rows = matrix.rows;\n  const cols = matrix.columns;\n  const variance = [];\n\n  for (let j = 0; j < cols; j++) {\n    let sum1 = 0;\n    let sum2 = 0;\n    let x = 0;\n    for (let i = 0; i < rows; i++) {\n      x = matrix.get(i, j) - mean[j];\n      sum1 += x;\n      sum2 += x * x;\n    }\n    if (unbiased) {\n      variance.push((sum2 - (sum1 * sum1) / rows) / (rows - 1));\n    } else {\n      variance.push((sum2 - (sum1 * sum1) / rows) / rows);\n    }\n  }\n  return variance;\n}\n\nexport function varianceAll(matrix, unbiased, mean) {\n  const rows = matrix.rows;\n  const cols = matrix.columns;\n  const size = rows * cols;\n\n  let sum1 = 0;\n  let sum2 = 0;\n  let x = 0;\n  for (let i = 0; i < rows; i++) {\n    for (let j = 0; j < cols; j++) {\n      x = matrix.get(i, j) - mean;\n      sum1 += x;\n      sum2 += x * x;\n    }\n  }\n  if (unbiased) {\n    return (sum2 - (sum1 * sum1) / size) / (size - 1);\n  } else {\n    return (sum2 - (sum1 * sum1) / size) / size;\n  }\n}\n\nexport function centerByRow(matrix, mean) {\n  for (let i = 0; i < matrix.rows; i++) {\n    for (let j = 0; j < matrix.columns; j++) {\n      matrix.set(i, j, matrix.get(i, j) - mean[i]);\n    }\n  }\n}\n\nexport function centerByColumn(matrix, mean) {\n  for (let i = 0; i < matrix.rows; i++) {\n    for (let j = 0; j < matrix.columns; j++) {\n      matrix.set(i, j, matrix.get(i, j) - mean[j]);\n    }\n  }\n}\n\nexport function centerAll(matrix, mean) {\n  for (let i = 0; i < matrix.rows; i++) {\n    for (let j = 0; j < matrix.columns; j++) {\n      matrix.set(i, j, matrix.get(i, j) - mean);\n    }\n  }\n}\n\nexport function getScaleByRow(matrix) {\n  const scale = [];\n  for (let i = 0; i < matrix.rows; i++) {\n    let sum = 0;\n    for (let j = 0; j < matrix.columns; j++) {\n      sum += Math.pow(matrix.get(i, j), 2) / (matrix.columns - 1);\n    }\n    scale.push(Math.sqrt(sum));\n  }\n  return scale;\n}\n\nexport function scaleByRow(matrix, scale) {\n  for (let i = 0; i < matrix.rows; i++) {\n    for (let j = 0; j < matrix.columns; j++) {\n      matrix.set(i, j, matrix.get(i, j) / scale[i]);\n    }\n  }\n}\n\nexport function getScaleByColumn(matrix) {\n  const scale = [];\n  for (let j = 0; j < matrix.columns; j++) {\n    let sum = 0;\n    for (let i = 0; i < matrix.rows; i++) {\n      sum += Math.pow(matrix.get(i, j), 2) / (matrix.rows - 1);\n    }\n    scale.push(Math.sqrt(sum));\n  }\n  return scale;\n}\n\nexport function scaleByColumn(matrix, scale) {\n  for (let i = 0; i < matrix.rows; i++) {\n    for (let j = 0; j < matrix.columns; j++) {\n      matrix.set(i, j, matrix.get(i, j) / scale[j]);\n    }\n  }\n}\n\nexport function getScaleAll(matrix) {\n  const divider = matrix.size - 1;\n  let sum = 0;\n  for (let j = 0; j < matrix.columns; j++) {\n    for (let i = 0; i < matrix.rows; i++) {\n      sum += Math.pow(matrix.get(i, j), 2) / divider;\n    }\n  }\n  return Math.sqrt(sum);\n}\n\nexport function scaleAll(matrix, scale) {\n  for (let i = 0; i < matrix.rows; i++) {\n    for (let j = 0; j < matrix.columns; j++) {\n      matrix.set(i, j, matrix.get(i, j) / scale);\n    }\n  }\n}\n","import { isAnyArray } from 'is-any-array';\nimport rescale from 'ml-array-rescale';\n\nimport { inspectMatrix, inspectMatrixWithOptions } from './inspect';\nimport { installMathOperations } from './mathOperations';\nimport {\n  sumByRow,\n  sumByColumn,\n  sumAll,\n  productByRow,\n  productByColumn,\n  productAll,\n  varianceByRow,\n  varianceByColumn,\n  varianceAll,\n  centerByRow,\n  centerByColumn,\n  centerAll,\n  scaleByRow,\n  scaleByColumn,\n  scaleAll,\n  getScaleByRow,\n  getScaleByColumn,\n  getScaleAll,\n} from './stat';\nimport {\n  checkRowVector,\n  checkRowIndex,\n  checkColumnIndex,\n  checkColumnVector,\n  checkRange,\n  checkNonEmpty,\n  checkRowIndices,\n  checkColumnIndices,\n} from './util';\n\nexport class AbstractMatrix {\n  static from1DArray(newRows, newColumns, newData) {\n    let length = newRows * newColumns;\n    if (length !== newData.length) {\n      throw new RangeError('data length does not match given dimensions');\n    }\n    let newMatrix = new Matrix(newRows, newColumns);\n    for (let row = 0; row < newRows; row++) {\n      for (let column = 0; column < newColumns; column++) {\n        newMatrix.set(row, column, newData[row * newColumns + column]);\n      }\n    }\n    return newMatrix;\n  }\n\n  static rowVector(newData) {\n    let vector = new Matrix(1, newData.length);\n    for (let i = 0; i < newData.length; i++) {\n      vector.set(0, i, newData[i]);\n    }\n    return vector;\n  }\n\n  static columnVector(newData) {\n    let vector = new Matrix(newData.length, 1);\n    for (let i = 0; i < newData.length; i++) {\n      vector.set(i, 0, newData[i]);\n    }\n    return vector;\n  }\n\n  static zeros(rows, columns) {\n    return new Matrix(rows, columns);\n  }\n\n  static ones(rows, columns) {\n    return new Matrix(rows, columns).fill(1);\n  }\n\n  static rand(rows, columns, options = {}) {\n    if (typeof options !== 'object') {\n      throw new TypeError('options must be an object');\n    }\n    const { random = Math.random } = options;\n    let matrix = new Matrix(rows, columns);\n    for (let i = 0; i < rows; i++) {\n      for (let j = 0; j < columns; j++) {\n        matrix.set(i, j, random());\n      }\n    }\n    return matrix;\n  }\n\n  static randInt(rows, columns, options = {}) {\n    if (typeof options !== 'object') {\n      throw new TypeError('options must be an object');\n    }\n    const { min = 0, max = 1000, random = Math.random } = options;\n    if (!Number.isInteger(min)) throw new TypeError('min must be an integer');\n    if (!Number.isInteger(max)) throw new TypeError('max must be an integer');\n    if (min >= max) throw new RangeError('min must be smaller than max');\n    let interval = max - min;\n    let matrix = new Matrix(rows, columns);\n    for (let i = 0; i < rows; i++) {\n      for (let j = 0; j < columns; j++) {\n        let value = min + Math.round(random() * interval);\n        matrix.set(i, j, value);\n      }\n    }\n    return matrix;\n  }\n\n  static eye(rows, columns, value) {\n    if (columns === undefined) columns = rows;\n    if (value === undefined) value = 1;\n    let min = Math.min(rows, columns);\n    let matrix = this.zeros(rows, columns);\n    for (let i = 0; i < min; i++) {\n      matrix.set(i, i, value);\n    }\n    return matrix;\n  }\n\n  static diag(data, rows, columns) {\n    let l = data.length;\n    if (rows === undefined) rows = l;\n    if (columns === undefined) columns = rows;\n    let min = Math.min(l, rows, columns);\n    let matrix = this.zeros(rows, columns);\n    for (let i = 0; i < min; i++) {\n      matrix.set(i, i, data[i]);\n    }\n    return matrix;\n  }\n\n  static min(matrix1, matrix2) {\n    matrix1 = this.checkMatrix(matrix1);\n    matrix2 = this.checkMatrix(matrix2);\n    let rows = matrix1.rows;\n    let columns = matrix1.columns;\n    let result = new Matrix(rows, columns);\n    for (let i = 0; i < rows; i++) {\n      for (let j = 0; j < columns; j++) {\n        result.set(i, j, Math.min(matrix1.get(i, j), matrix2.get(i, j)));\n      }\n    }\n    return result;\n  }\n\n  static max(matrix1, matrix2) {\n    matrix1 = this.checkMatrix(matrix1);\n    matrix2 = this.checkMatrix(matrix2);\n    let rows = matrix1.rows;\n    let columns = matrix1.columns;\n    let result = new this(rows, columns);\n    for (let i = 0; i < rows; i++) {\n      for (let j = 0; j < columns; j++) {\n        result.set(i, j, Math.max(matrix1.get(i, j), matrix2.get(i, j)));\n      }\n    }\n    return result;\n  }\n\n  static checkMatrix(value) {\n    return AbstractMatrix.isMatrix(value) ? value : new Matrix(value);\n  }\n\n  static isMatrix(value) {\n    return value != null && value.klass === 'Matrix';\n  }\n\n  get size() {\n    return this.rows * this.columns;\n  }\n\n  apply(callback) {\n    if (typeof callback !== 'function') {\n      throw new TypeError('callback must be a function');\n    }\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        callback.call(this, i, j);\n      }\n    }\n    return this;\n  }\n\n  to1DArray() {\n    let array = [];\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        array.push(this.get(i, j));\n      }\n    }\n    return array;\n  }\n\n  to2DArray() {\n    let copy = [];\n    for (let i = 0; i < this.rows; i++) {\n      copy.push([]);\n      for (let j = 0; j < this.columns; j++) {\n        copy[i].push(this.get(i, j));\n      }\n    }\n    return copy;\n  }\n\n  toJSON() {\n    return this.to2DArray();\n  }\n\n  isRowVector() {\n    return this.rows === 1;\n  }\n\n  isColumnVector() {\n    return this.columns === 1;\n  }\n\n  isVector() {\n    return this.rows === 1 || this.columns === 1;\n  }\n\n  isSquare() {\n    return this.rows === this.columns;\n  }\n\n  isEmpty() {\n    return this.rows === 0 || this.columns === 0;\n  }\n\n  isSymmetric() {\n    if (this.isSquare()) {\n      for (let i = 0; i < this.rows; i++) {\n        for (let j = 0; j <= i; j++) {\n          if (this.get(i, j) !== this.get(j, i)) {\n            return false;\n          }\n        }\n      }\n      return true;\n    }\n    return false;\n  }\n\n  isEchelonForm() {\n    let i = 0;\n    let j = 0;\n    let previousColumn = -1;\n    let isEchelonForm = true;\n    let checked = false;\n    while (i < this.rows && isEchelonForm) {\n      j = 0;\n      checked = false;\n      while (j < this.columns && checked === false) {\n        if (this.get(i, j) === 0) {\n          j++;\n        } else if (this.get(i, j) === 1 && j > previousColumn) {\n          checked = true;\n          previousColumn = j;\n        } else {\n          isEchelonForm = false;\n          checked = true;\n        }\n      }\n      i++;\n    }\n    return isEchelonForm;\n  }\n\n  isReducedEchelonForm() {\n    let i = 0;\n    let j = 0;\n    let previousColumn = -1;\n    let isReducedEchelonForm = true;\n    let checked = false;\n    while (i < this.rows && isReducedEchelonForm) {\n      j = 0;\n      checked = false;\n      while (j < this.columns && checked === false) {\n        if (this.get(i, j) === 0) {\n          j++;\n        } else if (this.get(i, j) === 1 && j > previousColumn) {\n          checked = true;\n          previousColumn = j;\n        } else {\n          isReducedEchelonForm = false;\n          checked = true;\n        }\n      }\n      for (let k = j + 1; k < this.rows; k++) {\n        if (this.get(i, k) !== 0) {\n          isReducedEchelonForm = false;\n        }\n      }\n      i++;\n    }\n    return isReducedEchelonForm;\n  }\n\n  echelonForm() {\n    let result = this.clone();\n    let h = 0;\n    let k = 0;\n    while (h < result.rows && k < result.columns) {\n      let iMax = h;\n      for (let i = h; i < result.rows; i++) {\n        if (result.get(i, k) > result.get(iMax, k)) {\n          iMax = i;\n        }\n      }\n      if (result.get(iMax, k) === 0) {\n        k++;\n      } else {\n        result.swapRows(h, iMax);\n        let tmp = result.get(h, k);\n        for (let j = k; j < result.columns; j++) {\n          result.set(h, j, result.get(h, j) / tmp);\n        }\n        for (let i = h + 1; i < result.rows; i++) {\n          let factor = result.get(i, k) / result.get(h, k);\n          result.set(i, k, 0);\n          for (let j = k + 1; j < result.columns; j++) {\n            result.set(i, j, result.get(i, j) - result.get(h, j) * factor);\n          }\n        }\n        h++;\n        k++;\n      }\n    }\n    return result;\n  }\n\n  reducedEchelonForm() {\n    let result = this.echelonForm();\n    let m = result.columns;\n    let n = result.rows;\n    let h = n - 1;\n    while (h >= 0) {\n      if (result.maxRow(h) === 0) {\n        h--;\n      } else {\n        let p = 0;\n        let pivot = false;\n        while (p < n && pivot === false) {\n          if (result.get(h, p) === 1) {\n            pivot = true;\n          } else {\n            p++;\n          }\n        }\n        for (let i = 0; i < h; i++) {\n          let factor = result.get(i, p);\n          for (let j = p; j < m; j++) {\n            let tmp = result.get(i, j) - factor * result.get(h, j);\n            result.set(i, j, tmp);\n          }\n        }\n        h--;\n      }\n    }\n    return result;\n  }\n\n  set() {\n    throw new Error('set method is unimplemented');\n  }\n\n  get() {\n    throw new Error('get method is unimplemented');\n  }\n\n  repeat(options = {}) {\n    if (typeof options !== 'object') {\n      throw new TypeError('options must be an object');\n    }\n    const { rows = 1, columns = 1 } = options;\n    if (!Number.isInteger(rows) || rows <= 0) {\n      throw new TypeError('rows must be a positive integer');\n    }\n    if (!Number.isInteger(columns) || columns <= 0) {\n      throw new TypeError('columns must be a positive integer');\n    }\n    let matrix = new Matrix(this.rows * rows, this.columns * columns);\n    for (let i = 0; i < rows; i++) {\n      for (let j = 0; j < columns; j++) {\n        matrix.setSubMatrix(this, this.rows * i, this.columns * j);\n      }\n    }\n    return matrix;\n  }\n\n  fill(value) {\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, value);\n      }\n    }\n    return this;\n  }\n\n  neg() {\n    return this.mulS(-1);\n  }\n\n  getRow(index) {\n    checkRowIndex(this, index);\n    let row = [];\n    for (let i = 0; i < this.columns; i++) {\n      row.push(this.get(index, i));\n    }\n    return row;\n  }\n\n  getRowVector(index) {\n    return Matrix.rowVector(this.getRow(index));\n  }\n\n  setRow(index, array) {\n    checkRowIndex(this, index);\n    array = checkRowVector(this, array);\n    for (let i = 0; i < this.columns; i++) {\n      this.set(index, i, array[i]);\n    }\n    return this;\n  }\n\n  swapRows(row1, row2) {\n    checkRowIndex(this, row1);\n    checkRowIndex(this, row2);\n    for (let i = 0; i < this.columns; i++) {\n      let temp = this.get(row1, i);\n      this.set(row1, i, this.get(row2, i));\n      this.set(row2, i, temp);\n    }\n    return this;\n  }\n\n  getColumn(index) {\n    checkColumnIndex(this, index);\n    let column = [];\n    for (let i = 0; i < this.rows; i++) {\n      column.push(this.get(i, index));\n    }\n    return column;\n  }\n\n  getColumnVector(index) {\n    return Matrix.columnVector(this.getColumn(index));\n  }\n\n  setColumn(index, array) {\n    checkColumnIndex(this, index);\n    array = checkColumnVector(this, array);\n    for (let i = 0; i < this.rows; i++) {\n      this.set(i, index, array[i]);\n    }\n    return this;\n  }\n\n  swapColumns(column1, column2) {\n    checkColumnIndex(this, column1);\n    checkColumnIndex(this, column2);\n    for (let i = 0; i < this.rows; i++) {\n      let temp = this.get(i, column1);\n      this.set(i, column1, this.get(i, column2));\n      this.set(i, column2, temp);\n    }\n    return this;\n  }\n\n  addRowVector(vector) {\n    vector = checkRowVector(this, vector);\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) + vector[j]);\n      }\n    }\n    return this;\n  }\n\n  subRowVector(vector) {\n    vector = checkRowVector(this, vector);\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) - vector[j]);\n      }\n    }\n    return this;\n  }\n\n  mulRowVector(vector) {\n    vector = checkRowVector(this, vector);\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) * vector[j]);\n      }\n    }\n    return this;\n  }\n\n  divRowVector(vector) {\n    vector = checkRowVector(this, vector);\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) / vector[j]);\n      }\n    }\n    return this;\n  }\n\n  addColumnVector(vector) {\n    vector = checkColumnVector(this, vector);\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) + vector[i]);\n      }\n    }\n    return this;\n  }\n\n  subColumnVector(vector) {\n    vector = checkColumnVector(this, vector);\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) - vector[i]);\n      }\n    }\n    return this;\n  }\n\n  mulColumnVector(vector) {\n    vector = checkColumnVector(this, vector);\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) * vector[i]);\n      }\n    }\n    return this;\n  }\n\n  divColumnVector(vector) {\n    vector = checkColumnVector(this, vector);\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        this.set(i, j, this.get(i, j) / vector[i]);\n      }\n    }\n    return this;\n  }\n\n  mulRow(index, value) {\n    checkRowIndex(this, index);\n    for (let i = 0; i < this.columns; i++) {\n      this.set(index, i, this.get(index, i) * value);\n    }\n    return this;\n  }\n\n  mulColumn(index, value) {\n    checkColumnIndex(this, index);\n    for (let i = 0; i < this.rows; i++) {\n      this.set(i, index, this.get(i, index) * value);\n    }\n    return this;\n  }\n\n  max(by) {\n    if (this.isEmpty()) {\n      return NaN;\n    }\n    switch (by) {\n      case 'row': {\n        const max = new Array(this.rows).fill(Number.NEGATIVE_INFINITY);\n        for (let row = 0; row < this.rows; row++) {\n          for (let column = 0; column < this.columns; column++) {\n            if (this.get(row, column) > max[row]) {\n              max[row] = this.get(row, column);\n            }\n          }\n        }\n        return max;\n      }\n      case 'column': {\n        const max = new Array(this.columns).fill(Number.NEGATIVE_INFINITY);\n        for (let row = 0; row < this.rows; row++) {\n          for (let column = 0; column < this.columns; column++) {\n            if (this.get(row, column) > max[column]) {\n              max[column] = this.get(row, column);\n            }\n          }\n        }\n        return max;\n      }\n      case undefined: {\n        let max = this.get(0, 0);\n        for (let row = 0; row < this.rows; row++) {\n          for (let column = 0; column < this.columns; column++) {\n            if (this.get(row, column) > max) {\n              max = this.get(row, column);\n            }\n          }\n        }\n        return max;\n      }\n      default:\n        throw new Error(`invalid option: ${by}`);\n    }\n  }\n\n  maxIndex() {\n    checkNonEmpty(this);\n    let v = this.get(0, 0);\n    let idx = [0, 0];\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        if (this.get(i, j) > v) {\n          v = this.get(i, j);\n          idx[0] = i;\n          idx[1] = j;\n        }\n      }\n    }\n    return idx;\n  }\n\n  min(by) {\n    if (this.isEmpty()) {\n      return NaN;\n    }\n\n    switch (by) {\n      case 'row': {\n        const min = new Array(this.rows).fill(Number.POSITIVE_INFINITY);\n        for (let row = 0; row < this.rows; row++) {\n          for (let column = 0; column < this.columns; column++) {\n            if (this.get(row, column) < min[row]) {\n              min[row] = this.get(row, column);\n            }\n          }\n        }\n        return min;\n      }\n      case 'column': {\n        const min = new Array(this.columns).fill(Number.POSITIVE_INFINITY);\n        for (let row = 0; row < this.rows; row++) {\n          for (let column = 0; column < this.columns; column++) {\n            if (this.get(row, column) < min[column]) {\n              min[column] = this.get(row, column);\n            }\n          }\n        }\n        return min;\n      }\n      case undefined: {\n        let min = this.get(0, 0);\n        for (let row = 0; row < this.rows; row++) {\n          for (let column = 0; column < this.columns; column++) {\n            if (this.get(row, column) < min) {\n              min = this.get(row, column);\n            }\n          }\n        }\n        return min;\n      }\n      default:\n        throw new Error(`invalid option: ${by}`);\n    }\n  }\n\n  minIndex() {\n    checkNonEmpty(this);\n    let v = this.get(0, 0);\n    let idx = [0, 0];\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        if (this.get(i, j) < v) {\n          v = this.get(i, j);\n          idx[0] = i;\n          idx[1] = j;\n        }\n      }\n    }\n    return idx;\n  }\n\n  maxRow(row) {\n    checkRowIndex(this, row);\n    if (this.isEmpty()) {\n      return NaN;\n    }\n    let v = this.get(row, 0);\n    for (let i = 1; i < this.columns; i++) {\n      if (this.get(row, i) > v) {\n        v = this.get(row, i);\n      }\n    }\n    return v;\n  }\n\n  maxRowIndex(row) {\n    checkRowIndex(this, row);\n    checkNonEmpty(this);\n    let v = this.get(row, 0);\n    let idx = [row, 0];\n    for (let i = 1; i < this.columns; i++) {\n      if (this.get(row, i) > v) {\n        v = this.get(row, i);\n        idx[1] = i;\n      }\n    }\n    return idx;\n  }\n\n  minRow(row) {\n    checkRowIndex(this, row);\n    if (this.isEmpty()) {\n      return NaN;\n    }\n    let v = this.get(row, 0);\n    for (let i = 1; i < this.columns; i++) {\n      if (this.get(row, i) < v) {\n        v = this.get(row, i);\n      }\n    }\n    return v;\n  }\n\n  minRowIndex(row) {\n    checkRowIndex(this, row);\n    checkNonEmpty(this);\n    let v = this.get(row, 0);\n    let idx = [row, 0];\n    for (let i = 1; i < this.columns; i++) {\n      if (this.get(row, i) < v) {\n        v = this.get(row, i);\n        idx[1] = i;\n      }\n    }\n    return idx;\n  }\n\n  maxColumn(column) {\n    checkColumnIndex(this, column);\n    if (this.isEmpty()) {\n      return NaN;\n    }\n    let v = this.get(0, column);\n    for (let i = 1; i < this.rows; i++) {\n      if (this.get(i, column) > v) {\n        v = this.get(i, column);\n      }\n    }\n    return v;\n  }\n\n  maxColumnIndex(column) {\n    checkColumnIndex(this, column);\n    checkNonEmpty(this);\n    let v = this.get(0, column);\n    let idx = [0, column];\n    for (let i = 1; i < this.rows; i++) {\n      if (this.get(i, column) > v) {\n        v = this.get(i, column);\n        idx[0] = i;\n      }\n    }\n    return idx;\n  }\n\n  minColumn(column) {\n    checkColumnIndex(this, column);\n    if (this.isEmpty()) {\n      return NaN;\n    }\n    let v = this.get(0, column);\n    for (let i = 1; i < this.rows; i++) {\n      if (this.get(i, column) < v) {\n        v = this.get(i, column);\n      }\n    }\n    return v;\n  }\n\n  minColumnIndex(column) {\n    checkColumnIndex(this, column);\n    checkNonEmpty(this);\n    let v = this.get(0, column);\n    let idx = [0, column];\n    for (let i = 1; i < this.rows; i++) {\n      if (this.get(i, column) < v) {\n        v = this.get(i, column);\n        idx[0] = i;\n      }\n    }\n    return idx;\n  }\n\n  diag() {\n    let min = Math.min(this.rows, this.columns);\n    let diag = [];\n    for (let i = 0; i < min; i++) {\n      diag.push(this.get(i, i));\n    }\n    return diag;\n  }\n\n  norm(type = 'frobenius') {\n    let result = 0;\n    if (type === 'max') {\n      return this.max();\n    } else if (type === 'frobenius') {\n      for (let i = 0; i < this.rows; i++) {\n        for (let j = 0; j < this.columns; j++) {\n          result = result + this.get(i, j) * this.get(i, j);\n        }\n      }\n      return Math.sqrt(result);\n    } else {\n      throw new RangeError(`unknown norm type: ${type}`);\n    }\n  }\n\n  cumulativeSum() {\n    let sum = 0;\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        sum += this.get(i, j);\n        this.set(i, j, sum);\n      }\n    }\n    return this;\n  }\n\n  dot(vector2) {\n    if (AbstractMatrix.isMatrix(vector2)) vector2 = vector2.to1DArray();\n    let vector1 = this.to1DArray();\n    if (vector1.length !== vector2.length) {\n      throw new RangeError('vectors do not have the same size');\n    }\n    let dot = 0;\n    for (let i = 0; i < vector1.length; i++) {\n      dot += vector1[i] * vector2[i];\n    }\n    return dot;\n  }\n\n  mmul(other) {\n    other = Matrix.checkMatrix(other);\n\n    let m = this.rows;\n    let n = this.columns;\n    let p = other.columns;\n\n    let result = new Matrix(m, p);\n\n    let Bcolj = new Float64Array(n);\n    for (let j = 0; j < p; j++) {\n      for (let k = 0; k < n; k++) {\n        Bcolj[k] = other.get(k, j);\n      }\n\n      for (let i = 0; i < m; i++) {\n        let s = 0;\n        for (let k = 0; k < n; k++) {\n          s += this.get(i, k) * Bcolj[k];\n        }\n\n        result.set(i, j, s);\n      }\n    }\n    return result;\n  }\n\n  strassen2x2(other) {\n    other = Matrix.checkMatrix(other);\n    let result = new Matrix(2, 2);\n    const a11 = this.get(0, 0);\n    const b11 = other.get(0, 0);\n    const a12 = this.get(0, 1);\n    const b12 = other.get(0, 1);\n    const a21 = this.get(1, 0);\n    const b21 = other.get(1, 0);\n    const a22 = this.get(1, 1);\n    const b22 = other.get(1, 1);\n\n    // Compute intermediate values.\n    const m1 = (a11 + a22) * (b11 + b22);\n    const m2 = (a21 + a22) * b11;\n    const m3 = a11 * (b12 - b22);\n    const m4 = a22 * (b21 - b11);\n    const m5 = (a11 + a12) * b22;\n    const m6 = (a21 - a11) * (b11 + b12);\n    const m7 = (a12 - a22) * (b21 + b22);\n\n    // Combine intermediate values into the output.\n    const c00 = m1 + m4 - m5 + m7;\n    const c01 = m3 + m5;\n    const c10 = m2 + m4;\n    const c11 = m1 - m2 + m3 + m6;\n\n    result.set(0, 0, c00);\n    result.set(0, 1, c01);\n    result.set(1, 0, c10);\n    result.set(1, 1, c11);\n    return result;\n  }\n\n  strassen3x3(other) {\n    other = Matrix.checkMatrix(other);\n    let result = new Matrix(3, 3);\n\n    const a00 = this.get(0, 0);\n    const a01 = this.get(0, 1);\n    const a02 = this.get(0, 2);\n    const a10 = this.get(1, 0);\n    const a11 = this.get(1, 1);\n    const a12 = this.get(1, 2);\n    const a20 = this.get(2, 0);\n    const a21 = this.get(2, 1);\n    const a22 = this.get(2, 2);\n\n    const b00 = other.get(0, 0);\n    const b01 = other.get(0, 1);\n    const b02 = other.get(0, 2);\n    const b10 = other.get(1, 0);\n    const b11 = other.get(1, 1);\n    const b12 = other.get(1, 2);\n    const b20 = other.get(2, 0);\n    const b21 = other.get(2, 1);\n    const b22 = other.get(2, 2);\n\n    const m1 = (a00 + a01 + a02 - a10 - a11 - a21 - a22) * b11;\n    const m2 = (a00 - a10) * (-b01 + b11);\n    const m3 = a11 * (-b00 + b01 + b10 - b11 - b12 - b20 + b22);\n    const m4 = (-a00 + a10 + a11) * (b00 - b01 + b11);\n    const m5 = (a10 + a11) * (-b00 + b01);\n    const m6 = a00 * b00;\n    const m7 = (-a00 + a20 + a21) * (b00 - b02 + b12);\n    const m8 = (-a00 + a20) * (b02 - b12);\n    const m9 = (a20 + a21) * (-b00 + b02);\n    const m10 = (a00 + a01 + a02 - a11 - a12 - a20 - a21) * b12;\n    const m11 = a21 * (-b00 + b02 + b10 - b11 - b12 - b20 + b21);\n    const m12 = (-a02 + a21 + a22) * (b11 + b20 - b21);\n    const m13 = (a02 - a22) * (b11 - b21);\n    const m14 = a02 * b20;\n    const m15 = (a21 + a22) * (-b20 + b21);\n    const m16 = (-a02 + a11 + a12) * (b12 + b20 - b22);\n    const m17 = (a02 - a12) * (b12 - b22);\n    const m18 = (a11 + a12) * (-b20 + b22);\n    const m19 = a01 * b10;\n    const m20 = a12 * b21;\n    const m21 = a10 * b02;\n    const m22 = a20 * b01;\n    const m23 = a22 * b22;\n\n    const c00 = m6 + m14 + m19;\n    const c01 = m1 + m4 + m5 + m6 + m12 + m14 + m15;\n    const c02 = m6 + m7 + m9 + m10 + m14 + m16 + m18;\n    const c10 = m2 + m3 + m4 + m6 + m14 + m16 + m17;\n    const c11 = m2 + m4 + m5 + m6 + m20;\n    const c12 = m14 + m16 + m17 + m18 + m21;\n    const c20 = m6 + m7 + m8 + m11 + m12 + m13 + m14;\n    const c21 = m12 + m13 + m14 + m15 + m22;\n    const c22 = m6 + m7 + m8 + m9 + m23;\n\n    result.set(0, 0, c00);\n    result.set(0, 1, c01);\n    result.set(0, 2, c02);\n    result.set(1, 0, c10);\n    result.set(1, 1, c11);\n    result.set(1, 2, c12);\n    result.set(2, 0, c20);\n    result.set(2, 1, c21);\n    result.set(2, 2, c22);\n    return result;\n  }\n\n  mmulStrassen(y) {\n    y = Matrix.checkMatrix(y);\n    let x = this.clone();\n    let r1 = x.rows;\n    let c1 = x.columns;\n    let r2 = y.rows;\n    let c2 = y.columns;\n    if (c1 !== r2) {\n      // eslint-disable-next-line no-console\n      console.warn(\n        `Multiplying ${r1} x ${c1} and ${r2} x ${c2} matrix: dimensions do not match.`,\n      );\n    }\n\n    // Put a matrix into the top left of a matrix of zeros.\n    // `rows` and `cols` are the dimensions of the output matrix.\n    function embed(mat, rows, cols) {\n      let r = mat.rows;\n      let c = mat.columns;\n      if (r === rows && c === cols) {\n        return mat;\n      } else {\n        let resultat = AbstractMatrix.zeros(rows, cols);\n        resultat = resultat.setSubMatrix(mat, 0, 0);\n        return resultat;\n      }\n    }\n\n    // Make sure both matrices are the same size.\n    // This is exclusively for simplicity:\n    // this algorithm can be implemented with matrices of different sizes.\n\n    let r = Math.max(r1, r2);\n    let c = Math.max(c1, c2);\n    x = embed(x, r, c);\n    y = embed(y, r, c);\n\n    // Our recursive multiplication function.\n    function blockMult(a, b, rows, cols) {\n      // For small matrices, resort to naive multiplication.\n      if (rows <= 512 || cols <= 512) {\n        return a.mmul(b); // a is equivalent to this\n      }\n\n      // Apply dynamic padding.\n      if (rows % 2 === 1 && cols % 2 === 1) {\n        a = embed(a, rows + 1, cols + 1);\n        b = embed(b, rows + 1, cols + 1);\n      } else if (rows % 2 === 1) {\n        a = embed(a, rows + 1, cols);\n        b = embed(b, rows + 1, cols);\n      } else if (cols % 2 === 1) {\n        a = embed(a, rows, cols + 1);\n        b = embed(b, rows, cols + 1);\n      }\n\n      let halfRows = parseInt(a.rows / 2, 10);\n      let halfCols = parseInt(a.columns / 2, 10);\n      // Subdivide input matrices.\n      let a11 = a.subMatrix(0, halfRows - 1, 0, halfCols - 1);\n      let b11 = b.subMatrix(0, halfRows - 1, 0, halfCols - 1);\n\n      let a12 = a.subMatrix(0, halfRows - 1, halfCols, a.columns - 1);\n      let b12 = b.subMatrix(0, halfRows - 1, halfCols, b.columns - 1);\n\n      let a21 = a.subMatrix(halfRows, a.rows - 1, 0, halfCols - 1);\n      let b21 = b.subMatrix(halfRows, b.rows - 1, 0, halfCols - 1);\n\n      let a22 = a.subMatrix(halfRows, a.rows - 1, halfCols, a.columns - 1);\n      let b22 = b.subMatrix(halfRows, b.rows - 1, halfCols, b.columns - 1);\n\n      // Compute intermediate values.\n      let m1 = blockMult(\n        AbstractMatrix.add(a11, a22),\n        AbstractMatrix.add(b11, b22),\n        halfRows,\n        halfCols,\n      );\n      let m2 = blockMult(AbstractMatrix.add(a21, a22), b11, halfRows, halfCols);\n      let m3 = blockMult(a11, AbstractMatrix.sub(b12, b22), halfRows, halfCols);\n      let m4 = blockMult(a22, AbstractMatrix.sub(b21, b11), halfRows, halfCols);\n      let m5 = blockMult(AbstractMatrix.add(a11, a12), b22, halfRows, halfCols);\n      let m6 = blockMult(\n        AbstractMatrix.sub(a21, a11),\n        AbstractMatrix.add(b11, b12),\n        halfRows,\n        halfCols,\n      );\n      let m7 = blockMult(\n        AbstractMatrix.sub(a12, a22),\n        AbstractMatrix.add(b21, b22),\n        halfRows,\n        halfCols,\n      );\n\n      // Combine intermediate values into the output.\n      let c11 = AbstractMatrix.add(m1, m4);\n      c11.sub(m5);\n      c11.add(m7);\n      let c12 = AbstractMatrix.add(m3, m5);\n      let c21 = AbstractMatrix.add(m2, m4);\n      let c22 = AbstractMatrix.sub(m1, m2);\n      c22.add(m3);\n      c22.add(m6);\n\n      // Crop output to the desired size (undo dynamic padding).\n      let resultat = AbstractMatrix.zeros(2 * c11.rows, 2 * c11.columns);\n      resultat = resultat.setSubMatrix(c11, 0, 0);\n      resultat = resultat.setSubMatrix(c12, c11.rows, 0);\n      resultat = resultat.setSubMatrix(c21, 0, c11.columns);\n      resultat = resultat.setSubMatrix(c22, c11.rows, c11.columns);\n      return resultat.subMatrix(0, rows - 1, 0, cols - 1);\n    }\n\n    return blockMult(x, y, r, c);\n  }\n\n  scaleRows(options = {}) {\n    if (typeof options !== 'object') {\n      throw new TypeError('options must be an object');\n    }\n    const { min = 0, max = 1 } = options;\n    if (!Number.isFinite(min)) throw new TypeError('min must be a number');\n    if (!Number.isFinite(max)) throw new TypeError('max must be a number');\n    if (min >= max) throw new RangeError('min must be smaller than max');\n    let newMatrix = new Matrix(this.rows, this.columns);\n    for (let i = 0; i < this.rows; i++) {\n      const row = this.getRow(i);\n      if (row.length > 0) {\n        rescale(row, { min, max, output: row });\n      }\n      newMatrix.setRow(i, row);\n    }\n    return newMatrix;\n  }\n\n  scaleColumns(options = {}) {\n    if (typeof options !== 'object') {\n      throw new TypeError('options must be an object');\n    }\n    const { min = 0, max = 1 } = options;\n    if (!Number.isFinite(min)) throw new TypeError('min must be a number');\n    if (!Number.isFinite(max)) throw new TypeError('max must be a number');\n    if (min >= max) throw new RangeError('min must be smaller than max');\n    let newMatrix = new Matrix(this.rows, this.columns);\n    for (let i = 0; i < this.columns; i++) {\n      const column = this.getColumn(i);\n      if (column.length) {\n        rescale(column, {\n          min: min,\n          max: max,\n          output: column,\n        });\n      }\n      newMatrix.setColumn(i, column);\n    }\n    return newMatrix;\n  }\n\n  flipRows() {\n    const middle = Math.ceil(this.columns / 2);\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < middle; j++) {\n        let first = this.get(i, j);\n        let last = this.get(i, this.columns - 1 - j);\n        this.set(i, j, last);\n        this.set(i, this.columns - 1 - j, first);\n      }\n    }\n    return this;\n  }\n\n  flipColumns() {\n    const middle = Math.ceil(this.rows / 2);\n    for (let j = 0; j < this.columns; j++) {\n      for (let i = 0; i < middle; i++) {\n        let first = this.get(i, j);\n        let last = this.get(this.rows - 1 - i, j);\n        this.set(i, j, last);\n        this.set(this.rows - 1 - i, j, first);\n      }\n    }\n    return this;\n  }\n\n  kroneckerProduct(other) {\n    other = Matrix.checkMatrix(other);\n\n    let m = this.rows;\n    let n = this.columns;\n    let p = other.rows;\n    let q = other.columns;\n\n    let result = new Matrix(m * p, n * q);\n    for (let i = 0; i < m; i++) {\n      for (let j = 0; j < n; j++) {\n        for (let k = 0; k < p; k++) {\n          for (let l = 0; l < q; l++) {\n            result.set(p * i + k, q * j + l, this.get(i, j) * other.get(k, l));\n          }\n        }\n      }\n    }\n    return result;\n  }\n\n  kroneckerSum(other) {\n    other = Matrix.checkMatrix(other);\n    if (!this.isSquare() || !other.isSquare()) {\n      throw new Error('Kronecker Sum needs two Square Matrices');\n    }\n    let m = this.rows;\n    let n = other.rows;\n    let AxI = this.kroneckerProduct(Matrix.eye(n, n));\n    let IxB = Matrix.eye(m, m).kroneckerProduct(other);\n    return AxI.add(IxB);\n  }\n\n  transpose() {\n    let result = new Matrix(this.columns, this.rows);\n    for (let i = 0; i < this.rows; i++) {\n      for (let j = 0; j < this.columns; j++) {\n        result.set(j, i, this.get(i, j));\n      }\n    }\n    return result;\n  }\n\n  sortRows(compareFunction = compareNumbers) {\n    for (let i = 0; i < this.rows; i++) {\n      this.setRow(i, this.getRow(i).sort(compareFunction));\n    }\n    return this;\n  }\n\n  sortColumns(compareFunction = compareNumbers) {\n    for (let i = 0; i < this.columns; i++) {\n      this.setColumn(i, this.getColumn(i).sort(compareFunction));\n    }\n    return this;\n  }\n\n  subMatrix(startRow, endRow, startColumn, endColumn) {\n    checkRange(this, startRow, endRow, startColumn, endColumn);\n    let newMatrix = new Matrix(\n      endRow - startRow + 1,\n      endColumn - startColumn + 1,\n    );\n    for (let i = startRow; i <= endRow; i++) {\n      for (let j = startColumn; j <= endColumn; j++) {\n        newMatrix.set(i - startRow, j - startColumn, this.get(i, j));\n      }\n    }\n    return newMatrix;\n  }\n\n  subMatrixRow(indices, startColumn, endColumn) {\n    if (startColumn === undefined) startColumn = 0;\n    if (endColumn === undefined) endColumn = this.columns - 1;\n    if (\n      startColumn > endColumn ||\n      startColumn < 0 ||\n      startColumn >= this.columns ||\n      endColumn < 0 ||\n      endColumn >= this.columns\n    ) {\n      throw new RangeError('Argument out of range');\n    }\n\n    let newMatrix = new Matrix(indices.length, endColumn - startColumn + 1);\n    for (let i = 0; i < indices.length; i++) {\n      for (let j = startColumn; j <= endColumn; j++) {\n        if (indices[i] < 0 || indices[i] >= this.rows) {\n          throw new RangeError(`Row index out of range: ${indices[i]}`);\n        }\n        newMatrix.set(i, j - startColumn, this.get(indices[i], j));\n      }\n    }\n    return newMatrix;\n  }\n\n  subMatrixColumn(indices, startRow, endRow) {\n    if (startRow === undefined) startRow = 0;\n    if (endRow === undefined) endRow = this.rows - 1;\n    if (\n      startRow > endRow ||\n      startRow < 0 ||\n      startRow >= this.rows ||\n      endRow < 0 ||\n      endRow >= this.rows\n    ) {\n      throw new RangeError('Argument out of range');\n    }\n\n    let newMatrix = new Matrix(endRow - startRow + 1, indices.length);\n    for (let i = 0; i < indices.length; i++) {\n      for (let j = startRow; j <= endRow; j++) {\n        if (indices[i] < 0 || indices[i] >= this.columns) {\n          throw new RangeError(`Column index out of range: ${indices[i]}`);\n        }\n        newMatrix.set(j - startRow, i, this.get(j, indices[i]));\n      }\n    }\n    return newMatrix;\n  }\n\n  setSubMatrix(matrix, startRow, startColumn) {\n    matrix = Matrix.checkMatrix(matrix);\n    if (matrix.isEmpty()) {\n      return this;\n    }\n    let endRow = startRow + matrix.rows - 1;\n    let endColumn = startColumn + matrix.columns - 1;\n    checkRange(this, startRow, endRow, startColumn, endColumn);\n    for (let i = 0; i < matrix.rows; i++) {\n      for (let j = 0; j < matrix.columns; j++) {\n        this.set(startRow + i, startColumn + j, matrix.get(i, j));\n      }\n    }\n    return this;\n  }\n\n  selection(rowIndices, columnIndices) {\n    checkRowIndices(this, rowIndices);\n    checkColumnIndices(this, columnIndices);\n    let newMatrix = new Matrix(rowIndices.length, columnIndices.length);\n    for (let i = 0; i < rowIndices.length; i++) {\n      let rowIndex = rowIndices[i];\n      for (let j = 0; j < columnIndices.length; j++) {\n        let columnIndex = columnIndices[j];\n        newMatrix.set(i, j, this.get(rowIndex, columnIndex));\n      }\n    }\n    return newMatrix;\n  }\n\n  trace() {\n    let min = Math.min(this.rows, this.columns);\n    let trace = 0;\n    for (let i = 0; i < min; i++) {\n      trace += this.get(i, i);\n    }\n    return trace;\n  }\n\n  clone() {\n    let newMatrix = new Matrix(this.rows, this.columns);\n    for (let row = 0; row < this.rows; row++) {\n      for (let column = 0; column < this.columns; column++) {\n        newMatrix.set(row, column, this.get(row, column));\n      }\n    }\n    return newMatrix;\n  }\n\n  sum(by) {\n    switch (by) {\n      case 'row':\n        return sumByRow(this);\n      case 'column':\n        return sumByColumn(this);\n      case undefined:\n        return sumAll(this);\n      default:\n        throw new Error(`invalid option: ${by}`);\n    }\n  }\n\n  product(by) {\n    switch (by) {\n      case 'row':\n        return productByRow(this);\n      case 'column':\n        return productByColumn(this);\n      case undefined:\n        return productAll(this);\n      default:\n        throw new Error(`invalid option: ${by}`);\n    }\n  }\n\n  mean(by) {\n    const sum = this.sum(by);\n    switch (by) {\n      case 'row': {\n        for (let i = 0; i < this.rows; i++) {\n          sum[i] /= this.columns;\n        }\n        return sum;\n      }\n      case 'column': {\n        for (let i = 0; i < this.columns; i++) {\n          sum[i] /= this.rows;\n        }\n        return sum;\n      }\n      case undefined:\n        return sum / this.size;\n      default:\n        throw new Error(`invalid option: ${by}`);\n    }\n  }\n\n  variance(by, options = {}) {\n    if (typeof by === 'object') {\n      options = by;\n      by = undefined;\n    }\n    if (typeof options !== 'object') {\n      throw new TypeError('options must be an object');\n    }\n    const { unbiased = true, mean = this.mean(by) } = options;\n    if (typeof unbiased !== 'boolean') {\n      throw new TypeError('unbiased must be a boolean');\n    }\n    switch (by) {\n      case 'row': {\n        if (!isAnyArray(mean)) {\n          throw new TypeError('mean must be an array');\n        }\n        return varianceByRow(this, unbiased, mean);\n      }\n      case 'column': {\n        if (!isAnyArray(mean)) {\n          throw new TypeError('mean must be an array');\n        }\n        return varianceByColumn(this, unbiased, mean);\n      }\n      case undefined: {\n        if (typeof mean !== 'number') {\n          throw new TypeError('mean must be a number');\n        }\n        return varianceAll(this, unbiased, mean);\n      }\n      default:\n        throw new Error(`invalid option: ${by}`);\n    }\n  }\n\n  standardDeviation(by, options) {\n    if (typeof by === 'object') {\n      options = by;\n      by = undefined;\n    }\n    const variance = this.variance(by, options);\n    if (by === undefined) {\n      return Math.sqrt(variance);\n    } else {\n      for (let i = 0; i < variance.length; i++) {\n        variance[i] = Math.sqrt(variance[i]);\n      }\n      return variance;\n    }\n  }\n\n  center(by, options = {}) {\n    if (typeof by === 'object') {\n      options = by;\n      by = undefined;\n    }\n    if (typeof options !== 'object') {\n      throw new TypeError('options must be an object');\n    }\n    const { center = this.mean(by) } = options;\n    switch (by) {\n      case 'row': {\n        if (!isAnyArray(center)) {\n          throw new TypeError('center must be an array');\n        }\n        centerByRow(this, center);\n        return this;\n      }\n      case 'column': {\n        if (!isAnyArray(center)) {\n          throw new TypeError('center must be an array');\n        }\n        centerByColumn(this, center);\n        return this;\n      }\n      case undefined: {\n        if (typeof center !== 'number') {\n          throw new TypeError('center must be a number');\n        }\n        centerAll(this, center);\n        return this;\n      }\n      default:\n        throw new Error(`invalid option: ${by}`);\n    }\n  }\n\n  scale(by, options = {}) {\n    if (typeof by === 'object') {\n      options = by;\n      by = undefined;\n    }\n    if (typeof options !== 'object') {\n      throw new TypeError('options must be an object');\n    }\n    let scale = options.scale;\n    switch (by) {\n      case 'row': {\n        if (scale === undefined) {\n          scale = getScaleByRow(this);\n        } else if (!isAnyArray(scale)) {\n          throw new TypeError('scale must be an array');\n        }\n        scaleByRow(this, scale);\n        return this;\n      }\n      case 'column': {\n        if (scale === undefined) {\n          scale = getScaleByColumn(this);\n        } else if (!isAnyArray(scale)) {\n          throw new TypeError('scale must be an array');\n        }\n        scaleByColumn(this, scale);\n        return this;\n      }\n      case undefined: {\n        if (scale === undefined) {\n          scale = getScaleAll(this);\n        } else if (typeof scale !== 'number') {\n          throw new TypeError('scale must be a number');\n        }\n        scaleAll(this, scale);\n        return this;\n      }\n      default:\n        throw new Error(`invalid option: ${by}`);\n    }\n  }\n\n  toString(options) {\n    return inspectMatrixWithOptions(this, options);\n  }\n}\n\nAbstractMatrix.prototype.klass = 'Matrix';\nif (typeof Symbol !== 'undefined') {\n  AbstractMatrix.prototype[Symbol.for('nodejs.util.inspect.custom')] =\n    inspectMatrix;\n}\n\nfunction compareNumbers(a, b) {\n  return a - b;\n}\n\nfunction isArrayOfNumbers(array) {\n  return array.every((element) => {\n    return typeof element === 'number';\n  });\n}\n\n// Synonyms\nAbstractMatrix.random = AbstractMatrix.rand;\nAbstractMatrix.randomInt = AbstractMatrix.randInt;\nAbstractMatrix.diagonal = AbstractMatrix.diag;\nAbstractMatrix.prototype.diagonal = AbstractMatrix.prototype.diag;\nAbstractMatrix.identity = AbstractMatrix.eye;\nAbstractMatrix.prototype.negate = AbstractMatrix.prototype.neg;\nAbstractMatrix.prototype.tensorProduct =\n  AbstractMatrix.prototype.kroneckerProduct;\n\nexport default class Matrix extends AbstractMatrix {\n  constructor(nRows, nColumns) {\n    super();\n    if (Matrix.isMatrix(nRows)) {\n      // eslint-disable-next-line no-constructor-return\n      return nRows.clone();\n    } else if (Number.isInteger(nRows) && nRows >= 0) {\n      // Create an empty matrix\n      this.data = [];\n      if (Number.isInteger(nColumns) && nColumns >= 0) {\n        for (let i = 0; i < nRows; i++) {\n          this.data.push(new Float64Array(nColumns));\n        }\n      } else {\n        throw new TypeError('nColumns must be a positive integer');\n      }\n    } else if (isAnyArray(nRows)) {\n      // Copy the values from the 2D array\n      const arrayData = nRows;\n      nRows = arrayData.length;\n      nColumns = nRows ? arrayData[0].length : 0;\n      if (typeof nColumns !== 'number') {\n        throw new TypeError(\n          'Data must be a 2D array with at least one element',\n        );\n      }\n      this.data = [];\n      for (let i = 0; i < nRows; i++) {\n        if (arrayData[i].length !== nColumns) {\n          throw new RangeError('Inconsistent array dimensions');\n        }\n        if (!isArrayOfNumbers(arrayData[i])) {\n          throw new TypeError('Input data contains non-numeric values');\n        }\n        this.data.push(Float64Array.from(arrayData[i]));\n      }\n    } else {\n      throw new TypeError(\n        'First argument must be a positive number or an array',\n      );\n    }\n    this.rows = nRows;\n    this.columns = nColumns;\n  }\n\n  set(rowIndex, columnIndex, value) {\n    this.data[rowIndex][columnIndex] = value;\n    return this;\n  }\n\n  get(rowIndex, columnIndex) {\n    return this.data[rowIndex][columnIndex];\n  }\n\n  removeRow(index) {\n    checkRowIndex(this, index);\n    this.data.splice(index, 1);\n    this.rows -= 1;\n    return this;\n  }\n\n  addRow(index, array) {\n    if (array === undefined) {\n      array = index;\n      index = this.rows;\n    }\n    checkRowIndex(this, index, true);\n    array = Float64Array.from(checkRowVector(this, array));\n    this.data.splice(index, 0, array);\n    this.rows += 1;\n    return this;\n  }\n\n  removeColumn(index) {\n    checkColumnIndex(this, index);\n    for (let i = 0; i < this.rows; i++) {\n      const newRow = new Float64Array(this.columns - 1);\n      for (let j = 0; j < index; j++) {\n        newRow[j] = this.data[i][j];\n      }\n      for (let j = index + 1; j < this.columns; j++) {\n        newRow[j - 1] = this.data[i][j];\n      }\n      this.data[i] = newRow;\n    }\n    this.columns -= 1;\n    return this;\n  }\n\n  addColumn(index, array) {\n    if (typeof array === 'undefined') {\n      array = index;\n      index = this.columns;\n    }\n    checkColumnIndex(this, index, true);\n    array = checkColumnVector(this, array);\n    for (let i = 0; i < this.rows; i++) {\n      const newRow = new Float64Array(this.columns + 1);\n      let j = 0;\n      for (; j < index; j++) {\n        newRow[j] = this.data[i][j];\n      }\n      newRow[j++] = array[i];\n      for (; j < this.columns + 1; j++) {\n        newRow[j] = this.data[i][j - 1];\n      }\n      this.data[i] = newRow;\n    }\n    this.columns += 1;\n    return this;\n  }\n}\n\ninstallMathOperations(AbstractMatrix, Matrix);\n","import { AbstractMatrix } from '../matrix';\n\nexport default class WrapperMatrix2D extends AbstractMatrix {\n  constructor(data) {\n    super();\n    this.data = data;\n    this.rows = data.length;\n    this.columns = data[0].length;\n  }\n\n  set(rowIndex, columnIndex, value) {\n    this.data[rowIndex][columnIndex] = value;\n    return this;\n  }\n\n  get(rowIndex, columnIndex) {\n    return this.data[rowIndex][columnIndex];\n  }\n}\n","import Matrix from '../matrix';\nimport WrapperMatrix2D from '../wrap/WrapperMatrix2D';\n\nexport default class LuDecomposition {\n  constructor(matrix) {\n    matrix = WrapperMatrix2D.checkMatrix(matrix);\n\n    let lu = matrix.clone();\n    let rows = lu.rows;\n    let columns = lu.columns;\n    let pivotVector = new Float64Array(rows);\n    let pivotSign = 1;\n    let i, j, k, p, s, t, v;\n    let LUcolj, kmax;\n\n    for (i = 0; i < rows; i++) {\n      pivotVector[i] = i;\n    }\n\n    LUcolj = new Float64Array(rows);\n\n    for (j = 0; j < columns; j++) {\n      for (i = 0; i < rows; i++) {\n        LUcolj[i] = lu.get(i, j);\n      }\n\n      for (i = 0; i < rows; i++) {\n        kmax = Math.min(i, j);\n        s = 0;\n        for (k = 0; k < kmax; k++) {\n          s += lu.get(i, k) * LUcolj[k];\n        }\n        LUcolj[i] -= s;\n        lu.set(i, j, LUcolj[i]);\n      }\n\n      p = j;\n      for (i = j + 1; i < rows; i++) {\n        if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p])) {\n          p = i;\n        }\n      }\n\n      if (p !== j) {\n        for (k = 0; k < columns; k++) {\n          t = lu.get(p, k);\n          lu.set(p, k, lu.get(j, k));\n          lu.set(j, k, t);\n        }\n\n        v = pivotVector[p];\n        pivotVector[p] = pivotVector[j];\n        pivotVector[j] = v;\n\n        pivotSign = -pivotSign;\n      }\n\n      if (j < rows && lu.get(j, j) !== 0) {\n        for (i = j + 1; i < rows; i++) {\n          lu.set(i, j, lu.get(i, j) / lu.get(j, j));\n        }\n      }\n    }\n\n    this.LU = lu;\n    this.pivotVector = pivotVector;\n    this.pivotSign = pivotSign;\n  }\n\n  isSingular() {\n    let data = this.LU;\n    let col = data.columns;\n    for (let j = 0; j < col; j++) {\n      if (data.get(j, j) === 0) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  solve(value) {\n    value = Matrix.checkMatrix(value);\n\n    let lu = this.LU;\n    let rows = lu.rows;\n\n    if (rows !== value.rows) {\n      throw new Error('Invalid matrix dimensions');\n    }\n    if (this.isSingular()) {\n      throw new Error('LU matrix is singular');\n    }\n\n    let count = value.columns;\n    let X = value.subMatrixRow(this.pivotVector, 0, count - 1);\n    let columns = lu.columns;\n    let i, j, k;\n\n    for (k = 0; k < columns; k++) {\n      for (i = k + 1; i < columns; i++) {\n        for (j = 0; j < count; j++) {\n          X.set(i, j, X.get(i, j) - X.get(k, j) * lu.get(i, k));\n        }\n      }\n    }\n    for (k = columns - 1; k >= 0; k--) {\n      for (j = 0; j < count; j++) {\n        X.set(k, j, X.get(k, j) / lu.get(k, k));\n      }\n      for (i = 0; i < k; i++) {\n        for (j = 0; j < count; j++) {\n          X.set(i, j, X.get(i, j) - X.get(k, j) * lu.get(i, k));\n        }\n      }\n    }\n    return X;\n  }\n\n  get determinant() {\n    let data = this.LU;\n    if (!data.isSquare()) {\n      throw new Error('Matrix must be square');\n    }\n    let determinant = this.pivotSign;\n    let col = data.columns;\n    for (let j = 0; j < col; j++) {\n      determinant *= data.get(j, j);\n    }\n    return determinant;\n  }\n\n  get lowerTriangularMatrix() {\n    let data = this.LU;\n    let rows = data.rows;\n    let columns = data.columns;\n    let X = new Matrix(rows, columns);\n    for (let i = 0; i < rows; i++) {\n      for (let j = 0; j < columns; j++) {\n        if (i > j) {\n          X.set(i, j, data.get(i, j));\n        } else if (i === j) {\n          X.set(i, j, 1);\n        } else {\n          X.set(i, j, 0);\n        }\n      }\n    }\n    return X;\n  }\n\n  get upperTriangularMatrix() {\n    let data = this.LU;\n    let rows = data.rows;\n    let columns = data.columns;\n    let X = new Matrix(rows, columns);\n    for (let i = 0; i < rows; i++) {\n      for (let j = 0; j < columns; j++) {\n        if (i <= j) {\n          X.set(i, j, data.get(i, j));\n        } else {\n          X.set(i, j, 0);\n        }\n      }\n    }\n    return X;\n  }\n\n  get pivotPermutationVector() {\n    return Array.from(this.pivotVector);\n  }\n}\n","export function hypotenuse(a, b) {\n  let r = 0;\n  if (Math.abs(a) > Math.abs(b)) {\n    r = b / a;\n    return Math.abs(a) * Math.sqrt(1 + r * r);\n  }\n  if (b !== 0) {\n    r = a / b;\n    return Math.abs(b) * Math.sqrt(1 + r * r);\n  }\n  return 0;\n}\n","import Matrix from '../matrix';\nimport WrapperMatrix2D from '../wrap/WrapperMatrix2D';\n\nimport { hypotenuse } from './util';\n\nexport default class QrDecomposition {\n  constructor(value) {\n    value = WrapperMatrix2D.checkMatrix(value);\n\n    let qr = value.clone();\n    let m = value.rows;\n    let n = value.columns;\n    let rdiag = new Float64Array(n);\n    let i, j, k, s;\n\n    for (k = 0; k < n; k++) {\n      let nrm = 0;\n      for (i = k; i < m; i++) {\n        nrm = hypotenuse(nrm, qr.get(i, k));\n      }\n      if (nrm !== 0) {\n        if (qr.get(k, k) < 0) {\n          nrm = -nrm;\n        }\n        for (i = k; i < m; i++) {\n          qr.set(i, k, qr.get(i, k) / nrm);\n        }\n        qr.set(k, k, qr.get(k, k) + 1);\n        for (j = k + 1; j < n; j++) {\n          s = 0;\n          for (i = k; i < m; i++) {\n            s += qr.get(i, k) * qr.get(i, j);\n          }\n          s = -s / qr.get(k, k);\n          for (i = k; i < m; i++) {\n            qr.set(i, j, qr.get(i, j) + s * qr.get(i, k));\n          }\n        }\n      }\n      rdiag[k] = -nrm;\n    }\n\n    this.QR = qr;\n    this.Rdiag = rdiag;\n  }\n\n  solve(value) {\n    value = Matrix.checkMatrix(value);\n\n    let qr = this.QR;\n    let m = qr.rows;\n\n    if (value.rows !== m) {\n      throw new Error('Matrix row dimensions must agree');\n    }\n    if (!this.isFullRank()) {\n      throw new Error('Matrix is rank deficient');\n    }\n\n    let count = value.columns;\n    let X = value.clone();\n    let n = qr.columns;\n    let i, j, k, s;\n\n    for (k = 0; k < n; k++) {\n      for (j = 0; j < count; j++) {\n        s = 0;\n        for (i = k; i < m; i++) {\n          s += qr.get(i, k) * X.get(i, j);\n        }\n        s = -s / qr.get(k, k);\n        for (i = k; i < m; i++) {\n          X.set(i, j, X.get(i, j) + s * qr.get(i, k));\n        }\n      }\n    }\n    for (k = n - 1; k >= 0; k--) {\n      for (j = 0; j < count; j++) {\n        X.set(k, j, X.get(k, j) / this.Rdiag[k]);\n      }\n      for (i = 0; i < k; i++) {\n        for (j = 0; j < count; j++) {\n          X.set(i, j, X.get(i, j) - X.get(k, j) * qr.get(i, k));\n        }\n      }\n    }\n\n    return X.subMatrix(0, n - 1, 0, count - 1);\n  }\n\n  isFullRank() {\n    let columns = this.QR.columns;\n    for (let i = 0; i < columns; i++) {\n      if (this.Rdiag[i] === 0) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  get upperTriangularMatrix() {\n    let qr = this.QR;\n    let n = qr.columns;\n    let X = new Matrix(n, n);\n    let i, j;\n    for (i = 0; i < n; i++) {\n      for (j = 0; j < n; j++) {\n        if (i < j) {\n          X.set(i, j, qr.get(i, j));\n        } else if (i === j) {\n          X.set(i, j, this.Rdiag[i]);\n        } else {\n          X.set(i, j, 0);\n        }\n      }\n    }\n    return X;\n  }\n\n  get orthogonalMatrix() {\n    let qr = this.QR;\n    let rows = qr.rows;\n    let columns = qr.columns;\n    let X = new Matrix(rows, columns);\n    let i, j, k, s;\n\n    for (k = columns - 1; k >= 0; k--) {\n      for (i = 0; i < rows; i++) {\n        X.set(i, k, 0);\n      }\n      X.set(k, k, 1);\n      for (j = k; j < columns; j++) {\n        if (qr.get(k, k) !== 0) {\n          s = 0;\n          for (i = k; i < rows; i++) {\n            s += qr.get(i, k) * X.get(i, j);\n          }\n\n          s = -s / qr.get(k, k);\n\n          for (i = k; i < rows; i++) {\n            X.set(i, j, X.get(i, j) + s * qr.get(i, k));\n          }\n        }\n      }\n    }\n    return X;\n  }\n}\n","import Matrix from '../matrix';\nimport WrapperMatrix2D from '../wrap/WrapperMatrix2D';\n\nimport { hypotenuse } from './util';\n\nexport default class SingularValueDecomposition {\n  constructor(value, options = {}) {\n    value = WrapperMatrix2D.checkMatrix(value);\n\n    if (value.isEmpty()) {\n      throw new Error('Matrix must be non-empty');\n    }\n\n    let m = value.rows;\n    let n = value.columns;\n\n    const {\n      computeLeftSingularVectors = true,\n      computeRightSingularVectors = true,\n      autoTranspose = false,\n    } = options;\n\n    let wantu = Boolean(computeLeftSingularVectors);\n    let wantv = Boolean(computeRightSingularVectors);\n\n    let swapped = false;\n    let a;\n    if (m < n) {\n      if (!autoTranspose) {\n        a = value.clone();\n        // eslint-disable-next-line no-console\n        console.warn(\n          'Computing SVD on a matrix with more columns than rows. Consider enabling autoTranspose',\n        );\n      } else {\n        a = value.transpose();\n        m = a.rows;\n        n = a.columns;\n        swapped = true;\n        let aux = wantu;\n        wantu = wantv;\n        wantv = aux;\n      }\n    } else {\n      a = value.clone();\n    }\n\n    let nu = Math.min(m, n);\n    let ni = Math.min(m + 1, n);\n    let s = new Float64Array(ni);\n    let U = new Matrix(m, nu);\n    let V = new Matrix(n, n);\n\n    let e = new Float64Array(n);\n    let work = new Float64Array(m);\n\n    let si = new Float64Array(ni);\n    for (let i = 0; i < ni; i++) si[i] = i;\n\n    let nct = Math.min(m - 1, n);\n    let nrt = Math.max(0, Math.min(n - 2, m));\n    let mrc = Math.max(nct, nrt);\n\n    for (let k = 0; k < mrc; k++) {\n      if (k < nct) {\n        s[k] = 0;\n        for (let i = k; i < m; i++) {\n          s[k] = hypotenuse(s[k], a.get(i, k));\n        }\n        if (s[k] !== 0) {\n          if (a.get(k, k) < 0) {\n            s[k] = -s[k];\n          }\n          for (let i = k; i < m; i++) {\n            a.set(i, k, a.get(i, k) / s[k]);\n          }\n          a.set(k, k, a.get(k, k) + 1);\n        }\n        s[k] = -s[k];\n      }\n\n      for (let j = k + 1; j < n; j++) {\n        if (k < nct && s[k] !== 0) {\n          let t = 0;\n          for (let i = k; i < m; i++) {\n            t += a.get(i, k) * a.get(i, j);\n          }\n          t = -t / a.get(k, k);\n          for (let i = k; i < m; i++) {\n            a.set(i, j, a.get(i, j) + t * a.get(i, k));\n          }\n        }\n        e[j] = a.get(k, j);\n      }\n\n      if (wantu && k < nct) {\n        for (let i = k; i < m; i++) {\n          U.set(i, k, a.get(i, k));\n        }\n      }\n\n      if (k < nrt) {\n        e[k] = 0;\n        for (let i = k + 1; i < n; i++) {\n          e[k] = hypotenuse(e[k], e[i]);\n        }\n        if (e[k] !== 0) {\n          if (e[k + 1] < 0) {\n            e[k] = 0 - e[k];\n          }\n          for (let i = k + 1; i < n; i++) {\n            e[i] /= e[k];\n          }\n          e[k + 1] += 1;\n        }\n        e[k] = -e[k];\n        if (k + 1 < m && e[k] !== 0) {\n          for (let i = k + 1; i < m; i++) {\n            work[i] = 0;\n          }\n          for (let i = k + 1; i < m; i++) {\n            for (let j = k + 1; j < n; j++) {\n              work[i] += e[j] * a.get(i, j);\n            }\n          }\n          for (let j = k + 1; j < n; j++) {\n            let t = -e[j] / e[k + 1];\n            for (let i = k + 1; i < m; i++) {\n              a.set(i, j, a.get(i, j) + t * work[i]);\n            }\n          }\n        }\n        if (wantv) {\n          for (let i = k + 1; i < n; i++) {\n            V.set(i, k, e[i]);\n          }\n        }\n      }\n    }\n\n    let p = Math.min(n, m + 1);\n    if (nct < n) {\n      s[nct] = a.get(nct, nct);\n    }\n    if (m < p) {\n      s[p - 1] = 0;\n    }\n    if (nrt + 1 < p) {\n      e[nrt] = a.get(nrt, p - 1);\n    }\n    e[p - 1] = 0;\n\n    if (wantu) {\n      for (let j = nct; j < nu; j++) {\n        for (let i = 0; i < m; i++) {\n          U.set(i, j, 0);\n        }\n        U.set(j, j, 1);\n      }\n      for (let k = nct - 1; k >= 0; k--) {\n        if (s[k] !== 0) {\n          for (let j = k + 1; j < nu; j++) {\n            let t = 0;\n            for (let i = k; i < m; i++) {\n              t += U.get(i, k) * U.get(i, j);\n            }\n            t = -t / U.get(k, k);\n            for (let i = k; i < m; i++) {\n              U.set(i, j, U.get(i, j) + t * U.get(i, k));\n            }\n          }\n          for (let i = k; i < m; i++) {\n            U.set(i, k, -U.get(i, k));\n          }\n          U.set(k, k, 1 + U.get(k, k));\n          for (let i = 0; i < k - 1; i++) {\n            U.set(i, k, 0);\n          }\n        } else {\n          for (let i = 0; i < m; i++) {\n            U.set(i, k, 0);\n          }\n          U.set(k, k, 1);\n        }\n      }\n    }\n\n    if (wantv) {\n      for (let k = n - 1; k >= 0; k--) {\n        if (k < nrt && e[k] !== 0) {\n          for (let j = k + 1; j < n; j++) {\n            let t = 0;\n            for (let i = k + 1; i < n; i++) {\n              t += V.get(i, k) * V.get(i, j);\n            }\n            t = -t / V.get(k + 1, k);\n            for (let i = k + 1; i < n; i++) {\n              V.set(i, j, V.get(i, j) + t * V.get(i, k));\n            }\n          }\n        }\n        for (let i = 0; i < n; i++) {\n          V.set(i, k, 0);\n        }\n        V.set(k, k, 1);\n      }\n    }\n\n    let pp = p - 1;\n    let iter = 0;\n    let eps = Number.EPSILON;\n    while (p > 0) {\n      let k, kase;\n      for (k = p - 2; k >= -1; k--) {\n        if (k === -1) {\n          break;\n        }\n        const alpha =\n          Number.MIN_VALUE + eps * Math.abs(s[k] + Math.abs(s[k + 1]));\n        if (Math.abs(e[k]) <= alpha || Number.isNaN(e[k])) {\n          e[k] = 0;\n          break;\n        }\n      }\n      if (k === p - 2) {\n        kase = 4;\n      } else {\n        let ks;\n        for (ks = p - 1; ks >= k; ks--) {\n          if (ks === k) {\n            break;\n          }\n          let t =\n            (ks !== p ? Math.abs(e[ks]) : 0) +\n            (ks !== k + 1 ? Math.abs(e[ks - 1]) : 0);\n          if (Math.abs(s[ks]) <= eps * t) {\n            s[ks] = 0;\n            break;\n          }\n        }\n        if (ks === k) {\n          kase = 3;\n        } else if (ks === p - 1) {\n          kase = 1;\n        } else {\n          kase = 2;\n          k = ks;\n        }\n      }\n\n      k++;\n\n      switch (kase) {\n        case 1: {\n          let f = e[p - 2];\n          e[p - 2] = 0;\n          for (let j = p - 2; j >= k; j--) {\n            let t = hypotenuse(s[j], f);\n            let cs = s[j] / t;\n            let sn = f / t;\n            s[j] = t;\n            if (j !== k) {\n              f = -sn * e[j - 1];\n              e[j - 1] = cs * e[j - 1];\n            }\n            if (wantv) {\n              for (let i = 0; i < n; i++) {\n                t = cs * V.get(i, j) + sn * V.get(i, p - 1);\n                V.set(i, p - 1, -sn * V.get(i, j) + cs * V.get(i, p - 1));\n                V.set(i, j, t);\n              }\n            }\n          }\n          break;\n        }\n        case 2: {\n          let f = e[k - 1];\n          e[k - 1] = 0;\n          for (let j = k; j < p; j++) {\n            let t = hypotenuse(s[j], f);\n            let cs = s[j] / t;\n            let sn = f / t;\n            s[j] = t;\n            f = -sn * e[j];\n            e[j] = cs * e[j];\n            if (wantu) {\n              for (let i = 0; i < m; i++) {\n                t = cs * U.get(i, j) + sn * U.get(i, k - 1);\n                U.set(i, k - 1, -sn * U.get(i, j) + cs * U.get(i, k - 1));\n                U.set(i, j, t);\n              }\n            }\n          }\n          break;\n        }\n        case 3: {\n          const scale = Math.max(\n            Math.abs(s[p - 1]),\n            Math.abs(s[p - 2]),\n            Math.abs(e[p - 2]),\n            Math.abs(s[k]),\n            Math.abs(e[k]),\n          );\n          const sp = s[p - 1] / scale;\n          const spm1 = s[p - 2] / scale;\n          const epm1 = e[p - 2] / scale;\n          const sk = s[k] / scale;\n          const ek = e[k] / scale;\n          const b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2;\n          const c = sp * epm1 * (sp * epm1);\n          let shift = 0;\n          if (b !== 0 || c !== 0) {\n            if (b < 0) {\n              shift = 0 - Math.sqrt(b * b + c);\n            } else {\n              shift = Math.sqrt(b * b + c);\n            }\n            shift = c / (b + shift);\n          }\n          let f = (sk + sp) * (sk - sp) + shift;\n          let g = sk * ek;\n          for (let j = k; j < p - 1; j++) {\n            let t = hypotenuse(f, g);\n            if (t === 0) t = Number.MIN_VALUE;\n            let cs = f / t;\n            let sn = g / t;\n            if (j !== k) {\n              e[j - 1] = t;\n            }\n            f = cs * s[j] + sn * e[j];\n            e[j] = cs * e[j] - sn * s[j];\n            g = sn * s[j + 1];\n            s[j + 1] = cs * s[j + 1];\n            if (wantv) {\n              for (let i = 0; i < n; i++) {\n                t = cs * V.get(i, j) + sn * V.get(i, j + 1);\n                V.set(i, j + 1, -sn * V.get(i, j) + cs * V.get(i, j + 1));\n                V.set(i, j, t);\n              }\n            }\n            t = hypotenuse(f, g);\n            if (t === 0) t = Number.MIN_VALUE;\n            cs = f / t;\n            sn = g / t;\n            s[j] = t;\n            f = cs * e[j] + sn * s[j + 1];\n            s[j + 1] = -sn * e[j] + cs * s[j + 1];\n            g = sn * e[j + 1];\n            e[j + 1] = cs * e[j + 1];\n            if (wantu && j < m - 1) {\n              for (let i = 0; i < m; i++) {\n                t = cs * U.get(i, j) + sn * U.get(i, j + 1);\n                U.set(i, j + 1, -sn * U.get(i, j) + cs * U.get(i, j + 1));\n                U.set(i, j, t);\n              }\n            }\n          }\n          e[p - 2] = f;\n          iter = iter + 1;\n          break;\n        }\n        case 4: {\n          if (s[k] <= 0) {\n            s[k] = s[k] < 0 ? -s[k] : 0;\n            if (wantv) {\n              for (let i = 0; i <= pp; i++) {\n                V.set(i, k, -V.get(i, k));\n              }\n            }\n          }\n          while (k < pp) {\n            if (s[k] >= s[k + 1]) {\n              break;\n            }\n            let t = s[k];\n            s[k] = s[k + 1];\n            s[k + 1] = t;\n            if (wantv && k < n - 1) {\n              for (let i = 0; i < n; i++) {\n                t = V.get(i, k + 1);\n                V.set(i, k + 1, V.get(i, k));\n                V.set(i, k, t);\n              }\n            }\n            if (wantu && k < m - 1) {\n              for (let i = 0; i < m; i++) {\n                t = U.get(i, k + 1);\n                U.set(i, k + 1, U.get(i, k));\n                U.set(i, k, t);\n              }\n            }\n            k++;\n          }\n          iter = 0;\n          p--;\n          break;\n        }\n        // no default\n      }\n    }\n\n    if (swapped) {\n      let tmp = V;\n      V = U;\n      U = tmp;\n    }\n\n    this.m = m;\n    this.n = n;\n    this.s = s;\n    this.U = U;\n    this.V = V;\n  }\n\n  solve(value) {\n    let Y = value;\n    let e = this.threshold;\n    let scols = this.s.length;\n    let Ls = Matrix.zeros(scols, scols);\n\n    for (let i = 0; i < scols; i++) {\n      if (Math.abs(this.s[i]) <= e) {\n        Ls.set(i, i, 0);\n      } else {\n        Ls.set(i, i, 1 / this.s[i]);\n      }\n    }\n\n    let U = this.U;\n    let V = this.rightSingularVectors;\n\n    let VL = V.mmul(Ls);\n    let vrows = V.rows;\n    let urows = U.rows;\n    let VLU = Matrix.zeros(vrows, urows);\n\n    for (let i = 0; i < vrows; i++) {\n      for (let j = 0; j < urows; j++) {\n        let sum = 0;\n        for (let k = 0; k < scols; k++) {\n          sum += VL.get(i, k) * U.get(j, k);\n        }\n        VLU.set(i, j, sum);\n      }\n    }\n\n    return VLU.mmul(Y);\n  }\n\n  solveForDiagonal(value) {\n    return this.solve(Matrix.diag(value));\n  }\n\n  inverse() {\n    let V = this.V;\n    let e = this.threshold;\n    let vrows = V.rows;\n    let vcols = V.columns;\n    let X = new Matrix(vrows, this.s.length);\n\n    for (let i = 0; i < vrows; i++) {\n      for (let j = 0; j < vcols; j++) {\n        if (Math.abs(this.s[j]) > e) {\n          X.set(i, j, V.get(i, j) / this.s[j]);\n        }\n      }\n    }\n\n    let U = this.U;\n\n    let urows = U.rows;\n    let ucols = U.columns;\n    let Y = new Matrix(vrows, urows);\n\n    for (let i = 0; i < vrows; i++) {\n      for (let j = 0; j < urows; j++) {\n        let sum = 0;\n        for (let k = 0; k < ucols; k++) {\n          sum += X.get(i, k) * U.get(j, k);\n        }\n        Y.set(i, j, sum);\n      }\n    }\n\n    return Y;\n  }\n\n  get condition() {\n    return this.s[0] / this.s[Math.min(this.m, this.n) - 1];\n  }\n\n  get norm2() {\n    return this.s[0];\n  }\n\n  get rank() {\n    let tol = Math.max(this.m, this.n) * this.s[0] * Number.EPSILON;\n    let r = 0;\n    let s = this.s;\n    for (let i = 0, ii = s.length; i < ii; i++) {\n      if (s[i] > tol) {\n        r++;\n      }\n    }\n    return r;\n  }\n\n  get diagonal() {\n    return Array.from(this.s);\n  }\n\n  get threshold() {\n    return (Number.EPSILON / 2) * Math.max(this.m, this.n) * this.s[0];\n  }\n\n  get leftSingularVectors() {\n    return this.U;\n  }\n\n  get rightSingularVectors() {\n    return this.V;\n  }\n\n  get diagonalMatrix() {\n    return Matrix.diag(this.s);\n  }\n}\n","import LuDecomposition from './dc/lu';\nimport QrDecomposition from './dc/qr';\nimport SingularValueDecomposition from './dc/svd';\nimport Matrix from './matrix';\nimport WrapperMatrix2D from './wrap/WrapperMatrix2D';\n\nexport function inverse(matrix, useSVD = false) {\n  matrix = WrapperMatrix2D.checkMatrix(matrix);\n  if (useSVD) {\n    return new SingularValueDecomposition(matrix).inverse();\n  } else {\n    return solve(matrix, Matrix.eye(matrix.rows));\n  }\n}\n\nexport function solve(leftHandSide, rightHandSide, useSVD = false) {\n  leftHandSide = WrapperMatrix2D.checkMatrix(leftHandSide);\n  rightHandSide = WrapperMatrix2D.checkMatrix(rightHandSide);\n  if (useSVD) {\n    return new SingularValueDecomposition(leftHandSide).solve(rightHandSide);\n  } else {\n    return leftHandSide.isSquare()\n      ? new LuDecomposition(leftHandSide).solve(rightHandSide)\n      : new QrDecomposition(leftHandSide).solve(rightHandSide);\n  }\n}\n","import Matrix from '../matrix';\nimport WrapperMatrix2D from '../wrap/WrapperMatrix2D';\n\nimport { hypotenuse } from './util';\n\nexport default class EigenvalueDecomposition {\n  constructor(matrix, options = {}) {\n    const { assumeSymmetric = false } = options;\n\n    matrix = WrapperMatrix2D.checkMatrix(matrix);\n    if (!matrix.isSquare()) {\n      throw new Error('Matrix is not a square matrix');\n    }\n\n    if (matrix.isEmpty()) {\n      throw new Error('Matrix must be non-empty');\n    }\n\n    let n = matrix.columns;\n    let V = new Matrix(n, n);\n    let d = new Float64Array(n);\n    let e = new Float64Array(n);\n    let value = matrix;\n    let i, j;\n\n    let isSymmetric = false;\n    if (assumeSymmetric) {\n      isSymmetric = true;\n    } else {\n      isSymmetric = matrix.isSymmetric();\n    }\n\n    if (isSymmetric) {\n      for (i = 0; i < n; i++) {\n        for (j = 0; j < n; j++) {\n          V.set(i, j, value.get(i, j));\n        }\n      }\n      tred2(n, e, d, V);\n      tql2(n, e, d, V);\n    } else {\n      let H = new Matrix(n, n);\n      let ort = new Float64Array(n);\n      for (j = 0; j < n; j++) {\n        for (i = 0; i < n; i++) {\n          H.set(i, j, value.get(i, j));\n        }\n      }\n      orthes(n, H, ort, V);\n      hqr2(n, e, d, V, H);\n    }\n\n    this.n = n;\n    this.e = e;\n    this.d = d;\n    this.V = V;\n  }\n\n  get realEigenvalues() {\n    return Array.from(this.d);\n  }\n\n  get imaginaryEigenvalues() {\n    return Array.from(this.e);\n  }\n\n  get eigenvectorMatrix() {\n    return this.V;\n  }\n\n  get diagonalMatrix() {\n    let n = this.n;\n    let e = this.e;\n    let d = this.d;\n    let X = new Matrix(n, n);\n    let i, j;\n    for (i = 0; i < n; i++) {\n      for (j = 0; j < n; j++) {\n        X.set(i, j, 0);\n      }\n      X.set(i, i, d[i]);\n      if (e[i] > 0) {\n        X.set(i, i + 1, e[i]);\n      } else if (e[i] < 0) {\n        X.set(i, i - 1, e[i]);\n      }\n    }\n    return X;\n  }\n}\n\nfunction tred2(n, e, d, V) {\n  let f, g, h, i, j, k, hh, scale;\n\n  for (j = 0; j < n; j++) {\n    d[j] = V.get(n - 1, j);\n  }\n\n  for (i = n - 1; i > 0; i--) {\n    scale = 0;\n    h = 0;\n    for (k = 0; k < i; k++) {\n      scale = scale + Math.abs(d[k]);\n    }\n\n    if (scale === 0) {\n      e[i] = d[i - 1];\n      for (j = 0; j < i; j++) {\n        d[j] = V.get(i - 1, j);\n        V.set(i, j, 0);\n        V.set(j, i, 0);\n      }\n    } else {\n      for (k = 0; k < i; k++) {\n        d[k] /= scale;\n        h += d[k] * d[k];\n      }\n\n      f = d[i - 1];\n      g = Math.sqrt(h);\n      if (f > 0) {\n        g = -g;\n      }\n\n      e[i] = scale * g;\n      h = h - f * g;\n      d[i - 1] = f - g;\n      for (j = 0; j < i; j++) {\n        e[j] = 0;\n      }\n\n      for (j = 0; j < i; j++) {\n        f = d[j];\n        V.set(j, i, f);\n        g = e[j] + V.get(j, j) * f;\n        for (k = j + 1; k <= i - 1; k++) {\n          g += V.get(k, j) * d[k];\n          e[k] += V.get(k, j) * f;\n        }\n        e[j] = g;\n      }\n\n      f = 0;\n      for (j = 0; j < i; j++) {\n        e[j] /= h;\n        f += e[j] * d[j];\n      }\n\n      hh = f / (h + h);\n      for (j = 0; j < i; j++) {\n        e[j] -= hh * d[j];\n      }\n\n      for (j = 0; j < i; j++) {\n        f = d[j];\n        g = e[j];\n        for (k = j; k <= i - 1; k++) {\n          V.set(k, j, V.get(k, j) - (f * e[k] + g * d[k]));\n        }\n        d[j] = V.get(i - 1, j);\n        V.set(i, j, 0);\n      }\n    }\n    d[i] = h;\n  }\n\n  for (i = 0; i < n - 1; i++) {\n    V.set(n - 1, i, V.get(i, i));\n    V.set(i, i, 1);\n    h = d[i + 1];\n    if (h !== 0) {\n      for (k = 0; k <= i; k++) {\n        d[k] = V.get(k, i + 1) / h;\n      }\n\n      for (j = 0; j <= i; j++) {\n        g = 0;\n        for (k = 0; k <= i; k++) {\n          g += V.get(k, i + 1) * V.get(k, j);\n        }\n        for (k = 0; k <= i; k++) {\n          V.set(k, j, V.get(k, j) - g * d[k]);\n        }\n      }\n    }\n\n    for (k = 0; k <= i; k++) {\n      V.set(k, i + 1, 0);\n    }\n  }\n\n  for (j = 0; j < n; j++) {\n    d[j] = V.get(n - 1, j);\n    V.set(n - 1, j, 0);\n  }\n\n  V.set(n - 1, n - 1, 1);\n  e[0] = 0;\n}\n\nfunction tql2(n, e, d, V) {\n  let g, h, i, j, k, l, m, p, r, dl1, c, c2, c3, el1, s, s2, iter;\n\n  for (i = 1; i < n; i++) {\n    e[i - 1] = e[i];\n  }\n\n  e[n - 1] = 0;\n\n  let f = 0;\n  let tst1 = 0;\n  let eps = Number.EPSILON;\n\n  for (l = 0; l < n; l++) {\n    tst1 = Math.max(tst1, Math.abs(d[l]) + Math.abs(e[l]));\n    m = l;\n    while (m < n) {\n      if (Math.abs(e[m]) <= eps * tst1) {\n        break;\n      }\n      m++;\n    }\n\n    if (m > l) {\n      iter = 0;\n      do {\n        iter = iter + 1;\n\n        g = d[l];\n        p = (d[l + 1] - g) / (2 * e[l]);\n        r = hypotenuse(p, 1);\n        if (p < 0) {\n          r = -r;\n        }\n\n        d[l] = e[l] / (p + r);\n        d[l + 1] = e[l] * (p + r);\n        dl1 = d[l + 1];\n        h = g - d[l];\n        for (i = l + 2; i < n; i++) {\n          d[i] -= h;\n        }\n\n        f = f + h;\n\n        p = d[m];\n        c = 1;\n        c2 = c;\n        c3 = c;\n        el1 = e[l + 1];\n        s = 0;\n        s2 = 0;\n        for (i = m - 1; i >= l; i--) {\n          c3 = c2;\n          c2 = c;\n          s2 = s;\n          g = c * e[i];\n          h = c * p;\n          r = hypotenuse(p, e[i]);\n          e[i + 1] = s * r;\n          s = e[i] / r;\n          c = p / r;\n          p = c * d[i] - s * g;\n          d[i + 1] = h + s * (c * g + s * d[i]);\n\n          for (k = 0; k < n; k++) {\n            h = V.get(k, i + 1);\n            V.set(k, i + 1, s * V.get(k, i) + c * h);\n            V.set(k, i, c * V.get(k, i) - s * h);\n          }\n        }\n\n        p = (-s * s2 * c3 * el1 * e[l]) / dl1;\n        e[l] = s * p;\n        d[l] = c * p;\n      } while (Math.abs(e[l]) > eps * tst1);\n    }\n    d[l] = d[l] + f;\n    e[l] = 0;\n  }\n\n  for (i = 0; i < n - 1; i++) {\n    k = i;\n    p = d[i];\n    for (j = i + 1; j < n; j++) {\n      if (d[j] < p) {\n        k = j;\n        p = d[j];\n      }\n    }\n\n    if (k !== i) {\n      d[k] = d[i];\n      d[i] = p;\n      for (j = 0; j < n; j++) {\n        p = V.get(j, i);\n        V.set(j, i, V.get(j, k));\n        V.set(j, k, p);\n      }\n    }\n  }\n}\n\nfunction orthes(n, H, ort, V) {\n  let low = 0;\n  let high = n - 1;\n  let f, g, h, i, j, m;\n  let scale;\n\n  for (m = low + 1; m <= high - 1; m++) {\n    scale = 0;\n    for (i = m; i <= high; i++) {\n      scale = scale + Math.abs(H.get(i, m - 1));\n    }\n\n    if (scale !== 0) {\n      h = 0;\n      for (i = high; i >= m; i--) {\n        ort[i] = H.get(i, m - 1) / scale;\n        h += ort[i] * ort[i];\n      }\n\n      g = Math.sqrt(h);\n      if (ort[m] > 0) {\n        g = -g;\n      }\n\n      h = h - ort[m] * g;\n      ort[m] = ort[m] - g;\n\n      for (j = m; j < n; j++) {\n        f = 0;\n        for (i = high; i >= m; i--) {\n          f += ort[i] * H.get(i, j);\n        }\n\n        f = f / h;\n        for (i = m; i <= high; i++) {\n          H.set(i, j, H.get(i, j) - f * ort[i]);\n        }\n      }\n\n      for (i = 0; i <= high; i++) {\n        f = 0;\n        for (j = high; j >= m; j--) {\n          f += ort[j] * H.get(i, j);\n        }\n\n        f = f / h;\n        for (j = m; j <= high; j++) {\n          H.set(i, j, H.get(i, j) - f * ort[j]);\n        }\n      }\n\n      ort[m] = scale * ort[m];\n      H.set(m, m - 1, scale * g);\n    }\n  }\n\n  for (i = 0; i < n; i++) {\n    for (j = 0; j < n; j++) {\n      V.set(i, j, i === j ? 1 : 0);\n    }\n  }\n\n  for (m = high - 1; m >= low + 1; m--) {\n    if (H.get(m, m - 1) !== 0) {\n      for (i = m + 1; i <= high; i++) {\n        ort[i] = H.get(i, m - 1);\n      }\n\n      for (j = m; j <= high; j++) {\n        g = 0;\n        for (i = m; i <= high; i++) {\n          g += ort[i] * V.get(i, j);\n        }\n\n        g = g / ort[m] / H.get(m, m - 1);\n        for (i = m; i <= high; i++) {\n          V.set(i, j, V.get(i, j) + g * ort[i]);\n        }\n      }\n    }\n  }\n}\n\nfunction hqr2(nn, e, d, V, H) {\n  let n = nn - 1;\n  let low = 0;\n  let high = nn - 1;\n  let eps = Number.EPSILON;\n  let exshift = 0;\n  let norm = 0;\n  let p = 0;\n  let q = 0;\n  let r = 0;\n  let s = 0;\n  let z = 0;\n  let iter = 0;\n  let i, j, k, l, m, t, w, x, y;\n  let ra, sa, vr, vi;\n  let notlast, cdivres;\n\n  for (i = 0; i < nn; i++) {\n    if (i < low || i > high) {\n      d[i] = H.get(i, i);\n      e[i] = 0;\n    }\n\n    for (j = Math.max(i - 1, 0); j < nn; j++) {\n      norm = norm + Math.abs(H.get(i, j));\n    }\n  }\n\n  while (n >= low) {\n    l = n;\n    while (l > low) {\n      s = Math.abs(H.get(l - 1, l - 1)) + Math.abs(H.get(l, l));\n      if (s === 0) {\n        s = norm;\n      }\n      if (Math.abs(H.get(l, l - 1)) < eps * s) {\n        break;\n      }\n      l--;\n    }\n\n    if (l === n) {\n      H.set(n, n, H.get(n, n) + exshift);\n      d[n] = H.get(n, n);\n      e[n] = 0;\n      n--;\n      iter = 0;\n    } else if (l === n - 1) {\n      w = H.get(n, n - 1) * H.get(n - 1, n);\n      p = (H.get(n - 1, n - 1) - H.get(n, n)) / 2;\n      q = p * p + w;\n      z = Math.sqrt(Math.abs(q));\n      H.set(n, n, H.get(n, n) + exshift);\n      H.set(n - 1, n - 1, H.get(n - 1, n - 1) + exshift);\n      x = H.get(n, n);\n\n      if (q >= 0) {\n        z = p >= 0 ? p + z : p - z;\n        d[n - 1] = x + z;\n        d[n] = d[n - 1];\n        if (z !== 0) {\n          d[n] = x - w / z;\n        }\n        e[n - 1] = 0;\n        e[n] = 0;\n        x = H.get(n, n - 1);\n        s = Math.abs(x) + Math.abs(z);\n        p = x / s;\n        q = z / s;\n        r = Math.sqrt(p * p + q * q);\n        p = p / r;\n        q = q / r;\n\n        for (j = n - 1; j < nn; j++) {\n          z = H.get(n - 1, j);\n          H.set(n - 1, j, q * z + p * H.get(n, j));\n          H.set(n, j, q * H.get(n, j) - p * z);\n        }\n\n        for (i = 0; i <= n; i++) {\n          z = H.get(i, n - 1);\n          H.set(i, n - 1, q * z + p * H.get(i, n));\n          H.set(i, n, q * H.get(i, n) - p * z);\n        }\n\n        for (i = low; i <= high; i++) {\n          z = V.get(i, n - 1);\n          V.set(i, n - 1, q * z + p * V.get(i, n));\n          V.set(i, n, q * V.get(i, n) - p * z);\n        }\n      } else {\n        d[n - 1] = x + p;\n        d[n] = x + p;\n        e[n - 1] = z;\n        e[n] = -z;\n      }\n\n      n = n - 2;\n      iter = 0;\n    } else {\n      x = H.get(n, n);\n      y = 0;\n      w = 0;\n      if (l < n) {\n        y = H.get(n - 1, n - 1);\n        w = H.get(n, n - 1) * H.get(n - 1, n);\n      }\n\n      if (iter === 10) {\n        exshift += x;\n        for (i = low; i <= n; i++) {\n          H.set(i, i, H.get(i, i) - x);\n        }\n        s = Math.abs(H.get(n, n - 1)) + Math.abs(H.get(n - 1, n - 2));\n        x = y = 0.75 * s;\n        w = -0.4375 * s * s;\n      }\n\n      if (iter === 30) {\n        s = (y - x) / 2;\n        s = s * s + w;\n        if (s > 0) {\n          s = Math.sqrt(s);\n          if (y < x) {\n            s = -s;\n          }\n          s = x - w / ((y - x) / 2 + s);\n          for (i = low; i <= n; i++) {\n            H.set(i, i, H.get(i, i) - s);\n          }\n          exshift += s;\n          x = y = w = 0.964;\n        }\n      }\n\n      iter = iter + 1;\n\n      m = n - 2;\n      while (m >= l) {\n        z = H.get(m, m);\n        r = x - z;\n        s = y - z;\n        p = (r * s - w) / H.get(m + 1, m) + H.get(m, m + 1);\n        q = H.get(m + 1, m + 1) - z - r - s;\n        r = H.get(m + 2, m + 1);\n        s = Math.abs(p) + Math.abs(q) + Math.abs(r);\n        p = p / s;\n        q = q / s;\n        r = r / s;\n        if (m === l) {\n          break;\n        }\n        if (\n          Math.abs(H.get(m, m - 1)) * (Math.abs(q) + Math.abs(r)) <\n          eps *\n            (Math.abs(p) *\n              (Math.abs(H.get(m - 1, m - 1)) +\n                Math.abs(z) +\n                Math.abs(H.get(m + 1, m + 1))))\n        ) {\n          break;\n        }\n        m--;\n      }\n\n      for (i = m + 2; i <= n; i++) {\n        H.set(i, i - 2, 0);\n        if (i > m + 2) {\n          H.set(i, i - 3, 0);\n        }\n      }\n\n      for (k = m; k <= n - 1; k++) {\n        notlast = k !== n - 1;\n        if (k !== m) {\n          p = H.get(k, k - 1);\n          q = H.get(k + 1, k - 1);\n          r = notlast ? H.get(k + 2, k - 1) : 0;\n          x = Math.abs(p) + Math.abs(q) + Math.abs(r);\n          if (x !== 0) {\n            p = p / x;\n            q = q / x;\n            r = r / x;\n          }\n        }\n\n        if (x === 0) {\n          break;\n        }\n\n        s = Math.sqrt(p * p + q * q + r * r);\n        if (p < 0) {\n          s = -s;\n        }\n\n        if (s !== 0) {\n          if (k !== m) {\n            H.set(k, k - 1, -s * x);\n          } else if (l !== m) {\n            H.set(k, k - 1, -H.get(k, k - 1));\n          }\n\n          p = p + s;\n          x = p / s;\n          y = q / s;\n          z = r / s;\n          q = q / p;\n          r = r / p;\n\n          for (j = k; j < nn; j++) {\n            p = H.get(k, j) + q * H.get(k + 1, j);\n            if (notlast) {\n              p = p + r * H.get(k + 2, j);\n              H.set(k + 2, j, H.get(k + 2, j) - p * z);\n            }\n\n            H.set(k, j, H.get(k, j) - p * x);\n            H.set(k + 1, j, H.get(k + 1, j) - p * y);\n          }\n\n          for (i = 0; i <= Math.min(n, k + 3); i++) {\n            p = x * H.get(i, k) + y * H.get(i, k + 1);\n            if (notlast) {\n              p = p + z * H.get(i, k + 2);\n              H.set(i, k + 2, H.get(i, k + 2) - p * r);\n            }\n\n            H.set(i, k, H.get(i, k) - p);\n            H.set(i, k + 1, H.get(i, k + 1) - p * q);\n          }\n\n          for (i = low; i <= high; i++) {\n            p = x * V.get(i, k) + y * V.get(i, k + 1);\n            if (notlast) {\n              p = p + z * V.get(i, k + 2);\n              V.set(i, k + 2, V.get(i, k + 2) - p * r);\n            }\n\n            V.set(i, k, V.get(i, k) - p);\n            V.set(i, k + 1, V.get(i, k + 1) - p * q);\n          }\n        }\n      }\n    }\n  }\n\n  if (norm === 0) {\n    return;\n  }\n\n  for (n = nn - 1; n >= 0; n--) {\n    p = d[n];\n    q = e[n];\n\n    if (q === 0) {\n      l = n;\n      H.set(n, n, 1);\n      for (i = n - 1; i >= 0; i--) {\n        w = H.get(i, i) - p;\n        r = 0;\n        for (j = l; j <= n; j++) {\n          r = r + H.get(i, j) * H.get(j, n);\n        }\n\n        if (e[i] < 0) {\n          z = w;\n          s = r;\n        } else {\n          l = i;\n          if (e[i] === 0) {\n            H.set(i, n, w !== 0 ? -r / w : -r / (eps * norm));\n          } else {\n            x = H.get(i, i + 1);\n            y = H.get(i + 1, i);\n            q = (d[i] - p) * (d[i] - p) + e[i] * e[i];\n            t = (x * s - z * r) / q;\n            H.set(i, n, t);\n            H.set(\n              i + 1,\n              n,\n              Math.abs(x) > Math.abs(z) ? (-r - w * t) / x : (-s - y * t) / z,\n            );\n          }\n\n          t = Math.abs(H.get(i, n));\n          if (eps * t * t > 1) {\n            for (j = i; j <= n; j++) {\n              H.set(j, n, H.get(j, n) / t);\n            }\n          }\n        }\n      }\n    } else if (q < 0) {\n      l = n - 1;\n\n      if (Math.abs(H.get(n, n - 1)) > Math.abs(H.get(n - 1, n))) {\n        H.set(n - 1, n - 1, q / H.get(n, n - 1));\n        H.set(n - 1, n, -(H.get(n, n) - p) / H.get(n, n - 1));\n      } else {\n        cdivres = cdiv(0, -H.get(n - 1, n), H.get(n - 1, n - 1) - p, q);\n        H.set(n - 1, n - 1, cdivres[0]);\n        H.set(n - 1, n, cdivres[1]);\n      }\n\n      H.set(n, n - 1, 0);\n      H.set(n, n, 1);\n      for (i = n - 2; i >= 0; i--) {\n        ra = 0;\n        sa = 0;\n        for (j = l; j <= n; j++) {\n          ra = ra + H.get(i, j) * H.get(j, n - 1);\n          sa = sa + H.get(i, j) * H.get(j, n);\n        }\n\n        w = H.get(i, i) - p;\n\n        if (e[i] < 0) {\n          z = w;\n          r = ra;\n          s = sa;\n        } else {\n          l = i;\n          if (e[i] === 0) {\n            cdivres = cdiv(-ra, -sa, w, q);\n            H.set(i, n - 1, cdivres[0]);\n            H.set(i, n, cdivres[1]);\n          } else {\n            x = H.get(i, i + 1);\n            y = H.get(i + 1, i);\n            vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;\n            vi = (d[i] - p) * 2 * q;\n            if (vr === 0 && vi === 0) {\n              vr =\n                eps *\n                norm *\n                (Math.abs(w) +\n                  Math.abs(q) +\n                  Math.abs(x) +\n                  Math.abs(y) +\n                  Math.abs(z));\n            }\n            cdivres = cdiv(\n              x * r - z * ra + q * sa,\n              x * s - z * sa - q * ra,\n              vr,\n              vi,\n            );\n            H.set(i, n - 1, cdivres[0]);\n            H.set(i, n, cdivres[1]);\n            if (Math.abs(x) > Math.abs(z) + Math.abs(q)) {\n              H.set(\n                i + 1,\n                n - 1,\n                (-ra - w * H.get(i, n - 1) + q * H.get(i, n)) / x,\n              );\n              H.set(\n                i + 1,\n                n,\n                (-sa - w * H.get(i, n) - q * H.get(i, n - 1)) / x,\n              );\n            } else {\n              cdivres = cdiv(\n                -r - y * H.get(i, n - 1),\n                -s - y * H.get(i, n),\n                z,\n                q,\n              );\n              H.set(i + 1, n - 1, cdivres[0]);\n              H.set(i + 1, n, cdivres[1]);\n            }\n          }\n\n          t = Math.max(Math.abs(H.get(i, n - 1)), Math.abs(H.get(i, n)));\n          if (eps * t * t > 1) {\n            for (j = i; j <= n; j++) {\n              H.set(j, n - 1, H.get(j, n - 1) / t);\n              H.set(j, n, H.get(j, n) / t);\n            }\n          }\n        }\n      }\n    }\n  }\n\n  for (i = 0; i < nn; i++) {\n    if (i < low || i > high) {\n      for (j = i; j < nn; j++) {\n        V.set(i, j, H.get(i, j));\n      }\n    }\n  }\n\n  for (j = nn - 1; j >= low; j--) {\n    for (i = low; i <= high; i++) {\n      z = 0;\n      for (k = low; k <= Math.min(j, high); k++) {\n        z = z + V.get(i, k) * H.get(k, j);\n      }\n      V.set(i, j, z);\n    }\n  }\n}\n\nfunction cdiv(xr, xi, yr, yi) {\n  let r, d;\n  if (Math.abs(yr) > Math.abs(yi)) {\n    r = yi / yr;\n    d = yr + r * yi;\n    return [(xr + r * xi) / d, (xi - r * xr) / d];\n  } else {\n    r = yr / yi;\n    d = yi + r * yr;\n    return [(r * xr + xi) / d, (r * xi - xr) / d];\n  }\n}\n","const LOOP = 8;\nconst FLOAT_MUL = 1 / 16777216;\nconst sh1 = 15;\nconst sh2 = 18;\nconst sh3 = 11;\nfunction multiply_uint32(n, m) {\n    n >>>= 0;\n    m >>>= 0;\n    const nlo = n & 0xffff;\n    const nhi = n - nlo;\n    return (((nhi * m) >>> 0) + nlo * m) >>> 0;\n}\nexport default class XSadd {\n    constructor(seed = Date.now()) {\n        this.state = new Uint32Array(4);\n        this.init(seed);\n        this.random = this.getFloat.bind(this);\n    }\n    /**\n     * Returns a 32-bit integer r (0 <= r < 2^32)\n     */\n    getUint32() {\n        this.nextState();\n        return (this.state[3] + this.state[2]) >>> 0;\n    }\n    /**\n     * Returns a floating point number r (0.0 <= r < 1.0)\n     */\n    getFloat() {\n        return (this.getUint32() >>> 8) * FLOAT_MUL;\n    }\n    init(seed) {\n        if (!Number.isInteger(seed)) {\n            throw new TypeError('seed must be an integer');\n        }\n        this.state[0] = seed;\n        this.state[1] = 0;\n        this.state[2] = 0;\n        this.state[3] = 0;\n        for (let i = 1; i < LOOP; i++) {\n            this.state[i & 3] ^=\n                (i +\n                    multiply_uint32(1812433253, this.state[(i - 1) & 3] ^ ((this.state[(i - 1) & 3] >>> 30) >>> 0))) >>>\n                    0;\n        }\n        this.periodCertification();\n        for (let i = 0; i < LOOP; i++) {\n            this.nextState();\n        }\n    }\n    periodCertification() {\n        if (this.state[0] === 0 &&\n            this.state[1] === 0 &&\n            this.state[2] === 0 &&\n            this.state[3] === 0) {\n            this.state[0] = 88; // X\n            this.state[1] = 83; // S\n            this.state[2] = 65; // A\n            this.state[3] = 68; // D\n        }\n    }\n    nextState() {\n        let t = this.state[0];\n        t ^= t << sh1;\n        t ^= t >>> sh2;\n        t ^= this.state[3] << sh3;\n        this.state[0] = this.state[1];\n        this.state[1] = this.state[2];\n        this.state[2] = this.state[3];\n        this.state[3] = t;\n    }\n}\n","import XSAdd from 'ml-xsadd';\n/**\n * Create a random array of numbers of a specific length\n *\n * @return - array of random floats normally distributed\n */\nlet spare;\nlet hasSpare = false;\nexport function createRandomArray(options = {}) {\n    let { mean = 0, standardDeviation = 1, length = 1000, range = 1, seed, distribution = 'normal', } = options;\n    const generator = new XSAdd(seed);\n    let returnArray = new Float64Array(length);\n    switch (distribution) {\n        case 'normal':\n            for (let i = 0; i < length; i++) {\n                returnArray[i] = generateGaussian(mean, standardDeviation, generator);\n            }\n            break;\n        case 'uniform':\n            for (let i = 0; i < length; i++) {\n                returnArray[i] = (generator.random() - 0.5) * range + mean;\n            }\n            break;\n        default:\n            // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n            throw new Error(`unknown distribution: ${distribution}`);\n    }\n    return returnArray;\n}\nfunction generateGaussian(mean, standardDeviation, generator) {\n    let val, u, v, s;\n    if (hasSpare) {\n        hasSpare = false;\n        val = spare * standardDeviation + mean;\n    }\n    else {\n        do {\n            u = generator.random() * 2 - 1;\n            v = generator.random() * 2 - 1;\n            s = u * u + v * v;\n        } while (s >= 1 || s === 0);\n        s = Math.sqrt((-2 * Math.log(s)) / s);\n        spare = v * s;\n        hasSpare = true;\n        val = mean + standardDeviation * u * s;\n    }\n    return val;\n}\n//# sourceMappingURL=createRandomArray.js.map","import { xMaxValue, xAdd, createRandomArray } from 'ml-spectra-processing';\nexport default function addNoise(data, options = {}) {\n    const { seed = 0, distribution = 'normal', percent = 1 } = options;\n    const range = (xMaxValue(data.y) * percent) / 100;\n    const noise = createRandomArray({\n        distribution,\n        seed,\n        mean: 0,\n        standardDeviation: range,\n        range,\n        length: data.x.length,\n    });\n    data.y = xAdd(data.y, noise);\n    return data;\n}\n//# sourceMappingURL=addNoise.js.map","import { getShape1D } from 'ml-peak-shape-generator';\nimport addBaseline from './util/addBaseline';\nimport addNoise from './util/addNoise';\nexport class SpectrumGenerator {\n    constructor(options = {}) {\n        const { from = 0, to = 1000, nbPoints = 10001, peakWidthFct, shape = { kind: 'gaussian', fwhm: 5 }, } = options;\n        this.from = from;\n        this.to = to;\n        this.nbPoints = nbPoints;\n        this.interval = (this.to - this.from) / (this.nbPoints - 1);\n        this.peakWidthFct = peakWidthFct;\n        this.maxPeakHeight = Number.MIN_SAFE_INTEGER;\n        this.data = {\n            x: new Float64Array(this.nbPoints),\n            y: new Float64Array(this.nbPoints),\n        };\n        let shapeGenerator = getShape1D(shape);\n        this.shape = shapeGenerator;\n        assertNumber(this.from, 'from');\n        assertNumber(this.to, 'to');\n        assertInteger(this.nbPoints, 'nbPoints');\n        if (this.to <= this.from) {\n            throw new RangeError('to option must be larger than from');\n        }\n        if (this.peakWidthFct && typeof this.peakWidthFct !== 'function') {\n            throw new TypeError('peakWidthFct option must be a function');\n        }\n        this.reset();\n    }\n    /**\n     * Add a series of peaks to the spectrum.\n     * @param peaks - Peaks to add.\n     */\n    addPeaks(peaks, options) {\n        if (!Array.isArray(peaks) &&\n            (typeof peaks !== 'object' ||\n                peaks.x === undefined ||\n                peaks.y === undefined ||\n                !Array.isArray(peaks.x) ||\n                !Array.isArray(peaks.y) ||\n                peaks.x.length !== peaks.y.length)) {\n            throw new TypeError('peaks must be an array or an object containing x[] and y[]');\n        }\n        if (Array.isArray(peaks)) {\n            for (const peak of peaks) {\n                this.addPeak(peak, options);\n            }\n        }\n        else {\n            for (let i = 0; i < peaks.x.length; i++) {\n                this.addPeak([peaks.x[i], peaks.y[i]], options);\n            }\n        }\n    }\n    /**\n     * Add a single peak to the spectrum.\n     * A peak may be either defined as [x,y,fwhm,...] or as {x, y, shape}\n     * @param peak\n     * @param options\n     */\n    addPeak(peak, options = {}) {\n        if (Array.isArray(peak) && peak.length < 2) {\n            throw new Error('peak must be an array with two (or three) values or an object with {x,y,width?}');\n        }\n        if (!Array.isArray(peak) &&\n            (peak.x === undefined || peak.y === undefined)) {\n            throw new Error('peak must be an array with two (or three) values or an object with {x,y,width?}');\n        }\n        let xPosition;\n        let intensity;\n        let peakFWHM;\n        let peakWidth;\n        let peakShapeOptions;\n        if (Array.isArray(peak)) {\n            [xPosition, intensity, peakFWHM, peakShapeOptions] = peak;\n        }\n        else {\n            xPosition = peak.x;\n            intensity = peak.y;\n            peakWidth = peak.width;\n            peakShapeOptions = peak.shape;\n        }\n        if (intensity > this.maxPeakHeight)\n            this.maxPeakHeight = intensity;\n        let { shape: shapeOptions } = options;\n        if (peakShapeOptions) {\n            shapeOptions = shapeOptions\n                ? { ...shapeOptions, ...peakShapeOptions }\n                : peakShapeOptions;\n        }\n        const shape = shapeOptions\n            ? getShape1D(shapeOptions)\n            : Object.assign(Object.create(Object.getPrototypeOf(this.shape)), this.shape);\n        let { width, widthLeft, widthRight } = options;\n        /*\n         if we don't force the fwhm we just take the one from the shape\n         however we have many way to force it:\n         - use [x,y,fwhm]\n         - define `width` that will be converted to fwhm\n         - define `widthLeft` and `widthRight` to define asymmetric peaks\n         - have a callback `peakWidthFct`\n         This should evolve in the future because we will not always have `fwhm`\n         */\n        const fwhm = peakFWHM !== undefined\n            ? peakFWHM\n            : peakWidth\n                ? shape.widthToFWHM(peakWidth)\n                : this.peakWidthFct\n                    ? this.peakWidthFct(xPosition)\n                    : width !== undefined\n                        ? width\n                        : shape.fwhm;\n        if (!widthLeft)\n            widthLeft = fwhm;\n        if (!widthRight)\n            widthRight = fwhm;\n        if (!widthLeft || !widthRight) {\n            throw new Error('Width left or right is undefined or zero');\n        }\n        let factor = options.factor === undefined ? shape.getFactor() : options.factor;\n        const firstValue = xPosition - (widthLeft / 2) * factor;\n        const lastValue = xPosition + (widthRight / 2) * factor;\n        const firstPoint = Math.max(0, Math.floor((firstValue - this.from) / this.interval));\n        const lastPoint = Math.min(this.nbPoints - 1, Math.ceil((lastValue - this.from) / this.interval));\n        const middlePoint = Math.round((xPosition - this.from) / this.interval);\n        // PEAK SHAPE MAY BE ASYMMETRC (widthLeft and widthRight) !\n        // we calculate the left part of the shape\n        shape.fwhm = widthLeft;\n        for (let index = firstPoint; index < Math.max(middlePoint, 0); index++) {\n            this.data.y[index] +=\n                intensity * shape.fct(this.data.x[index] - xPosition);\n        }\n        // we calculate the right part of the gaussian\n        shape.fwhm = widthRight;\n        for (let index = Math.min(middlePoint, lastPoint); index <= lastPoint; index++) {\n            this.data.y[index] +=\n                intensity * shape.fct(this.data.x[index] - xPosition);\n        }\n    }\n    /**\n     * Add a baseline to the spectrum.\n     * @param baselineFct - Mathematical function producing the baseline you want.\n     */\n    addBaseline(baselineFct) {\n        addBaseline(this.data, baselineFct);\n        return this;\n    }\n    /**\n     * Add noise to the spectrum.\n     *\n     * @param percent - Noise's amplitude in percents of the spectrum max value. Default: 1.\n     */\n    addNoise(options) {\n        addNoise(this.data, options);\n        return this;\n    }\n    /**\n     * Get the generated spectrum.\n     */\n    getSpectrum(options = {}) {\n        if (typeof options === 'boolean') {\n            options = { copy: options };\n        }\n        const { copy = true, threshold = 0 } = options;\n        if (threshold) {\n            let minPeakHeight = this.maxPeakHeight * threshold;\n            let x = [];\n            let y = [];\n            for (let i = 0; i < this.data.x.length; i++) {\n                if (this.data.y[i] >= minPeakHeight) {\n                    x.push(this.data.x[i]);\n                    y.push(this.data.y[i]);\n                }\n            }\n            return { x, y };\n        }\n        if (copy) {\n            return {\n                x: this.data.x.slice(),\n                y: this.data.y.slice(),\n            };\n        }\n        else {\n            return this.data;\n        }\n    }\n    /**\n     * Resets the generator with an empty spectrum.\n     */\n    reset() {\n        const spectrum = this.data;\n        for (let i = 0; i < this.nbPoints; i++) {\n            spectrum.x[i] = this.from + i * this.interval;\n        }\n        return this;\n    }\n}\nfunction assertInteger(value, name) {\n    if (!Number.isInteger(value)) {\n        throw new TypeError(`${name} option must be an integer`);\n    }\n}\nfunction assertNumber(value, name) {\n    if (!Number.isFinite(value)) {\n        throw new TypeError(`${name} option must be a number`);\n    }\n}\n/**\n * Generates a spectrum and returns it.\n * @param peaks - List of peaks to put in the spectrum.\n * @param options\n */\nexport function generateSpectrum(peaks, options = {}) {\n    const { generator: generatorOptions, noise, baseline, threshold, peakOptions, } = options;\n    const generator = new SpectrumGenerator(generatorOptions);\n    generator.addPeaks(peaks, peakOptions);\n    if (baseline)\n        generator.addBaseline(baseline);\n    if (noise) {\n        generator.addNoise(noise);\n    }\n    return generator.getSpectrum({\n        threshold,\n    });\n}\n//# sourceMappingURL=SpectrumGenerator.js.map","import { getShape2D } from 'ml-peak-shape-generator';\nimport { matrixMinMaxZ } from 'ml-spectra-processing';\nconst axis2D = ['x', 'y'];\nconst peakCoordinates = ['x', 'y', 'z'];\nconst convertWidthToFWHM = (shape, width) => {\n    const widthData = ensureXYNumber(width);\n    for (let key of axis2D) {\n        widthData[key] = shape.widthToFWHM(widthData[key]);\n    }\n    return widthData;\n};\nexport class Spectrum2DGenerator {\n    constructor(options = {}) {\n        let { from = 0, to = 100, nbPoints = 1001, peakWidthFct = () => 5, shape = {\n            kind: 'gaussian',\n        }, } = options;\n        from = ensureXYNumber(from);\n        to = ensureXYNumber(to);\n        nbPoints = ensureXYNumber(nbPoints);\n        for (const axis of axis2D) {\n            assertNumber(from[axis], `from-${axis}`);\n            assertNumber(to[axis], `to-${axis}`);\n            assertInteger(nbPoints[axis], `nbPoints-${axis}`);\n        }\n        this.from = from;\n        this.to = to;\n        this.nbPoints = nbPoints;\n        this.interval = calculeIntervals(from, to, nbPoints);\n        this.peakWidthFct = peakWidthFct;\n        this.maxPeakHeight = Number.MIN_SAFE_INTEGER;\n        let shapeGenerator = getShape2D(shape);\n        this.shape = shapeGenerator;\n        this.data = {\n            x: new Float64Array(nbPoints.x),\n            y: new Float64Array(nbPoints.y),\n            z: createMatrix(this.nbPoints),\n        };\n        for (const axis of axis2D) {\n            if (this.to[axis] <= this.from[axis]) {\n                throw new RangeError('to option must be larger than from');\n            }\n        }\n        if (typeof this.peakWidthFct !== 'function') {\n            throw new TypeError('peakWidthFct option must be a function');\n        }\n        this.reset();\n    }\n    addPeaks(peaks, options) {\n        if (!Array.isArray(peaks) &&\n            (typeof peaks !== 'object' ||\n                peaks.x === undefined ||\n                peaks.y === undefined ||\n                !Array.isArray(peaks.x) ||\n                !Array.isArray(peaks.y) ||\n                peaks.x.length !== peaks.y.length)) {\n            throw new TypeError('peaks must be an array or an object containing x[] and y[]');\n        }\n        if (Array.isArray(peaks)) {\n            for (const peak of peaks) {\n                this.addPeak(peak, options);\n            }\n        }\n        else {\n            let nbPeaks = peaks.x.length;\n            for (const c of peakCoordinates) {\n                if (peaks[c] && Array.isArray(peaks[c])) {\n                    if (nbPeaks !== peaks[c].length) {\n                        throw new Error('x, y, z should have the same length');\n                    }\n                }\n            }\n            for (let i = 0; i < peaks.x.length; i++) {\n                this.addPeak([peaks.x[i], peaks.y[i], peaks.z[i]], options);\n            }\n        }\n        return this;\n    }\n    addPeak(peak, options = {}) {\n        if (Array.isArray(peak) && peak.length < 3) {\n            throw new Error('peak must be an array with three (or four) values or an object with {x,y,z,width?}');\n        }\n        if (!Array.isArray(peak) &&\n            peakCoordinates.some((e) => peak[e] === undefined)) {\n            throw new Error('peak must be an array with three (or four) values or an object with {x,y,z,width?}');\n        }\n        let xPosition;\n        let yPosition;\n        let intensity;\n        let peakFWHM;\n        let peakWidth;\n        let peakShapeOptions;\n        if (Array.isArray(peak)) {\n            [xPosition, yPosition, intensity, peakFWHM, peakShapeOptions] = peak;\n        }\n        else {\n            xPosition = peak.x;\n            yPosition = peak.y;\n            intensity = peak.z;\n            peakFWHM = peak.fwhm;\n            peakWidth = peak.width;\n            peakShapeOptions = peak.shape;\n        }\n        const position = { x: xPosition, y: yPosition };\n        if (intensity > this.maxPeakHeight)\n            this.maxPeakHeight = intensity;\n        let { shape: shapeOptions, width } = options;\n        if (peakShapeOptions) {\n            shapeOptions = shapeOptions\n                ? { ...shapeOptions, ...peakShapeOptions }\n                : peakShapeOptions;\n        }\n        const shape = shapeOptions\n            ? getShape2D(shapeOptions)\n            : Object.assign(Object.create(Object.getPrototypeOf(this.shape)), JSON.parse(JSON.stringify(this.shape)));\n        let { fwhm = peakFWHM !== undefined\n            ? peakFWHM\n            : peakWidth\n                ? convertWidthToFWHM(shape, peakWidth)\n                : width\n                    ? convertWidthToFWHM(shape, width)\n                    : this.peakWidthFct(xPosition, yPosition), } = options;\n        fwhm = ensureXYNumber(fwhm);\n        let factor = options.factor === undefined ? shape.getFactor() : options.factor;\n        factor = ensureXYNumber(factor);\n        const firstPoint = { x: 0, y: 0 };\n        const lastPoint = { x: 0, y: 0 };\n        for (const axis of axis2D) {\n            const first = position[axis] - (fwhm[axis] / 2) * factor[axis];\n            const last = position[axis] + (fwhm[axis] / 2) * factor[axis];\n            firstPoint[axis] = Math.max(0, Math.floor((first - this.from[axis]) / this.interval[axis]));\n            lastPoint[axis] = Math.min(this.nbPoints[axis], Math.ceil((last - this.from[axis]) / this.interval[axis]));\n        }\n        shape.fwhm = fwhm;\n        for (let xIndex = firstPoint.x; xIndex < lastPoint.x; xIndex++) {\n            for (let yIndex = firstPoint.y; yIndex < lastPoint.y; yIndex++) {\n                const value = intensity *\n                    shape.fct(this.data.x[xIndex] - position.x, this.data.y[yIndex] - position.y);\n                if (value > 1e-6) {\n                    this.data.z[yIndex][xIndex] += value;\n                }\n            }\n        }\n        return this;\n    }\n    getSpectrum(options = {}) {\n        if (typeof options === 'boolean') {\n            options = { copy: options };\n        }\n        const { copy = true } = options;\n        let minMaxZ = matrixMinMaxZ(this.data.z);\n        return {\n            minX: this.from.x,\n            maxX: this.to.x,\n            maxY: this.to.y,\n            minY: this.from.y,\n            minZ: minMaxZ.min,\n            maxZ: minMaxZ.max,\n            z: copy ? this.data.z.slice() : this.data.z,\n        };\n    }\n    reset() {\n        const spectrum = this.data;\n        for (const axis of axis2D) {\n            for (let i = 0; i < this.nbPoints[axis]; i++) {\n                spectrum[axis][i] = this.from[axis] + i * this.interval[axis];\n            }\n        }\n        for (let row of spectrum.z) {\n            for (let j = 0; j < row.length; j++) {\n                row[j] = 0;\n            }\n        }\n        return this;\n    }\n}\nexport function generateSpectrum2D(peaks, options = {}) {\n    const { generator: generatorOptions, peaks: addPeaksOptions } = options;\n    const generator = new Spectrum2DGenerator(generatorOptions);\n    generator.addPeaks(peaks, addPeaksOptions);\n    return generator.getSpectrum();\n}\nfunction ensureXYNumber(input) {\n    return typeof input !== 'object' ? { x: input, y: input } : { ...input };\n}\nfunction calculeIntervals(from, to, nbPoints) {\n    return {\n        x: (to.x - from.x) / (nbPoints.x - 1),\n        y: (to.y - from.y) / (nbPoints.y - 1),\n    };\n}\nfunction assertInteger(value, name) {\n    if (!Number.isInteger(value)) {\n        throw new TypeError(`${name} option must be an integer`);\n    }\n}\nfunction assertNumber(value, name) {\n    if (!Number.isFinite(value)) {\n        throw new TypeError(`${name} option must be a number`);\n    }\n}\nfunction createMatrix(nbPoints) {\n    const zMatrix = new Array(nbPoints.y);\n    for (let i = 0; i < nbPoints.y; i++) {\n        zMatrix[i] = new Float64Array(nbPoints.x);\n    }\n    return zMatrix;\n}\n//# sourceMappingURL=Spectrum2DGenerator.js.map","export function hasProperty(data, key) {\n    return key in data;\n}\n//# sourceMappingURL=hasProperty.js.map","import { hasProperty } from '../../utilities/hasProperty';\nconst { parse, stringify } = JSON;\n/**\n * convert width and fwhm to ppm\n */\nexport function convertWidth(peaks, options) {\n    const { frequency, convertTo, output = parse(stringify(peaks)), } = options;\n    const convert = getConverter(convertTo, frequency);\n    for (const peak of output) {\n        peak.width = convert(peak.width);\n        if (hasProperty(peak, 'shape')) {\n            const shape = peak.shape;\n            if (shape.fwhm) {\n                shape.fwhm = convert(shape.fwhm);\n            }\n        }\n    }\n    return output;\n}\nfunction getConverter(convertTo, frequency) {\n    switch (convertTo) {\n        case 'ppm':\n            return (x) => x / frequency;\n        case 'hz':\n            return (x) => x * frequency;\n        default:\n            throw new Error(`Does not support convert to ${convertTo}`);\n    }\n}\n//# sourceMappingURL=convertWidth.js.map","import { convertWidth } from './convertWidth';\nexport function convertWidthToPPM(peaks, options) {\n    return convertWidth(peaks, { ...options, convertTo: 'ppm' });\n}\n//# sourceMappingURL=convertWidthToPPM.js.map","import { generateSpectrum } from 'spectrum-generator';\nimport { convertWidthToPPM } from './util/convertWidthToPPM';\nexport function peaksToXY(peaks, options) {\n    const { frequency, nbPoints = 1024, shape } = options;\n    if (!frequency) {\n        throw new Error('frequency is mandatory');\n    }\n    const newPeaks = convertWidthToPPM(peaks, { frequency });\n    return generateSpectrum(newPeaks, {\n        generator: {\n            ...getFromTo(newPeaks, options),\n            nbPoints,\n            shape,\n        },\n    });\n}\nfunction getFromTo(newPeaks, options) {\n    if ('to' in options && 'from' in options) {\n        return {\n            from: options.from,\n            to: options.to,\n        };\n    }\n    newPeaks.sort((a, b) => a.x - b.x);\n    const firstPeak = newPeaks[0];\n    const lastPeak = newPeaks[newPeaks.length - 1];\n    const { from = firstPeak.x - (firstPeak.width * 2) / options.frequency, to = lastPeak.x + (lastPeak.width * 2) / options.frequency, } = options;\n    return {\n        from,\n        to,\n    };\n}\n//# sourceMappingURL=peaksToXY.js.map","var IDX=256, HEX=[], BUFFER;\nwhile (IDX--) HEX[IDX] = (IDX + 256).toString(16).substring(1);\n\nexport function v4() {\n\tvar i=0, num, out='';\n\n\tif (!BUFFER || ((IDX + 16) > 256)) {\n\t\tBUFFER = Array(i=256);\n\t\twhile (i--) BUFFER[i] = 256 * Math.random() | 0;\n\t\ti = IDX = 0;\n\t}\n\n\tfor (; i < 16; i++) {\n\t\tnum = BUFFER[IDX + i];\n\t\tif (i==6) out += HEX[num & 15 | 64];\n\t\telse if (i==8) out += HEX[num & 63 | 128];\n\t\telse out += HEX[num];\n\n\t\tif (i & 1 && i > 1 && i < 11) out += '-';\n\t}\n\n\tIDX++;\n\treturn out;\n}\n","import { isAnyArray } from 'is-any-array';\n/**\n * Apply Savitzky Golay algorithm\n * @param [ys] Array of y values\n * @param [xs] Array of X or deltaX\n * @return  Array containing the new ys (same length)\n */\nexport function sgg(ys, xs, options = {}) {\n    let { windowSize = 9, derivative = 0, polynomial = 3 } = options;\n    if (windowSize % 2 === 0 || windowSize < 5 || !Number.isInteger(windowSize)) {\n        throw new RangeError('Invalid window size (should be odd and at least 5 integer number)');\n    }\n    if (!isAnyArray(ys)) {\n        throw new TypeError('Y values must be an array');\n    }\n    if (typeof xs === 'undefined') {\n        throw new TypeError('X must be defined');\n    }\n    if (windowSize > ys.length) {\n        throw new RangeError(`Window size is higher than the data length ${windowSize}>${ys.length}`);\n    }\n    if (derivative < 0 || !Number.isInteger(derivative)) {\n        throw new RangeError('Derivative should be a positive integer');\n    }\n    if (polynomial < 1 || !Number.isInteger(polynomial)) {\n        throw new RangeError('Polynomial should be a positive integer');\n    }\n    if (polynomial >= 6) {\n        // eslint-disable-next-line no-console\n        console.warn('You should not use polynomial grade higher than 5 if you are' +\n            ' not sure that your data arises from such a model. Possible polynomial oscillation problems');\n    }\n    let half = Math.floor(windowSize / 2);\n    let np = ys.length;\n    let ans = new Float64Array(np);\n    let weights = fullWeights(windowSize, polynomial, derivative);\n    let hs = 0;\n    let constantH = true;\n    if (isAnyArray(xs)) {\n        constantH = false;\n    }\n    else {\n        hs = Math.pow(xs, derivative);\n    }\n    //For the borders\n    for (let i = 0; i < half; i++) {\n        let wg1 = weights[half - i - 1];\n        let wg2 = weights[half + i + 1];\n        let d1 = 0;\n        let d2 = 0;\n        for (let l = 0; l < windowSize; l++) {\n            d1 += wg1[l] * ys[l];\n            d2 += wg2[l] * ys[np - windowSize + l];\n        }\n        if (constantH) {\n            ans[half - i - 1] = d1 / hs;\n            ans[np - half + i] = d2 / hs;\n        }\n        else {\n            hs = getHs(xs, half - i - 1, half, derivative);\n            ans[half - i - 1] = d1 / hs;\n            hs = getHs(xs, np - half + i, half, derivative);\n            ans[np - half + i] = d2 / hs;\n        }\n    }\n    //For the internal points\n    let wg = weights[half];\n    for (let i = windowSize; i <= np; i++) {\n        let d = 0;\n        for (let l = 0; l < windowSize; l++)\n            d += wg[l] * ys[l + i - windowSize];\n        if (!constantH) {\n            hs = getHs(xs, i - half - 1, half, derivative);\n        }\n        ans[i - half - 1] = d / hs;\n    }\n    return ans;\n}\nfunction getHs(h, center, half, derivative) {\n    let hs = 0;\n    let count = 0;\n    for (let i = center - half; i < center + half; i++) {\n        if (i >= 0 && i < h.length - 1) {\n            hs += h[i + 1] - h[i];\n            count++;\n        }\n    }\n    return Math.pow(hs / count, derivative);\n}\nfunction gramPoly(i, m, k, s) {\n    let Grampoly = 0;\n    if (k > 0) {\n        Grampoly =\n            ((4 * k - 2) / (k * (2 * m - k + 1))) *\n                (i * gramPoly(i, m, k - 1, s) + s * gramPoly(i, m, k - 1, s - 1)) -\n                (((k - 1) * (2 * m + k)) / (k * (2 * m - k + 1))) *\n                    gramPoly(i, m, k - 2, s);\n    }\n    else {\n        if (k === 0 && s === 0) {\n            Grampoly = 1;\n        }\n        else {\n            Grampoly = 0;\n        }\n    }\n    return Grampoly;\n}\nfunction genFact(a, b) {\n    let gf = 1;\n    if (a >= b) {\n        for (let j = a - b + 1; j <= a; j++) {\n            gf *= j;\n        }\n    }\n    return gf;\n}\nfunction weight(i, t, m, n, s) {\n    let sum = 0;\n    for (let k = 0; k <= n; k++) {\n        sum +=\n            (2 * k + 1) *\n                (genFact(2 * m, k) / genFact(2 * m + k + 1, k + 1)) *\n                gramPoly(i, m, k, 0) *\n                gramPoly(t, m, k, s);\n    }\n    return sum;\n}\n/**\n * @private\n * @param m  Number of points\n * @param n  Polynomial grade\n * @param s  Derivative\n */\nfunction fullWeights(m, n, s) {\n    let weights = new Array(m);\n    let np = Math.floor(m / 2);\n    for (let t = -np; t <= np; t++) {\n        weights[t + np] = new Float64Array(m);\n        for (let j = -np; j <= np; j++) {\n            weights[t + np][j + np] = weight(j, t, np, n, s);\n        }\n    }\n    return weights;\n}\n//# sourceMappingURL=index.js.map","/**\n * Correction of the x and y coordinates using a quadratic optimizations with the peak and its 3 closest neighbors to determine the true x,y values of the peak.\n * This process is done in place and is very fast.\n * @param data\n * @param peaks\n */\nexport function optimizeTop(data, peaks) {\n    const { x, y } = data;\n    for (const peak of peaks) {\n        let currentIndex = peak.index;\n        // The detected peak could be moved 1 or 2 units to left or right.\n        if (y[currentIndex - 1] >= y[currentIndex - 2] &&\n            y[currentIndex - 1] >= y[currentIndex]) {\n            currentIndex--;\n        }\n        else {\n            if (y[currentIndex + 1] >= y[currentIndex] &&\n                y[currentIndex + 1] >= y[currentIndex + 2]) {\n                currentIndex++;\n            }\n            else {\n                if (y[currentIndex - 2] >= y[currentIndex - 3] &&\n                    y[currentIndex - 2] >= y[currentIndex - 1]) {\n                    currentIndex -= 2;\n                }\n                else {\n                    if (y[currentIndex + 2] >= y[currentIndex + 1] &&\n                        y[currentIndex + 2] >= y[currentIndex + 3]) {\n                        currentIndex += 2;\n                    }\n                }\n            }\n        }\n        // interpolation to a sin() function\n        if (y[currentIndex - 1] > 0 &&\n            y[currentIndex + 1] > 0 &&\n            y[currentIndex] >= y[currentIndex - 1] &&\n            y[currentIndex] >= y[currentIndex + 1] &&\n            (y[currentIndex] !== y[currentIndex - 1] ||\n                y[currentIndex] !== y[currentIndex + 1])) {\n            let alpha = 20 * Math.log10(y[currentIndex - 1]);\n            let beta = 20 * Math.log10(y[currentIndex]);\n            let gamma = 20 * Math.log10(y[currentIndex + 1]);\n            let p = (0.5 * (alpha - gamma)) / (alpha - 2 * beta + gamma);\n            peak.x = x[currentIndex] + (x[currentIndex] - x[currentIndex - 1]) * p;\n            peak.y =\n                y[currentIndex] -\n                    0.25 * (y[currentIndex - 1] - y[currentIndex + 1]) * p;\n        }\n    }\n}\n//# sourceMappingURL=optimizeTop.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport { sgg } from 'ml-savitzky-golay-generalized';\nimport { xIsEquallySpaced, xIsMonotoneIncreasing, xMinValue, xMaxValue, xNoiseStandardDeviation, } from 'ml-spectra-processing';\nimport { optimizeTop } from './utils/optimizeTop';\n/**\n * Global spectra deconvolution\n * @param  data - Object data with x and y arrays. Values in x has to be growing\n * @param {number} [options.broadRatio = 0.00] - If `broadRatio` is higher than 0, then all the peaks which second derivative\n * smaller than `broadRatio * maxAbsSecondDerivative` will be marked with the soft mask equal to true.\n\n */\nexport function gsd(data, options = {}) {\n    let { sgOptions = {\n        windowSize: 9,\n        polynomial: 3,\n    }, noiseLevel, smoothY = false, maxCriteria = true, minMaxRatio = 0.00025, realTopDetection = false, } = options;\n    let { x, y } = data;\n    if (!xIsMonotoneIncreasing(x)) {\n        throw new Error('GSD only accepts monotone increasing x values');\n    }\n    //rescale;\n    y = y.slice();\n    // If the max difference between delta x is less than 5%, then,\n    // we can assume it to be equally spaced variable\n    let equallySpaced = xIsEquallySpaced(x);\n    if (noiseLevel === undefined) {\n        if (equallySpaced) {\n            const noiseInfo = xNoiseStandardDeviation(y);\n            if (maxCriteria) {\n                noiseLevel = noiseInfo.median + 1.5 * noiseInfo.sd;\n            }\n            else {\n                noiseLevel = -noiseInfo.median + 1.5 * noiseInfo.sd;\n            }\n        }\n        else {\n            noiseLevel = 0;\n        }\n    }\n    else {\n        if (maxCriteria === false) {\n            noiseLevel *= -1;\n        }\n    }\n    if (maxCriteria === false) {\n        for (let i = 0; i < y.length; i++) {\n            y[i] *= -1;\n        }\n    }\n    if (noiseLevel !== undefined) {\n        for (let i = 0; i < y.length; i++) {\n            if (y[i] < noiseLevel) {\n                y[i] = noiseLevel;\n            }\n        }\n    }\n    let yData = y;\n    let dY, ddY;\n    const { windowSize, polynomial } = sgOptions;\n    if (equallySpaced) {\n        if (smoothY) {\n            yData = sgg(y, x[1] - x[0], {\n                windowSize,\n                polynomial,\n                derivative: 0,\n            });\n        }\n        dY = sgg(y, x[1] - x[0], {\n            windowSize,\n            polynomial,\n            derivative: 1,\n        });\n        ddY = sgg(y, x[1] - x[0], {\n            windowSize,\n            polynomial,\n            derivative: 2,\n        });\n    }\n    else {\n        if (smoothY) {\n            yData = sgg(y, x, {\n                windowSize,\n                polynomial,\n                derivative: 0,\n            });\n        }\n        dY = sgg(y, x, {\n            windowSize,\n            polynomial,\n            derivative: 1,\n        });\n        ddY = sgg(y, x, {\n            windowSize,\n            polynomial,\n            derivative: 2,\n        });\n    }\n    const minY = xMinValue(yData);\n    const maxY = xMaxValue(yData);\n    if (minY > maxY || minY === maxY)\n        return [];\n    const yThreshold = minY + (maxY - minY) * minMaxRatio;\n    const dX = x[1] - x[0];\n    let lastMax = null;\n    let lastMin = null;\n    let minddY = [];\n    let intervalL = [];\n    let intervalR = [];\n    // By the intermediate value theorem We cannot find 2 consecutive maximum or minimum\n    for (let i = 1; i < yData.length - 1; ++i) {\n        if ((dY[i] < dY[i - 1] && dY[i] <= dY[i + 1]) ||\n            (dY[i] <= dY[i - 1] && dY[i] < dY[i + 1])) {\n            lastMin = {\n                x: x[i],\n                index: i,\n            };\n            if (dX > 0 && lastMax !== null) {\n                intervalL.push(lastMax);\n                intervalR.push(lastMin);\n            }\n        }\n        // Maximum in first derivative\n        if ((dY[i] >= dY[i - 1] && dY[i] > dY[i + 1]) ||\n            (dY[i] > dY[i - 1] && dY[i] >= dY[i + 1])) {\n            lastMax = {\n                x: x[i],\n                index: i,\n            };\n            if (dX < 0 && lastMin !== null) {\n                intervalL.push(lastMax);\n                intervalR.push(lastMin);\n            }\n        }\n        // Minimum in second derivative\n        if (ddY[i] < ddY[i - 1] && ddY[i] < ddY[i + 1]) {\n            minddY.push(i);\n        }\n    }\n    let lastK = -1;\n    const peaks = [];\n    for (const minddYIndex of minddY) {\n        let deltaX = x[minddYIndex];\n        let possible = -1;\n        let k = lastK + 1;\n        let minDistance = Number.POSITIVE_INFINITY;\n        let currentDistance = 0;\n        while (possible === -1 && k < intervalL.length) {\n            currentDistance = Math.abs(deltaX - (intervalL[k].x + intervalR[k].x) / 2);\n            if (currentDistance < (intervalR[k].x - intervalL[k].x) / 2) {\n                possible = k;\n                lastK = k;\n            }\n            ++k;\n            // Not getting closer?\n            if (currentDistance >= minDistance) {\n                break;\n            }\n            minDistance = currentDistance;\n        }\n        if (possible !== -1) {\n            if (yData[minddYIndex] > yThreshold) {\n                let width = Math.abs(intervalR[possible].x - intervalL[possible].x);\n                peaks.push({\n                    id: generateID(),\n                    x: deltaX,\n                    y: yData[minddYIndex],\n                    width,\n                    index: minddYIndex,\n                    ddY: ddY[minddYIndex],\n                    inflectionPoints: {\n                        from: intervalL[possible],\n                        to: intervalR[possible],\n                    },\n                });\n            }\n        }\n    }\n    if (realTopDetection) {\n        optimizeTop({ x, y: yData }, peaks);\n    }\n    peaks.forEach((peak) => {\n        if (!maxCriteria) {\n            peak.y *= -1;\n            peak.ddY = peak.ddY * -1;\n        }\n    });\n    peaks.sort((a, b) => {\n        return a.x - b.x;\n    });\n    return peaks;\n}\n//# sourceMappingURL=gsd.js.map","/**\n * This function returns the sumOfShapes function\n * This function gives sumOfShapes access to the peak list and the associated data\n * @param parameters - parameters\n */\nexport function getSumOfShapes(internalPeaks) {\n    return function sumOfShapes(parameters) {\n        return (x) => {\n            let totalY = 0;\n            for (const peak of internalPeaks) {\n                const peakX = parameters[peak.fromIndex];\n                const y = parameters[peak.fromIndex + 1];\n                for (let i = 2; i < parameters.length; i++) {\n                    //@ts-expect-error Not simply to solve the issue\n                    peak.shapeFct[peak.parameters[i]] = parameters[peak.fromIndex + i];\n                }\n                totalY += y * peak.shapeFct.fct(x - peakX);\n            }\n            return totalY;\n        };\n    };\n}\n//# sourceMappingURL=getSumOfShapes.js.map","/**\n * Asserts that value is truthy.\n *\n * @param value - Value to check.\n * @param message - Optional error message to throw.\n */\nexport function assert(value, message) {\n    if (!value) {\n        throw new Error(message ? message : 'unreachable');\n    }\n}\n//# sourceMappingURL=assert.js.map","export const DefaultParameters = {\n    x: {\n        init: (peak) => peak.x,\n        min: (peak, peakShape) => peak.x - peakShape.fwhm * 2,\n        max: (peak, peakShape) => peak.x + peakShape.fwhm * 2,\n        gradientDifference: (peak, peakShape) => peakShape.fwhm * 2e-3,\n    },\n    y: {\n        init: (peak) => peak.y,\n        min: (peak) => (peak.y < 0 ? -1.1 : 0),\n        max: (peak) => (peak.y < 0 ? 0 : 1.1),\n        gradientDifference: () => 1e-3,\n    },\n    fwhm: {\n        init: (peak, peakShape) => peakShape.fwhm,\n        min: (peak, peakShape) => peakShape.fwhm * 0.25,\n        max: (peak, peakShape) => peakShape.fwhm * 4,\n        gradientDifference: (peak, peakShape) => peakShape.fwhm * 2e-3,\n    },\n    mu: {\n        init: (peak, peakShape) => peakShape.mu,\n        min: () => 0,\n        max: () => 1,\n        gradientDifference: () => 0.01,\n    },\n};\n//# sourceMappingURL=DefaultParameters.js.map","import { getShape1D } from 'ml-peak-shape-generator';\nimport { assert } from '../assert';\nimport { DefaultParameters } from './DefaultParameters';\nconst properties = ['init', 'min', 'max', 'gradientDifference'];\n/**\n * Return an array of internalPeaks that contains the exact init, min, max values based on the options\n * @param peaks\n * @param options\n * @returns\n */\nexport function getInternalPeaks(peaks, minMaxY, options = {}) {\n    let index = 0;\n    let internalPeaks = [];\n    const { baseline: shiftValue = minMaxY.min } = options;\n    const normalizedPeaks = peaks.map((peak) => {\n        return {\n            ...peak,\n            y: (peak.y - shiftValue) / minMaxY.range,\n        };\n    });\n    for (const peak of normalizedPeaks) {\n        const { id, shape = options.shape ? options.shape : { kind: 'gaussian' } } = peak;\n        const shapeFct = getShape1D(shape);\n        const parameters = ['x', 'y', ...shapeFct.getParameters()];\n        const propertiesValues = {\n            min: [],\n            max: [],\n            init: [],\n            gradientDifference: [],\n        };\n        for (let parameter of parameters) {\n            for (let property of properties) {\n                // check if the property is specified in the peak\n                let propertyValue = peak?.parameters?.[parameter]?.[property];\n                if (propertyValue) {\n                    propertyValue = getNormalizedValue(propertyValue, parameter, property, minMaxY, options.baseline);\n                    propertiesValues[property].push(propertyValue);\n                    continue;\n                }\n                // check if there are some global option, it could be a number or a callback\n                let generalParameterValue = options?.parameters?.[parameter]?.[property];\n                if (generalParameterValue) {\n                    if (typeof generalParameterValue === 'number') {\n                        generalParameterValue = getNormalizedValue(generalParameterValue, parameter, property, minMaxY, options.baseline);\n                        propertiesValues[property].push(generalParameterValue);\n                        continue;\n                    }\n                    else {\n                        let value = generalParameterValue(peak);\n                        value = getNormalizedValue(value, parameter, property, minMaxY, options.baseline);\n                        propertiesValues[property].push(value);\n                        continue;\n                    }\n                }\n                // we just need to take the default parameters\n                assert(DefaultParameters[parameter], `No default parameter for ${parameter}`);\n                const defaultParameterValues = DefaultParameters[parameter][property];\n                //@ts-expect-error should never happen\n                propertiesValues[property].push(defaultParameterValues(peak, shapeFct));\n            }\n        }\n        const fromIndex = index;\n        const toIndex = fromIndex + parameters.length - 1;\n        index += toIndex - fromIndex + 1;\n        internalPeaks.push({\n            id,\n            shape,\n            shapeFct,\n            parameters,\n            propertiesValues,\n            fromIndex,\n            toIndex,\n        });\n    }\n    return internalPeaks;\n}\nfunction getNormalizedValue(value, parameter, property, minMaxY, baseline) {\n    if (parameter === 'y') {\n        if (property === 'gradientDifference') {\n            return value;\n        }\n        else {\n            return baseline !== undefined\n                ? (value - baseline) / minMaxY.range\n                : (value - minMaxY.min) / minMaxY.range;\n        }\n    }\n    return value;\n}\n//# sourceMappingURL=getInternalPeaks.js.map","import { isAnyArray } from 'is-any-array';\nexport default function checkOptions(data, parameterizedFunction, options) {\n    let { timeout, minValues, maxValues, initialValues, weights = 1, damping = 1e-2, dampingStepUp = 11, dampingStepDown = 9, maxIterations = 100, errorTolerance = 1e-7, centralDifference = false, gradientDifference = 10e-2, improvementThreshold = 1e-3, } = options;\n    if (damping <= 0) {\n        throw new Error('The damping option must be a positive number');\n    }\n    else if (!data.x || !data.y) {\n        throw new Error('The data parameter must have x and y elements');\n    }\n    else if (!isAnyArray(data.x) ||\n        data.x.length < 2 ||\n        !isAnyArray(data.y) ||\n        data.y.length < 2) {\n        throw new Error('The data parameter elements must be an array with more than 2 points');\n    }\n    else if (data.x.length !== data.y.length) {\n        throw new Error('The data parameter elements must have the same size');\n    }\n    let parameters = initialValues || new Array(parameterizedFunction.length).fill(1);\n    let nbPoints = data.y.length;\n    let parLen = parameters.length;\n    maxValues = maxValues || new Array(parLen).fill(Number.MAX_SAFE_INTEGER);\n    minValues = minValues || new Array(parLen).fill(Number.MIN_SAFE_INTEGER);\n    if (maxValues.length !== minValues.length) {\n        throw new Error('minValues and maxValues must be the same size');\n    }\n    if (!isAnyArray(parameters)) {\n        throw new Error('initialValues must be an array');\n    }\n    if (typeof gradientDifference === 'number') {\n        gradientDifference = new Array(parameters.length).fill(gradientDifference);\n    }\n    else if (isAnyArray(gradientDifference)) {\n        if (gradientDifference.length !== parLen) {\n            gradientDifference = new Array(parLen).fill(gradientDifference[0]);\n        }\n    }\n    else {\n        throw new Error('gradientDifference should be a number or array with length equal to the number of parameters');\n    }\n    let filler;\n    if (typeof weights === 'number') {\n        let value = 1 / weights ** 2;\n        filler = () => value;\n    }\n    else if (isAnyArray(weights)) {\n        if (weights.length < data.x.length) {\n            let value = 1 / weights[0] ** 2;\n            filler = () => value;\n        }\n        else {\n            filler = (i) => 1 / weights[i] ** 2;\n        }\n    }\n    else {\n        throw new Error('weights should be a number or array with length equal to the number of data points');\n    }\n    let checkTimeout;\n    if (timeout !== undefined) {\n        if (typeof timeout !== 'number') {\n            throw new Error('timeout should be a number');\n        }\n        let endTime = Date.now() + timeout * 1000;\n        checkTimeout = () => Date.now() > endTime;\n    }\n    else {\n        checkTimeout = () => false;\n    }\n    let weightSquare = new Array(data.x.length);\n    for (let i = 0; i < nbPoints; i++) {\n        weightSquare[i] = filler(i);\n    }\n    return {\n        checkTimeout,\n        minValues,\n        maxValues,\n        parameters,\n        weightSquare,\n        damping,\n        dampingStepUp,\n        dampingStepDown,\n        maxIterations,\n        errorTolerance,\n        centralDifference,\n        gradientDifference,\n        improvementThreshold,\n    };\n}\n//# sourceMappingURL=checkOptions.js.map","/**\n * the sum of the weighted squares of the errors (or weighted residuals) between the data.y\n * and the curve-fit function.\n * @ignore\n * @param {{x:ArrayLike<number>, y:ArrayLike<number>}} data - Array of points to fit in the format [x1, x2, ... ], [y1, y2, ... ]\n * @param {ArrayLike<number>} parameters - Array of current parameter values\n * @param {function} parameterizedFunction - The parameters and returns a function with the independent variable as a parameter\n * @param {ArrayLike<number>} weightSquare - Square of weights\n * @return {number}\n */\nexport default function errorCalculation(data, parameters, parameterizedFunction, weightSquare) {\n    let error = 0;\n    const func = parameterizedFunction(parameters);\n    for (let i = 0; i < data.x.length; i++) {\n        error += Math.pow(data.y[i] - func(data.x[i]), 2) / weightSquare[i];\n    }\n    return error;\n}\n//# sourceMappingURL=errorCalculation.js.map","import { Matrix } from 'ml-matrix';\n/**\n * Difference of the matrix function over the parameters\n * @ignore\n * @param {{x:ArrayLike<number>, y:ArrayLike<number>}} data - Array of points to fit in the format [x1, x2, ... ], [y1, y2, ... ]\n * @param {ArrayLike<number>} evaluatedData - Array of previous evaluated function values\n * @param {Array<number>} params - Array of previous parameter values\n * @param {number|array} gradientDifference - The step size to approximate the jacobian matrix\n * @param {boolean} centralDifference - If true the jacobian matrix is approximated by central differences otherwise by forward differences\n * @param {function} paramFunction - The parameters and returns a function with the independent variable as a parameter\n * @return {Matrix}\n */\nexport default function gradientFunction(data, evaluatedData, params, gradientDifference, paramFunction, centralDifference) {\n    const nbParams = params.length;\n    const nbPoints = data.x.length;\n    let ans = Matrix.zeros(nbParams, nbPoints);\n    let rowIndex = 0;\n    for (let param = 0; param < nbParams; param++) {\n        if (gradientDifference[param] === 0)\n            continue;\n        let delta = gradientDifference[param];\n        let auxParams = params.slice();\n        auxParams[param] += delta;\n        let funcParam = paramFunction(auxParams);\n        if (!centralDifference) {\n            for (let point = 0; point < nbPoints; point++) {\n                ans.set(rowIndex, point, (evaluatedData[point] - funcParam(data.x[point])) / delta);\n            }\n        }\n        else {\n            auxParams = params.slice();\n            auxParams[param] -= delta;\n            delta *= 2;\n            let funcParam2 = paramFunction(auxParams);\n            for (let point = 0; point < nbPoints; point++) {\n                ans.set(rowIndex, point, (funcParam2(data.x[point]) - funcParam(data.x[point])) / delta);\n            }\n        }\n        rowIndex++;\n    }\n    return ans;\n}\n//# sourceMappingURL=gradientFunction.js.map","import { inverse, Matrix } from 'ml-matrix';\nimport gradientFunction from './gradientFunction';\n/**\n * Matrix function over the samples\n * @ignore\n * @param {{x:ArrayLike<number>, y:ArrayLike<number>}} data - Array of points to fit in the format [x1, x2, ... ], [y1, y2, ... ]\n * @param {ArrayLike<number>} evaluatedData - Array of previous evaluated function values\n * @return {Matrix}\n */\nfunction matrixFunction(data, evaluatedData) {\n    const m = data.x.length;\n    let ans = new Matrix(m, 1);\n    for (let point = 0; point < m; point++) {\n        ans.set(point, 0, data.y[point] - evaluatedData[point]);\n    }\n    return ans;\n}\n/**\n * Iteration for Levenberg-Marquardt\n * @ignore\n * @param {{x:ArrayLike<number>, y:ArrayLike<number>}} data - Array of points to fit in the format [x1, x2, ... ], [y1, y2, ... ]\n * @param {Array<number>} params - Array of previous parameter values\n * @param {number} damping - Levenberg-Marquardt parameter\n * @param {number|array} gradientDifference - The step size to approximate the jacobian matrix\n * @param {boolean} centralDifference - If true the jacobian matrix is approximated by central differences otherwise by forward differences\n * @param {function} parameterizedFunction - The parameters and returns a function with the independent variable as a parameter\n */\nexport default function step(data, params, damping, gradientDifference, parameterizedFunction, centralDifference, weights) {\n    let value = damping;\n    let identity = Matrix.eye(params.length, params.length, value);\n    const func = parameterizedFunction(params);\n    let evaluatedData = new Float64Array(data.x.length);\n    for (let i = 0; i < data.x.length; i++) {\n        evaluatedData[i] = func(data.x[i]);\n    }\n    let gradientFunc = gradientFunction(data, evaluatedData, params, gradientDifference, parameterizedFunction, centralDifference);\n    let residualError = matrixFunction(data, evaluatedData);\n    let inverseMatrix = inverse(identity.add(gradientFunc.mmul(gradientFunc.transpose().scale('row', { scale: weights }))));\n    let jacobianWeightResidualError = gradientFunc.mmul(residualError.scale('row', { scale: weights }));\n    let perturbations = inverseMatrix.mmul(jacobianWeightResidualError);\n    return {\n        perturbations,\n        jacobianWeightResidualError,\n    };\n}\n//# sourceMappingURL=step.js.map","import checkOptions from './checkOptions';\nimport errorCalculation from './errorCalculation';\nimport step from './step';\n/**\n * Curve fitting algorithm\n * @param {{x:ArrayLike<number>, y:ArrayLike<number>}} data - Array of points to fit in the format [x1, x2, ... ], [y1, y2, ... ]\n * @param {function} parameterizedFunction - The parameters and returns a function with the independent variable as a parameter\n * @param {object} [options] - Options object\n * @param {number|ArrayLike<number>} [options.weights = 1] - weighting vector, if the length does not match with the number of data points, the vector is reconstructed with first value.\n * @param {number} [options.damping = 1e-2] - Levenberg-Marquardt parameter, small values of the damping parameter λ result in a Gauss-Newton update and large\nvalues of λ result in a gradient descent update\n * @param {number} [options.dampingStepDown = 9] - factor to reduce the damping (Levenberg-Marquardt parameter) when there is not an improvement when updating parameters.\n * @param {number} [options.dampingStepUp = 11] - factor to increase the damping (Levenberg-Marquardt parameter) when there is an improvement when updating parameters.\n * @param {number} [options.improvementThreshold = 1e-3] - the threshold to define an improvement through an update of parameters\n * @param {number|ArrayLike<number>} [options.gradientDifference = 10e-2] - The step size to approximate the jacobian matrix\n * @param {boolean} [options.centralDifference = false] - If true the jacobian matrix is approximated by central differences otherwise by forward differences\n * @param {ArrayLike<number>} [options.minValues] - Minimum allowed values for parameters\n * @param {ArrayLike<number>} [options.maxValues] - Maximum allowed values for parameters\n * @param {ArrayLike<number>} [options.initialValues] - Array of initial parameter values\n * @param {number} [options.maxIterations = 100] - Maximum of allowed iterations\n * @param {number} [options.errorTolerance = 10e-3] - Minimum uncertainty allowed for each point.\n * @param {number} [options.timeout] - maximum time running before throw in seconds.\n * @return {{parameterValues: Array<number>, parameterError: number, iterations: number}}\n */\nexport function levenbergMarquardt(data, parameterizedFunction, options = {}) {\n    let { checkTimeout, minValues, maxValues, parameters, weightSquare, damping, dampingStepUp, dampingStepDown, maxIterations, errorTolerance, centralDifference, gradientDifference, improvementThreshold, } = checkOptions(data, parameterizedFunction, options);\n    let error = errorCalculation(data, parameters, parameterizedFunction, weightSquare);\n    let optimalError = error;\n    let optimalParameters = parameters.slice();\n    let converged = error <= errorTolerance;\n    let iteration = 0;\n    for (; iteration < maxIterations && !converged; iteration++) {\n        let previousError = error;\n        let { perturbations, jacobianWeightResidualError } = step(data, parameters, damping, gradientDifference, parameterizedFunction, centralDifference, weightSquare);\n        for (let k = 0; k < parameters.length; k++) {\n            parameters[k] = Math.min(Math.max(minValues[k], parameters[k] - perturbations.get(k, 0)), maxValues[k]);\n        }\n        error = errorCalculation(data, parameters, parameterizedFunction, weightSquare);\n        if (isNaN(error))\n            break;\n        if (error < optimalError - errorTolerance) {\n            optimalError = error;\n            optimalParameters = parameters.slice();\n        }\n        let improvementMetric = (previousError - error) /\n            perturbations\n                .transpose()\n                .mmul(perturbations.mul(damping).add(jacobianWeightResidualError))\n                .get(0, 0);\n        if (improvementMetric > improvementThreshold) {\n            damping = Math.max(damping / dampingStepDown, 1e-7);\n        }\n        else {\n            damping = Math.min(damping * dampingStepUp, 1e7);\n        }\n        if (checkTimeout()) {\n            throw new Error(`The execution time is over to ${options.timeout} seconds`);\n        }\n        converged = error <= errorTolerance;\n    }\n    return {\n        parameterValues: optimalParameters,\n        parameterError: optimalError,\n        iterations: iteration,\n    };\n}\n//# sourceMappingURL=index.js.map","/**\n * Preparata, F. P., & Shamos, M. I. (2012). Computational geometry: an introduction. Springer Science & Business Media.\n * @param {Array} x - The array with x coordinates of the points.\n * @param {Array} y - The array with y coordinates of the points.\n * @return {Array} The indices of the points of anticlockwise lower convex hull\n * @private\n */\nexport default function antiLowerConvexHull(x, y) {\n  if (x.length !== y.length) {\n    throw new RangeError('X and Y vectors has different dimensions');\n  }\n\n  const nbPoints = x.length - 1;\n  if (nbPoints === 0) return [0];\n  if (nbPoints === 1) return [0, 1];\n\n  let currentPoint = 0;\n  let result = new Array(x.length).fill(true);\n  while (true) {\n    const a = currentPoint;\n    const b = moveOn(currentPoint, nbPoints, result);\n    const c = moveOn(moveOn(currentPoint, nbPoints, result), nbPoints, result);\n\n    const det =\n      x[c] * (y[a] - y[b]) + x[a] * (y[b] - y[c]) + x[b] * (y[c] - y[a]);\n\n    const leftTurn = det >= 0;\n\n    if (leftTurn) {\n      currentPoint = b;\n    } else {\n      result[b] = false;\n      currentPoint = moveBack(currentPoint, nbPoints, result);\n    }\n    if (c === nbPoints) break;\n  }\n\n  return result\n    .map((item, index) => (item === false ? false : index))\n    .filter((item) => item !== false);\n}\n\n/**\n * @param {number} currentPoint - The index of the current point to make the move\n * @param {number} nbPoints - The total number of points in the array\n * @param {Array} vector - The array with the points\n * @return {number} the index of the point after the move\n * @private\n */\n\nfunction moveBack(currentPoint, nbPoints, vector) {\n  let counter = currentPoint - 1;\n  while (vector[counter] === false) counter--;\n  return currentPoint === 0 ? nbPoints : counter;\n}\n\nfunction moveOn(currentPoint, nbPoints, vector) {\n  let counter = currentPoint + 1;\n  while (vector[counter] === false) counter++;\n  return currentPoint === nbPoints ? 0 : counter;\n}\n","import { xNorm, xMaxValue, xMinValue } from 'ml-spectra-processing';\n\nimport antiLowerConvexHull from './util/antiLowerConvexHull';\n\n/**\n * Performs a global optimization of required parameters\n * It will return an object containing:\n * - `minFunctionValue`: The minimum value found for the objetive function\n * - `optima`: Array of Array of values for all the variables where the function reach its minimum value\n * - `iterations`: Number of iterations performed in the process\n * - `finalState`: Internal state allowing to continue optimization (initialState)\n * @param {function} objectiveFunction Function to evaluate. It should accept an array of variables\n * @param {Array} lowerBoundaries Array containing for each variable the lower boundary\n * @param {Array} upperBoundaries Array containing for each variable the higher boundary\n * @param {Object} [options={}]\n * @param {number} [options.iterations] - Number of iterations.\n * @param {number} [options.epsilon] - Tolerance to choose best current value.\n * @param {number} [options.tolerance] - Minimum tollerance of the function.\n * @param {number} [options.tolerance2] - Minimum tollerance of the function.\n * @param {Object} [options.initialState={}}] - finalState of previous optimization.\n * @return {Object} {finalState, iterations, minFunctionValue}\n * */\n\nexport default function direct(\n  objectiveFunction,\n  lowerBoundaries,\n  upperBoundaries,\n  options = {},\n) {\n  const {\n    iterations = 50,\n    epsilon = 1e-4,\n    tolerance = 1e-16,\n    tolerance2 = 1e-12,\n    initialState = {},\n  } = options;\n\n  if (\n    objectiveFunction === undefined ||\n    lowerBoundaries === undefined ||\n    upperBoundaries === undefined\n  ) {\n    throw new RangeError('There is something undefined');\n  }\n\n  lowerBoundaries = new Float64Array(lowerBoundaries);\n  upperBoundaries = new Float64Array(upperBoundaries);\n\n  if (lowerBoundaries.length !== upperBoundaries.length) {\n    throw new Error(\n      'Lower bounds and Upper bounds for x are not of the same length',\n    );\n  }\n\n  //-------------------------------------------------------------------------\n  //                        STEP 1. Initialization\n  //-------------------------------------------------------------------------\n  let n = lowerBoundaries.length;\n  let diffBorders = upperBoundaries.map((x, i) => x - lowerBoundaries[i]);\n\n  let {\n    numberOfRectangles = 0,\n    totalIterations = 0,\n    unitaryCoordinates = [new Float64Array(n).fill(0.5)],\n    middlePoint = new Float64Array(n).map((value, index) => {\n      return (\n        lowerBoundaries[index] +\n        unitaryCoordinates[0][index] * diffBorders[index]\n      );\n    }),\n    bestCurrentValue = objectiveFunction(middlePoint),\n    fCalls = 1,\n    smallerDistance = 0,\n    edgeSizes = [new Float64Array(n).fill(0.5)],\n    diagonalDistances = [Math.sqrt(n * Math.pow(0.5, 2))],\n    functionValues = [bestCurrentValue],\n    differentDistances = diagonalDistances,\n    smallerValuesByDistance = [bestCurrentValue],\n    choiceLimit = undefined,\n  } = initialState;\n  if (\n    initialState.originalCoordinates &&\n    initialState.originalCoordinates.length > 0\n  ) {\n    bestCurrentValue = xMinValue(functionValues);\n    choiceLimit =\n      epsilon * Math.abs(bestCurrentValue) > 1e-8\n        ? epsilon * Math.abs(bestCurrentValue)\n        : 1e-8;\n\n    smallerDistance = getMinIndex(\n      functionValues,\n      diagonalDistances,\n      choiceLimit,\n      bestCurrentValue,\n    );\n\n    unitaryCoordinates = initialState.originalCoordinates.slice();\n    for (let j = 0; j < unitaryCoordinates.length; j++) {\n      for (let i = 0; i < lowerBoundaries.length; i++) {\n        unitaryCoordinates[j][i] =\n          (unitaryCoordinates[j][i] - lowerBoundaries[i]) / diffBorders[i];\n      }\n    }\n  }\n\n  let iteration = 0;\n  //-------------------------------------------------------------------------\n  //                          Iteration loop\n  //-------------------------------------------------------------------------\n\n  while (iteration < iterations) {\n    //----------------------------------------------------------------------\n    //  STEP 2. Identify the set S of all potentially optimal rectangles\n    //----------------------------------------------------------------------\n\n    let S1 = [];\n    let idx = differentDistances.findIndex(\n      // eslint-disable-next-line no-loop-func\n      (e) => e === diagonalDistances[smallerDistance],\n    );\n    let counter = 0;\n    for (let i = idx; i < differentDistances.length; i++) {\n      for (let f = 0; f < functionValues.length; f++) {\n        if (\n          (functionValues[f] === smallerValuesByDistance[i]) &\n          (diagonalDistances[f] === differentDistances[i])\n        ) {\n          S1[counter++] = f;\n        }\n      }\n    }\n\n    let optimumValuesIndex, S3;\n    if (differentDistances.length - idx > 1) {\n      let a1 = diagonalDistances[smallerDistance];\n      let b1 = functionValues[smallerDistance];\n      let a2 = differentDistances[differentDistances.length - 1];\n      let b2 = smallerValuesByDistance[differentDistances.length - 1];\n      let slope = (b2 - b1) / (a2 - a1);\n      let constant = b1 - slope * a1;\n      let S2 = new Uint32Array(counter);\n      counter = 0;\n      for (let i = 0; i < S2.length; i++) {\n        let j = S1[i];\n        if (\n          functionValues[j] <=\n          slope * diagonalDistances[j] + constant + tolerance2\n        ) {\n          S2[counter++] = j;\n        }\n      }\n\n      let xHull = [];\n      let yHull = [];\n      for (let i = 0; i < counter; i++) {\n        xHull.push(diagonalDistances[S2[i]]);\n        yHull.push(functionValues[S2[i]]);\n      }\n\n      let lowerIndexHull = antiLowerConvexHull(xHull, yHull);\n\n      S3 = [];\n      for (let i = 0; i < lowerIndexHull.length; i++) {\n        S3.push(S2[lowerIndexHull[i]]);\n      }\n    } else {\n      S3 = S1.slice(0, counter);\n    }\n    optimumValuesIndex = S3;\n    //--------------------------------------------------------------\n    // STEPS 3,5: Select any rectangle j in S\n    //--------------------------------------------------------------\n    for (let k = 0; k < optimumValuesIndex.length; k++) {\n      let j = optimumValuesIndex[k];\n      let largerSide = xMaxValue(edgeSizes[j]);\n      let largeSidesIndex = new Uint32Array(edgeSizes[j].length);\n      counter = 0;\n      for (let i = 0; i < edgeSizes[j].length; i++) {\n        if (Math.abs(edgeSizes[j][i] - largerSide) < tolerance) {\n          largeSidesIndex[counter++] = i;\n        }\n      }\n      let delta = (2 * largerSide) / 3;\n      let bestFunctionValues = [];\n      for (let r = 0; r < counter; r++) {\n        let i = largeSidesIndex[r];\n        let firstMiddleCenter = unitaryCoordinates[j].slice();\n        let secondMiddleCenter = unitaryCoordinates[j].slice();\n        firstMiddleCenter[i] += delta;\n        secondMiddleCenter[i] -= delta;\n        let firstMiddleValue = new Float64Array(firstMiddleCenter.length);\n        let secondMiddleValue = new Float64Array(secondMiddleCenter.length);\n        for (let i = 0; i < firstMiddleCenter.length; i++) {\n          firstMiddleValue[i] =\n            lowerBoundaries[i] + firstMiddleCenter[i] * diffBorders[i];\n          secondMiddleValue[i] =\n            lowerBoundaries[i] + secondMiddleCenter[i] * diffBorders[i];\n        }\n        let firstMinValue = objectiveFunction(firstMiddleValue);\n        let secondMinValue = objectiveFunction(secondMiddleValue);\n        fCalls += 2;\n        bestFunctionValues.push({\n          minValue: Math.min(firstMinValue, secondMinValue),\n          index: r,\n        });\n        // [Math.min(firstMinValue, secondMinValue), r];\n        unitaryCoordinates.push(firstMiddleCenter, secondMiddleCenter);\n        functionValues.push(firstMinValue, secondMinValue);\n      }\n\n      let b = bestFunctionValues.sort((a, b) => a.minValue - b.minValue);\n      for (let r = 0; r < counter; r++) {\n        let u = largeSidesIndex[b[r].index];\n        let ix1 = numberOfRectangles + 2 * (b[r].index + 1) - 1;\n        let ix2 = numberOfRectangles + 2 * (b[r].index + 1);\n        edgeSizes[j][u] = delta / 2;\n        edgeSizes[ix1] = edgeSizes[j].slice();\n        edgeSizes[ix2] = edgeSizes[j].slice();\n        diagonalDistances[j] = xNorm(edgeSizes[j]);\n        diagonalDistances[ix1] = diagonalDistances[j];\n        diagonalDistances[ix2] = diagonalDistances[j];\n      }\n      numberOfRectangles += 2 * counter;\n    }\n\n    //--------------------------------------------------------------\n    //                  Update\n    //--------------------------------------------------------------\n\n    bestCurrentValue = xMinValue(functionValues);\n\n    choiceLimit =\n      epsilon * Math.abs(bestCurrentValue) > 1e-8\n        ? epsilon * Math.abs(bestCurrentValue)\n        : 1e-8;\n\n    smallerDistance = getMinIndex(\n      functionValues,\n      diagonalDistances,\n      choiceLimit,\n      bestCurrentValue,\n      iteration,\n    );\n\n    differentDistances = Array.from(new Set(diagonalDistances));\n    differentDistances = differentDistances.sort((a, b) => a - b);\n\n    smallerValuesByDistance = [];\n    for (let i = 0; i < differentDistances.length; i++) {\n      let minIndex;\n      let minValue = Number.POSITIVE_INFINITY;\n      for (let k = 0; k < diagonalDistances.length; k++) {\n        if (diagonalDistances[k] === differentDistances[i]) {\n          if (functionValues[k] < minValue) {\n            minValue = functionValues[k];\n            minIndex = k;\n          }\n        }\n      }\n      smallerValuesByDistance.push(functionValues[minIndex]);\n    }\n\n    let currentMin = [];\n    for (let j = 0; j < functionValues.length; j++) {\n      if (functionValues[j] === bestCurrentValue) {\n        let temp = [];\n        for (let i = 0; i < lowerBoundaries.length; i++) {\n          temp.push(\n            lowerBoundaries[i] + unitaryCoordinates[j][i] * diffBorders[i],\n          );\n        }\n        currentMin.push(temp);\n      }\n    }\n    iteration += 1;\n  }\n  //--------------------------------------------------------------\n  //                  Saving results\n  //--------------------------------------------------------------\n\n  let result = {};\n  result.minFunctionValue = bestCurrentValue;\n  result.iterations = iteration;\n  let originalCoordinates = [];\n  for (let j = 0; j < numberOfRectangles + 1; j++) {\n    let pair = [];\n    for (let i = 0; i < lowerBoundaries.length; i++) {\n      pair.push(lowerBoundaries[i] + unitaryCoordinates[j][i] * diffBorders[i]);\n    }\n    originalCoordinates.push(pair);\n  }\n\n  result.finalState = {\n    numberOfRectangles,\n    totalIterations: (totalIterations += iterations),\n    originalCoordinates,\n    middlePoint,\n    fCalls,\n    smallerDistance,\n    edgeSizes,\n    diagonalDistances,\n    functionValues,\n    differentDistances,\n    smallerValuesByDistance,\n    choiceLimit,\n  };\n\n  let minimizer = [];\n  for (let i = 0; i < functionValues.length; i++) {\n    if (functionValues[i] === bestCurrentValue) {\n      minimizer.push(originalCoordinates[i]);\n    }\n  }\n\n  result.optima = minimizer;\n  return result;\n}\n\nfunction getMinIndex(\n  functionValues,\n  diagonalDistances,\n  choiceLimit,\n  bestCurrentValue,\n) {\n  let item = [];\n  for (let i = 0; i < functionValues.length; i++) {\n    item[i] =\n      Math.abs(functionValues[i] - (bestCurrentValue + choiceLimit)) /\n      diagonalDistances[i];\n  }\n  const min = xMinValue(item);\n  let result = item.findIndex((x) => x === min);\n  return result;\n}\n","import direct from 'ml-direct';\nexport function directOptimization(data, sumOfShapes, options) {\n    const { minValues, maxValues, maxIterations, epsilon, tolerance, tolerance2, initialState, } = options;\n    const objectiveFunction = getObjectiveFunction(data, sumOfShapes);\n    const result = direct(objectiveFunction, minValues, maxValues, {\n        iterations: maxIterations,\n        epsilon,\n        tolerance,\n        tolerance2,\n        initialState,\n    });\n    const { optima } = result;\n    return {\n        parameterError: result.minFunctionValue,\n        iterations: result.iterations,\n        parameterValues: optima[0],\n    };\n}\nfunction getObjectiveFunction(data, sumOfShapes) {\n    const { x, y } = data;\n    const nbPoints = x.length;\n    return (parameters) => {\n        const fct = sumOfShapes(parameters);\n        let error = 0;\n        for (let i = 0; i < nbPoints; i++) {\n            error += Math.pow(y[i] - fct(x[i]), 2);\n        }\n        return error;\n    };\n}\n//# sourceMappingURL=directOptimization.js.map","import { levenbergMarquardt } from 'ml-levenberg-marquardt';\nimport { directOptimization } from './wrappers/directOptimization';\n/** Algorithm to select the method.\n * @param optimizationOptions - Optimization options\n * @returns - The algorithm and optimization options\n */\nexport function selectMethod(optimizationOptions = {}) {\n    let { kind = 'lm', options } = optimizationOptions;\n    switch (kind) {\n        case 'lm':\n        case 'levenbergMarquardt':\n            return {\n                algorithm: levenbergMarquardt,\n                optimizationOptions: {\n                    damping: 1.5,\n                    maxIterations: 100,\n                    errorTolerance: 1e-8,\n                    ...options,\n                },\n            };\n        case 'direct': {\n            return {\n                algorithm: directOptimization,\n                optimizationOptions: {\n                    iterations: 20,\n                    epsilon: 1e-4,\n                    tolerance: 1e-16,\n                    tolerance2: 1e-12,\n                    initialState: {},\n                    ...options,\n                },\n            };\n        }\n        default:\n            throw new Error(`Unknown fitting algorithm`);\n    }\n}\n//# sourceMappingURL=selectMethod.js.map","import { xMinMaxValues } from 'ml-spectra-processing';\nimport { getSumOfShapes } from './shapes/getSumOfShapes';\nimport { getInternalPeaks } from './util/internalPeaks/getInternalPeaks';\nimport { selectMethod } from './util/selectMethod';\n/**\n * Fits a set of points to the sum of a set of bell functions.\n *\n * @param data - An object containing the x and y data to be fitted.\n * @param peaks - A list of initial parameters to be optimized. e.g. coming from a peak picking [{x, y, width}].\n * @param options - Options for optimize\n * @returns - An object with fitting error and the list of optimized parameters { parameters: [ {x, y, width} ], error } if the kind of shape is pseudoVoigt mu parameter is optimized.\n */\nexport function optimize(data, peaks, options = {}) {\n    // rescale data\n    let temp = xMinMaxValues(data.y);\n    const minMaxY = { ...temp, range: temp.max - temp.min };\n    const internalPeaks = getInternalPeaks(peaks, minMaxY, options);\n    // need to rescale what is related to Y\n    const { baseline: shiftValue = minMaxY.min } = options;\n    let normalizedY = new Float64Array(data.y.length);\n    for (let i = 0; i < data.y.length; i++) {\n        normalizedY[i] = (data.y[i] - shiftValue) / minMaxY.range;\n    }\n    const nbParams = internalPeaks[internalPeaks.length - 1].toIndex + 1;\n    const minValues = new Float64Array(nbParams);\n    const maxValues = new Float64Array(nbParams);\n    const initialValues = new Float64Array(nbParams);\n    const gradientDifferences = new Float64Array(nbParams);\n    let index = 0;\n    for (const peak of internalPeaks) {\n        for (let i = 0; i < peak.parameters.length; i++) {\n            minValues[index] = peak.propertiesValues.min[i];\n            maxValues[index] = peak.propertiesValues.max[i];\n            initialValues[index] = peak.propertiesValues.init[i];\n            gradientDifferences[index] = peak.propertiesValues.gradientDifference[i];\n            index++;\n        }\n    }\n    let { algorithm, optimizationOptions } = selectMethod(options.optimization);\n    let sumOfShapes = getSumOfShapes(internalPeaks);\n    let fitted = algorithm({ x: data.x, y: normalizedY }, sumOfShapes, {\n        minValues,\n        maxValues,\n        initialValues,\n        gradientDifference: gradientDifferences,\n        ...optimizationOptions,\n    });\n    const fittedValues = fitted.parameterValues;\n    let newPeaks = [];\n    for (let peak of internalPeaks) {\n        const { id, shape, parameters, fromIndex } = peak;\n        let newPeak = { x: 0, y: 0, shape };\n        if (id) {\n            newPeak = { ...newPeak, id };\n        }\n        newPeak.x = fittedValues[fromIndex];\n        newPeak.y = fittedValues[fromIndex + 1] * minMaxY.range + shiftValue;\n        for (let i = 2; i < parameters.length; i++) {\n            //@ts-expect-error should be fixed once\n            newPeak.shape[parameters[i]] = fittedValues[fromIndex + i];\n        }\n        newPeaks.push(newPeak);\n    }\n    return {\n        error: fitted.parameterError,\n        iterations: fitted.iterations,\n        peaks: newPeaks,\n    };\n}\n//# sourceMappingURL=index.js.map","import { getShape1D } from 'ml-peak-shape-generator';\nconst { parse, stringify } = JSON;\n/**\n * add missing property if it does not exist in the peak,\n * if shape exists but fwhm doesn't, it will be calculated from peak.width\n */\nexport function addMissingShape(peaks, options = {}) {\n    const { shape = { kind: 'gaussian' }, output = parse(stringify(peaks)) } = options;\n    let shapeInstance = getShape1D(shape);\n    return output.map((peak) => {\n        if (hasShape(peak)) {\n            if (!('fwhm' in peak.shape)) {\n                const shapeInstance = getShape1D(peak.shape);\n                peak.shape.fwhm = shapeInstance.widthToFWHM(peak.width);\n            }\n            return peak;\n        }\n        return {\n            ...peak,\n            shape: { fwhm: shapeInstance.widthToFWHM(peak.width), ...shape },\n        };\n    });\n}\nfunction hasShape(peak) {\n    return 'shape' in peak;\n}\n//# sourceMappingURL=addMissingShape.js.map","/**\n * Group peaks based on factor\n * In order to group peaks we only need the x and width value. This means that\n * in the current implementation we don't take into account the asymmetry of peaks\n */\nexport function groupPeaks(peaks, options = {}) {\n    if (peaks && peaks.length === 0)\n        return [];\n    const { factor = 1 } = options;\n    peaks = JSON.parse(JSON.stringify(peaks));\n    peaks.sort((a, b) => a.x - b.x);\n    let previousPeak = peaks[0];\n    let currentGroup = [previousPeak];\n    let groups = [currentGroup];\n    for (let i = 1; i < peaks.length; i++) {\n        const peak = peaks[i];\n        if ((peak.x - previousPeak.x) / ((peak.width + previousPeak.width) / 2) <=\n            factor) {\n            currentGroup.push(peak);\n        }\n        else {\n            currentGroup = [peak];\n            groups.push(currentGroup);\n        }\n        previousPeak = peak;\n    }\n    return groups;\n}\n//# sourceMappingURL=groupPeaks.js.map","import { getShape1D } from 'ml-peak-shape-generator';\nimport { optimize } from 'ml-spectra-fitting';\nimport { xGetFromToIndex } from 'ml-spectra-processing';\nimport { addMissingShape } from '../utils/addMissingShape';\nimport { groupPeaks } from '../utils/groupPeaks';\n/**\n * Optimize the position (x), max intensity (y), full width at half maximum (fwhm)\n * and the ratio of gaussian contribution (mu) if it's required. It currently supports three kind of shapes: gaussian, lorentzian and pseudovoigt\n * @param data - An object containing the x and y data to be fitted.\n * @param peakList - A list of initial parameters to be optimized. e.g. coming from a peak picking [{x, y, width}].\n */\nexport function optimizePeaksWithLogs(data, peakList, options = {}) {\n    const { fromTo = {}, baseline, shape = { kind: 'gaussian' }, groupingFactor = 1, factorLimits = 2, optimization = {\n        kind: 'lm',\n        options: {\n            timeout: 10,\n        },\n    }, } = options;\n    /*\n    The optimization algorithm will take some group of peaks.\n    We can not simply optimize everything because there would be too many variables to optimize\n    and it would be too time consuming.\n  */\n    let groups = groupPeaks(peakList, { factor: groupingFactor });\n    let logs = [];\n    let results = [];\n    groups.forEach((peakGroup) => {\n        const start = Date.now();\n        // In order to make optimization we will add fwhm and shape on all the peaks\n        const peaks = addMissingShape(peakGroup, { shape });\n        const firstPeak = peaks[0];\n        const lastPeak = peaks[peaks.length - 1];\n        const { from = firstPeak.x - firstPeak.width * factorLimits, to = lastPeak.x + lastPeak.width * factorLimits, } = fromTo;\n        const { fromIndex, toIndex } = xGetFromToIndex(data.x, { from, to });\n        const x = data.x instanceof Float64Array\n            ? data.x.subarray(fromIndex, toIndex)\n            : data.x.slice(fromIndex, toIndex);\n        const y = data.y instanceof Float64Array\n            ? data.y.subarray(fromIndex, toIndex)\n            : data.y.slice(fromIndex, toIndex);\n        const log = {\n            range: { from, to },\n            parameters: optimization,\n            groupSize: peakGroup.length,\n            time: Date.now() - start,\n        };\n        if (x.length > 5) {\n            const { iterations, error, peaks: optimizedPeaks, } = optimize({ x, y }, peaks, {\n                shape,\n                baseline,\n                optimization,\n            });\n            for (let i = 0; i < peaks.length; i++) {\n                results.push({\n                    ...optimizedPeaks[i],\n                    width: getShape1D(peaks[i].shape).fwhmToWidth(optimizedPeaks[i].shape.fwhm),\n                });\n            }\n            logs.push({\n                ...log,\n                iterations,\n                error,\n                message: 'optimization successful',\n            });\n        }\n        else {\n            results.push(...peaks);\n            logs.push({\n                ...log,\n                iterations: 0,\n                message: 'x length too small for optimization',\n            });\n        }\n    });\n    return { logs, optimizedPeaks: results };\n}\n//# sourceMappingURL=optimizePeaksWithLogs.js.map","import { optimizePeaksWithLogs } from './optimizePeaksWithLogs';\n/**\n * Optimize the position (x), max intensity (y), full width at half maximum (fwhm)\n * and the ratio of gaussian contribution (mu) if it's required. It currently supports three kind of shapes: gaussian, lorentzian and pseudovoigt\n * @param data - An object containing the x and y data to be fitted.\n * @param peakList - A list of initial parameters to be optimized. e.g. coming from a peak picking [{x, y, width}].\n */\nexport function optimizePeaks(data, peakList, options = {}) {\n    return optimizePeaksWithLogs(data, peakList, options).optimizedPeaks;\n}\n//# sourceMappingURL=optimizePeaks.js.map","import { v4 as generateID } from '@lukeed/uuid';\nconst { parse, stringify } = JSON;\nexport function addMissingIDs(peaks, options = {}) {\n    const { output = parse(stringify(peaks)) } = options;\n    for (const peak of output) {\n        if (!('id' in peak)) {\n            peak.id = generateID();\n        }\n    }\n    return output;\n}\n//# sourceMappingURL=addMissingIDs.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport { addMissingIDs } from '../utils/addMissingIDs';\nimport { addMissingShape } from '../utils/addMissingShape';\nimport { optimizePeaks } from './optimizePeaks';\nexport function joinBroadPeaks(peakList, options = {}) {\n    let { shape = { kind: 'gaussian' }, optimization = { kind: 'lm', options: { timeout: 10 } }, broadWidth = 0.25, broadRatio = 0.0025, } = options;\n    let max = 0;\n    let maxI = 0;\n    let count = 1;\n    const broadLines = [];\n    if (peakList.length < 2) {\n        return addMissingIDs(addMissingShape(peakList.map(getGSDPeakOptimizedStructure), { shape }));\n    }\n    let maxDdy = peakList[0].ddY;\n    for (let i = 1; i < peakList.length; i++) {\n        if (Math.abs(peakList[i].ddY) > maxDdy)\n            maxDdy = Math.abs(peakList[i].ddY);\n    }\n    const newPeaks = [];\n    for (const peak of peakList) {\n        if (Math.abs(peak.ddY) <= broadRatio * maxDdy) {\n            broadLines.push(peak);\n        }\n        else {\n            newPeaks.push(getGSDPeakOptimizedStructure(peak));\n        }\n    }\n    //@ts-expect-error Push a feke peak\n    broadLines.push({ x: Number.MAX_VALUE, y: 0 });\n    let candidates = {\n        x: [broadLines[0].x],\n        y: [broadLines[0].y],\n    };\n    let indexes = [0];\n    for (let i = 1; i < broadLines.length; i++) {\n        if (Math.abs(broadLines[i - 1].x - broadLines[i].x) < broadWidth) {\n            candidates.x.push(broadLines[i].x);\n            candidates.y.push(broadLines[i].y);\n            if (broadLines[i].y > max) {\n                max = broadLines[i].y;\n                maxI = i;\n            }\n            indexes.push(i);\n            count++;\n        }\n        else {\n            if (count > 2) {\n                let fitted = optimizePeaks(candidates, [\n                    {\n                        id: generateID(),\n                        x: broadLines[maxI].x,\n                        y: max,\n                        width: candidates.x[0] - candidates.x[candidates.x.length - 1],\n                    },\n                ], { shape, optimization });\n                newPeaks.push(fitted[0]);\n            }\n            else {\n                // Put back the candidates to the peak list\n                for (const index of indexes) {\n                    newPeaks.push(getGSDPeakOptimizedStructure(broadLines[index]));\n                }\n            }\n            candidates = { x: [broadLines[i].x], y: [broadLines[i].y] };\n            indexes = [i];\n            max = broadLines[i].y;\n            maxI = i;\n            count = 1;\n        }\n    }\n    newPeaks.sort((a, b) => {\n        return a.x - b.x;\n    });\n    return addMissingIDs(newPeaks, { output: newPeaks });\n}\nfunction getGSDPeakOptimizedStructure(peak) {\n    const { id, shape, x, y, width } = peak;\n    let newPeak = {\n        x,\n        y,\n        width,\n        shape,\n    };\n    if (id)\n        newPeak.id = id;\n    return newPeak;\n}\n//# sourceMappingURL=joinBroadPeaks.js.map","import { getShape1D } from 'ml-peak-shape-generator';\nconst { parse, stringify } = JSON;\n/**\n * Append 2 properties to the peaks, shape and fwhm\n */\nexport function setShape(peaks, options = {}) {\n    let { shape = { kind: 'gaussian' }, output = parse(stringify(peaks)), } = options;\n    let shapeInstance = getShape1D(shape);\n    return output.map((peak) => ({\n        ...peak,\n        shape: { fwhm: shapeInstance.widthToFWHM(peak.width), ...shape },\n    }));\n}\n//# sourceMappingURL=setShape.js.map","import { addMissingShape } from 'ml-gsd';\nimport { getShape1D } from 'ml-peak-shape-generator';\nimport { peaksToXY } from './peaksToXY';\nexport function peakToXY(peak, options) {\n    const newPeak = addMissingShape([peak])[0];\n    const factor = getShape1D(newPeak.shape).getFactor();\n    const { from = newPeak.x - (peak.width * factor) / options.frequency, to = newPeak.x + (peak.width * factor) / options.frequency, } = options;\n    return peaksToXY([peak], { ...options, from, to });\n}\n//# sourceMappingURL=peakToXY.js.map","var global = typeof self !== 'undefined' ? self : this;\nvar __self__ = (function () {\nfunction F() {\nthis.fetch = false;\nthis.DOMException = global.DOMException\n}\nF.prototype = global;\nreturn new F();\n})();\n(function(self) {\n\nvar irrelevant = (function (exports) {\n\n  var support = {\n    searchParams: 'URLSearchParams' in self,\n    iterable: 'Symbol' in self && 'iterator' in Symbol,\n    blob:\n      'FileReader' in self &&\n      'Blob' in self &&\n      (function() {\n        try {\n          new Blob();\n          return true\n        } catch (e) {\n          return false\n        }\n      })(),\n    formData: 'FormData' in self,\n    arrayBuffer: 'ArrayBuffer' in self\n  };\n\n  function isDataView(obj) {\n    return obj && DataView.prototype.isPrototypeOf(obj)\n  }\n\n  if (support.arrayBuffer) {\n    var viewClasses = [\n      '[object Int8Array]',\n      '[object Uint8Array]',\n      '[object Uint8ClampedArray]',\n      '[object Int16Array]',\n      '[object Uint16Array]',\n      '[object Int32Array]',\n      '[object Uint32Array]',\n      '[object Float32Array]',\n      '[object Float64Array]'\n    ];\n\n    var isArrayBufferView =\n      ArrayBuffer.isView ||\n      function(obj) {\n        return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1\n      };\n  }\n\n  function normalizeName(name) {\n    if (typeof name !== 'string') {\n      name = String(name);\n    }\n    if (/[^a-z0-9\\-#$%&'*+.^_`|~]/i.test(name)) {\n      throw new TypeError('Invalid character in header field name')\n    }\n    return name.toLowerCase()\n  }\n\n  function normalizeValue(value) {\n    if (typeof value !== 'string') {\n      value = String(value);\n    }\n    return value\n  }\n\n  // Build a destructive iterator for the value list\n  function iteratorFor(items) {\n    var iterator = {\n      next: function() {\n        var value = items.shift();\n        return {done: value === undefined, value: value}\n      }\n    };\n\n    if (support.iterable) {\n      iterator[Symbol.iterator] = function() {\n        return iterator\n      };\n    }\n\n    return iterator\n  }\n\n  function Headers(headers) {\n    this.map = {};\n\n    if (headers instanceof Headers) {\n      headers.forEach(function(value, name) {\n        this.append(name, value);\n      }, this);\n    } else if (Array.isArray(headers)) {\n      headers.forEach(function(header) {\n        this.append(header[0], header[1]);\n      }, this);\n    } else if (headers) {\n      Object.getOwnPropertyNames(headers).forEach(function(name) {\n        this.append(name, headers[name]);\n      }, this);\n    }\n  }\n\n  Headers.prototype.append = function(name, value) {\n    name = normalizeName(name);\n    value = normalizeValue(value);\n    var oldValue = this.map[name];\n    this.map[name] = oldValue ? oldValue + ', ' + value : value;\n  };\n\n  Headers.prototype['delete'] = function(name) {\n    delete this.map[normalizeName(name)];\n  };\n\n  Headers.prototype.get = function(name) {\n    name = normalizeName(name);\n    return this.has(name) ? this.map[name] : null\n  };\n\n  Headers.prototype.has = function(name) {\n    return this.map.hasOwnProperty(normalizeName(name))\n  };\n\n  Headers.prototype.set = function(name, value) {\n    this.map[normalizeName(name)] = normalizeValue(value);\n  };\n\n  Headers.prototype.forEach = function(callback, thisArg) {\n    for (var name in this.map) {\n      if (this.map.hasOwnProperty(name)) {\n        callback.call(thisArg, this.map[name], name, this);\n      }\n    }\n  };\n\n  Headers.prototype.keys = function() {\n    var items = [];\n    this.forEach(function(value, name) {\n      items.push(name);\n    });\n    return iteratorFor(items)\n  };\n\n  Headers.prototype.values = function() {\n    var items = [];\n    this.forEach(function(value) {\n      items.push(value);\n    });\n    return iteratorFor(items)\n  };\n\n  Headers.prototype.entries = function() {\n    var items = [];\n    this.forEach(function(value, name) {\n      items.push([name, value]);\n    });\n    return iteratorFor(items)\n  };\n\n  if (support.iterable) {\n    Headers.prototype[Symbol.iterator] = Headers.prototype.entries;\n  }\n\n  function consumed(body) {\n    if (body.bodyUsed) {\n      return Promise.reject(new TypeError('Already read'))\n    }\n    body.bodyUsed = true;\n  }\n\n  function fileReaderReady(reader) {\n    return new Promise(function(resolve, reject) {\n      reader.onload = function() {\n        resolve(reader.result);\n      };\n      reader.onerror = function() {\n        reject(reader.error);\n      };\n    })\n  }\n\n  function readBlobAsArrayBuffer(blob) {\n    var reader = new FileReader();\n    var promise = fileReaderReady(reader);\n    reader.readAsArrayBuffer(blob);\n    return promise\n  }\n\n  function readBlobAsText(blob) {\n    var reader = new FileReader();\n    var promise = fileReaderReady(reader);\n    reader.readAsText(blob);\n    return promise\n  }\n\n  function readArrayBufferAsText(buf) {\n    var view = new Uint8Array(buf);\n    var chars = new Array(view.length);\n\n    for (var i = 0; i < view.length; i++) {\n      chars[i] = String.fromCharCode(view[i]);\n    }\n    return chars.join('')\n  }\n\n  function bufferClone(buf) {\n    if (buf.slice) {\n      return buf.slice(0)\n    } else {\n      var view = new Uint8Array(buf.byteLength);\n      view.set(new Uint8Array(buf));\n      return view.buffer\n    }\n  }\n\n  function Body() {\n    this.bodyUsed = false;\n\n    this._initBody = function(body) {\n      this._bodyInit = body;\n      if (!body) {\n        this._bodyText = '';\n      } else if (typeof body === 'string') {\n        this._bodyText = body;\n      } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {\n        this._bodyBlob = body;\n      } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {\n        this._bodyFormData = body;\n      } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {\n        this._bodyText = body.toString();\n      } else if (support.arrayBuffer && support.blob && isDataView(body)) {\n        this._bodyArrayBuffer = bufferClone(body.buffer);\n        // IE 10-11 can't handle a DataView body.\n        this._bodyInit = new Blob([this._bodyArrayBuffer]);\n      } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {\n        this._bodyArrayBuffer = bufferClone(body);\n      } else {\n        this._bodyText = body = Object.prototype.toString.call(body);\n      }\n\n      if (!this.headers.get('content-type')) {\n        if (typeof body === 'string') {\n          this.headers.set('content-type', 'text/plain;charset=UTF-8');\n        } else if (this._bodyBlob && this._bodyBlob.type) {\n          this.headers.set('content-type', this._bodyBlob.type);\n        } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {\n          this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');\n        }\n      }\n    };\n\n    if (support.blob) {\n      this.blob = function() {\n        var rejected = consumed(this);\n        if (rejected) {\n          return rejected\n        }\n\n        if (this._bodyBlob) {\n          return Promise.resolve(this._bodyBlob)\n        } else if (this._bodyArrayBuffer) {\n          return Promise.resolve(new Blob([this._bodyArrayBuffer]))\n        } else if (this._bodyFormData) {\n          throw new Error('could not read FormData body as blob')\n        } else {\n          return Promise.resolve(new Blob([this._bodyText]))\n        }\n      };\n\n      this.arrayBuffer = function() {\n        if (this._bodyArrayBuffer) {\n          return consumed(this) || Promise.resolve(this._bodyArrayBuffer)\n        } else {\n          return this.blob().then(readBlobAsArrayBuffer)\n        }\n      };\n    }\n\n    this.text = function() {\n      var rejected = consumed(this);\n      if (rejected) {\n        return rejected\n      }\n\n      if (this._bodyBlob) {\n        return readBlobAsText(this._bodyBlob)\n      } else if (this._bodyArrayBuffer) {\n        return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))\n      } else if (this._bodyFormData) {\n        throw new Error('could not read FormData body as text')\n      } else {\n        return Promise.resolve(this._bodyText)\n      }\n    };\n\n    if (support.formData) {\n      this.formData = function() {\n        return this.text().then(decode)\n      };\n    }\n\n    this.json = function() {\n      return this.text().then(JSON.parse)\n    };\n\n    return this\n  }\n\n  // HTTP methods whose capitalization should be normalized\n  var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'];\n\n  function normalizeMethod(method) {\n    var upcased = method.toUpperCase();\n    return methods.indexOf(upcased) > -1 ? upcased : method\n  }\n\n  function Request(input, options) {\n    options = options || {};\n    var body = options.body;\n\n    if (input instanceof Request) {\n      if (input.bodyUsed) {\n        throw new TypeError('Already read')\n      }\n      this.url = input.url;\n      this.credentials = input.credentials;\n      if (!options.headers) {\n        this.headers = new Headers(input.headers);\n      }\n      this.method = input.method;\n      this.mode = input.mode;\n      this.signal = input.signal;\n      if (!body && input._bodyInit != null) {\n        body = input._bodyInit;\n        input.bodyUsed = true;\n      }\n    } else {\n      this.url = String(input);\n    }\n\n    this.credentials = options.credentials || this.credentials || 'same-origin';\n    if (options.headers || !this.headers) {\n      this.headers = new Headers(options.headers);\n    }\n    this.method = normalizeMethod(options.method || this.method || 'GET');\n    this.mode = options.mode || this.mode || null;\n    this.signal = options.signal || this.signal;\n    this.referrer = null;\n\n    if ((this.method === 'GET' || this.method === 'HEAD') && body) {\n      throw new TypeError('Body not allowed for GET or HEAD requests')\n    }\n    this._initBody(body);\n  }\n\n  Request.prototype.clone = function() {\n    return new Request(this, {body: this._bodyInit})\n  };\n\n  function decode(body) {\n    var form = new FormData();\n    body\n      .trim()\n      .split('&')\n      .forEach(function(bytes) {\n        if (bytes) {\n          var split = bytes.split('=');\n          var name = split.shift().replace(/\\+/g, ' ');\n          var value = split.join('=').replace(/\\+/g, ' ');\n          form.append(decodeURIComponent(name), decodeURIComponent(value));\n        }\n      });\n    return form\n  }\n\n  function parseHeaders(rawHeaders) {\n    var headers = new Headers();\n    // Replace instances of \\r\\n and \\n followed by at least one space or horizontal tab with a space\n    // https://tools.ietf.org/html/rfc7230#section-3.2\n    var preProcessedHeaders = rawHeaders.replace(/\\r?\\n[\\t ]+/g, ' ');\n    preProcessedHeaders.split(/\\r?\\n/).forEach(function(line) {\n      var parts = line.split(':');\n      var key = parts.shift().trim();\n      if (key) {\n        var value = parts.join(':').trim();\n        headers.append(key, value);\n      }\n    });\n    return headers\n  }\n\n  Body.call(Request.prototype);\n\n  function Response(bodyInit, options) {\n    if (!options) {\n      options = {};\n    }\n\n    this.type = 'default';\n    this.status = options.status === undefined ? 200 : options.status;\n    this.ok = this.status >= 200 && this.status < 300;\n    this.statusText = 'statusText' in options ? options.statusText : 'OK';\n    this.headers = new Headers(options.headers);\n    this.url = options.url || '';\n    this._initBody(bodyInit);\n  }\n\n  Body.call(Response.prototype);\n\n  Response.prototype.clone = function() {\n    return new Response(this._bodyInit, {\n      status: this.status,\n      statusText: this.statusText,\n      headers: new Headers(this.headers),\n      url: this.url\n    })\n  };\n\n  Response.error = function() {\n    var response = new Response(null, {status: 0, statusText: ''});\n    response.type = 'error';\n    return response\n  };\n\n  var redirectStatuses = [301, 302, 303, 307, 308];\n\n  Response.redirect = function(url, status) {\n    if (redirectStatuses.indexOf(status) === -1) {\n      throw new RangeError('Invalid status code')\n    }\n\n    return new Response(null, {status: status, headers: {location: url}})\n  };\n\n  exports.DOMException = self.DOMException;\n  try {\n    new exports.DOMException();\n  } catch (err) {\n    exports.DOMException = function(message, name) {\n      this.message = message;\n      this.name = name;\n      var error = Error(message);\n      this.stack = error.stack;\n    };\n    exports.DOMException.prototype = Object.create(Error.prototype);\n    exports.DOMException.prototype.constructor = exports.DOMException;\n  }\n\n  function fetch(input, init) {\n    return new Promise(function(resolve, reject) {\n      var request = new Request(input, init);\n\n      if (request.signal && request.signal.aborted) {\n        return reject(new exports.DOMException('Aborted', 'AbortError'))\n      }\n\n      var xhr = new XMLHttpRequest();\n\n      function abortXhr() {\n        xhr.abort();\n      }\n\n      xhr.onload = function() {\n        var options = {\n          status: xhr.status,\n          statusText: xhr.statusText,\n          headers: parseHeaders(xhr.getAllResponseHeaders() || '')\n        };\n        options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL');\n        var body = 'response' in xhr ? xhr.response : xhr.responseText;\n        resolve(new Response(body, options));\n      };\n\n      xhr.onerror = function() {\n        reject(new TypeError('Network request failed'));\n      };\n\n      xhr.ontimeout = function() {\n        reject(new TypeError('Network request failed'));\n      };\n\n      xhr.onabort = function() {\n        reject(new exports.DOMException('Aborted', 'AbortError'));\n      };\n\n      xhr.open(request.method, request.url, true);\n\n      if (request.credentials === 'include') {\n        xhr.withCredentials = true;\n      } else if (request.credentials === 'omit') {\n        xhr.withCredentials = false;\n      }\n\n      if ('responseType' in xhr && support.blob) {\n        xhr.responseType = 'blob';\n      }\n\n      request.headers.forEach(function(value, name) {\n        xhr.setRequestHeader(name, value);\n      });\n\n      if (request.signal) {\n        request.signal.addEventListener('abort', abortXhr);\n\n        xhr.onreadystatechange = function() {\n          // DONE (success or failure)\n          if (xhr.readyState === 4) {\n            request.signal.removeEventListener('abort', abortXhr);\n          }\n        };\n      }\n\n      xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit);\n    })\n  }\n\n  fetch.polyfill = true;\n\n  if (!self.fetch) {\n    self.fetch = fetch;\n    self.Headers = Headers;\n    self.Request = Request;\n    self.Response = Response;\n  }\n\n  exports.Headers = Headers;\n  exports.Request = Request;\n  exports.Response = Response;\n  exports.fetch = fetch;\n\n  Object.defineProperty(exports, '__esModule', { value: true });\n\n  return exports;\n\n})({});\n})(__self__);\n__self__.fetch.ponyfill = true;\n// Remove \"polyfill\" property added by whatwg-fetch\ndelete __self__.fetch.polyfill;\n// Choose between native implementation (global) or custom implementation (__self__)\n// var ctx = global.fetch ? global : __self__;\nvar ctx = __self__; // this line disable service worker support temporarily\nexports = ctx.fetch // To enable: import fetch from 'cross-fetch'\nexports.default = ctx.fetch // For TypeScript consumers without esModuleInterop.\nexports.fetch = ctx.fetch // To enable: import {fetch} from 'cross-fetch'\nexports.Headers = ctx.Headers\nexports.Request = ctx.Request\nexports.Response = ctx.Response\nmodule.exports = exports\n","/* eslint-env browser */\nmodule.exports = typeof self == 'object' ? self.FormData : window.FormData;\n","let xAtomicNumber = 0;\n\n/**\n * Tag an atom to be able to visualize it\n * @param {OCL.Molecule} molecule\n * @param {number} iAtom\n */\nexport function tagAtom(molecule, iAtom) {\n  let customLabel = `${molecule.getAtomLabel(iAtom)}*`;\n  molecule.setAtomCustomLabel(iAtom, customLabel);\n  if (molecule.getAtomicNo(iAtom) === 1) {\n    molecule.setAtomicNo(iAtom, getXAtomicNumber(molecule));\n  } else {\n    // we can not use X because we would have problems with valencies if it is\n    // expanded hydrogens or not\n    // we can not only use a custom label because it does not count for the canonisation\n    molecule.setAtomMass(iAtom, molecule.getAtomMass(iAtom) + 5);\n  }\n  return customLabel;\n}\n\nfunction getXAtomicNumber(molecule) {\n  if (!xAtomicNumber) {\n    const OCL = molecule.getOCL();\n    xAtomicNumber = OCL.Molecule.getAtomicNoFromLabel('X');\n  }\n  return xAtomicNumber;\n}\n","import { tagAtom } from '../util/tagAtom';\n\n/**\n * Add either missing chirality of diastereotopic missing chirality\n * The problem is that sometimes we need to add chiral bond that was not planned because it is the same group\n * This is the case for example for the valine where the 2 C of the methyl groups are diastereotopic\n * @param {OCL.Molecule} molecule\n * @param {object} [options={}]\n * @param {number} [options.esrType=cESRTypeAnd]\n */\nexport function addDiastereotopicMissingChirality(molecule, options = {}) {\n  const { Molecule } = molecule.getOCL();\n  const { esrType = Molecule.cESRTypeAnd } = options;\n\n  for (let iAtom = 0; iAtom < molecule.getAllAtoms(); iAtom++) {\n    let tempMolecule = molecule.getCompactCopy();\n    tagAtom(tempMolecule, iAtom);\n    // After copy, helpers must be recalculated\n    tempMolecule.ensureHelperArrays(Molecule.cHelperBitsStereo);\n    // We need to have >0 and not >1 because there could be unspecified chirality in racemate\n\n    for (let i = 0; i < tempMolecule.getAtoms(); i++) {\n      // changed from from handling below; TLS 9.Nov.2015\n      if (\n        tempMolecule.isAtomStereoCenter(i) &&\n        tempMolecule.getStereoBond(i) === -1\n      ) {\n        let stereoBond = tempMolecule.getAtomPreferredStereoBond(i);\n        if (stereoBond !== -1) {\n          molecule.setBondType(stereoBond, Molecule.cBondTypeUp);\n          if (molecule.getBondAtom(1, stereoBond) === i) {\n            let connAtom = molecule.getBondAtom(0, stereoBond);\n            molecule.setBondAtom(0, stereoBond, i);\n            molecule.setBondAtom(1, stereoBond, connAtom);\n          }\n          // To me it seems that we have to add all stereo centers into AND group 0. TLS 9.Nov.2015\n          molecule.setAtomESR(i, esrType, 0);\n        }\n      }\n    }\n  }\n}\n","/**\n *\n * @param {OCL.Molecule} [molecule] An instance of a molecule\n * @param {object} [options={}]\n * @param {object} [options.OCL] openchemlib library\n */\nexport function makeRacemic(molecule) {\n  const { Molecule } = molecule.getOCL();\n\n  // if we don't calculate this we have 2 epimers\n  molecule.ensureHelperArrays(Molecule.cHelperCIP);\n\n  // we need to make one group \"AND\" for chiral (to force to racemic, this means diastereotopic and not enantiotopic)\n  for (let i = 0; i < molecule.getAllAtoms(); i++) {\n    if (molecule.getAtomParity(i) !== Molecule.cAtomParityNone) {\n      molecule.setAtomESR(i, Molecule.cESRTypeAnd, 0); // changed to group 0; TLS 9.Nov.2015\n    }\n  }\n}\n","import { makeRacemic } from '../util/makeRacemic';\nimport { tagAtom } from '../util/tagAtom';\n\nimport { addDiastereotopicMissingChirality } from './addDiastereotopicMissingChirality';\n\n/**\n * Returns an array of diastereotopic ID (as oclCode)\n * @param {OCL.Molecule} molecule\n */\nexport function getDiastereotopicAtomIDs(molecule) {\n  const OCL = molecule.getOCL();\n  addDiastereotopicMissingChirality(molecule);\n\n  let numberAtoms = molecule.getAllAtoms();\n  let ids = [];\n  for (let iAtom = 0; iAtom < numberAtoms; iAtom++) {\n    let tempMolecule = molecule.getCompactCopy();\n    tagAtom(tempMolecule, iAtom);\n    makeRacemic(tempMolecule);\n    // We need to ensure the helper array in order to get correctly the result of racemisation\n    ids[iAtom] = tempMolecule.getCanonizedIDCode(\n      OCL.Molecule.CANONIZER_ENCODE_ATOM_CUSTOM_LABELS,\n    );\n  }\n  return ids;\n}\n","export function groupDiastereotopicAtomIDs(diaIDs, molecule, options) {\n  const { atomLabel } = options;\n  const diaIDsObject = {};\n  for (let i = 0; i < diaIDs.length; i++) {\n    if (!atomLabel || molecule.getAtomLabel(i) === atomLabel) {\n      let diaID = diaIDs[i];\n      if (!diaIDsObject[diaID]) {\n        diaIDsObject[diaID] = {\n          counter: 0,\n          atoms: [],\n          oclID: diaID,\n          atomLabel: molecule.getAtomLabel(i),\n        };\n      }\n      diaIDsObject[diaID].counter++;\n      diaIDsObject[diaID].atoms.push(i);\n    }\n  }\n\n  return Object.keys(diaIDsObject).map((key) => diaIDsObject[key]);\n}\n","import { getDiastereotopicAtomIDs } from './getDiastereotopicAtomIDs';\nimport { groupDiastereotopicAtomIDs } from './groupDiastereotopicAtomIDs';\n/**\n * This function groups the diasterotopic atomIds of the molecule based on equivalence of atoms. The output object contains\n * a set of chemically equivalent atoms(element.atoms) and the groups of magnetically equivalent atoms (element.magneticGroups)\n * @param {OCL.Molecule} molecule\n * @param {object} [options={}]\n * @param {string} [options.atomLabel] Select atoms of the given atomLabel. By default it returns all the explicit atoms in the molecule\n * @returns {Array}\n */\n\nexport function getGroupedDiastereotopicAtomIDs(molecule, options = {}) {\n  let diaIDs = getDiastereotopicAtomIDs(molecule);\n  return groupDiastereotopicAtomIDs(diaIDs, molecule, options);\n}\n","/**\n * Check if a specific atom is a sp3 carbon\n * @param {OCL.Molecule} molecule\n * @param {number} atomID\n */\n\nexport function isCsp3(molecule, atomID) {\n  if (molecule.getAtomicNo(atomID) !== 6) return false;\n  if (molecule.getAtomCharge(atomID) !== 0) return false;\n  if (\n    molecule.getImplicitHydrogens(atomID) + molecule.getConnAtoms(atomID) !==\n    4\n  ) {\n    return false;\n  }\n  return true;\n}\n","import { isCsp3 } from '../util/isCsp3';\nimport { makeRacemic } from '../util/makeRacemic';\nimport { tagAtom } from '../util/tagAtom';\n\nexport const FULL_HOSE_CODE = 1;\nexport const HOSE_CODE_CUT_C_SP3_SP3 = 2;\n\n/**\n * Returns the hose code for a specific atom number\n * @param {OCL.Molecule} originalMolecule\n * @param {array<number>} rootAtoms\n * @param {object} [options={}]\n * @param {boolean} [options.isTagged] Specify is the atoms are already tagged\n * @param {number} [options.minSphereSize=0] Smallest hose code sphere\n * @param {number} [options.maxSphereSize=4] Largest hose code sphere\n * @param {number} [options.kind=FULL_HOSE_CODE] Kind of hose code, default usual sphere\n */\nexport function getHoseCodesForAtoms(\n  originalMolecule,\n  rootAtoms = [],\n  options = {},\n) {\n  const OCL = originalMolecule.getOCL();\n  const {\n    minSphereSize = 0,\n    maxSphereSize = 4,\n    kind = FULL_HOSE_CODE,\n    isTagged = false,\n  } = options;\n\n  const molecule = originalMolecule.getCompactCopy();\n\n  if (!isTagged) {\n    const tags = [];\n    for (let i = 0; i < rootAtoms.length; i++) {\n      let rootAtom = rootAtoms[i];\n      tags.push(tagAtom(molecule, rootAtom));\n      molecule.addImplicitHydrogens();\n      molecule.addMissingChirality();\n      molecule.ensureHelperArrays(OCL.Molecule.cHelperNeighbours);\n      // because ensuring helper reorder atoms we need to look again for it\n    }\n    rootAtoms.length = 0;\n    for (let j = 0; j < molecule.getAllAtoms(); j++) {\n      if (tags.includes(molecule.getAtomCustomLabel(j))) {\n        rootAtoms.push(j);\n      }\n    }\n  }\n\n  let fragment = new OCL.Molecule(0, 0);\n  let results = [];\n  let min = 0;\n  let max = 0;\n  let atomMask = new Array(molecule.getAllAtoms());\n  let atomList = new Array(molecule.getAllAtoms());\n\n  for (let sphere = 0; sphere <= maxSphereSize; sphere++) {\n    if (max === 0) {\n      for (let rootAtom of rootAtoms) {\n        atomList[max] = rootAtom;\n        atomMask[rootAtom] = true;\n        max++;\n      }\n    } else {\n      let newMax = max;\n      for (let i = min; i < max; i++) {\n        let atom = atomList[i];\n        for (let j = 0; j < molecule.getAllConnAtoms(atom); j++) {\n          let connAtom = molecule.getConnAtom(atom, j);\n          if (!atomMask[connAtom]) {\n            switch (kind) {\n              case FULL_HOSE_CODE:\n                atomMask[connAtom] = true;\n                atomList[newMax++] = connAtom;\n                break;\n              case HOSE_CODE_CUT_C_SP3_SP3:\n                if (!(isCsp3(molecule, atom) && isCsp3(molecule, connAtom))) {\n                  atomMask[connAtom] = true;\n                  atomList[newMax++] = connAtom;\n                }\n                break;\n              default:\n                throw new Error('getHoseCoesForAtom unknown kind');\n            }\n          }\n        }\n      }\n      min = max;\n      max = newMax;\n    }\n    molecule.copyMoleculeByAtoms(fragment, atomMask, true, null);\n    if (sphere >= minSphereSize) {\n      makeRacemic(fragment);\n      results.push(\n        fragment.getCanonizedIDCode(\n          OCL.Molecule.CANONIZER_ENCODE_ATOM_CUSTOM_LABELS,\n        ),\n      );\n    }\n  }\n  return results;\n}\n","import { getHoseCodesForAtoms } from './getHoseCodesForAtoms.js';\n\n/**\n * Returns the hose code for a specific atom number\n * @param {OCL.Molecule} originalMolecule\n * @param {number} rootAtom\n * @param {object} [options={}]\n * @param {boolean} [options.isTagged] Specify is the atom is already tagged\n * @param {number} [options.minSphereSize=0] Smallest hose code sphere\n * @param {number} [options.maxSphereSize=4] Largest hose code sphere\n * @param {number} [options.kind=FULL_HOSE_CODE] Kind of hose code, default usual sphere\n */\nexport function getHoseCodesForAtom(originalMolecule, rootAtom, options = {}) {\n  return getHoseCodesForAtoms(originalMolecule, [rootAtom], options);\n}\n","import { getHoseCodesForAtom } from './getHoseCodesForAtom';\n/**\n * Returns the hose code for a specific marked atom\n * @param {OCL.Molecule} diastereotopicID\n * @param {object} options\n */\n\nexport function getHoseCodesFromDiastereotopicID(molecule, options = {}) {\n  molecule.addImplicitHydrogens();\n  molecule.addMissingChirality();\n\n  // One of the atom has to be marked !\n  let atomID = -1;\n  for (let i = 0; i < molecule.getAllAtoms(); i++) {\n    // we need to find the marked atom\n    const atomCustomLabel = molecule.getAtomCustomLabel(i);\n    if (atomCustomLabel != null && atomCustomLabel.endsWith('*')) {\n      atomID = i;\n      break;\n    }\n  }\n  if (atomID >= 0) {\n    options.isTagged = true;\n    return getHoseCodesForAtom(molecule, atomID, options);\n  }\n  return undefined;\n}\n","import { makeRacemic } from '../util/makeRacemic';\nimport { tagAtom } from '../util/tagAtom';\n\nlet fragment;\n\n/**\n * Returns the hose code for a specific atom number\n * @param {OCL.Molecule} molecule\n */\nexport function getHoseCodesForPath(molecule, from, to, maxLength) {\n  const OCL = molecule.getOCL();\n  const originalFrom = from;\n  const originalTo = to;\n  molecule = molecule.getCompactCopy();\n\n  let originalAtoms = []; // path before renumbering\n  molecule.getPath(originalAtoms, from, to, maxLength + 1);\n  let torsion;\n  if (originalAtoms.length === 4) {\n    torsion = molecule.calculateTorsion(originalAtoms);\n  }\n\n  const tag1 = tagAtom(molecule, from);\n  const tag2 = tagAtom(molecule, to);\n\n  molecule.addImplicitHydrogens();\n  molecule.addMissingChirality();\n\n  molecule.ensureHelperArrays(OCL.Molecule.cHelperNeighbours);\n\n  from = -1;\n  to = -1;\n  for (let i = 0; i < molecule.getAllAtoms(); i++) {\n    if (tag1 === tag2) {\n      if (molecule.getAtomCustomLabel(i) === tag1) {\n        if (from === -1) {\n          from = i;\n        } else {\n          to = i;\n        }\n      }\n    } else {\n      if (tag1 === molecule.getAtomCustomLabel(i)) {\n        from = i;\n      }\n      if (tag2 === molecule.getAtomCustomLabel(i)) {\n        to = i;\n      }\n    }\n  }\n\n  if (!fragment) fragment = new OCL.Molecule(0, 0);\n\n  let atoms = [];\n  molecule.getPath(atoms, from, to, maxLength + 1);\n\n  let min = 0;\n  let max = 0;\n  let atomMask = new Array(molecule.getAllAtoms()).fill(false);\n  let atomList = new Array(molecule.getAllAtoms()).fill(-1);\n  let hoses = [];\n\n  for (let sphere = 0; sphere <= 2; sphere++) {\n    if (max === 0) {\n      for (let atom of atoms) {\n        atomMask[atom] = true;\n        atomList[max++] = atom;\n      }\n    } else {\n      let newMax = max;\n      for (let i = min; i < max; i++) {\n        let atom = atomList[i];\n        for (let j = 0; j < molecule.getAllConnAtoms(atom); j++) {\n          let connAtom = molecule.getConnAtom(atom, j);\n          if (!atomMask[connAtom]) {\n            atomMask[connAtom] = true;\n            atomList[newMax++] = connAtom;\n          }\n        }\n      }\n      min = max;\n      max = newMax;\n    }\n    let atomMap = [];\n\n    molecule.copyMoleculeByAtoms(fragment, atomMask, true, atomMap);\n    makeRacemic(fragment);\n    let oclID = fragment.getCanonizedIDCode(\n      OCL.Molecule.CANONIZER_ENCODE_ATOM_CUSTOM_LABELS,\n    );\n\n    hoses.push({\n      sphere,\n      oclID,\n    });\n  }\n\n  return {\n    atoms: originalAtoms,\n    from: originalFrom,\n    to: originalTo,\n    torsion,\n    hoses,\n    length: originalAtoms.length - 1,\n  };\n}\n","import { getDiastereotopicAtomIDs } from '../diastereotopic/getDiastereotopicAtomIDs';\n\n/**\n * Returns various information about atoms in the molecule\n * @param {OCL.Molecule} [molecule]\n */\nexport function getAtomsInfo(molecule) {\n  const OCL = molecule.getOCL();\n  molecule.ensureHelperArrays(OCL.Molecule.cHelperRings);\n\n  let diaIDs = getDiastereotopicAtomIDs(molecule);\n\n  let results = [];\n  for (let i = 0; i < diaIDs.length; i++) {\n    let result = {\n      oclID: diaIDs[i],\n      extra: {\n        singleBonds: 0,\n        doubleBonds: 0,\n        tripleBonds: 0,\n        aromaticBonds: 0,\n        cnoHybridation: 0, // should be 1 (sp), 2 (sp2) or 3 (sp3)\n      },\n    };\n    let extra = result.extra;\n    results.push(result);\n    result.abnormalValence = molecule.getAtomAbnormalValence(i); // -1 is normal otherwise specified\n    result.charge = molecule.getAtomCharge(i);\n    result.cipParity = molecule.getAtomCIPParity(i);\n    result.color = molecule.getAtomColor(i);\n    result.customLabel = molecule.getAtomCustomLabel(i);\n    //        result.esrGroup=molecule.getAtomESRGroup(i);\n    //        result.esrType=molecule.getAtomESRType(i);\n    result.atomicNo = molecule.getAtomicNo(i);\n    result.label = molecule.getAtomLabel(i);\n    //        result.list=molecule.getAtomList(i);\n    //        result.listString=molecule.getAtomListString(i);\n    //        result.mapNo=molecule.getAtomMapNo(i);\n    result.mass = molecule.getAtomMass(i);\n    //        result.parity=molecule.getAtomParity(i);\n    //        result.pi=molecule.getAtomPi(i);\n    //        result.preferredStereoBond=molecule.getAtomPreferredStereoBond(i);\n    //        result.queryFeatures=molecule.getAtomQueryFeatures(i);\n    result.radical = molecule.getAtomRadical(i);\n    result.ringBondCount = molecule.getAtomRingBondCount(i);\n    //        result.ringCount=molecule.getAtomRingCount(i);\n    result.ringSize = molecule.getAtomRingSize(i);\n    result.x = molecule.getAtomX(i);\n    result.y = molecule.getAtomY(i);\n    result.z = molecule.getAtomZ(i);\n    result.allHydrogens = molecule.getAllHydrogens(i);\n    result.connAtoms = molecule.getConnAtoms(i);\n    result.allConnAtoms = molecule.getAllConnAtoms(i);\n\n    result.implicitHydrogens =\n      result.allHydrogens + result.connAtoms - result.allConnAtoms;\n\n    result.isAromatic = molecule.isAromaticAtom(i);\n    result.isAllylic = molecule.isAllylicAtom(i);\n    result.isStereoCenter = molecule.isAtomStereoCenter(i);\n    result.isRing = molecule.isRingAtom(i);\n    result.isSmallRing = molecule.isSmallRingAtom(i);\n    result.isStabilized = molecule.isStabilizedAtom(i);\n\n    // todo HACK to circumvent bug in OCL that consider than an hydrogen is connected to itself\n    result.extra.singleBonds =\n      result.atomicNo === 1 ? 0 : result.implicitHydrogens;\n    for (let j = 0; j < molecule.getAllConnAtoms(i); j++) {\n      let bond = molecule.getConnBond(i, j);\n      let bondOrder = molecule.getBondOrder(bond);\n      if (molecule.isAromaticBond(bond)) {\n        extra.aromaticBonds++;\n      } else if (bondOrder === 1) {\n        // not an hydrogen\n        extra.singleBonds++;\n      } else if (bondOrder === 2) {\n        extra.doubleBonds++;\n      } else if (bondOrder === 3) {\n        extra.tripleBonds++;\n      }\n    }\n    result.extra.totalBonds =\n      result.extra.singleBonds +\n      result.extra.doubleBonds +\n      result.extra.tripleBonds +\n      result.extra.aromaticBonds;\n\n    if (result.atomicNo === 6) {\n      result.extra.cnoHybridation = result.extra.totalBonds - 1;\n    } else if (result.atomicNo === 7) {\n      result.extra.cnoHybridation = result.extra.totalBonds;\n    } else if (result.atomicNo === 8) {\n      result.extra.cnoHybridation = result.extra.totalBonds + 1;\n    } else if (result.atomicNo === 1) {\n      let connectedAtom =\n        molecule.getAllConnAtoms(i) === 0\n          ? 0\n          : molecule.getAtomicNo(molecule.getConnAtom(i, 0));\n      result.extra.hydrogenOnAtomicNo = connectedAtom;\n      if (connectedAtom === 7 || connectedAtom === 8) {\n        result.extra.labileHydrogen = true;\n      }\n    }\n  }\n  return results;\n}\n","import { Matrix } from 'ml-matrix';\n\n/**\n * Algorithm that finds the shortest distance from one node to the other\n * @param {Matrix} adjMatrix - A squared adjacency matrix\n * @return {Matrix} - Distance from a node to the other, -1 if the node is unreachable\n */\nexport function floydWarshall(adjMatrix) {\n  if (Matrix.isMatrix(adjMatrix) && adjMatrix.columns !== adjMatrix.rows) {\n    throw new TypeError('The adjacency matrix should be squared');\n  }\n  const numVertices = adjMatrix.columns;\n  let distMatrix = new Matrix(numVertices, numVertices);\n  distMatrix.apply((row, column) => {\n    // principal diagonal is 0\n    if (row === column) {\n      distMatrix.set(row, column, 0);\n    } else {\n      let val = adjMatrix.get(row, column);\n\n      if (val || Object.is(val, -0)) {\n        // edges values remain the same\n        distMatrix.set(row, column, val);\n      } else {\n        // 0 values become infinity\n        distMatrix.set(row, column, Number.POSITIVE_INFINITY);\n      }\n    }\n  });\n\n  for (let k = 0; k < numVertices; ++k) {\n    for (let i = 0; i < numVertices; ++i) {\n      for (let j = 0; j < numVertices; ++j) {\n        let dist = distMatrix.get(i, k) + distMatrix.get(k, j);\n        if (distMatrix.get(i, j) > dist) {\n          distMatrix.set(i, j, dist);\n        }\n      }\n    }\n  }\n\n  // When there's no connection the value is -1\n  distMatrix.apply((row, column) => {\n    if (distMatrix.get(row, column) === Number.POSITIVE_INFINITY) {\n      distMatrix.set(row, column, -1);\n    }\n  });\n  return distMatrix;\n}\n","import { floydWarshall } from 'ml-floyd-warshall';\nimport { Matrix } from 'ml-matrix';\n\n/**\n * Returns a connectivity matrix\n * @param {OCL.Molecule} molecule\n * @param {object} [options={}]\n * @param {boolean} [options.pathLength=false] get the path length between atoms\n * @param {boolean} [options.mass=false] set the nominal mass of the atoms on diagonal\n * @param {boolean} [options.atomicNo=false] set the atomic number of the atom on diagonal\n * @param {boolean} [options.negativeAtomicNo=false] set the atomic number * -1 of the atom on diagonal\n * @param {boolean} [options.sdt=false] set 1, 2 or 3 depending if single, double or triple bond\n * @param {boolean} [options.sdta=false] set 1, 2, 3 or 4 depending if single, double, triple or aromatic  bond\n */\nexport function getConnectivityMatrix(molecule, options = {}) {\n  const OCL = molecule.getOCL();\n  molecule.ensureHelperArrays(OCL.Molecule.cHelperNeighbours);\n  let nbAtoms = molecule.getAllAtoms();\n\n  let result = new Array(nbAtoms).fill();\n  result = result.map(() => new Array(nbAtoms).fill(0));\n\n  if (!options.pathLength) {\n    if (options.atomicNo) {\n      for (let i = 0; i < nbAtoms; i++) {\n        result[i][i] = molecule.getAtomicNo(i);\n      }\n    } else if (options.negativeAtomicNo) {\n      for (let i = 0; i < nbAtoms; i++) {\n        result[i][i] = -molecule.getAtomicNo(i);\n      }\n    } else if (options.mass) {\n      for (let i = 0; i < nbAtoms; i++) {\n        result[i][i] = OCL.Molecule.cRoundedMass[molecule.getAtomicNo(i)];\n      }\n    } else {\n      for (let i = 0; i < nbAtoms; i++) {\n        result[i][i] = 1;\n      }\n    }\n  }\n\n  if (options.sdt) {\n    for (let i = 0; i < nbAtoms; i++) {\n      let l = molecule.getAllConnAtoms(i);\n      for (let j = 0; j < l; j++) {\n        result[i][molecule.getConnAtom(i, j)] = molecule.getConnBondOrder(i, j);\n      }\n    }\n  } else if (options.sdta) {\n    for (let i = 0; i < nbAtoms; i++) {\n      let l = molecule.getAllConnAtoms(i);\n      for (let j = 0; j < l; j++) {\n        let bondNumber = molecule.getConnBond(i, j);\n        if (molecule.isAromaticBond(bondNumber)) {\n          result[i][molecule.getConnAtom(i, j)] = 4;\n        } else {\n          result[i][molecule.getConnAtom(i, j)] = molecule.getConnBondOrder(\n            i,\n            j,\n          );\n        }\n      }\n    }\n  } else {\n    for (let i = 0; i < nbAtoms; i++) {\n      let l = molecule.getAllConnAtoms(i);\n      for (let j = 0; j < l; j++) {\n        result[i][molecule.getConnAtom(i, j)] = 1;\n      }\n    }\n  }\n\n  if (options.pathLength) {\n    result = floydWarshall(new Matrix(result)).to2DArray();\n  }\n  return result;\n}\n","/**\n * Calculates the path between 2 atoms\n * @param {OCL.Molecule} molecule\n * @param {number} from - index of the first atom\n * @param {number} to - index of the end atom\n * @param {number} maxLength - maximal length of the path\n */\nexport function getPathAndTorsion(molecule, from, to, maxLength) {\n  let originalAtoms = []; // path before renumbering\n  molecule.getPath(originalAtoms, from, to, maxLength + 1);\n  let torsion;\n  if (originalAtoms.length === 4) {\n    torsion = molecule.calculateTorsion(originalAtoms);\n  }\n\n  return {\n    atoms: originalAtoms,\n    from,\n    to,\n    torsion,\n    length: originalAtoms.length - 1,\n  };\n}\n","import { getHoseCodesForPath } from '../hose/getHoseCodesForPath';\nimport { getAtomsInfo } from '../util/getAtomsInfo';\nimport { getConnectivityMatrix } from '../util/getConnectivityMatrix';\n\nimport { getPathAndTorsion } from './getPathAndTorsion.js';\n\nlet fragment;\n\n/**\n *\n * @param {OCL.Molecule} molecule\n * @param {object} [options={}]\n * @param {string} [options.fromLabel='H']\n * @param {string} [options.toLabel='H']\n * @param {number} [options.minLength=1]\n * @param {number} [options.maxLength=4]\n * @param {boolean} [options.withHOSES=false]\n\n */\nexport function getPathsInfo(molecule, options = {}) {\n  const {\n    fromLabel = 'H',\n    toLabel = 'H',\n    minLength = 1,\n    maxLength = 4,\n    withHOSES = false,\n  } = options;\n\n  const OCL = molecule.getOCL();\n\n  if (!fragment) {\n    fragment = new OCL.Molecule(0, 0);\n  }\n\n  let fromAtomicNumber = OCL.Molecule.getAtomicNoFromLabel(fromLabel);\n  let toAtomicNumber = OCL.Molecule.getAtomicNoFromLabel(toLabel);\n\n  // we need to find all the atoms 'fromLabel' and 'toLabel'\n  let atomsInfo = getAtomsInfo(molecule);\n\n  let pathLengthMatrix = getConnectivityMatrix(molecule, {\n    pathLength: true,\n  });\n\n  for (let from = 0; from < molecule.getAllAtoms(); from++) {\n    atomsInfo[from].paths = [];\n    for (let to = 0; to < molecule.getAllAtoms(); to++) {\n      if (from !== to) {\n        if (molecule.getAtomicNo(from) === fromAtomicNumber) {\n          if (molecule.getAtomicNo(to) === toAtomicNumber) {\n            let pathLength = pathLengthMatrix[from][to];\n            if (pathLength >= minLength && pathLength <= maxLength) {\n              if (withHOSES) {\n                atomsInfo[from].paths.push(\n                  getHoseCodesForPath(molecule, from, to, pathLength),\n                );\n              } else {\n                atomsInfo[from].paths.push(\n                  getPathAndTorsion(molecule, from, to, pathLength),\n                );\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  return atomsInfo;\n}\n","import { isAnyArray } from 'is-any-array';\n\nfunction sum(input) {\n  if (!isAnyArray(input)) {\n    throw new TypeError('input must be an array');\n  }\n\n  if (input.length === 0) {\n    throw new TypeError('input must not be empty');\n  }\n\n  var sumValue = 0;\n\n  for (var i = 0; i < input.length; i++) {\n    sumValue += input[i];\n  }\n\n  return sumValue;\n}\n\nexport { sum as default };\n","import sum from 'ml-array-sum';\n\nfunction mean(input) {\n  return sum(input) / input.length;\n}\n\nexport { mean as default };\n","export const couplingValues = {\n    s: 0,\n    d: 1,\n    t: 2,\n    q: 3,\n    quint: 4,\n    h: 5,\n    hex: 5,\n    hept: 6,\n    sept: 6,\n    oct: 7,\n    o: 7,\n    non: 8,\n    n: 8,\n};\n//# sourceMappingURL=couplingValues.js.map","import { couplingPatterns } from '../constants/couplingPatterns';\nimport { couplingValues } from '../constants/couplingValues';\nexport function joinPatterns(patterns) {\n    const sum = patterns.reduce((sum, pattern) => {\n        if (isNaN(couplingValues[pattern])) {\n            throw new Error(`pattern ${pattern} is not in ${Object.keys(couplingValues).join(' ')}`);\n        }\n        return sum + couplingValues[pattern];\n    }, 0);\n    if (!couplingPatterns[sum]) {\n        throw new Error(\"The joined pattern doesn't exist\");\n    }\n    return couplingPatterns[sum];\n}\n//# sourceMappingURL=joinPatterns.js.map","import sum from 'ml-array-sum';\nimport { joinPatterns } from '../utilities/joinPatterns';\nconst localeCompare = (a, b) => a.localeCompare(b);\nconst localeCompareJcouplingKeys = (a, b) => {\n    const aa = `${a.diaIDs.sort(localeCompare).join(' ')}`;\n    const bb = `${b.diaIDs.sort(localeCompare).join(' ')}`;\n    return localeCompare(aa, bb);\n};\nconst areThanClose = (a, b, tolerance) => Math.abs(a.coupling - b.coupling) < tolerance;\nconst takeCareDiaIDs = (a, b, tolerance) => localeCompareJcouplingKeys(a, b) === 0 && areThanClose(a, b, tolerance);\n/**\n * Join couplings smaller than a define tolerance.\n * The resulting coupling should be an average of the existing one.\n * If pathLength is specified and is not always the same this property will be removed.\n */\nexport function signalJoinCouplings(signal, options = {}) {\n    const { tolerance = 0.05, ignoreDiaIDs = false } = options;\n    if (!signal.js || signal.js.length < 2)\n        return signal;\n    if (ignoreDiaIDs) {\n        checkJs(signal);\n        return groupJCouplings(signal, areThanClose, tolerance);\n    }\n    else {\n        checkJsAndDiaID(signal);\n        return groupJCouplings(signal, takeCareDiaIDs, tolerance);\n    }\n}\nfunction groupJCouplings(signal, comparator, tolerance) {\n    signal.js.sort((a, b) => b.coupling - a.coupling);\n    let currentGroup = [signal.js[0]];\n    let groups = [currentGroup];\n    for (let i = 1; i < signal.js.length; i++) {\n        let currentJ = signal.js[i];\n        if (comparator(currentGroup[currentGroup.length - 1], currentJ, tolerance)) {\n            currentGroup.push(currentJ);\n        }\n        else {\n            currentGroup = [currentJ];\n            groups.push(currentGroup);\n        }\n    }\n    signal.js = [];\n    for (let group of groups) {\n        let coupling = sum(group.map((group) => group.coupling)) / group.length;\n        let atoms = distinctValues(group\n            .filter((group) => group.atoms)\n            .map((group) => group.atoms)\n            .flat());\n        let assignment = distinctValues(group\n            .filter((group) => group.assignment)\n            .map((group) => group.assignment)\n            .flat()).join(' ');\n        let diaIDs = distinctValues(group\n            .filter((group) => group.diaIDs)\n            .map((group) => group.diaIDs)\n            .flat());\n        let distances = distinctValues(group.map((group) => group.pathLength));\n        let multiplicity = joinPatterns(group\n            .filter((group) => group.multiplicity)\n            .map((group) => group.multiplicity));\n        let newJ = {\n            coupling,\n            multiplicity,\n        };\n        if (diaIDs.length === 1)\n            newJ.diaIDs = diaIDs;\n        if (distances.length === 1 && distances[0])\n            newJ.pathLength = distances[0];\n        if (assignment.length > 0)\n            newJ.assignment = assignment;\n        if (atoms.length > 0)\n            newJ.atoms = atoms;\n        signal.js.push(newJ);\n    }\n    return signal;\n}\nfunction distinctValues(array) {\n    const onlyDifferents = new Set();\n    for (const element of array) {\n        onlyDifferents.add(element);\n    }\n    return Array.from(onlyDifferents);\n}\nfunction checkJsAndDiaID(signal) {\n    if (!signal.js)\n        throw new Error('there is not js');\n    for (const jcoupling of signal.js) {\n        if (!jcoupling.diaIDs)\n            throw new Error('there is not diaIDs');\n    }\n}\nfunction checkJs(signal) {\n    if (!signal.js)\n        throw new Error('there is not js');\n}\n//# sourceMappingURL=signalJoinCouplings.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport mean from 'ml-array-mean';\nimport sum from 'ml-array-sum';\nimport { signalJoinCouplings } from '../signal/signalJoinCouplings';\nconst localeCompare = (a, b) => a.localeCompare(b);\nconst localeCompareJcouplingKeys = (a, b) => {\n    const aa = `${a.diaIDs.join(' ')}${a.pathLength}`;\n    const bb = `${b.diaIDs.join(' ')}${b.pathLength}`;\n    return localeCompare(aa, bb);\n};\nfunction checkForMandatory(signals) {\n    for (const signal of signals) {\n        if (!signal.js)\n            throw new Error('there is not js');\n        if (!signal.diaIDs)\n            throw new Error('there is not diaIDs');\n        for (const jcoupling of signal.js) {\n            if (!jcoupling.diaIDs)\n                throw new Error('there is not diaIDs');\n            if (!jcoupling.pathLength)\n                throw new Error('there is not pathLength');\n        }\n    }\n}\n/**\n * Join signals if all the same diaID\n */\nexport function signalsJoin(signals, options = {}) {\n    checkForMandatory(signals);\n    const { joinCouplings = {} } = options;\n    const { tolerance, ignoreDiaIDs } = joinCouplings;\n    // we group them by diaIDs\n    const copySignals = JSON.parse(JSON.stringify(signals));\n    const groupedSignals = {};\n    for (let signal of copySignals) {\n        signal.js = signal.js.sort(localeCompareJcouplingKeys);\n        const keyDiaIDs = signal.diaIDs.join(' ');\n        let id = `${keyDiaIDs} ${signal.js\n            .map((j) => `${j.diaIDs.join(' ')} ${j.pathLength}`)\n            .sort(localeCompare)\n            .join(' ')}`;\n        if (!groupedSignals[id]) {\n            groupedSignals[id] = [];\n        }\n        groupedSignals[id].push(signal);\n    }\n    // for each group we need to combine assignments and average couplings\n    let newSignals = [];\n    Object.values(groupedSignals).forEach((group) => {\n        // joining couplings only if diaID and pathLength are equal\n        let js = [];\n        for (let i = 0; i < group[0].js.length; i++) {\n            const coupling = group[0].js[i];\n            js.push({\n                diaIDs: coupling.diaIDs,\n                pathLength: coupling.pathLength,\n                multiplicity: coupling.multiplicity,\n                coupling: mean(group.map((item) => item.js[i].coupling)),\n            });\n        }\n        let signal = {\n            id: generateID(),\n            nbAtoms: sum(group.map((item) => item.nbAtoms || 0)),\n            delta: mean(group.map((item) => item.delta)),\n            diaIDs: group[0].diaIDs,\n            atoms: group.map((item) => item.atoms || []).flat(),\n            js,\n        };\n        const assignment = group\n            .map((item) => item.assignment)\n            .filter((item) => item)\n            .join(' ');\n        if (assignment.length > 0)\n            signal.assignment = assignment;\n        newSignals.push(signal);\n    });\n    newSignals = newSignals\n        .map((signal) => {\n        let newSignal = signalJoinCouplings(signal, {\n            tolerance,\n            ignoreDiaIDs,\n        });\n        if (newSignal.js) {\n            newSignal.multiplicity =\n                newSignal.js.length > 0\n                    ? newSignal.js.map((j) => j.multiplicity).join('')\n                    : 's';\n        }\n        return newSignal;\n    })\n        .sort((a, b) => a.delta - b.delta);\n    return newSignals;\n}\n//# sourceMappingURL=signalsJoin.js.map","import { couplingValues } from '../constants/couplingValues';\nexport function rangeFromSignal(signal, options) {\n    const { nucleus = '1h', frequency = 400 } = options;\n    const { tolerance = getTolerance(nucleus) / frequency } = options;\n    let halfWidth = 0;\n    for (const js of signal.js || []) {\n        const { coupling, multiplicity = 'd' } = js;\n        halfWidth += (couplingValues[multiplicity] * coupling) / frequency;\n    }\n    halfWidth = tolerance + halfWidth / 2;\n    return {\n        from: signal.delta - halfWidth,\n        to: signal.delta + halfWidth,\n    };\n}\nfunction getTolerance(nucleus) {\n    switch (nucleus.toLocaleLowerCase()) {\n        case '1h':\n            return 1.5;\n        case '13C':\n            return 3;\n        default:\n            return 2;\n    }\n}\n//# sourceMappingURL=rangeFromSignal.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport { rangeFromSignal } from '../utilities/rangeFromSignal';\nfunction checkNbAtoms(signals) {\n    for (let signal of signals) {\n        if (!signal.nbAtoms)\n            throw new Error('nbAtoms is mandatory');\n    }\n}\nexport function signalsToRanges(signals, options = {}) {\n    checkNbAtoms(signals);\n    const { tolerance = 0.05, frequency = 400 } = options;\n    let wrapped = signals.map((signal) => ({\n        original: signal,\n    }));\n    wrapped.forEach((signal) => {\n        const fromTo = rangeFromSignal(signal.original, { frequency, tolerance });\n        signal.from = fromTo.from;\n        signal.to = fromTo.to;\n    });\n    wrapped = wrapped.sort((signal1, signal2) => signal1.from - signal2.from);\n    let ranges = [];\n    let range = {};\n    for (let signal of wrapped) {\n        if (range.from === undefined || signal.from > range.to) {\n            range = {\n                id: generateID(),\n                from: signal.from,\n                to: signal.to,\n                integration: signal.original.nbAtoms,\n                signals: [signal.original],\n            };\n            ranges.push(range);\n        }\n        else {\n            range.integration += signal.original.nbAtoms;\n            if (signal.to > range.to)\n                range.to = signal.to;\n            range.signals.push(signal.original);\n        }\n    }\n    return ranges;\n}\n//# sourceMappingURL=signalsToRanges.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport fetch from 'cross-fetch';\nimport FormData from 'form-data';\nimport { addDiastereotopicMissingChirality, getConnectivityMatrix, getDiastereotopicAtomIDs, } from 'openchemlib-utils';\nimport { signalsJoin } from '../signals/signalsJoin';\nimport { signalsToRanges } from '../signals/signalsToRanges';\nexport async function predictProton(molecule, options = {}) {\n    const { cache } = options;\n    molecule = molecule.getCompactCopy();\n    molecule.addImplicitHydrogens();\n    addDiastereotopicMissingChirality(molecule);\n    const molfile = molecule.toMolfile();\n    let result;\n    if (cache) {\n        result = cache(molfile);\n    }\n    if (result === undefined) {\n        const formData = new FormData();\n        formData.append('molfile', molfile);\n        const response = await fetch('https://www.nmrdb.org/service/predictor', {\n            method: 'POST',\n            // @ts-expect-error RequestInit type does not include FormData.\n            body: formData,\n        });\n        result = await response.text();\n        if (cache) {\n            cache(molfile, result);\n        }\n    }\n    const { diaIDs = getDiastereotopicAtomIDs(molecule) } = options;\n    const signals = protonParser(result, molecule, diaIDs);\n    const joinedSignals = signalsJoin(signals);\n    return {\n        molfile,\n        diaIDs,\n        nucleus: '1H',\n        joinedSignals,\n        signals,\n        ranges: signalsToRanges(joinedSignals),\n        molecule,\n    };\n}\nfunction protonParser(result, molecule, diaIDs) {\n    if (molecule.getAllAtoms() === 0)\n        return [];\n    if (result.includes('ERR')) {\n        throw Error(`Spinus optimization: ${result}`);\n    }\n    let distanceMatrix = getConnectivityMatrix(molecule, { pathLength: true });\n    let lines = result.split('\\n').filter((line) => line);\n    let signals = [];\n    for (let line of lines) {\n        let fields = line.split('\\t');\n        let couplings = fields.slice(4);\n        let atom = Number(fields[0]) - 1;\n        let signal = {\n            id: generateID(),\n            atoms: [atom],\n            diaIDs: [diaIDs[atom]],\n            nbAtoms: 1,\n            delta: Number(fields[2]),\n            js: [],\n        };\n        if (!signal.js) {\n            throw new Error(`For atom js property was not added`);\n        }\n        for (let i = 0; i < couplings.length; i += 3) {\n            let linked = Number(couplings[i]) - 1;\n            signal.js.push({\n                coupling: Number(couplings[i + 2]),\n                atoms: [linked],\n                diaIDs: [diaIDs[linked]],\n                multiplicity: 'd',\n                pathLength: distanceMatrix[atom][linked],\n            });\n            signal.js.sort((a, b) => b.coupling - a.coupling);\n        }\n        signals.push(signal);\n    }\n    return signals;\n}\n//# sourceMappingURL=predictProton.js.map","import { v4 as generateID } from '@lukeed/uuid';\nconst { parse, stringify } = JSON;\nexport function setIDs(peaks, options = {}) {\n    const output = (options.output || parse(stringify(peaks)));\n    for (const peak of output) {\n        peak.id = generateID();\n    }\n    return output;\n}\n//# sourceMappingURL=setIDs.js.map","import { fetch } from 'cross-fetch';\nexport async function fetchPrediction(molecule, options) {\n    const { webserviceURL } = options;\n    const response = await fetch(webserviceURL, {\n        headers: {\n            accept: 'application/json',\n            'content-type': 'application/json',\n        },\n        body: JSON.stringify({ molfile: molecule.toMolfile() }),\n        method: 'POST',\n    });\n    const prediction = (await response.json()).data;\n    prediction.molecule = molecule\n        .getOCL()\n        .Molecule.fromMolfile(prediction.molfile);\n    return prediction;\n}\n//# sourceMappingURL=fetchPrediction.js.map","import { getHoseCodesFromDiastereotopicID, addDiastereotopicMissingChirality, groupDiastereotopicAtomIDs, } from 'openchemlib-utils';\nexport function getFilteredIDiaIDs(molecule, options) {\n    const { maxSphereSize, diaIDs } = options;\n    molecule.addImplicitHydrogens();\n    molecule.addMissingChirality();\n    addDiastereotopicMissingChirality(molecule);\n    const molfile = molecule.toMolfile();\n    let groupedDiaIDs = groupDiastereotopicAtomIDs(diaIDs, molecule, {\n        atomLabel: 'C',\n    });\n    let carbonDiaIDs = groupedDiaIDs.sort((a, b) => {\n        if (a.atomLabel === b.atomLabel) {\n            return b.counter - a.counter;\n        }\n        return a.atomLabel < b.atomLabel ? 1 : -1;\n    });\n    const OCL = molecule.getOCL();\n    for (const diaId of carbonDiaIDs) {\n        diaId.hose = getHoseCodesFromDiastereotopicID(OCL.Molecule.fromIDCode(diaId.oclID), {\n            maxSphereSize,\n        });\n    }\n    let toReturn = {\n        molfile,\n        carbonDiaIDs: carbonDiaIDs,\n    };\n    return toReturn;\n}\n//# sourceMappingURL=getFilteredIDiaIDs.js.map","export function queryByHose(diaIDs, db, options) {\n    const { maxSphereSize } = options;\n    const toReturn = [];\n    for (const element of diaIDs) {\n        let res;\n        let level = null;\n        for (let k = maxSphereSize; !res && k >= 0; k--) {\n            if (db[k]) {\n                res = db[k][element.hose[k]];\n                level = k;\n            }\n        }\n        for (const atomNumber of element.atoms) {\n            let atom = {\n                diaIDs: [element.oclID],\n                delta: res ? res[0] : null,\n                atoms: [atomNumber],\n                nbAtoms: 1,\n                level,\n                statistic: res && res.length > 1\n                    ? {\n                        mean: res[1],\n                        sd: res[2],\n                        min: res[3],\n                        max: res[4],\n                        nb: res[5],\n                    }\n                    : undefined,\n            };\n            toReturn.push(atom);\n        }\n    }\n    return toReturn;\n}\n//# sourceMappingURL=queryByHOSE.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport fetch from 'cross-fetch';\nimport { getDiastereotopicAtomIDs } from 'openchemlib-utils';\nimport { setIDs } from '../peaks/util/setIDs';\nimport { signalsToRanges } from '../signals/signalsToRanges';\nimport { fetchPrediction } from './utils/fetchPrediction';\nimport { getFilteredIDiaIDs } from './utils/getFilteredIDiaIDs';\nimport { queryByHose } from './utils/queryByHOSE';\nconst cache = {};\nasync function loadDB(url = 'https://www.lactame.com/lib/nmr-processing-data/20210711/carbon.js') {\n    if (cache[url]) {\n        return cache[url];\n    }\n    const response = await fetch(url);\n    const database = await response.json();\n    cache[url] = database;\n    return database;\n}\nfunction checkFromPrediction(signal) {\n    if (!signal.atoms)\n        throw new Error('There is not atoms');\n    if (!signal.diaIDs)\n        throw new Error('There is not diaIDs');\n    if (!signal.nbAtoms)\n        throw new Error('There is not nbAtoms');\n}\n/**\n * Make a query to a hose code based database to predict carbon chemical shift\n * @returns {Promise<object>} - object with molfile, diaIDs, signals, joined signals by diaIDs and ranges.\n */\nexport async function predictCarbon(molecule, options = {}) {\n    let { url, database, webserviceURL, diaIDs = getDiastereotopicAtomIDs(molecule), } = options;\n    if (webserviceURL) {\n        return fetchPrediction(molecule, { webserviceURL });\n    }\n    if (!database)\n        database = await loadDB(url);\n    if (!database) {\n        throw new Error('There is not a database');\n    }\n    const maxLevel = database.length - 1;\n    let { maxSphereSize = maxLevel } = options;\n    if (maxSphereSize > maxLevel)\n        maxSphereSize = maxLevel;\n    const { carbonDiaIDs, molfile } = getFilteredIDiaIDs(molecule, {\n        maxSphereSize,\n        diaIDs,\n    });\n    let predictions = queryByHose(carbonDiaIDs, database, {\n        maxSphereSize,\n    });\n    const signals = formatSignals(predictions);\n    const joinedSignals = joinSignalByDiaID(signals);\n    return {\n        molfile,\n        nucleus: '13C',\n        diaIDs,\n        joinedSignals,\n        signals,\n        ranges: signalsToRanges(joinedSignals),\n        molecule,\n    };\n}\nfunction formatSignals(predictions) {\n    let signals = [];\n    for (const prediction of predictions) {\n        const { atoms, nbAtoms, delta, diaIDs, statistic } = prediction;\n        const signal = {\n            id: generateID(),\n            delta: delta || NaN,\n            atoms,\n            diaIDs,\n            multiplicity: 's',\n            nbAtoms,\n            statistic,\n            js: [],\n        };\n        signals.push(signal);\n    }\n    return signals;\n}\nfunction joinSignalByDiaID(signals) {\n    let joinedSignals = {};\n    for (let signal of signals) {\n        checkFromPrediction(signal);\n        let diaID = signal.diaIDs[0];\n        if (!joinedSignals[diaID]) {\n            joinedSignals[diaID] = JSON.parse(JSON.stringify(signal));\n        }\n        else {\n            joinedSignals[diaID].nbAtoms += signal.nbAtoms;\n            joinedSignals[diaID].atoms.push(...signal.atoms);\n        }\n    }\n    return setIDs(Object.values(joinedSignals));\n}\n//# sourceMappingURL=predictCarbon.js.map","export function squaredEuclidean(p, q) {\r\n    let d = 0;\r\n    for (let i = 0; i < p.length; i++) {\r\n        d += (p[i] - q[i]) * (p[i] - q[i]);\r\n    }\r\n    return d;\r\n}\r\nexport function euclidean(p, q) {\r\n    return Math.sqrt(squaredEuclidean(p, q));\r\n}\r\n","/**\n * Computes a distance/similarity matrix given an array of data and a distance/similarity function.\n * @param {Array} data An array of data\n * @param {function} distanceFn  A function that accepts two arguments and computes a distance/similarity between them\n * @return {Array<Array>} The distance/similarity matrix. The matrix is square and has a size equal to the length of\n * the data array\n */\nexport default function distanceMatrix(data, distanceFn) {\n  const result = getMatrix(data.length);\n\n  // Compute upper distance matrix\n  for (let i = 0; i < data.length; i++) {\n    for (let j = 0; j <= i; j++) {\n      result[i][j] = distanceFn(data[i], data[j]);\n      result[j][i] = result[i][j];\n    }\n  }\n\n  return result;\n}\n\nfunction getMatrix(size) {\n  const matrix = [];\n  for (let i = 0; i < size; i++) {\n    const row = [];\n    matrix.push(row);\n    for (let j = 0; j < size; j++) {\n      row.push(0);\n    }\n  }\n  return matrix;\n}\n","// Generated by CoffeeScript 1.8.0\n(function() {\n  var Heap, defaultCmp, floor, heapify, heappop, heappush, heappushpop, heapreplace, insort, min, nlargest, nsmallest, updateItem, _siftdown, _siftup;\n\n  floor = Math.floor, min = Math.min;\n\n\n  /*\n  Default comparison function to be used\n   */\n\n  defaultCmp = function(x, y) {\n    if (x < y) {\n      return -1;\n    }\n    if (x > y) {\n      return 1;\n    }\n    return 0;\n  };\n\n\n  /*\n  Insert item x in list a, and keep it sorted assuming a is sorted.\n  \n  If x is already in a, insert it to the right of the rightmost x.\n  \n  Optional args lo (default 0) and hi (default a.length) bound the slice\n  of a to be searched.\n   */\n\n  insort = function(a, x, lo, hi, cmp) {\n    var mid;\n    if (lo == null) {\n      lo = 0;\n    }\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    if (lo < 0) {\n      throw new Error('lo must be non-negative');\n    }\n    if (hi == null) {\n      hi = a.length;\n    }\n    while (lo < hi) {\n      mid = floor((lo + hi) / 2);\n      if (cmp(x, a[mid]) < 0) {\n        hi = mid;\n      } else {\n        lo = mid + 1;\n      }\n    }\n    return ([].splice.apply(a, [lo, lo - lo].concat(x)), x);\n  };\n\n\n  /*\n  Push item onto heap, maintaining the heap invariant.\n   */\n\n  heappush = function(array, item, cmp) {\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    array.push(item);\n    return _siftdown(array, 0, array.length - 1, cmp);\n  };\n\n\n  /*\n  Pop the smallest item off the heap, maintaining the heap invariant.\n   */\n\n  heappop = function(array, cmp) {\n    var lastelt, returnitem;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    lastelt = array.pop();\n    if (array.length) {\n      returnitem = array[0];\n      array[0] = lastelt;\n      _siftup(array, 0, cmp);\n    } else {\n      returnitem = lastelt;\n    }\n    return returnitem;\n  };\n\n\n  /*\n  Pop and return the current smallest value, and add the new item.\n  \n  This is more efficient than heappop() followed by heappush(), and can be\n  more appropriate when using a fixed size heap. Note that the value\n  returned may be larger than item! That constrains reasonable use of\n  this routine unless written as part of a conditional replacement:\n      if item > array[0]\n        item = heapreplace(array, item)\n   */\n\n  heapreplace = function(array, item, cmp) {\n    var returnitem;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    returnitem = array[0];\n    array[0] = item;\n    _siftup(array, 0, cmp);\n    return returnitem;\n  };\n\n\n  /*\n  Fast version of a heappush followed by a heappop.\n   */\n\n  heappushpop = function(array, item, cmp) {\n    var _ref;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    if (array.length && cmp(array[0], item) < 0) {\n      _ref = [array[0], item], item = _ref[0], array[0] = _ref[1];\n      _siftup(array, 0, cmp);\n    }\n    return item;\n  };\n\n\n  /*\n  Transform list into a heap, in-place, in O(array.length) time.\n   */\n\n  heapify = function(array, cmp) {\n    var i, _i, _j, _len, _ref, _ref1, _results, _results1;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    _ref1 = (function() {\n      _results1 = [];\n      for (var _j = 0, _ref = floor(array.length / 2); 0 <= _ref ? _j < _ref : _j > _ref; 0 <= _ref ? _j++ : _j--){ _results1.push(_j); }\n      return _results1;\n    }).apply(this).reverse();\n    _results = [];\n    for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n      i = _ref1[_i];\n      _results.push(_siftup(array, i, cmp));\n    }\n    return _results;\n  };\n\n\n  /*\n  Update the position of the given item in the heap.\n  This function should be called every time the item is being modified.\n   */\n\n  updateItem = function(array, item, cmp) {\n    var pos;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    pos = array.indexOf(item);\n    if (pos === -1) {\n      return;\n    }\n    _siftdown(array, 0, pos, cmp);\n    return _siftup(array, pos, cmp);\n  };\n\n\n  /*\n  Find the n largest elements in a dataset.\n   */\n\n  nlargest = function(array, n, cmp) {\n    var elem, result, _i, _len, _ref;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    result = array.slice(0, n);\n    if (!result.length) {\n      return result;\n    }\n    heapify(result, cmp);\n    _ref = array.slice(n);\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      elem = _ref[_i];\n      heappushpop(result, elem, cmp);\n    }\n    return result.sort(cmp).reverse();\n  };\n\n\n  /*\n  Find the n smallest elements in a dataset.\n   */\n\n  nsmallest = function(array, n, cmp) {\n    var elem, i, los, result, _i, _j, _len, _ref, _ref1, _results;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    if (n * 10 <= array.length) {\n      result = array.slice(0, n).sort(cmp);\n      if (!result.length) {\n        return result;\n      }\n      los = result[result.length - 1];\n      _ref = array.slice(n);\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        elem = _ref[_i];\n        if (cmp(elem, los) < 0) {\n          insort(result, elem, 0, null, cmp);\n          result.pop();\n          los = result[result.length - 1];\n        }\n      }\n      return result;\n    }\n    heapify(array, cmp);\n    _results = [];\n    for (i = _j = 0, _ref1 = min(n, array.length); 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {\n      _results.push(heappop(array, cmp));\n    }\n    return _results;\n  };\n\n  _siftdown = function(array, startpos, pos, cmp) {\n    var newitem, parent, parentpos;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    newitem = array[pos];\n    while (pos > startpos) {\n      parentpos = (pos - 1) >> 1;\n      parent = array[parentpos];\n      if (cmp(newitem, parent) < 0) {\n        array[pos] = parent;\n        pos = parentpos;\n        continue;\n      }\n      break;\n    }\n    return array[pos] = newitem;\n  };\n\n  _siftup = function(array, pos, cmp) {\n    var childpos, endpos, newitem, rightpos, startpos;\n    if (cmp == null) {\n      cmp = defaultCmp;\n    }\n    endpos = array.length;\n    startpos = pos;\n    newitem = array[pos];\n    childpos = 2 * pos + 1;\n    while (childpos < endpos) {\n      rightpos = childpos + 1;\n      if (rightpos < endpos && !(cmp(array[childpos], array[rightpos]) < 0)) {\n        childpos = rightpos;\n      }\n      array[pos] = array[childpos];\n      pos = childpos;\n      childpos = 2 * pos + 1;\n    }\n    array[pos] = newitem;\n    return _siftdown(array, startpos, pos, cmp);\n  };\n\n  Heap = (function() {\n    Heap.push = heappush;\n\n    Heap.pop = heappop;\n\n    Heap.replace = heapreplace;\n\n    Heap.pushpop = heappushpop;\n\n    Heap.heapify = heapify;\n\n    Heap.updateItem = updateItem;\n\n    Heap.nlargest = nlargest;\n\n    Heap.nsmallest = nsmallest;\n\n    function Heap(cmp) {\n      this.cmp = cmp != null ? cmp : defaultCmp;\n      this.nodes = [];\n    }\n\n    Heap.prototype.push = function(x) {\n      return heappush(this.nodes, x, this.cmp);\n    };\n\n    Heap.prototype.pop = function() {\n      return heappop(this.nodes, this.cmp);\n    };\n\n    Heap.prototype.peek = function() {\n      return this.nodes[0];\n    };\n\n    Heap.prototype.contains = function(x) {\n      return this.nodes.indexOf(x) !== -1;\n    };\n\n    Heap.prototype.replace = function(x) {\n      return heapreplace(this.nodes, x, this.cmp);\n    };\n\n    Heap.prototype.pushpop = function(x) {\n      return heappushpop(this.nodes, x, this.cmp);\n    };\n\n    Heap.prototype.heapify = function() {\n      return heapify(this.nodes, this.cmp);\n    };\n\n    Heap.prototype.updateItem = function(x) {\n      return updateItem(this.nodes, x, this.cmp);\n    };\n\n    Heap.prototype.clear = function() {\n      return this.nodes = [];\n    };\n\n    Heap.prototype.empty = function() {\n      return this.nodes.length === 0;\n    };\n\n    Heap.prototype.size = function() {\n      return this.nodes.length;\n    };\n\n    Heap.prototype.clone = function() {\n      var heap;\n      heap = new Heap();\n      heap.nodes = this.nodes.slice(0);\n      return heap;\n    };\n\n    Heap.prototype.toArray = function() {\n      return this.nodes.slice(0);\n    };\n\n    Heap.prototype.insert = Heap.prototype.push;\n\n    Heap.prototype.top = Heap.prototype.peek;\n\n    Heap.prototype.front = Heap.prototype.peek;\n\n    Heap.prototype.has = Heap.prototype.contains;\n\n    Heap.prototype.copy = Heap.prototype.clone;\n\n    return Heap;\n\n  })();\n\n  (function(root, factory) {\n    if (typeof define === 'function' && define.amd) {\n      return define([], factory);\n    } else if (typeof exports === 'object') {\n      return module.exports = factory();\n    } else {\n      return root.Heap = factory();\n    }\n  })(this, function() {\n    return Heap;\n  });\n\n}).call(this);\n","module.exports = require('./lib/heap');\n","import Heap from 'heap';\n\nexport default class Cluster {\n  constructor() {\n    this.children = [];\n    this.height = 0;\n    this.size = 1;\n    this.index = -1;\n    this.isLeaf = false;\n  }\n\n  /**\n   * Creates an array of clusters where the maximum height is smaller than the threshold\n   * @param {number} threshold\n   * @return {Array<Cluster>}\n   */\n  cut(threshold) {\n    if (typeof threshold !== 'number') {\n      throw new TypeError('threshold must be a number');\n    }\n    if (threshold < 0) {\n      throw new RangeError('threshold must be a positive number');\n    }\n    let list = [this];\n    const ans = [];\n    while (list.length > 0) {\n      const aux = list.shift();\n      if (threshold >= aux.height) {\n        ans.push(aux);\n      } else {\n        list = list.concat(aux.children);\n      }\n    }\n    return ans;\n  }\n\n  /**\n   * Merge the leaves in the minimum way to have `groups` number of clusters.\n   * @param {number} groups - Them number of children the first level of the tree should have.\n   * @return {Cluster}\n   */\n  group(groups) {\n    if (!Number.isInteger(groups) || groups < 1) {\n      throw new RangeError('groups must be a positive integer');\n    }\n\n    const heap = new Heap((a, b) => {\n      return b.height - a.height;\n    });\n\n    heap.push(this);\n\n    while (heap.size() < groups) {\n      const first = heap.pop();\n      if (first.children.length === 0) {\n        break;\n      }\n      first.children.forEach((child) => heap.push(child));\n    }\n\n    const root = new Cluster();\n    root.children = heap.toArray();\n    root.height = this.height;\n\n    return root;\n  }\n\n  /**\n   * Traverses the tree depth-first and calls the provided callback with each individual node\n   * @param {function} cb - The callback to be called on each node encounter\n   */\n  traverse(cb) {\n    function visit(root, callback) {\n      callback(root);\n      if (root.children) {\n        for (const child of root.children) {\n          visit(child, callback);\n        }\n      }\n    }\n    visit(this, cb);\n  }\n\n  /**\n   * Returns a list of indices for all the leaves of this cluster.\n   * The list is ordered in such a way that a dendrogram could be drawn without crossing branches.\n   * @returns {Array<number>}\n   */\n  indices() {\n    const result = [];\n    this.traverse((cluster) => {\n      if (cluster.isLeaf) {\n        result.push(cluster.index);\n      }\n    });\n    return result;\n  }\n}\n","import { euclidean } from 'ml-distance-euclidean';\nimport getDistanceMatrix from 'ml-distance-matrix';\nimport { Matrix } from 'ml-matrix';\n\nimport Cluster from './Cluster';\n\nfunction singleLink(dKI, dKJ) {\n  return Math.min(dKI, dKJ);\n}\n\nfunction completeLink(dKI, dKJ) {\n  return Math.max(dKI, dKJ);\n}\n\nfunction averageLink(dKI, dKJ, dIJ, ni, nj) {\n  const ai = ni / (ni + nj);\n  const aj = nj / (ni + nj);\n  return ai * dKI + aj * dKJ;\n}\n\nfunction weightedAverageLink(dKI, dKJ) {\n  return (dKI + dKJ) / 2;\n}\n\nfunction centroidLink(dKI, dKJ, dIJ, ni, nj) {\n  const ai = ni / (ni + nj);\n  const aj = nj / (ni + nj);\n  const b = -(ni * nj) / (ni + nj) ** 2;\n  return ai * dKI + aj * dKJ + b * dIJ;\n}\n\nfunction medianLink(dKI, dKJ, dIJ) {\n  return dKI / 2 + dKJ / 2 - dIJ / 4;\n}\n\nfunction wardLink(dKI, dKJ, dIJ, ni, nj, nk) {\n  const ai = (ni + nk) / (ni + nj + nk);\n  const aj = (nj + nk) / (ni + nj + nk);\n  const b = -nk / (ni + nj + nk);\n  return ai * dKI + aj * dKJ + b * dIJ;\n}\n\nfunction wardLink2(dKI, dKJ, dIJ, ni, nj, nk) {\n  const ai = (ni + nk) / (ni + nj + nk);\n  const aj = (nj + nk) / (ni + nj + nk);\n  const b = -nk / (ni + nj + nk);\n  return Math.sqrt(ai * dKI * dKI + aj * dKJ * dKJ + b * dIJ * dIJ);\n}\n\n/**\n * Continuously merge nodes that have the least dissimilarity\n * @param {Array<Array<number>>} data - Array of points to be clustered\n * @param {object} [options]\n * @param {Function} [options.distanceFunction]\n * @param {string} [options.method] - Default: `'complete'`\n * @param {boolean} [options.isDistanceMatrix] - Is the input already a distance matrix?\n * @constructor\n */\nexport function agnes(data, options = {}) {\n  const {\n    distanceFunction = euclidean,\n    method = 'complete',\n    isDistanceMatrix = false,\n  } = options;\n\n  let updateFunc;\n  if (!isDistanceMatrix) {\n    data = getDistanceMatrix(data, distanceFunction);\n  }\n  let distanceMatrix = new Matrix(data);\n  const numLeaves = distanceMatrix.rows;\n\n  // allows to use a string or a given function\n  if (typeof method === 'string') {\n    switch (method.toLowerCase()) {\n      case 'single':\n        updateFunc = singleLink;\n        break;\n      case 'complete':\n        updateFunc = completeLink;\n        break;\n      case 'average':\n      case 'upgma':\n        updateFunc = averageLink;\n        break;\n      case 'wpgma':\n        updateFunc = weightedAverageLink;\n        break;\n      case 'centroid':\n      case 'upgmc':\n        updateFunc = centroidLink;\n        break;\n      case 'median':\n      case 'wpgmc':\n        updateFunc = medianLink;\n        break;\n      case 'ward':\n        updateFunc = wardLink;\n        break;\n      case 'ward2':\n        updateFunc = wardLink2;\n        break;\n      default:\n        throw new RangeError(`unknown clustering method: ${method}`);\n    }\n  } else if (typeof method !== 'function') {\n    throw new TypeError('method must be a string or function');\n  }\n\n  let clusters = [];\n  for (let i = 0; i < numLeaves; i++) {\n    const cluster = new Cluster();\n    cluster.isLeaf = true;\n    cluster.index = i;\n    clusters.push(cluster);\n  }\n\n  for (let n = 0; n < numLeaves - 1; n++) {\n    const [row, column, distance] = getSmallestDistance(distanceMatrix);\n    const cluster1 = clusters[row];\n    const cluster2 = clusters[column];\n    const newCluster = new Cluster();\n    newCluster.size = cluster1.size + cluster2.size;\n    newCluster.children.push(cluster1, cluster2);\n    newCluster.height = distance;\n\n    const newClusters = [newCluster];\n    const newDistanceMatrix = new Matrix(\n      distanceMatrix.rows - 1,\n      distanceMatrix.rows - 1,\n    );\n    const previous = (newIndex) =>\n      getPreviousIndex(newIndex, Math.min(row, column), Math.max(row, column));\n\n    for (let i = 1; i < newDistanceMatrix.rows; i++) {\n      const prevI = previous(i);\n      const prevICluster = clusters[prevI];\n      newClusters.push(prevICluster);\n      for (let j = 0; j < i; j++) {\n        if (j === 0) {\n          const dKI = distanceMatrix.get(row, prevI);\n          const dKJ = distanceMatrix.get(prevI, column);\n          const val = updateFunc(\n            dKI,\n            dKJ,\n            distance,\n            cluster1.size,\n            cluster2.size,\n            prevICluster.size,\n          );\n          newDistanceMatrix.set(i, j, val);\n          newDistanceMatrix.set(j, i, val);\n        } else {\n          // Just copy distance from previous matrix\n          const val = distanceMatrix.get(prevI, previous(j));\n          newDistanceMatrix.set(i, j, val);\n          newDistanceMatrix.set(j, i, val);\n        }\n      }\n    }\n\n    clusters = newClusters;\n    distanceMatrix = newDistanceMatrix;\n  }\n\n  return clusters[0];\n}\n\nfunction getSmallestDistance(distance) {\n  let smallest = Infinity;\n  let smallestI = 0;\n  let smallestJ = 0;\n  for (let i = 1; i < distance.rows; i++) {\n    for (let j = 0; j < i; j++) {\n      if (distance.get(i, j) < smallest) {\n        smallest = distance.get(i, j);\n        smallestI = i;\n        smallestJ = j;\n      }\n    }\n  }\n  return [smallestI, smallestJ, smallest];\n}\n\nfunction getPreviousIndex(newIndex, prev1, prev2) {\n  newIndex -= 1;\n  if (newIndex >= prev1) newIndex++;\n  if (newIndex >= prev2) newIndex++;\n  return newIndex;\n}\n","const nucleusMap = {\n    h: '1H',\n    c: '13C',\n};\nexport function getNuclei(input) {\n    return Object.values(input).map((e) => nucleusMap[e.toLowerCase()]);\n}\n//# sourceMappingURL=getNuclei.js.map","export async function getPredictions(key, molecule, predictOptions, predictor, predictions) {\n    let prediction;\n    if (predictions === null || predictions === void 0 ? void 0 : predictions[key]) {\n        prediction = predictions[key];\n    }\n    else if (predictor) {\n        const fromPredictor = predictor[key];\n        prediction = fromPredictor\n            ? await fromPredictor(molecule, predictOptions[key])\n            : undefined;\n    }\n    return prediction;\n}\n//# sourceMappingURL=getPredictions.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport { agnes } from 'ml-hclust';\nimport { Matrix } from 'ml-matrix';\nimport { getGroupedDiastereotopicAtomIDs, getPathsInfo, groupDiastereotopicAtomIDs, } from 'openchemlib-utils';\nimport { setIDs } from '../../peaks/util/setIDs';\nimport { getNuclei } from './getNuclei';\nimport { getPredictions } from './getPredictions';\nfunction checkFromTo(options) {\n    if (!options.from || !options.to) {\n        throw new Error('options from and to are mandatory');\n    }\n}\nexport async function predict2D(molecule, options = {}) {\n    checkFromTo(options);\n    molecule.addImplicitHydrogens();\n    let { from, to, diaIDs, minLength = 0, maxLength, predictOptions = {}, predictions, predictor, joinDistance = { H: 0.05, C: 0.5 }, includeDiagonal = false, } = options;\n    const pathsInfo = getPathsInfo(molecule, {\n        fromLabel: from,\n        toLabel: to,\n        minLength,\n        maxLength,\n    });\n    const groupedDiaIDS = diaIDs\n        ? groupDiastereotopicAtomIDs(diaIDs, molecule)\n        : getGroupedDiastereotopicAtomIDs(molecule);\n    let diaIDswithAtomInfo = [];\n    for (let diaID of groupedDiaIDS) {\n        diaIDswithAtomInfo.push({\n            ...diaID,\n            pathInfo: JSON.parse(JSON.stringify(pathsInfo[diaID.atoms[0]])),\n        });\n    }\n    const xPrediction = await getPredictions(from, molecule, predictOptions, predictor, predictions);\n    const yPrediction = from === to\n        ? xPrediction\n        : await getPredictions(to, molecule, predictOptions, predictor, predictions);\n    if (!xPrediction || !yPrediction) {\n        throw new Error('predictions are not availaible');\n    }\n    const spectra = {\n        x: xPrediction,\n        y: yPrediction,\n    };\n    const signalsByDiaID = {\n        x: {},\n        y: {},\n    };\n    for (const axis in signalsByDiaID) {\n        for (const signal of spectra[axis].joinedSignals) {\n            if (!signal.diaIDs)\n                throw new Error('Signal has not diaIDs');\n            signalsByDiaID[axis][signal.diaIDs[0]] = signal;\n        }\n    }\n    let group = {};\n    for (const diaID of diaIDswithAtomInfo) {\n        const pathInfo = diaID.pathInfo;\n        if (pathInfo.paths.length < 1)\n            continue;\n        if (!signalsByDiaID.x[pathInfo.oclID])\n            continue;\n        const currentPaths = pathInfo.paths;\n        for (const path of currentPaths) {\n            if (!signalsByDiaID.y[pathsInfo[path.to].oclID])\n                continue;\n            let fromToDiaID = {\n                x: pathInfo,\n                y: pathsInfo[path.to],\n            };\n            const key = `${fromToDiaID.x.oclID}-${fromToDiaID.y.oclID}`;\n            if (key === `${pathInfo.oclID}-${pathInfo.oclID}` || group[key]) {\n                continue;\n            }\n            let peak = { id: generateID(), z: 100 };\n            let signal = { id: generateID(), x: {}, y: {} };\n            for (let axis in fromToDiaID) {\n                let diaID = fromToDiaID[axis].oclID;\n                peak[axis] = signalsByDiaID[axis][diaID].delta;\n                signal[axis].delta = signalsByDiaID[axis][diaID].delta;\n                signal[axis].diaIDs = [diaID];\n                signal[axis].atoms = signalsByDiaID[axis][diaID].atoms;\n            }\n            signal.peaks = [peak];\n            group[key] = signal;\n        }\n    }\n    if (includeDiagonal) {\n        addSelftCorrelation(group, { paths: pathsInfo, signalsByDiaID });\n    }\n    // clusterize signals by distance\n    const joinedSignals = Object.values(group);\n    const zones = createZones(joinedSignals, { joinDistance, from, to });\n    return {\n        molfile: molecule.toMolfile(),\n        diaIDs: spectra.x.diaIDs,\n        nuclei: getNuclei({ from, to }),\n        joinedSignals,\n        signals: splitSignals(joinedSignals),\n        zones,\n        molecule,\n    };\n}\nfunction splitSignals(joinedSignals) {\n    let signals = [];\n    for (const signal of joinedSignals) {\n        for (const xAtom of signal.x.atoms || []) {\n            for (const yAtom of signal.y.atoms || []) {\n                let newSignal = JSON.parse(JSON.stringify(signal));\n                newSignal.x.atoms = [xAtom];\n                newSignal.y.atoms = [yAtom];\n                signals.push(newSignal);\n            }\n        }\n    }\n    return setIDs(signals);\n}\nfunction addSelftCorrelation(group, options) {\n    const { paths = [], signalsByDiaID } = options;\n    for (const atom of paths) {\n        if (atom.paths.length < 1)\n            continue;\n        let diaID = atom.oclID;\n        if (!signalsByDiaID.x[diaID])\n            continue;\n        if (group[`${diaID}-${diaID}`])\n            continue;\n        let signal = { x: {}, y: {} };\n        let peak = { z: 1 };\n        for (let axis of ['x', 'y']) {\n            peak[axis] = signalsByDiaID[axis][diaID].delta;\n            signal[axis].delta = signalsByDiaID[axis][diaID].delta;\n            signal[axis].diaIDs = [diaID];\n            signal[axis].atoms = signalsByDiaID[axis][diaID].atoms;\n        }\n        signal.peaks = [peak];\n        group[`${atom.oclID}-${atom.oclID}`] = signal;\n    }\n}\nfunction createZones(signals, options) {\n    const { joinDistance, from, to } = options;\n    const deltas = new Matrix(signals.map((e) => [e.x.delta, e.y.delta]));\n    const minX = deltas.minColumn(0);\n    const maxX = deltas.maxColumn(0);\n    const minY = deltas.minColumn(1);\n    const maxY = deltas.maxColumn(1);\n    deltas.mulColumn(0, 1 / (maxX - minX));\n    deltas.mulColumn(1, 1 / (maxY - minY));\n    const cutOff = Math.sqrt(Math.pow(joinDistance[from] / (maxX - minX), 2) +\n        Math.pow(joinDistance[to] / (maxY - minY), 2));\n    let hClusters = agnes(deltas.to2DArray(), { method: 'centroid' });\n    const clusters = splitClusters([hClusters], cutOff);\n    const zones = [];\n    for (const cluster of clusters) {\n        const signal = [];\n        if (cluster.isLeaf)\n            signal.push(signals[cluster.index]);\n        for (const child of cluster.children) {\n            for (const index of child.indices()) {\n                signal.push(signals[index]);\n            }\n        }\n        zones.push({\n            id: generateID(),\n            ...fromTo(signal, { joinDistance, from, to }),\n            signals: signal,\n        });\n    }\n    return zones;\n}\nfunction fromTo(signals, options) {\n    const { joinDistance, from, to } = options;\n    let minX = Number.MAX_SAFE_INTEGER;\n    let minY = Number.MAX_SAFE_INTEGER;\n    let maxX = Number.MIN_SAFE_INTEGER;\n    let maxY = Number.MIN_SAFE_INTEGER;\n    for (const signal of signals) {\n        if (signal.x.delta < minX)\n            minX = signal.x.delta;\n        if (signal.x.delta > maxX)\n            maxX = signal.x.delta;\n        if (signal.y.delta < minY)\n            minY = signal.y.delta;\n        if (signal.y.delta > maxY)\n            maxY = signal.y.delta;\n    }\n    return {\n        x: { from: minX - joinDistance[from], to: maxX + joinDistance[from] },\n        y: { from: minY - joinDistance[to], to: maxY + joinDistance[to] },\n    };\n}\nfunction splitClusters(clusters, maxDistance) {\n    let originalLength = clusters.length;\n    for (let i = 0; i < clusters.length; i++) {\n        const cluster = clusters[i];\n        if (cluster.height > maxDistance) {\n            clusters.push(...cluster.children);\n            clusters.splice(i--, 1);\n        }\n    }\n    return clusters.length < originalLength\n        ? splitClusters(clusters, maxDistance)\n        : clusters;\n}\n//# sourceMappingURL=predict2D.js.map","import { predictProton } from './predictProton';\nimport { predict2D } from './utils/predict2D';\n/**\n * Generate the correlation bidimensional nmr peaks based on the number of bonds between a pair of atoms\n * @returns {Promise<object>} - object with molfile, diaIDs, 2D signals joined signals and zones.\n */\nexport async function predictCOSY(molecule, options = {}) {\n    let { minLength = 2, maxLength = 3, predictions, predictor = { H: predictProton }, predictOptions, joinDistance = { H: 0.05, C: 0.5 }, includeDiagonal = true, } = options;\n    return predict2D(molecule, {\n        from: 'H',\n        to: 'H',\n        predictor,\n        minLength,\n        maxLength,\n        joinDistance,\n        predictions,\n        includeDiagonal,\n        predictOptions,\n    });\n}\n//# sourceMappingURL=predictCOSY.js.map","import { predictCarbon } from './predictCarbon';\nimport { predictProton } from './predictProton';\nimport { predict2D } from './utils/predict2D';\n/**\n * Generate the correlation bidimensional nmr peaks based on the number of bonds between a pair of atoms\n * @returns {Promise<object>} - object with molfile, diaIDs, 2D signals joined signals and zones.\n */\nexport async function predictHSQC(molecule, options = {}) {\n    let { minLength = 1, maxLength = 1, predictor = { H: predictProton, C: predictCarbon }, predictions, joinDistance = { H: 0.05, C: 0.5 }, predictOptions, } = options;\n    return predict2D(molecule, {\n        from: 'H',\n        to: 'C',\n        predictor,\n        minLength,\n        maxLength,\n        predictions,\n        predictOptions,\n        joinDistance,\n    });\n}\n//# sourceMappingURL=predictHSQC.js.map","import { predictCarbon } from './predictCarbon';\nimport { predictProton } from './predictProton';\nimport { predict2D } from './utils/predict2D';\nexport async function predictHMBC(molecule, options = {}) {\n    let { minLength = 2, maxLength = 3, predictor = { H: predictProton, C: predictCarbon }, predictOptions, predictions, joinDistance = { H: 0.05, C: 0.5 }, } = options;\n    return predict2D(molecule, {\n        from: 'H',\n        to: 'C',\n        predictor,\n        minLength,\n        maxLength,\n        predictions,\n        predictOptions,\n        joinDistance,\n    });\n}\n//# sourceMappingURL=predictHMBC.js.map","import { getDiastereotopicAtomIDs } from 'openchemlib-utils';\nimport { predictCOSY } from './predictCOSY';\nimport { predictCarbon } from './predictCarbon';\nimport { predictHMBC } from './predictHMBC';\nimport { predictHSQC } from './predictHSQC';\nimport { predictProton } from './predictProton';\nimport { getPredictions } from './utils/getPredictions';\n/**\n * Generate the correlation bidimensional nmr peaks based on the number of bonds between a pair of atoms\n * @returns {Promise<object>} - object with molfile, diaIDs, 1D and 2D signals, joined signals, ranges and zones.\n */\nexport async function predictAll(molecule, options = {}) {\n    let { from = 'H', to = 'C', predictor = { H: predictProton, C: predictCarbon }, predictions, joinDistance = { H: 0.05, C: 0.5 }, predictOptions = {}, } = options;\n    const diaIDs = getDiastereotopicAtomIDs(molecule);\n    const xPrediction = await getPredictions(from, molecule, predictOptions, predictor, predictions);\n    const yPrediction = await getPredictions(to, molecule, predictOptions, predictor, predictions);\n    if (!xPrediction || !yPrediction) {\n        throw new Error('predictions are not availaible');\n    }\n    predictions = {\n        H: xPrediction,\n        C: yPrediction,\n    };\n    const { molfile } = xPrediction;\n    const spectra = {\n        proton: predictions.H,\n        carbon: predictions.C,\n    };\n    spectra.cosy = await predictCOSY(molecule, {\n        predictions,\n        joinDistance,\n    });\n    spectra.hsqc = await predictHSQC(molecule, {\n        predictions,\n        joinDistance,\n    });\n    spectra.hmbc = await predictHMBC(molecule, {\n        predictions,\n        joinDistance,\n    });\n    for (const key in spectra) {\n        delete spectra[key].molfile;\n        delete spectra[key].diaIDs;\n    }\n    return {\n        molfile,\n        diaIDs,\n        ...spectra,\n    };\n}\n//# sourceMappingURL=predictAll.js.map","import { generateSpectrum2D } from 'spectrum-generator';\nexport function signals2DToZ(signals, options = {}) {\n    let { from = -1, to = 12, nbPoints = 512, width = 0.02, factor = 3, } = options;\n    const peaks = signals.reduce((acc, { x, y }) => {\n        acc.x.push(x.delta);\n        acc.y.push(y.delta);\n        acc.z.push(1e6);\n        return acc;\n    }, { x: [], y: [], z: [] });\n    width = ensureXYNumber(width);\n    return generateSpectrum2D(mergeClosePeaks(peaks), {\n        generator: {\n            from: ensureXYNumber(from),\n            to: ensureXYNumber(to),\n            nbPoints: ensureXYNumber(nbPoints),\n        },\n        peaks: {\n            width,\n            factor,\n        },\n    });\n}\nfunction ensureXYNumber(input) {\n    return typeof input !== 'object' ? { x: input, y: input } : { ...input };\n}\nfunction mergeClosePeaks(peaksIn) {\n    let peaks = JSON.parse(JSON.stringify(peaksIn));\n    for (let i = 0; i < peaks.x.length; i++) {\n        for (let j = i + 1; j < peaks.x.length; j++) {\n            if (peaks.x[i] === peaks.x[j] && peaks.y[i] === peaks.y[j]) {\n                peaks.z[i] += peaks.z[j];\n                peaks.x.splice(j, 1);\n                peaks.y.splice(j, 1);\n                peaks.z.splice(j, 1);\n                j--;\n            }\n        }\n    }\n    return peaks;\n}\n//# sourceMappingURL=signals2DToZ.js.map","/**\n * Created by acastillo on 8/8/16.\n */\n'use strict';\n\nconst defOptions = {\n    threshold:0,\n    out:\"assignment\"\n};\n//TODO Consider a matrix of distances too\nmodule.exports = function fullClusterGenerator(conMat, opt) {\n    const options = Object.assign({}, defOptions, opt);\n    var clList, i, j, k;\n    if(typeof conMat[0] === \"number\"){\n        clList = fullClusterGeneratorVector(conMat);\n    }\n    else{\n        if(typeof conMat[0] === \"object\"){\n            var nRows = conMat.length;\n            var conn = new Array(nRows*(nRows+1)/2);\n            var index = 0;\n            for(var i=0;i<nRows;i++){\n                for(var j=i;j<nRows;j++){\n                    if(conMat[i][j]>options.threshold)\n                        conn[index++]= 1;\n                    else\n                        conn[index++]= 0;\n                }\n            }\n            clList = fullClusterGeneratorVector(conn);\n        }\n    }\n    if (options.out === \"indexes\" || options.out === \"values\") {\n        var result = new Array(clList.length);\n        for(i=0;i<clList.length;i++){\n            result[i] = [];\n            for(j=0;j<clList[i].length;j++){\n                if(clList[i][j] != 0){\n                    result[i].push(j);\n                }\n            }\n        }\n        if (options.out === \"values\") {\n            var resultAsMatrix = new Array(result.length);\n            for (i = 0; i<result.length;i++){\n                resultAsMatrix[i]=new Array(result[i].length);\n                for(j = 0; j < result[i].length; j++){\n                    resultAsMatrix[i][j]=new Array(result[i].length);\n                    for(k = 0; k < result[i].length; k++){\n                        resultAsMatrix[i][j][k]=conMat[result[i][j]][result[i][k]];\n                    }\n                }\n            }\n            return resultAsMatrix;\n        }\n        else{\n            return result;\n        }\n    }\n\n    return clList;\n\n}\n\nfunction fullClusterGeneratorVector(conn){\n    var nRows = Math.sqrt(conn.length*2+0.25)-0.5;\n    var clusterList = [];\n    var available = new Array(nRows);\n    var remaining = nRows, i=0;\n    var cluster = [];\n    //Mark all the elements as available\n    for(i=nRows-1;i>=0;i--){\n        available[i]=1;\n    }\n    var nextAv=-1;\n    var toInclude = [];\n    while(remaining>0){\n        if(toInclude.length===0){\n            //If there is no more elements to include. Start a new cluster\n            cluster = new Array(nRows);\n            for(i = 0;i < nRows ;i++)\n                cluster[i]=0;\n            clusterList.push(cluster);\n            for(nextAv = 0;available[nextAv]==0;nextAv++){};\n        }\n        else{\n            nextAv=toInclude.splice(0,1);\n        }\n        cluster[nextAv]=1;\n        available[nextAv]=0;\n        remaining--;\n        //Copy the next available row\n        var row = new Array(nRows);\n        for( i = 0;i < nRows;i++){\n            var c=Math.max(nextAv,i);\n            var r=Math.min(nextAv,i);\n            //The element in the conn matrix\n            //console.log(\"index: \"+r*(2*nRows-r-1)/2+c)\n            row[i]=conn[r*(2*nRows-r-1)/2+c];\n            //There is new elements to include in this row?\n            //Then, include it to the current cluster\n            if(row[i]==1&&available[i]==1&&cluster[i]==0){\n                toInclude.push(i);\n                cluster[i]=1;\n            }\n        }\n    }\n    return clusterList;\n}","import { Matrix } from 'ml-matrix';\nimport simpleClustering from 'ml-simple-clustering';\nfunction checkForMandatory(signals) {\n    for (const signal of signals) {\n        if (!signal.js)\n            throw new Error('there is not js');\n        if (!signal.atoms)\n            throw new Error('there is not atoms');\n        for (const jcoupling of signal.js) {\n            if (!jcoupling.atoms)\n                throw new Error('there is not atoms');\n        }\n    }\n}\nexport function signalsToSpinSystem(signals) {\n    checkForMandatory(signals);\n    const nSpins = signals.length;\n    const chemicalShifts = new Array(nSpins);\n    const multiplicity = new Array(nSpins);\n    const couplingConstants = Matrix.zeros(nSpins, nSpins);\n    //create a list of assignments\n    const ids = {};\n    for (let i = 0; i < nSpins; i++) {\n        multiplicity[i] = 2;\n        chemicalShifts[i] = signals[i].delta;\n        const index = signals[i].atoms[0];\n        ids[index] = i;\n    }\n    //create the coupling matrix\n    for (let i = 0; i < nSpins; i++) {\n        let { atoms: signalAssignment, js: jCoupling } = signals[i];\n        const fromIndex = signalAssignment[0];\n        for (const jcoupling of jCoupling) {\n            let { coupling, atoms } = jcoupling;\n            const toIndex = atoms[0];\n            couplingConstants.set(ids[fromIndex], ids[toIndex], coupling);\n            couplingConstants.set(ids[toIndex], ids[fromIndex], coupling);\n        }\n    }\n    const connectivity = Matrix.ones(couplingConstants.rows, couplingConstants.rows);\n    for (let i = 0; i < couplingConstants.rows; i++) {\n        for (let j = i; j < couplingConstants.columns; j++) {\n            if (couplingConstants.get(i, j) === 0) {\n                connectivity.set(i, j, 0);\n                connectivity.set(j, i, 0);\n            }\n        }\n    }\n    let clusters = simpleClustering(connectivity.to2DArray(), {\n        out: 'indexes',\n    });\n    return {\n        clusters,\n        couplingConstants,\n        chemicalShifts,\n        multiplicity,\n        connectivity,\n    };\n}\n//# sourceMappingURL=signalsToSpinSystem.js.map","module.exports = function(haystack, needle, comparator, low, high) {\n  var mid, cmp;\n\n  if(low === undefined)\n    low = 0;\n\n  else {\n    low = low|0;\n    if(low < 0 || low >= haystack.length)\n      throw new RangeError(\"invalid lower bound\");\n  }\n\n  if(high === undefined)\n    high = haystack.length - 1;\n\n  else {\n    high = high|0;\n    if(high < low || high >= haystack.length)\n      throw new RangeError(\"invalid upper bound\");\n  }\n\n  while(low <= high) {\n    // The naive `low + high >>> 1` could fail for array lengths > 2**31\n    // because `>>>` converts its operands to int32. `low + (high - low >>> 1)`\n    // works for array lengths <= 2**32-1 which is also Javascript's max array\n    // length.\n    mid = low + ((high - low) >>> 1);\n    cmp = +comparator(haystack[mid], needle, mid, haystack);\n\n    // Too low.\n    if(cmp < 0.0)\n      low  = mid + 1;\n\n    // Too high.\n    else if(cmp > 0.0)\n      high = mid - 1;\n\n    // Key found.\n    else\n      return mid;\n  }\n\n  // Key not found.\n  return ~low;\n}\n","'use strict';\n\nfunction assertNumber(number) {\n\tif (typeof number !== 'number') {\n\t\tthrow new TypeError('Expected a number');\n\t}\n}\n\nexports.ascending = (left, right) => {\n\tassertNumber(left);\n\tassertNumber(right);\n\n\tif (Number.isNaN(left)) {\n\t\treturn -1;\n\t}\n\n\tif (Number.isNaN(right)) {\n\t\treturn 1;\n\t}\n\n\treturn left - right;\n};\n\nexports.descending = (left, right) => {\n\tassertNumber(left);\n\tassertNumber(right);\n\n\tif (Number.isNaN(left)) {\n\t\treturn 1;\n\t}\n\n\tif (Number.isNaN(right)) {\n\t\treturn -1;\n\t}\n\n\treturn right - left;\n};\n","import binarySearch from 'binary-search';\nimport { ascending } from 'num-sort';\n\nexport const largestPrime = 0x7fffffff;\n\nconst primeNumbers = [\n  // chunk #0\n  largestPrime, // 2^31-1\n\n  // chunk #1\n  5,\n  11,\n  23,\n  47,\n  97,\n  197,\n  397,\n  797,\n  1597,\n  3203,\n  6421,\n  12853,\n  25717,\n  51437,\n  102877,\n  205759,\n  411527,\n  823117,\n  1646237,\n  3292489,\n  6584983,\n  13169977,\n  26339969,\n  52679969,\n  105359939,\n  210719881,\n  421439783,\n  842879579,\n  1685759167,\n\n  // chunk #2\n  433,\n  877,\n  1759,\n  3527,\n  7057,\n  14143,\n  28289,\n  56591,\n  113189,\n  226379,\n  452759,\n  905551,\n  1811107,\n  3622219,\n  7244441,\n  14488931,\n  28977863,\n  57955739,\n  115911563,\n  231823147,\n  463646329,\n  927292699,\n  1854585413,\n\n  // chunk #3\n  953,\n  1907,\n  3821,\n  7643,\n  15287,\n  30577,\n  61169,\n  122347,\n  244703,\n  489407,\n  978821,\n  1957651,\n  3915341,\n  7830701,\n  15661423,\n  31322867,\n  62645741,\n  125291483,\n  250582987,\n  501165979,\n  1002331963,\n  2004663929,\n\n  // chunk #4\n  1039,\n  2081,\n  4177,\n  8363,\n  16729,\n  33461,\n  66923,\n  133853,\n  267713,\n  535481,\n  1070981,\n  2141977,\n  4283963,\n  8567929,\n  17135863,\n  34271747,\n  68543509,\n  137087021,\n  274174111,\n  548348231,\n  1096696463,\n\n  // chunk #5\n  31,\n  67,\n  137,\n  277,\n  557,\n  1117,\n  2237,\n  4481,\n  8963,\n  17929,\n  35863,\n  71741,\n  143483,\n  286973,\n  573953,\n  1147921,\n  2295859,\n  4591721,\n  9183457,\n  18366923,\n  36733847,\n  73467739,\n  146935499,\n  293871013,\n  587742049,\n  1175484103,\n\n  // chunk #6\n  599,\n  1201,\n  2411,\n  4831,\n  9677,\n  19373,\n  38747,\n  77509,\n  155027,\n  310081,\n  620171,\n  1240361,\n  2480729,\n  4961459,\n  9922933,\n  19845871,\n  39691759,\n  79383533,\n  158767069,\n  317534141,\n  635068283,\n  1270136683,\n\n  // chunk #7\n  311,\n  631,\n  1277,\n  2557,\n  5119,\n  10243,\n  20507,\n  41017,\n  82037,\n  164089,\n  328213,\n  656429,\n  1312867,\n  2625761,\n  5251529,\n  10503061,\n  21006137,\n  42012281,\n  84024581,\n  168049163,\n  336098327,\n  672196673,\n  1344393353,\n\n  // chunk #8\n  3,\n  7,\n  17,\n  37,\n  79,\n  163,\n  331,\n  673,\n  1361,\n  2729,\n  5471,\n  10949,\n  21911,\n  43853,\n  87719,\n  175447,\n  350899,\n  701819,\n  1403641,\n  2807303,\n  5614657,\n  11229331,\n  22458671,\n  44917381,\n  89834777,\n  179669557,\n  359339171,\n  718678369,\n  1437356741,\n\n  // chunk #9\n  43,\n  89,\n  179,\n  359,\n  719,\n  1439,\n  2879,\n  5779,\n  11579,\n  23159,\n  46327,\n  92657,\n  185323,\n  370661,\n  741337,\n  1482707,\n  2965421,\n  5930887,\n  11861791,\n  23723597,\n  47447201,\n  94894427,\n  189788857,\n  379577741,\n  759155483,\n  1518310967,\n\n  // chunk #10\n  379,\n  761,\n  1523,\n  3049,\n  6101,\n  12203,\n  24407,\n  48817,\n  97649,\n  195311,\n  390647,\n  781301,\n  1562611,\n  3125257,\n  6250537,\n  12501169,\n  25002389,\n  50004791,\n  100009607,\n  200019221,\n  400038451,\n  800076929,\n  1600153859,\n\n  // chunk #11\n  13,\n  29,\n  59,\n  127,\n  257,\n  521,\n  1049,\n  2099,\n  4201,\n  8419,\n  16843,\n  33703,\n  67409,\n  134837,\n  269683,\n  539389,\n  1078787,\n  2157587,\n  4315183,\n  8630387,\n  17260781,\n  34521589,\n  69043189,\n  138086407,\n  276172823,\n  552345671,\n  1104691373,\n\n  // chunk #12\n  19,\n  41,\n  83,\n  167,\n  337,\n  677,\n  1361,\n  2729,\n  5471,\n  10949,\n  21911,\n  43853,\n  87719,\n  175447,\n  350899,\n  701819,\n  1403641,\n  2807303,\n  5614657,\n  11229331,\n  22458671,\n  44917381,\n  89834777,\n  179669557,\n  359339171,\n  718678369,\n  1437356741,\n\n  // chunk #13\n  53,\n  107,\n  223,\n  449,\n  907,\n  1823,\n  3659,\n  7321,\n  14653,\n  29311,\n  58631,\n  117269,\n  234539,\n  469099,\n  938207,\n  1876417,\n  3752839,\n  7505681,\n  15011389,\n  30022781,\n  60045577,\n  120091177,\n  240182359,\n  480364727,\n  960729461,\n  1921458943\n];\n\nprimeNumbers.sort(ascending);\n\nexport function nextPrime(value) {\n  let index = binarySearch(primeNumbers, value, ascending);\n  if (index < 0) {\n    index = ~index;\n  }\n  return primeNumbers[index];\n}\n","import { largestPrime, nextPrime } from './primeFinder';\n\nconst FREE = 0;\nconst FULL = 1;\nconst REMOVED = 2;\n\nconst defaultInitialCapacity = 150;\nconst defaultMinLoadFactor = 1 / 6;\nconst defaultMaxLoadFactor = 2 / 3;\n\nexport default class HashTable {\n  constructor(options = {}) {\n    if (options instanceof HashTable) {\n      this.table = options.table.slice();\n      this.values = options.values.slice();\n      this.state = options.state.slice();\n      this.minLoadFactor = options.minLoadFactor;\n      this.maxLoadFactor = options.maxLoadFactor;\n      this.distinct = options.distinct;\n      this.freeEntries = options.freeEntries;\n      this.lowWaterMark = options.lowWaterMark;\n      this.highWaterMark = options.maxLoadFactor;\n      return;\n    }\n\n    const initialCapacity =\n      options.initialCapacity === undefined\n        ? defaultInitialCapacity\n        : options.initialCapacity;\n    if (initialCapacity < 0) {\n      throw new RangeError(\n        `initial capacity must not be less than zero: ${initialCapacity}`\n      );\n    }\n\n    const minLoadFactor =\n      options.minLoadFactor === undefined\n        ? defaultMinLoadFactor\n        : options.minLoadFactor;\n    const maxLoadFactor =\n      options.maxLoadFactor === undefined\n        ? defaultMaxLoadFactor\n        : options.maxLoadFactor;\n    if (minLoadFactor < 0 || minLoadFactor >= 1) {\n      throw new RangeError(`invalid minLoadFactor: ${minLoadFactor}`);\n    }\n    if (maxLoadFactor <= 0 || maxLoadFactor >= 1) {\n      throw new RangeError(`invalid maxLoadFactor: ${maxLoadFactor}`);\n    }\n    if (minLoadFactor >= maxLoadFactor) {\n      throw new RangeError(\n        `minLoadFactor (${minLoadFactor}) must be smaller than maxLoadFactor (${maxLoadFactor})`\n      );\n    }\n\n    let capacity = initialCapacity;\n    // User wants to put at least capacity elements. We need to choose the size based on the maxLoadFactor to\n    // avoid the need to rehash before this capacity is reached.\n    // actualCapacity * maxLoadFactor >= capacity\n    capacity = (capacity / maxLoadFactor) | 0;\n    capacity = nextPrime(capacity);\n    if (capacity === 0) capacity = 1;\n\n    this.table = newArray(capacity);\n    this.values = newArray(capacity);\n    this.state = newArray(capacity);\n\n    this.minLoadFactor = minLoadFactor;\n    if (capacity === largestPrime) {\n      this.maxLoadFactor = 1;\n    } else {\n      this.maxLoadFactor = maxLoadFactor;\n    }\n\n    this.distinct = 0;\n    this.freeEntries = capacity;\n\n    this.lowWaterMark = 0;\n    this.highWaterMark = chooseHighWaterMark(capacity, this.maxLoadFactor);\n  }\n\n  clone() {\n    return new HashTable(this);\n  }\n\n  get size() {\n    return this.distinct;\n  }\n\n  get(key) {\n    const i = this.indexOfKey(key);\n    if (i < 0) return 0;\n    return this.values[i];\n  }\n\n  set(key, value) {\n    let i = this.indexOfInsertion(key);\n    if (i < 0) {\n      i = -i - 1;\n      this.values[i] = value;\n      return false;\n    }\n\n    if (this.distinct > this.highWaterMark) {\n      const newCapacity = chooseGrowCapacity(\n        this.distinct + 1,\n        this.minLoadFactor,\n        this.maxLoadFactor\n      );\n      this.rehash(newCapacity);\n      return this.set(key, value);\n    }\n\n    this.table[i] = key;\n    this.values[i] = value;\n    if (this.state[i] === FREE) this.freeEntries--;\n    this.state[i] = FULL;\n    this.distinct++;\n\n    if (this.freeEntries < 1) {\n      const newCapacity = chooseGrowCapacity(\n        this.distinct + 1,\n        this.minLoadFactor,\n        this.maxLoadFactor\n      );\n      this.rehash(newCapacity);\n    }\n\n    return true;\n  }\n\n  remove(key, noRehash) {\n    const i = this.indexOfKey(key);\n    if (i < 0) return false;\n\n    this.state[i] = REMOVED;\n    this.distinct--;\n\n    if (!noRehash) this.maybeShrinkCapacity();\n\n    return true;\n  }\n\n  delete(key, noRehash) {\n    const i = this.indexOfKey(key);\n    if (i < 0) return false;\n\n    this.state[i] = FREE;\n    this.distinct--;\n\n    if (!noRehash) this.maybeShrinkCapacity();\n\n    return true;\n  }\n\n  maybeShrinkCapacity() {\n    if (this.distinct < this.lowWaterMark) {\n      const newCapacity = chooseShrinkCapacity(\n        this.distinct,\n        this.minLoadFactor,\n        this.maxLoadFactor\n      );\n      this.rehash(newCapacity);\n    }\n  }\n\n  containsKey(key) {\n    return this.indexOfKey(key) >= 0;\n  }\n\n  indexOfKey(key) {\n    const table = this.table;\n    const state = this.state;\n    const length = this.table.length;\n\n    const hash = key & 0x7fffffff;\n    let i = hash % length;\n    let decrement = hash % (length - 2);\n    if (decrement === 0) decrement = 1;\n\n    while (state[i] !== FREE && (state[i] === REMOVED || table[i] !== key)) {\n      i -= decrement;\n      if (i < 0) i += length;\n    }\n\n    if (state[i] === FREE) return -1;\n    return i;\n  }\n\n  containsValue(value) {\n    return this.indexOfValue(value) >= 0;\n  }\n\n  indexOfValue(value) {\n    const values = this.values;\n    const state = this.state;\n\n    for (var i = 0; i < state.length; i++) {\n      if (state[i] === FULL && values[i] === value) {\n        return i;\n      }\n    }\n\n    return -1;\n  }\n\n  indexOfInsertion(key) {\n    const table = this.table;\n    const state = this.state;\n    const length = table.length;\n\n    const hash = key & 0x7fffffff;\n    let i = hash % length;\n    let decrement = hash % (length - 2);\n    if (decrement === 0) decrement = 1;\n\n    while (state[i] === FULL && table[i] !== key) {\n      i -= decrement;\n      if (i < 0) i += length;\n    }\n\n    if (state[i] === REMOVED) {\n      const j = i;\n      while (state[i] !== FREE && (state[i] === REMOVED || table[i] !== key)) {\n        i -= decrement;\n        if (i < 0) i += length;\n      }\n      if (state[i] === FREE) i = j;\n    }\n\n    if (state[i] === FULL) {\n      return -i - 1;\n    }\n\n    return i;\n  }\n\n  ensureCapacity(minCapacity) {\n    if (this.table.length < minCapacity) {\n      const newCapacity = nextPrime(minCapacity);\n      this.rehash(newCapacity);\n    }\n  }\n\n  rehash(newCapacity) {\n    const oldCapacity = this.table.length;\n\n    if (newCapacity <= this.distinct) throw new Error('Unexpected');\n\n    const oldTable = this.table;\n    const oldValues = this.values;\n    const oldState = this.state;\n\n    const newTable = newArray(newCapacity);\n    const newValues = newArray(newCapacity);\n    const newState = newArray(newCapacity);\n\n    this.lowWaterMark = chooseLowWaterMark(newCapacity, this.minLoadFactor);\n    this.highWaterMark = chooseHighWaterMark(newCapacity, this.maxLoadFactor);\n\n    this.table = newTable;\n    this.values = newValues;\n    this.state = newState;\n    this.freeEntries = newCapacity - this.distinct;\n\n    for (var i = 0; i < oldCapacity; i++) {\n      if (oldState[i] === FULL) {\n        var element = oldTable[i];\n        var index = this.indexOfInsertion(element);\n        newTable[index] = element;\n        newValues[index] = oldValues[i];\n        newState[index] = FULL;\n      }\n    }\n  }\n\n  forEachKey(callback) {\n    for (var i = 0; i < this.state.length; i++) {\n      if (this.state[i] === FULL) {\n        if (!callback(this.table[i])) return false;\n      }\n    }\n    return true;\n  }\n\n  forEachValue(callback) {\n    for (var i = 0; i < this.state.length; i++) {\n      if (this.state[i] === FULL) {\n        if (!callback(this.values[i])) return false;\n      }\n    }\n    return true;\n  }\n\n  forEachPair(callback) {\n    for (var i = 0; i < this.state.length; i++) {\n      if (this.state[i] === FULL) {\n        if (!callback(this.table[i], this.values[i])) return false;\n      }\n    }\n    return true;\n  }\n}\n\nfunction chooseLowWaterMark(capacity, minLoad) {\n  return (capacity * minLoad) | 0;\n}\n\nfunction chooseHighWaterMark(capacity, maxLoad) {\n  return Math.min(capacity - 2, (capacity * maxLoad) | 0);\n}\n\nfunction chooseGrowCapacity(size, minLoad, maxLoad) {\n  return nextPrime(\n    Math.max(size + 1, ((4 * size) / (3 * minLoad + maxLoad)) | 0)\n  );\n}\n\nfunction chooseShrinkCapacity(size, minLoad, maxLoad) {\n  return nextPrime(\n    Math.max(size + 1, ((4 * size) / (minLoad + 3 * maxLoad)) | 0)\n  );\n}\n\nfunction newArray(size) {\n  return Array(size).fill(0);\n}\n","/* eslint-disable no-eval */\nimport HashTable from 'ml-hash-table';\n\nexport class SparseMatrix {\n  constructor(rows, columns, options = {}) {\n    if (rows instanceof SparseMatrix) {\n      // clone\n      const other = rows;\n      this._init(\n        other.rows,\n        other.columns,\n        other.elements.clone(),\n        other.threshold,\n      );\n      return;\n    }\n\n    if (Array.isArray(rows)) {\n      const matrix = rows;\n      rows = matrix.length;\n      options = columns || {};\n      columns = matrix[0].length;\n      this._init(rows, columns, new HashTable(options), options.threshold);\n      for (let i = 0; i < rows; i++) {\n        for (let j = 0; j < columns; j++) {\n          let value = matrix[i][j];\n          if (this.threshold && Math.abs(value) < this.threshold) value = 0;\n          if (value !== 0) {\n            this.elements.set(i * columns + j, matrix[i][j]);\n          }\n        }\n      }\n    } else {\n      this._init(rows, columns, new HashTable(options), options.threshold);\n    }\n  }\n\n  _init(rows, columns, elements, threshold) {\n    this.rows = rows;\n    this.columns = columns;\n    this.elements = elements;\n    this.threshold = threshold || 0;\n  }\n\n  static eye(rows = 1, columns = rows) {\n    const min = Math.min(rows, columns);\n    const matrix = new SparseMatrix(rows, columns, { initialCapacity: min });\n    for (let i = 0; i < min; i++) {\n      matrix.set(i, i, 1);\n    }\n    return matrix;\n  }\n\n  clone() {\n    return new SparseMatrix(this);\n  }\n\n  to2DArray() {\n    const copy = new Array(this.rows);\n    for (let i = 0; i < this.rows; i++) {\n      copy[i] = new Array(this.columns);\n      for (let j = 0; j < this.columns; j++) {\n        copy[i][j] = this.get(i, j);\n      }\n    }\n    return copy;\n  }\n\n  isSquare() {\n    return this.rows === this.columns;\n  }\n\n  isSymmetric() {\n    if (!this.isSquare()) return false;\n\n    let symmetric = true;\n    this.forEachNonZero((i, j, v) => {\n      if (this.get(j, i) !== v) {\n        symmetric = false;\n        return false;\n      }\n      return v;\n    });\n    return symmetric;\n  }\n\n  /**\n   * Search for the wither band in the main diagonals\n   * @return {number}\n   */\n  bandWidth() {\n    let min = this.columns;\n    let max = -1;\n    this.forEachNonZero((i, j, v) => {\n      let diff = i - j;\n      min = Math.min(min, diff);\n      max = Math.max(max, diff);\n      return v;\n    });\n    return max - min;\n  }\n\n  /**\n   * Test if a matrix is consider banded using a threshold\n   * @param {number} width\n   * @return {boolean}\n   */\n  isBanded(width) {\n    let bandWidth = this.bandWidth();\n    return bandWidth <= width;\n  }\n\n  get cardinality() {\n    return this.elements.size;\n  }\n\n  get size() {\n    return this.rows * this.columns;\n  }\n\n  get(row, column) {\n    return this.elements.get(row * this.columns + column);\n  }\n\n  set(row, column, value) {\n    if (this.threshold && Math.abs(value) < this.threshold) value = 0;\n    if (value === 0) {\n      this.elements.remove(row * this.columns + column);\n    } else {\n      this.elements.set(row * this.columns + column, value);\n    }\n    return this;\n  }\n\n  mmul(other) {\n    if (this.columns !== other.rows) {\n      // eslint-disable-next-line no-console\n      console.warn(\n        'Number of columns of left matrix are not equal to number of rows of right matrix.',\n      );\n    }\n\n    const m = this.rows;\n    const p = other.columns;\n\n    const result = new SparseMatrix(m, p);\n    this.forEachNonZero((i, j, v1) => {\n      other.forEachNonZero((k, l, v2) => {\n        if (j === k) {\n          result.set(i, l, result.get(i, l) + v1 * v2);\n        }\n        return v2;\n      });\n      return v1;\n    });\n    return result;\n  }\n\n  kroneckerProduct(other) {\n    const m = this.rows;\n    const n = this.columns;\n    const p = other.rows;\n    const q = other.columns;\n\n    const result = new SparseMatrix(m * p, n * q, {\n      initialCapacity: this.cardinality * other.cardinality,\n    });\n    this.forEachNonZero((i, j, v1) => {\n      other.forEachNonZero((k, l, v2) => {\n        result.set(p * i + k, q * j + l, v1 * v2);\n        return v2;\n      });\n      return v1;\n    });\n    return result;\n  }\n\n  forEachNonZero(callback) {\n    this.elements.forEachPair((key, value) => {\n      const i = (key / this.columns) | 0;\n      const j = key % this.columns;\n      let r = callback(i, j, value);\n      if (r === false) return false; // stop iteration\n      if (this.threshold && Math.abs(r) < this.threshold) r = 0;\n      if (r !== value) {\n        if (r === 0) {\n          this.elements.remove(key, true);\n        } else {\n          this.elements.set(key, r);\n        }\n      }\n      return true;\n    });\n    this.elements.maybeShrinkCapacity();\n    return this;\n  }\n\n  getNonZeros() {\n    const cardinality = this.cardinality;\n    const rows = new Array(cardinality);\n    const columns = new Array(cardinality);\n    const values = new Array(cardinality);\n    let idx = 0;\n    this.forEachNonZero((i, j, value) => {\n      rows[idx] = i;\n      columns[idx] = j;\n      values[idx] = value;\n      idx++;\n      return value;\n    });\n    return { rows, columns, values };\n  }\n\n  setThreshold(newThreshold) {\n    if (newThreshold !== 0 && newThreshold !== this.threshold) {\n      this.threshold = newThreshold;\n      this.forEachNonZero((i, j, v) => v);\n    }\n    return this;\n  }\n\n  /**\n   * @return {SparseMatrix} - New transposed sparse matrix\n   */\n  transpose() {\n    let trans = new SparseMatrix(this.columns, this.rows, {\n      initialCapacity: this.cardinality,\n    });\n    this.forEachNonZero((i, j, value) => {\n      trans.set(j, i, value);\n      return value;\n    });\n    return trans;\n  }\n\n  isEmpty() {\n    return this.rows === 0 || this.columns === 0;\n  }\n}\n\nSparseMatrix.prototype.klass = 'Matrix';\n\nSparseMatrix.identity = SparseMatrix.eye;\nSparseMatrix.prototype.tensorProduct = SparseMatrix.prototype.kroneckerProduct;\n\n/*\n Add dynamically instance and static methods for mathematical operations\n */\n\nlet inplaceOperator = `\n(function %name%(value) {\n    if (typeof value === 'number') return this.%name%S(value);\n    return this.%name%M(value);\n})\n`;\n\nlet inplaceOperatorScalar = `\n(function %name%S(value) {\n    this.forEachNonZero((i, j, v) => v %op% value);\n    return this;\n})\n`;\n\nlet inplaceOperatorMatrix = `\n(function %name%M(matrix) {\n    matrix.forEachNonZero((i, j, v) => {\n        this.set(i, j, this.get(i, j) %op% v);\n        return v;\n    });\n    return this;\n})\n`;\n\nlet staticOperator = `\n(function %name%(matrix, value) {\n    var newMatrix = new SparseMatrix(matrix);\n    return newMatrix.%name%(value);\n})\n`;\n\nlet inplaceMethod = `\n(function %name%() {\n    this.forEachNonZero((i, j, v) => %method%(v));\n    return this;\n})\n`;\n\nlet staticMethod = `\n(function %name%(matrix) {\n    var newMatrix = new SparseMatrix(matrix);\n    return newMatrix.%name%();\n})\n`;\n\nconst operators = [\n  // Arithmetic operators\n  ['+', 'add'],\n  ['-', 'sub', 'subtract'],\n  ['*', 'mul', 'multiply'],\n  ['/', 'div', 'divide'],\n  ['%', 'mod', 'modulus'],\n  // Bitwise operators\n  ['&', 'and'],\n  ['|', 'or'],\n  ['^', 'xor'],\n  ['<<', 'leftShift'],\n  ['>>', 'signPropagatingRightShift'],\n  ['>>>', 'rightShift', 'zeroFillRightShift'],\n];\n\nfor (const operator of operators) {\n  for (let i = 1; i < operator.length; i++) {\n    SparseMatrix.prototype[operator[i]] = eval(\n      fillTemplateFunction(inplaceOperator, {\n        name: operator[i],\n        op: operator[0],\n      }),\n    );\n    SparseMatrix.prototype[`${operator[i]}S`] = eval(\n      fillTemplateFunction(inplaceOperatorScalar, {\n        name: `${operator[i]}S`,\n        op: operator[0],\n      }),\n    );\n    SparseMatrix.prototype[`${operator[i]}M`] = eval(\n      fillTemplateFunction(inplaceOperatorMatrix, {\n        name: `${operator[i]}M`,\n        op: operator[0],\n      }),\n    );\n\n    SparseMatrix[operator[i]] = eval(\n      fillTemplateFunction(staticOperator, { name: operator[i] }),\n    );\n  }\n}\n\nlet methods = [['~', 'not']];\n\n[\n  'abs',\n  'acos',\n  'acosh',\n  'asin',\n  'asinh',\n  'atan',\n  'atanh',\n  'cbrt',\n  'ceil',\n  'clz32',\n  'cos',\n  'cosh',\n  'exp',\n  'expm1',\n  'floor',\n  'fround',\n  'log',\n  'log1p',\n  'log10',\n  'log2',\n  'round',\n  'sign',\n  'sin',\n  'sinh',\n  'sqrt',\n  'tan',\n  'tanh',\n  'trunc',\n].forEach(function (mathMethod) {\n  methods.push([`Math.${mathMethod}`, mathMethod]);\n});\n\nfor (const method of methods) {\n  for (let i = 1; i < method.length; i++) {\n    SparseMatrix.prototype[method[i]] = eval(\n      fillTemplateFunction(inplaceMethod, {\n        name: method[i],\n        method: method[0],\n      }),\n    );\n    SparseMatrix[method[i]] = eval(\n      fillTemplateFunction(staticMethod, { name: method[i] }),\n    );\n  }\n}\n\nfunction fillTemplateFunction(template, values) {\n  for (const i in values) {\n    template = template.replace(new RegExp(`%${i}%`, 'g'), values[i]);\n  }\n  return template;\n}\n","import { SparseMatrix } from 'ml-sparse-matrix';\nfunction createPauli(mult) {\n    const spin = (mult - 1) / 2;\n    const prjs = new Array(mult);\n    const temp = new Array(mult);\n    for (let i = 0; i < mult; i++) {\n        prjs[i] = mult - 1 - i - spin;\n        temp[i] = Math.sqrt(spin * (spin + 1) - prjs[i] * (prjs[i] + 1));\n    }\n    const p = diag(temp, 1, mult, mult);\n    for (let i = 0; i < mult; i++) {\n        temp[i] = Math.sqrt(spin * (spin + 1) - prjs[i] * (prjs[i] - 1));\n    }\n    const m = diag(temp, -1, mult, mult);\n    const x = p.clone().add(m).mul(0.5);\n    const y = m.clone().mul(-1).add(p).mul(-0.5);\n    const z = diag(prjs, 0, mult, mult);\n    return { x, y, z, m, p };\n}\nfunction diag(A, d, n, m) {\n    const diag = new SparseMatrix(n, m, { initialCapacity: 20 });\n    for (let i = 0; i < A.length; i++) {\n        if (i - d >= 0 && i - d < n && i < m) {\n            diag.set(i - d, i, A[i]);\n        }\n    }\n    return diag;\n}\nconst pauli2 = createPauli(2);\nexport default function getPauliMatrix(mult) {\n    if (mult === 2)\n        return pauli2;\n    else\n        return createPauli(mult);\n}\n//# sourceMappingURL=getPauliMatrix.js.map","import binarySearch from 'binary-search';\nimport { Matrix, EVD } from 'ml-matrix';\nimport { SparseMatrix } from 'ml-sparse-matrix';\nimport getPauliMatrix from './getPauliMatrix';\nconst smallValue = 1e-2;\nexport function simulateXYPeaks(\n/**\n * The SpinSystem object to be simulated\n */\nspinSystem, options = {}) {\n    let { lineWidth = 1, maxClusterSize = 8, frequency: frequencyMHz = 400, } = options;\n    const chemicalShifts = spinSystem.chemicalShifts.slice();\n    for (let i = 0; i < chemicalShifts.length; i++) {\n        chemicalShifts[i] = chemicalShifts[i] * frequencyMHz;\n    }\n    const multiplicity = spinSystem.multiplicity;\n    const xyPeaks = [];\n    for (const cluster of spinSystem.clusters) {\n        let clusterFake = cluster.map((cluster) => cluster < 0 ? -cluster - 1 : cluster);\n        let weight = 1;\n        let sumI = 0;\n        let frequencies = [];\n        let intensities = [];\n        if (cluster.length > maxClusterSize) {\n            // This is a single spin, but the cluster exceeds the maxClusterSize criteria\n            // we use the simple multiplicity algorithm\n            // Add the central peak. It will be split with every single J coupling.\n            let index = 0;\n            while (cluster[index++] < 0)\n                ;\n            index = cluster[index - 1];\n            frequencies.push(-chemicalShifts[index]);\n            for (let i = 0; i < cluster.length; i++) {\n                if (cluster[i] < 0) {\n                    let jc = spinSystem.couplingConstants.get(index, clusterFake[i]) / 2;\n                    let currentSize = frequencies.length;\n                    for (let j = 0; j < currentSize; j++) {\n                        frequencies.push(frequencies[j] + jc);\n                        frequencies[j] -= jc;\n                    }\n                }\n            }\n            frequencies.sort((a, b) => a - b);\n            sumI = frequencies.length;\n            weight = 1;\n            for (let i = 0; i < sumI; i++) {\n                intensities.push(1);\n            }\n        }\n        else {\n            const hamiltonian = getHamiltonian(chemicalShifts, spinSystem.couplingConstants, multiplicity, spinSystem.connectivity, clusterFake);\n            const hamSize = hamiltonian.rows;\n            // TODO: add support for sparse matrix in matrix types.\n            // @ts-expect-error sparse matrix not supported\n            const evd = new EVD(hamiltonian);\n            const V = evd.eigenvectorMatrix;\n            const diagB = evd.realEigenvalues;\n            const assignmentMatrix = new SparseMatrix(hamSize, hamSize);\n            const multLen = cluster.length;\n            weight = 0;\n            for (let n = 0; n < multLen; n++) {\n                const L = getPauliMatrix(multiplicity[clusterFake[n]]);\n                let temp = 1;\n                for (let j = 0; j < n; j++) {\n                    temp *= multiplicity[clusterFake[j]];\n                }\n                const A = SparseMatrix.eye(temp);\n                temp = 1;\n                for (let j = n + 1; j < multLen; j++) {\n                    temp *= multiplicity[clusterFake[j]];\n                }\n                const B = SparseMatrix.eye(temp);\n                const tempMat = A.kroneckerProduct(L.m).kroneckerProduct(B);\n                if (cluster[n] >= 0) {\n                    assignmentMatrix.add(tempMat.mul(cluster[n] + 1));\n                    weight++;\n                }\n                else {\n                    assignmentMatrix.add(tempMat.mul(cluster[n]));\n                }\n            }\n            let rhoip = Matrix.zeros(hamSize, hamSize);\n            assignmentMatrix.forEachNonZero((i, j, v) => {\n                if (v > 0) {\n                    for (let k = 0; k < V.columns; k++) {\n                        let element = V.get(j, k);\n                        if (element !== 0) {\n                            rhoip.set(i, k, rhoip.get(i, k) + element);\n                        }\n                    }\n                }\n                return v;\n            });\n            let rhoip2 = rhoip.clone();\n            assignmentMatrix.forEachNonZero((i, j, v) => {\n                if (v < 0) {\n                    for (let k = 0; k < V.columns; k++) {\n                        let element = V.get(j, k);\n                        if (element !== 0) {\n                            rhoip2.set(i, k, rhoip2.get(i, k) + element);\n                        }\n                    }\n                }\n                return v;\n            });\n            const tV = V.transpose();\n            rhoip = tV.mmul(rhoip);\n            const sparseRhoip = new SparseMatrix(rhoip.to2DArray(), {\n                threshold: smallValue,\n            });\n            triuTimesAbs(sparseRhoip, smallValue);\n            rhoip2 = tV.mmul(rhoip2);\n            const sparseRhoip2 = new SparseMatrix(rhoip2.to2DArray(), {\n                threshold: smallValue,\n            });\n            sparseRhoip2.forEachNonZero((i, j, v) => {\n                return v;\n            });\n            triuTimesAbs(sparseRhoip2, smallValue);\n            sparseRhoip2.forEachNonZero((i, j, v) => {\n                let val = rhoip.get(i, j);\n                val = Math.min(Math.abs(val), Math.abs(v));\n                val *= val;\n                sumI += val;\n                let valFreq = diagB[i] - diagB[j];\n                let insertIn = binarySearch(frequencies, valFreq, (a, b) => a - b);\n                if (insertIn < 0) {\n                    frequencies.splice(-1 - insertIn, 0, valFreq);\n                    intensities.splice(-1 - insertIn, 0, val);\n                }\n                else {\n                    intensities[insertIn] += val;\n                }\n            });\n        }\n        const numFreq = frequencies.length;\n        if (numFreq > 0) {\n            weight /= sumI;\n            const diff = lineWidth / 64;\n            let valFreq = frequencies[0];\n            let inte = intensities[0];\n            let count = 1;\n            for (let i = 1; i < numFreq; i++) {\n                if (Math.abs(frequencies[i] - valFreq / count) < diff) {\n                    inte += intensities[i];\n                    valFreq += frequencies[i];\n                    count++;\n                }\n                else {\n                    xyPeaks.push({\n                        x: -valFreq / count / frequencyMHz,\n                        y: inte * weight,\n                    });\n                    valFreq = frequencies[i];\n                    inte = intensities[i];\n                    count = 1;\n                }\n            }\n            xyPeaks.push({\n                x: -valFreq / count / frequencyMHz,\n                y: inte * weight,\n            });\n        }\n    }\n    return xyPeaks.filter((peak) => peak.x < 1000);\n}\nfunction triuTimesAbs(A, val) {\n    A.forEachNonZero((i, j, v) => {\n        if (i > j)\n            return 0;\n        if (Math.abs(v) <= val)\n            return 0;\n        return v;\n    });\n}\n/**\n * Create a hamiltonian matrix for the given spinsystem\n * @param {Array} chemicalShifts - An array containing the chemical shift in Hz\n * @param {Array} couplingConstants - An array containing the coupling constants in Hz\n * @param {Array} multiplicity - An array specifiying the multiplicities of each scalar coupling\n * @param {Array} conMatrix - A one step connectivity matrix for the given spin system\n * @param {Array} cluster - An binary array specifiying the spins to be considered for this hamiltonial\n * @return {object}\n */\nfunction getHamiltonian(chemicalShifts, couplingConstants, multiplicity, conMatrix, cluster) {\n    let hamSize = 1;\n    for (const element of cluster) {\n        hamSize *= multiplicity[element];\n    }\n    const clusterHam = new SparseMatrix(hamSize, hamSize);\n    for (let pos = 0; pos < cluster.length; pos++) {\n        let n = cluster[pos];\n        const L = getPauliMatrix(multiplicity[n]);\n        let A1, B1;\n        let temp = 1;\n        for (let i = 0; i < pos; i++) {\n            temp *= multiplicity[cluster[i]];\n        }\n        A1 = SparseMatrix.eye(temp);\n        temp = 1;\n        for (let i = pos + 1; i < cluster.length; i++) {\n            temp *= multiplicity[cluster[i]];\n        }\n        B1 = SparseMatrix.eye(temp);\n        const alpha = chemicalShifts[n];\n        const kronProd = A1.kroneckerProduct(L.z).kroneckerProduct(B1);\n        clusterHam.add(kronProd.mul(alpha));\n        for (let pos2 = 0; pos2 < cluster.length; pos2++) {\n            const k = cluster[pos2];\n            if (conMatrix.get(n, k) === 1) {\n                const S = getPauliMatrix(multiplicity[k]);\n                let A2, B2;\n                let temp = 1;\n                for (let i = 0; i < pos2; i++) {\n                    temp *= multiplicity[cluster[i]];\n                }\n                A2 = SparseMatrix.eye(temp);\n                temp = 1;\n                for (let i = pos2 + 1; i < cluster.length; i++) {\n                    temp *= multiplicity[cluster[i]];\n                }\n                B2 = SparseMatrix.eye(temp);\n                const kron1 = A1.kroneckerProduct(L.x)\n                    .kroneckerProduct(B1)\n                    .mmul(A2.kroneckerProduct(S.x).kroneckerProduct(B2));\n                kron1.add(A1.kroneckerProduct(L.y)\n                    .kroneckerProduct(B1)\n                    .mul(-1)\n                    .mmul(A2.kroneckerProduct(S.y).kroneckerProduct(B2)));\n                kron1.add(A1.kroneckerProduct(L.z)\n                    .kroneckerProduct(B1)\n                    .mmul(A2.kroneckerProduct(S.z).kroneckerProduct(B2)));\n                clusterHam.add(kron1.mul(couplingConstants.get(n, k) / 2));\n            }\n        }\n    }\n    return clusterHam;\n}\n//# sourceMappingURL=simulateXYPeaks.js.map","import { generateSpectrum } from 'spectrum-generator';\nimport { simulateXYPeaks } from './simulateXYPeaks';\n/**\n * This function simulates a one dimensional nmr spectrum. This function returns an array containing the relative intensities of the spectrum in the specified simulation window (from-to).\n */\nexport default function simulate1D(\n/**\n * The SpinSystem object to be simulated\n */\nspinSystem, options = {}) {\n    let { lineWidth = 1, frequency: frequencyMHz = 400, from = 0, to = 10, nbPoints = 1024, shape = {\n        kind: 'gaussian',\n    }, } = options;\n    let peakWidth = lineWidth / frequencyMHz;\n    const xyPeaks = simulateXYPeaks(spinSystem, options);\n    return generateSpectrum(xyPeaks, {\n        generator: {\n            from,\n            to,\n            nbPoints,\n        },\n        peakOptions: {\n            shape,\n            width: peakWidth,\n        },\n    });\n}\n//# sourceMappingURL=simulate1D.js.map","import { agnes } from 'ml-hclust';\nimport { Matrix } from 'ml-matrix';\nexport function splitSpinSystem(spinSystem, options = {}) {\n    let { chemicalShifts, couplingConstants, connectivity } = spinSystem;\n    let { frequency = 400, maxClusterSize = 8 } = options;\n    let betas = calculateBetas(chemicalShifts, couplingConstants, frequency);\n    let initClusters = agnes(betas, { method: 'single', isDistanceMatrix: true });\n    let clusterList = [];\n    let nSpins = chemicalShifts.length;\n    splitCluster(initClusters, clusterList, {\n        maxClusterSize,\n        force: false,\n        nSpins,\n        connectivity,\n    });\n    let mergedClusters = mergeClusters(clusterList, maxClusterSize);\n    let nClusters = mergedClusters.length;\n    let clusters = new Array(nClusters);\n    for (let j = 0; j < nClusters; j++) {\n        clusters[j] = [];\n        for (let i = 0; i < nSpins; i++) {\n            let element = mergedClusters[j][i];\n            if (element === 0)\n                continue;\n            clusters[j].push(element < 0 ? -(i + 1) : i);\n        }\n    }\n    return clusters;\n}\nfunction splitCluster(cluster, clusterList, options) {\n    let { maxClusterSize, force, nSpins, connectivity } = options;\n    if (!force && cluster.size <= maxClusterSize) {\n        clusterList.push(getMembers(cluster.indices(), nSpins));\n    }\n    else {\n        for (let child of cluster.children) {\n            if (child.size <= maxClusterSize) {\n                let members = getMembers(child.indices(), nSpins);\n                // Add the neighbors that shares at least 1 coupling with the given cluster\n                let count = 0;\n                for (let i = 0; i < nSpins; i++) {\n                    if (members[i] === 1) {\n                        for (let j = 0; j < nSpins; j++) {\n                            if (connectivity.get(i, j) === 1 && members[j] === 0) {\n                                members[j] = -1;\n                                count++;\n                            }\n                        }\n                        count++;\n                    }\n                }\n                if (count <= maxClusterSize) {\n                    clusterList.push(members);\n                }\n                else if (child.index < 0) {\n                    splitCluster(child, clusterList, {\n                        maxClusterSize,\n                        force: true,\n                        nSpins,\n                        connectivity,\n                    });\n                }\n                else {\n                    // We have to threat this spin alone and use the resurrection algorithm instead of the simulation\n                    members[child.index] = 2;\n                    clusterList.push(members);\n                }\n            }\n            else {\n                splitCluster(child, clusterList, {\n                    maxClusterSize,\n                    force: false,\n                    nSpins,\n                    connectivity,\n                });\n            }\n        }\n    }\n}\nfunction calculateBetas(chemicalShifts, couplingConstants, frequency) {\n    let nRows = couplingConstants.rows;\n    let nColumns = couplingConstants.columns;\n    let betas = Matrix.zeros(nRows, nRows);\n    // Before clustering, we must add hidden couplingConstants, we could use molecular information if available\n    for (let i = 0; i < nRows; i++) {\n        for (let j = i; j < nColumns; j++) {\n            let element = couplingConstants.get(i, j);\n            if (chemicalShifts[i] - chemicalShifts[j] !== 0) {\n                let value = 1 -\n                    Math.abs(element / ((chemicalShifts[i] - chemicalShifts[j]) * frequency));\n                betas.set(i, j, value);\n                betas.set(j, i, value);\n            }\n            else if (!(i === j || element !== 0)) {\n                betas.set(i, j, 1);\n                betas.set(j, i, 1);\n            }\n        }\n    }\n    return betas.to2DArray();\n}\nfunction mergeClusters(list, maxClusterSize) {\n    for (let i = list.length - 1; i >= 0; i--) {\n        let clusterA = list[i];\n        let nElements = clusterA.length;\n        let index = 0;\n        // Is it a candidate to be merged?\n        while (index < nElements && clusterA[index++] !== -1)\n            ;\n        if (index >= nElements)\n            continue;\n        for (let j = list.length - 1; j >= i + 1; j--) {\n            let clusterB = list[j];\n            // Do they have common elements?\n            let count = 0;\n            let common = 0;\n            for (let index = 0; index < nElements; index++) {\n                if (clusterA[index] * clusterB[index] === -1)\n                    common++;\n                if (clusterA[index] !== 0 || clusterB[index] !== 0)\n                    count++;\n            }\n            if (common > 0 && count <= maxClusterSize) {\n                // Then we can merge those 2 clusters\n                for (let index = 0; index < nElements; index++) {\n                    if (clusterB[index] === 1) {\n                        clusterA[index] = 1;\n                    }\n                    else if (clusterB[index] === -1 && clusterA[index] !== 1) {\n                        clusterA[index] = -1;\n                    }\n                }\n                list.splice(j, 1);\n            }\n        }\n    }\n    return list;\n}\nfunction getMembers(cluster, nSpins) {\n    let members = new Int16Array(nSpins);\n    for (let e of cluster) {\n        members[e] = 1;\n    }\n    return members;\n}\n//# sourceMappingURL=splitSpinSystem.js.map","import rescale from 'ml-array-rescale';\nimport { xSequentialFill } from 'ml-spectra-processing';\nimport { signalsToSpinSystem } from './simulation/signalsToSpinSystem';\nimport simulate1D from './simulation/simulate1D';\nimport { splitSpinSystem } from './simulation/splitSpinSystem';\nfunction checkForMandatory(signals) {\n    for (const signal of signals) {\n        if (!signal.js)\n            throw new Error('There is not js');\n        // if (!signal.diaID) throw new Error('There is not diaID');\n        if (!signal.atoms)\n            throw new Error('There is not atoms');\n        for (const j of signal.js) {\n            // if (!j.diaID) throw new Error('There is not diaID');\n            if (!j.atoms)\n                throw new Error('There is not atoms');\n        }\n    }\n}\n/**\n * Generate a spectrum from an array of singals\n */\nexport function signalsToXY(signals, options = {}) {\n    checkForMandatory(signals);\n    let { frequency = 400, shape = {\n        kind: 'gaussian',\n    }, from = 0, to = 10, lineWidth = 1, nbPoints = 16 * 1024, maxValue = 1e8, maxClusterSize = 8, } = options;\n    if (signals.length === 0) {\n        return {\n            x: xSequentialFill({ from, to, size: nbPoints }),\n            y: Array.from(new Float64Array(nbPoints)),\n        };\n    }\n    let spinSystem = signalsToSpinSystem(signals);\n    spinSystem.clusters = splitSpinSystem(spinSystem, {\n        frequency,\n        maxClusterSize,\n    });\n    let spectrum = simulate1D(spinSystem, {\n        frequency,\n        from,\n        to,\n        nbPoints,\n        lineWidth,\n        shape,\n    });\n    if (maxValue) {\n        spectrum.y = rescale(spectrum.y, { max: maxValue });\n    }\n    return spectrum;\n}\n//# sourceMappingURL=signalsToXY.js.map","import { gyromagneticRatio } from 'gyromagnetic-ratio';\n/**\n * calculate the frequency of a nucleus with respect to a reference nucleus\n */\nexport function getFrequency(\n/**\n * nucleus to calculate the frequency\n */\nnucleus, observedNucleusData) {\n    const { nucleus: obsNucleus, frequency } = observedNucleusData;\n    checkExistence(nucleus, obsNucleus);\n    return ((frequency * gyromagneticRatio[nucleus]) /\n        gyromagneticRatio[obsNucleus]);\n}\nfunction checkExistence(...nucleus) {\n    let nuclei = [];\n    for (const n of nucleus) {\n        if (!(n in gyromagneticRatio)) {\n            nuclei.push(n);\n        }\n    }\n    if (nuclei.length !== 0) {\n        throw new Error(`${nuclei.join(' , ')} is not supported`);\n    }\n}\n//# sourceMappingURL=getFrequency.js.map","import { signals2DToZ } from '../signals/signals2DToZ';\nimport { signalsToXY } from '../signals/signalsToXY';\nimport { getFrequency } from '../utilities/getFrequency';\nimport { predictAll } from './predictAll';\nexport async function predictAllSpectra(molecule, options = {}) {\n    const { simulation: simulationOptions = { oneD: {}, twoD: {} }, prediction: predictionOptions = {}, } = options;\n    const predictions = await predictAll(molecule, predictionOptions);\n    const spectra = [];\n    const result = { spectra, molecules: [{ molfile: predictions.molfile }] };\n    const oneDOptions = {\n        ...{\n            proton: { from: 0, to: 14 },\n            carbon: { from: 0, to: 200 },\n            nbPoints: 65536,\n            lineWidth: 1,\n        },\n        ...(simulationOptions.oneD || {}),\n    };\n    const twoDOptions = {\n        ...{\n            from: { x: oneDOptions.proton.from, y: oneDOptions.carbon.from },\n            to: { x: oneDOptions.proton.to, y: oneDOptions.carbon.to },\n            nbPoints: { x: 1024, y: 1024 },\n        },\n        ...(simulationOptions.twoD || {}),\n    };\n    for (const experiment in predictions) {\n        switch (experiment) {\n            case 'carbon':\n            case 'proton': {\n                spectra.push(get1DSpectrum(predictions[experiment], {\n                    nbPoints: oneDOptions.nbPoints,\n                    lineWidth: oneDOptions.lineWidth,\n                    ...oneDOptions[experiment],\n                    experiment,\n                    frequency: simulationOptions.frequency,\n                }));\n                break;\n            }\n            case 'cosy':\n            case 'hsqc':\n            case 'hmbc': {\n                spectra.push(get2DSpectrum(predictions[experiment], {\n                    ...twoDOptions,\n                    experiment,\n                    frequency: simulationOptions.frequency,\n                }));\n                break;\n            }\n            default:\n                break;\n        }\n    }\n    return result;\n}\nfunction get2DSpectrum(prediction, options) {\n    const { signals, zones, nuclei } = prediction;\n    const { frequency: baseFrequency, experiment } = options;\n    const width = get2DWidth(nuclei);\n    const frequency = calculateFrequency(nuclei, baseFrequency);\n    const minMaxContent = signals2DToZ(signals, {\n        ...options,\n        width,\n        factor: 3,\n    });\n    const spectrum = {\n        data: { rr: { ...minMaxContent, noise: 0.01 } },\n        info: {\n            nucleus: nuclei,\n            originFrequency: frequency,\n            baseFrequency: frequency,\n            pulseSequence: experiment,\n            experiment: '2d',\n        },\n        zones: { values: zones },\n    };\n    return spectrum;\n}\nfunction get2DWidth(nucleus) {\n    return nucleus[0] === nucleus[1] ? 0.02 : { x: 0.02, y: 0.2133 };\n}\nfunction get1DSpectrum(prediction, options) {\n    const { frequency = 400, experiment } = options;\n    const { signals, nucleus } = prediction;\n    const realFrequency = calculateFrequency(nucleus, frequency);\n    const { x, y } = signalsToXY(signals, {\n        ...options,\n        frequency: realFrequency,\n    });\n    const spectrum = {\n        // todo Array.from is temporary for the developement\n        data: { x: Array.from(x), re: Array.from(y), im: null },\n        info: {\n            nucleus: prediction.nucleus,\n            dimension: 1,\n            originFrequency: realFrequency,\n            baseFrequency: realFrequency,\n            pulseSequence: 'prediction',\n            experiment,\n            isFt: true,\n        },\n        ranges: { values: prediction.ranges },\n    };\n    return spectrum;\n}\nfunction calculateFrequency(nucleus, frequency) {\n    if (typeof nucleus === 'string') {\n        return getFrequency(nucleus, { nucleus: '1H', frequency });\n    }\n    else if (nucleus[0] === nucleus[1]) {\n        return `${frequency},${frequency}`;\n    }\n    else {\n        return `${frequency},${getFrequency(nucleus[1], {\n            nucleus: nucleus[0],\n            frequency,\n        })}`;\n    }\n}\n//# sourceMappingURL=predictAllSpectra.js.map","'use strict';\n/**\n * Created by acastillo on 9/3/16.\n */\n\nclass TreeSet{\n\n    constructor(compatator){\n        this.length = 0;\n        this.elements = [];\n        if(compatator)\n            this.compatator = compatator;\n        else\n            this.compatator = function(a, b){ return a - b };\n    }\n\n    size(){\n        return this.elements.length;\n    }\n\n    last(){\n        return this.elements[this.length-1];\n    }\n\n    first(){\n        return this.elements[0];\n    }\n\n    isEmpty(){\n        return this.size()===0;\n    }\n\n    pollLast(){\n        if(this.length>0){\n            this.length--;\n            return this.elements.splice(this.length, 1);\n        }\n        return null;\n    }\n\n    pollFirst(){\n        if(this.length>0) {\n            this.length--;\n            return this.elements.splice(0, 1);\n        }\n        return null;\n    }\n\n    add(element){\n        let index = this.binarySearch(element);\n        if(index < 0){\n            index = -index-1;\n        }\n        this.elements.splice(index, 0, element);\n        this.length++;\n    }\n\n    /**\n     * Performs a binary search of value in array\n     * @param {number[]} array - Array in which value will be searched. It must be sorted.\n     * @param {number} value - Value to search in array\n     * @return {number} If value is found, returns its index in array. Otherwise, returns a negative number indicating where the value should be inserted: -(index + 1)\n     */\n    binarySearch(value) {\n        var low = 0;\n        var high = this.elements.length - 1;\n\n        while (low <= high) {\n            var mid = (low + high) >>> 1;\n            var midValue = this.elements[mid];\n            var cmp = this.compatator(midValue, value);\n            if (cmp < 0) {\n                low = mid + 1;\n            } else if (cmp > 0) {\n                high = mid - 1;\n            } else {\n                return mid;\n            }\n        }\n\n        return -(low + 1);\n    }\n}\n\nmodule.exports = TreeSet;","export function createMapPossibleAssignments(props) {\n    const { restrictionByCS, predictions, targets, useIntegrationRestriction } = props;\n    const { tolerance: toleranceCS, chemicalShiftRestriction } = restrictionByCS;\n    let errorAbs = Math.abs(toleranceCS);\n    const expandMap = {};\n    for (const diaID in predictions) {\n        let prediction = predictions[diaID];\n        if (prediction.error)\n            prediction.error = Math.abs(prediction.error);\n        expandMap[diaID] = [];\n        if (targets) {\n            for (const targetID in targets) {\n                let target = targets[targetID];\n                const { nbAtoms } = prediction;\n                const { integration } = target;\n                const couldBeAssigned = useIntegrationRestriction\n                    ? integration > 0\n                        ? nbAtoms - integration < 1\n                        : true\n                    : true;\n                if (couldBeAssigned) {\n                    if (!chemicalShiftRestriction ||\n                        typeof prediction.delta === 'undefined') {\n                        // Chemical shift is not a restriction\n                        expandMap[diaID].push(targetID);\n                    }\n                    else {\n                        let error = errorAbs;\n                        if (prediction.error) {\n                            error = Math.max(error, prediction.error);\n                        }\n                        const delta = target.signals && target.signals.length > 0\n                            ? target.signals[0].delta\n                            : (target.to + target.from) / 2;\n                        let distAfterLimit = Math.abs(prediction.delta - delta - errorAbs);\n                        if (distAfterLimit < 4 * errorAbs) {\n                            expandMap[diaID].push(targetID);\n                        }\n                    }\n                }\n            }\n        }\n        expandMap[diaID].push('*');\n    }\n    return expandMap;\n}\n//# sourceMappingURL=createMapPossibleAssignments.js.map","export function partialScore(partial, options) {\n    const { useIntegrationRestriction, diaIDPeerPossibleAssignment, nbAllowedUnAssigned, restrictionByCS, predictions, targets, } = options;\n    const { useChemicalShiftScore } = restrictionByCS;\n    let countStars = 0;\n    let totalPartial = partial.length;\n    let partialInverse = {};\n    let activeDomainOnPrediction = [];\n    for (let i = 0; i < partial.length; i++) {\n        const targetID = partial[i];\n        if (targetID && targetID !== '*') {\n            activeDomainOnPrediction.push(i);\n            if (!partialInverse[targetID]) {\n                partialInverse[targetID] = [];\n            }\n            partialInverse[targetID].push(diaIDPeerPossibleAssignment[i]);\n        }\n        if (targetID === '*')\n            countStars++;\n    }\n    if (countStars > nbAllowedUnAssigned)\n        return 0;\n    const activeDomainOnTarget = Object.keys(partialInverse);\n    if (activeDomainOnTarget.length === 0) {\n        return 0;\n    }\n    if (useIntegrationRestriction) {\n        for (let targetID of activeDomainOnTarget) {\n            let targetToSource = partialInverse[targetID];\n            let total = 0;\n            for (const diaID of targetToSource) {\n                const prediction = predictions[diaID];\n                total += prediction.allHydrogens;\n            }\n            const { integration } = targets[targetID];\n            if (total - integration >= 0.5) {\n                return 0;\n            }\n        }\n    }\n    //chemical shift score\n    let chemicalShiftScore = useChemicalShiftScore\n        ? chemicalShiftScoring(partial, options)\n        : 1;\n    const penaltyByStarts = countStars / totalPartial;\n    return chemicalShiftScore - penaltyByStarts;\n}\nfunction chemicalShiftScoring(partial, options) {\n    const { tolerance } = options.restrictionByCS;\n    const { diaIDPeerPossibleAssignment, predictions, targets } = options;\n    let chemicalShiftScore = 0;\n    let count = 0;\n    for (let index = 0; index < partial.length; index++) {\n        const targetID = partial[index];\n        if (targetID && targetID !== '*') {\n            count++;\n            let diaID = diaIDPeerPossibleAssignment[index];\n            let source = predictions[diaID];\n            let target = targets[targetID];\n            let error = tolerance;\n            if (source.error) {\n                error = Math.max(source.error, tolerance);\n            }\n            if (typeof source.delta === 'undefined') {\n                // Chemical shift is not a restriction\n                chemicalShiftScore += 1;\n            }\n            else {\n                const delta = target.signals && target.signals.length > 0\n                    ? target.signals[0].delta\n                    : (target.to + target.from) / 2;\n                let diff = Math.abs(source.delta - delta);\n                if (diff < error) {\n                    chemicalShiftScore += 1;\n                }\n                else {\n                    diff = Math.abs(diff - error);\n                    chemicalShiftScore += (-0.25 / error) * diff + 1;\n                }\n            }\n        }\n    }\n    if (count > 0) {\n        chemicalShiftScore /= count;\n    }\n    return chemicalShiftScore;\n}\n//# sourceMappingURL=partialScore.js.map","import { partialScore } from './partialScore';\nexport function exploreTreeRec(props, currentIndex, partial, store) {\n    const { nSources, restrictionByCS, timeout, timeStart, maxSolutions, targets, predictions, lowerBoundScore, nbAllowedUnAssigned, possibleAssignmentMap, useIntegrationRestriction, diaIDPeerPossibleAssignment, } = props;\n    const currentDate = new Date();\n    if (currentDate.getTime() - timeStart > timeout) {\n        new Error('timeout expired');\n        return store;\n    }\n    const diaID = diaIDPeerPossibleAssignment[currentIndex];\n    const possibleAssignments = possibleAssignmentMap[diaID];\n    for (let targetID of possibleAssignments) {\n        partial[currentIndex] = targetID;\n        let score = partialScore(partial, {\n            useIntegrationRestriction,\n            diaIDPeerPossibleAssignment,\n            nbAllowedUnAssigned,\n            restrictionByCS,\n            predictions,\n            targets,\n        });\n        if (score === 0) {\n            if (targetID === '*') {\n                partial[currentIndex] = null;\n            }\n            continue;\n        }\n        if (currentIndex === nSources - 1 && score >= lowerBoundScore) {\n            addSolution(store, { predictions, partial, score, maxSolutions });\n        }\n        else if (currentIndex < nSources - 1) {\n            exploreTreeRec({\n                nSources,\n                restrictionByCS,\n                timeout,\n                timeStart,\n                maxSolutions,\n                targets,\n                predictions,\n                lowerBoundScore,\n                nbAllowedUnAssigned,\n                possibleAssignmentMap,\n                useIntegrationRestriction,\n                diaIDPeerPossibleAssignment,\n            }, currentIndex + 1, JSON.parse(JSON.stringify(partial)), store);\n        }\n    }\n}\nfunction addSolution(store, props) {\n    let { score, maxSolutions, partial, predictions } = props;\n    score /= doubleAssignmentPenalty(partial, predictions);\n    store.nSolutions++;\n    let solution = {\n        assignment: JSON.parse(JSON.stringify(partial)),\n        score,\n    };\n    if (store.nSolutions >= maxSolutions) {\n        if (solution.score > store.solutions.last().score) {\n            store.solutions.pollLast();\n            store.solutions.add(solution);\n        }\n    }\n    else {\n        store.solutions.add(solution);\n        store.nSolutions++;\n    }\n}\nfunction doubleAssignmentPenalty(partial, predictions) {\n    const nbSources = Object.keys(predictions).length;\n    let assignments = new Set(partial);\n    let nbDoubleAssignment = nbSources - assignments.size;\n    return nbDoubleAssignment > 0 ? 2 * nbDoubleAssignment : 1;\n}\n//# sourceMappingURL=exploreTreeRec.js.map","import TreeSet from 'ml-tree-set';\nimport { createMapPossibleAssignments } from './createMapPossibleAssignments';\nimport { exploreTreeRec } from './exploreTreeRec';\nconst comparator = (a, b) => {\n    return b.score - a.score;\n};\nexport async function buildAssignments(props) {\n    const { restrictionByCS = {}, useIntegrationRestriction, timeout, minScore, nbAllowedUnAssigned, maxSolutions, targets, joinedSignals, } = props;\n    const { tolerance = 1, useChemicalShiftScore = false, chemicalShiftRestriction = true, } = restrictionByCS;\n    let date = new Date();\n    let timeStart = date.getTime();\n    let store = {\n        solutions: new TreeSet(comparator),\n        nSolutions: 0,\n    };\n    let nSources = joinedSignals.length;\n    const predictions = {};\n    for (let prediction of joinedSignals) {\n        const diaID = prediction.diaIDs[0];\n        const index = prediction.atoms[0];\n        predictions[diaID] = {\n            ...prediction,\n            diaIDIndex: index,\n            allHydrogens: prediction.nbAtoms,\n        };\n    }\n    const possibleAssignmentMap = createMapPossibleAssignments({\n        restrictionByCS: {\n            tolerance,\n            useChemicalShiftScore,\n            chemicalShiftRestriction,\n        },\n        useIntegrationRestriction,\n        predictions,\n        targets,\n    });\n    const diaIDPeerPossibleAssignment = Object.keys(possibleAssignmentMap);\n    let partial = fillPartial(nSources);\n    store = {\n        solutions: new TreeSet(comparator),\n        nSolutions: 0,\n    };\n    exploreTreeRec({\n        nSources,\n        restrictionByCS: {\n            tolerance,\n            useChemicalShiftScore,\n            chemicalShiftRestriction,\n        },\n        timeout,\n        timeStart,\n        targets,\n        predictions,\n        maxSolutions,\n        lowerBoundScore: minScore,\n        nbAllowedUnAssigned,\n        possibleAssignmentMap,\n        diaIDPeerPossibleAssignment,\n        useIntegrationRestriction,\n    }, 0, partial, store);\n    const assignments = [];\n    for (const solution of store.solutions.elements) {\n        const { assignment, score } = solution;\n        const currentAssignment = JSON.parse(JSON.stringify(targets));\n        for (let i = 0; i < assignment.length; i++) {\n            let range = currentAssignment[assignment[i]];\n            if (!range.diaIDs)\n                range.diaIDs = [];\n            if (assignment[i])\n                range.diaIDs.push(diaIDPeerPossibleAssignment[i]);\n        }\n        assignments.push({\n            score,\n            assignment: Object.values(currentAssignment),\n        });\n    }\n    return assignments;\n}\nfunction fillPartial(nSources, value = null) {\n    const partial = new Array(nSources);\n    for (let i = 0; i < nSources; i++) {\n        partial[i] = value;\n    }\n    return partial;\n}\n//# sourceMappingURL=buildAssignments.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport { addDiastereotopicMissingChirality } from 'openchemlib-utils';\nimport { predictProton, } from '../prediction/predictProton';\nimport { buildAssignments } from './utils/buildAssignments';\nfunction checkAtomsAndDiaIDs(signals) {\n    for (const signal of signals) {\n        if (!signal.atoms)\n            throw new Error('signal has not atoms property');\n        if (!signal.diaIDs)\n            throw new Error('signal has not diaIDs property');\n        if (!signal.nbAtoms)\n            throw new Error('signal has not nbAtoms property');\n    }\n}\nfunction checkForIntegration(ranges) {\n    for (let range of ranges) {\n        if (range.integration === undefined) {\n            throw new Error('ranges has not integration property');\n        }\n    }\n}\nexport async function get1HAssignments(ranges, molecule, options = {}) {\n    let { restrictionByCS, minScore = 1, maxSolutions = 10, nbAllowedUnAssigned = 0, timeout = 6000, predictionOptions = {}, } = options;\n    if (!molecule) {\n        throw new Error('It is needed a OCL molecule instance to assign');\n    }\n    molecule.addImplicitHydrogens();\n    addDiastereotopicMissingChirality(molecule);\n    const { joinedSignals } = await predictProton(molecule, predictionOptions);\n    checkForIntegration(ranges);\n    checkAtomsAndDiaIDs(joinedSignals);\n    const targets = {};\n    for (const range of ranges) {\n        const { id = generateID() } = range;\n        targets[id] = JSON.parse(JSON.stringify(range));\n    }\n    return buildAssignments({\n        restrictionByCS,\n        timeout,\n        minScore,\n        nbAllowedUnAssigned,\n        maxSolutions,\n        targets,\n        joinedSignals,\n        useIntegrationRestriction: true,\n    });\n}\n//# sourceMappingURL=get1HAssignments.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport { addDiastereotopicMissingChirality } from 'openchemlib-utils';\nimport { predictCarbon, } from '../prediction/predictCarbon';\nimport { buildAssignments } from './utils/buildAssignments';\nfunction checkAtomsAndDiaIDs(signals) {\n    for (const signal of signals) {\n        if (!signal.atoms)\n            throw new Error('signal has not atoms property');\n        if (!signal.diaIDs)\n            throw new Error('signal has not diaIDs property');\n        if (!signal.nbAtoms)\n            throw new Error('signal has not nbAtoms property');\n    }\n}\nfunction checkIntegration(ranges) {\n    for (let range of ranges) {\n        if (range.integration === undefined)\n            range.integration = 0;\n    }\n    return ranges;\n}\nexport async function get13CAssignments(ranges, molecule, options = {}) {\n    let { restrictionByCS = {}, minScore = 1, maxSolutions = 10, nbAllowedUnAssigned = 0, timeout = 6000, predictionOptions = {}, } = options;\n    if (!molecule) {\n        throw new Error('It is needed a OCL molecule instance to assign');\n    }\n    addDiastereotopicMissingChirality(molecule);\n    const { joinedSignals } = await predictCarbon(molecule, predictionOptions);\n    checkAtomsAndDiaIDs(joinedSignals);\n    const copyRanges = checkIntegration(ranges);\n    const targets = {};\n    for (const range of copyRanges) {\n        const { id = generateID() } = range;\n        targets[id] = JSON.parse(JSON.stringify(range));\n    }\n    return buildAssignments({\n        restrictionByCS,\n        timeout,\n        minScore,\n        nbAllowedUnAssigned,\n        maxSolutions,\n        targets,\n        joinedSignals,\n        useIntegrationRestriction: false,\n    });\n}\n//# sourceMappingURL=get13CAssignments.js.map","/**\n * Returns the number of atoms per atom type for a given molecular formula.\n *\n * @param {string} mf\n */\nexport function getAtomCounts(mf) {\n    const elements = mf ? mf.match(/[A-Z][a-z]{0,1}/g) : [];\n    const counts = {};\n    if (elements) {\n        elements.forEach((elem) => {\n            const regex = new RegExp(`(${elem}\\\\d+)`, 'g');\n            const match = regex.exec(mf);\n            let count = 1;\n            if (match) {\n                count = Number(match[0].split(elem)[1]);\n            }\n            counts[elem] = count;\n        });\n    }\n    return counts;\n}\n//# sourceMappingURL=getAtomCounts.js.map","/**\n * Returns the array index of a correlation.\n *\n * @param {Values} correlations\n * @param {Correlation} correlation\n */\nexport function getCorrelationIndex(correlations, correlation) {\n    return correlations.findIndex((_correlation) => _correlation.id === correlation.id);\n}\n//# sourceMappingURL=getCorrelationIndex.js.map","/**\n * Returns all correlations of a certain atom type.\n *\n * @param {Values} correlations\n * @param {string} atomType\n */\nexport function getCorrelationsByAtomType(correlations, atomType) {\n    return correlations\n        ? correlations.filter((correlation) => correlation.atomType === atomType)\n        : [];\n}\n//# sourceMappingURL=getCorrelationsByAtomType.js.map","import { getAtomCounts } from '../general/getAtomCounts';\nimport { getCorrelationIndex } from '../general/getCorrelationIndex';\nimport { getCorrelationsByAtomType } from '../general/getCorrelationsByAtomType';\n/**\n * Builds a state from current values and an optional molecular formula.\n *\n * @param {Values} values\n * @param {string} mf\n */\nexport function buildState(values, mf) {\n    const state = {};\n    const atoms = getAtomCounts(mf);\n    const atomTypesInCorrelations = values.reduce((array, correlation) => array.includes(correlation.atomType)\n        ? array\n        : array.concat(correlation.atomType), []);\n    atomTypesInCorrelations.forEach((atomType) => {\n        const correlationsAtomType = getCorrelationsByAtomType(values, atomType);\n        // create state for specific atom type only if there is at least one real correlation\n        if (correlationsAtomType.some((correlation) => !correlation.pseudo)) {\n            // create state error\n            const stateAtomTypeError = {};\n            const atomCount = atoms[atomType];\n            let atomCountAtomType = correlationsAtomType.reduce((sum, correlation) => !correlation.pseudo ? sum + correlation.equivalence : sum, 0);\n            if (atomType === 'H') {\n                // add protons count from pseudo correlations without any pseudo HSQC correlation\n                values.forEach((correlation) => {\n                    if (correlation.pseudo &&\n                        correlation.atomType !== 'H' &&\n                        correlation.protonsCount.length === 1 &&\n                        !correlation.link.some((link) => link.experimentType === 'hsqc')) {\n                        atomCountAtomType += correlation.protonsCount[0];\n                    }\n                });\n                // determine the number of pseudo correlations\n                const pseudoCorrelationCount = correlationsAtomType.reduce((sum, correlation) => (correlation.pseudo ? sum + 1 : sum), 0);\n                // determine the not attached protons\n                const notAttached = correlationsAtomType.reduce((array, correlation) => Object.keys(correlation.attachment).length === 0\n                    ? array.concat(getCorrelationIndex(values, correlation))\n                    : array, []);\n                if (notAttached.length > 0) {\n                    stateAtomTypeError.notAttached = notAttached;\n                }\n                atomCountAtomType -= notAttached.length - pseudoCorrelationCount;\n                if (atomCountAtomType < 0) {\n                    atomCountAtomType = 0;\n                }\n                // determine the ambiguous attached protons\n                const ambiguousAttachment = correlationsAtomType.reduce((array, correlation) => Object.keys(correlation.attachment).length > 1 ||\n                    Object.keys(correlation.attachment).some((otherAtomType) => correlation.attachment[otherAtomType].length > 1)\n                    ? array.concat(getCorrelationIndex(values, correlation))\n                    : array, []);\n                if (ambiguousAttachment.length > 0) {\n                    stateAtomTypeError.ambiguousAttachment = ambiguousAttachment;\n                }\n            }\n            if (atomCount !== undefined) {\n                const outOfLimit = correlationsAtomType.some((correlation, k) => !correlation.pseudo &&\n                    correlation.atomType === atomType &&\n                    k >= atomCount);\n                if (outOfLimit) {\n                    stateAtomTypeError.outOfLimit = true;\n                }\n            }\n            const complete = atomCount === undefined ? undefined : atomCountAtomType === atomCount;\n            if (complete === false) {\n                stateAtomTypeError.incomplete = true;\n            }\n            state[atomType] = {\n                current: atomCountAtomType,\n                total: atomCount,\n                complete,\n                error: stateAtomTypeError,\n            };\n        }\n    });\n    return state;\n}\n//# sourceMappingURL=buildState.js.map","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nmodule.exports = isArray;\n","/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nmodule.exports = freeGlobal;\n","var freeGlobal = require('./_freeGlobal');\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nmodule.exports = root;\n","var root = require('./_root');\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nmodule.exports = Symbol;\n","var Symbol = require('./_Symbol');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\nfunction getRawTag(value) {\n  var isOwn = hasOwnProperty.call(value, symToStringTag),\n      tag = value[symToStringTag];\n\n  try {\n    value[symToStringTag] = undefined;\n    var unmasked = true;\n  } catch (e) {}\n\n  var result = nativeObjectToString.call(value);\n  if (unmasked) {\n    if (isOwn) {\n      value[symToStringTag] = tag;\n    } else {\n      delete value[symToStringTag];\n    }\n  }\n  return result;\n}\n\nmodule.exports = getRawTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n  return nativeObjectToString.call(value);\n}\n\nmodule.exports = objectToString;\n","var Symbol = require('./_Symbol'),\n    getRawTag = require('./_getRawTag'),\n    objectToString = require('./_objectToString');\n\n/** `Object#toString` result references. */\nvar nullTag = '[object Null]',\n    undefinedTag = '[object Undefined]';\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n  if (value == null) {\n    return value === undefined ? undefinedTag : nullTag;\n  }\n  return (symToStringTag && symToStringTag in Object(value))\n    ? getRawTag(value)\n    : objectToString(value);\n}\n\nmodule.exports = baseGetTag;\n","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n  return value != null && typeof value == 'object';\n}\n\nmodule.exports = isObjectLike;\n","var baseGetTag = require('./_baseGetTag'),\n    isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n  return typeof value == 'symbol' ||\n    (isObjectLike(value) && baseGetTag(value) == symbolTag);\n}\n\nmodule.exports = isSymbol;\n","var isArray = require('./isArray'),\n    isSymbol = require('./isSymbol');\n\n/** Used to match property names within property paths. */\nvar reIsDeepProp = /\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\\\]|\\\\.)*?\\1)\\]/,\n    reIsPlainProp = /^\\w*$/;\n\n/**\n * Checks if `value` is a property name and not a property path.\n *\n * @private\n * @param {*} value The value to check.\n * @param {Object} [object] The object to query keys on.\n * @returns {boolean} Returns `true` if `value` is a property name, else `false`.\n */\nfunction isKey(value, object) {\n  if (isArray(value)) {\n    return false;\n  }\n  var type = typeof value;\n  if (type == 'number' || type == 'symbol' || type == 'boolean' ||\n      value == null || isSymbol(value)) {\n    return true;\n  }\n  return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||\n    (object != null && value in Object(object));\n}\n\nmodule.exports = isKey;\n","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n  var type = typeof value;\n  return value != null && (type == 'object' || type == 'function');\n}\n\nmodule.exports = isObject;\n","var baseGetTag = require('./_baseGetTag'),\n    isObject = require('./isObject');\n\n/** `Object#toString` result references. */\nvar asyncTag = '[object AsyncFunction]',\n    funcTag = '[object Function]',\n    genTag = '[object GeneratorFunction]',\n    proxyTag = '[object Proxy]';\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n  if (!isObject(value)) {\n    return false;\n  }\n  // The use of `Object#toString` avoids issues with the `typeof` operator\n  // in Safari 9 which returns 'object' for typed arrays and other constructors.\n  var tag = baseGetTag(value);\n  return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n}\n\nmodule.exports = isFunction;\n","var root = require('./_root');\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nmodule.exports = coreJsData;\n","var coreJsData = require('./_coreJsData');\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n  var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n  return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n  return !!maskSrcKey && (maskSrcKey in func);\n}\n\nmodule.exports = isMasked;\n","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n  if (func != null) {\n    try {\n      return funcToString.call(func);\n    } catch (e) {}\n    try {\n      return (func + '');\n    } catch (e) {}\n  }\n  return '';\n}\n\nmodule.exports = toSource;\n","var isFunction = require('./isFunction'),\n    isMasked = require('./_isMasked'),\n    isObject = require('./isObject'),\n    toSource = require('./_toSource');\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n    objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n  funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n  .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n *  else `false`.\n */\nfunction baseIsNative(value) {\n  if (!isObject(value) || isMasked(value)) {\n    return false;\n  }\n  var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n  return pattern.test(toSource(value));\n}\n\nmodule.exports = baseIsNative;\n","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n  return object == null ? undefined : object[key];\n}\n\nmodule.exports = getValue;\n","var baseIsNative = require('./_baseIsNative'),\n    getValue = require('./_getValue');\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n  var value = getValue(object, key);\n  return baseIsNative(value) ? value : undefined;\n}\n\nmodule.exports = getNative;\n","var getNative = require('./_getNative');\n\n/* Built-in method references that are verified to be native. */\nvar nativeCreate = getNative(Object, 'create');\n\nmodule.exports = nativeCreate;\n","var nativeCreate = require('./_nativeCreate');\n\n/**\n * Removes all key-value entries from the hash.\n *\n * @private\n * @name clear\n * @memberOf Hash\n */\nfunction hashClear() {\n  this.__data__ = nativeCreate ? nativeCreate(null) : {};\n  this.size = 0;\n}\n\nmodule.exports = hashClear;\n","/**\n * Removes `key` and its value from the hash.\n *\n * @private\n * @name delete\n * @memberOf Hash\n * @param {Object} hash The hash to modify.\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction hashDelete(key) {\n  var result = this.has(key) && delete this.__data__[key];\n  this.size -= result ? 1 : 0;\n  return result;\n}\n\nmodule.exports = hashDelete;\n","var nativeCreate = require('./_nativeCreate');\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Gets the hash value for `key`.\n *\n * @private\n * @name get\n * @memberOf Hash\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction hashGet(key) {\n  var data = this.__data__;\n  if (nativeCreate) {\n    var result = data[key];\n    return result === HASH_UNDEFINED ? undefined : result;\n  }\n  return hasOwnProperty.call(data, key) ? data[key] : undefined;\n}\n\nmodule.exports = hashGet;\n","var nativeCreate = require('./_nativeCreate');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Checks if a hash value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Hash\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction hashHas(key) {\n  var data = this.__data__;\n  return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);\n}\n\nmodule.exports = hashHas;\n","var nativeCreate = require('./_nativeCreate');\n\n/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Sets the hash `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Hash\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the hash instance.\n */\nfunction hashSet(key, value) {\n  var data = this.__data__;\n  this.size += this.has(key) ? 0 : 1;\n  data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;\n  return this;\n}\n\nmodule.exports = hashSet;\n","var hashClear = require('./_hashClear'),\n    hashDelete = require('./_hashDelete'),\n    hashGet = require('./_hashGet'),\n    hashHas = require('./_hashHas'),\n    hashSet = require('./_hashSet');\n\n/**\n * Creates a hash object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Hash(entries) {\n  var index = -1,\n      length = entries == null ? 0 : entries.length;\n\n  this.clear();\n  while (++index < length) {\n    var entry = entries[index];\n    this.set(entry[0], entry[1]);\n  }\n}\n\n// Add methods to `Hash`.\nHash.prototype.clear = hashClear;\nHash.prototype['delete'] = hashDelete;\nHash.prototype.get = hashGet;\nHash.prototype.has = hashHas;\nHash.prototype.set = hashSet;\n\nmodule.exports = Hash;\n","/**\n * Removes all key-value entries from the list cache.\n *\n * @private\n * @name clear\n * @memberOf ListCache\n */\nfunction listCacheClear() {\n  this.__data__ = [];\n  this.size = 0;\n}\n\nmodule.exports = listCacheClear;\n","/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n  return value === other || (value !== value && other !== other);\n}\n\nmodule.exports = eq;\n","var eq = require('./eq');\n\n/**\n * Gets the index at which the `key` is found in `array` of key-value pairs.\n *\n * @private\n * @param {Array} array The array to inspect.\n * @param {*} key The key to search for.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction assocIndexOf(array, key) {\n  var length = array.length;\n  while (length--) {\n    if (eq(array[length][0], key)) {\n      return length;\n    }\n  }\n  return -1;\n}\n\nmodule.exports = assocIndexOf;\n","var assocIndexOf = require('./_assocIndexOf');\n\n/** Used for built-in method references. */\nvar arrayProto = Array.prototype;\n\n/** Built-in value references. */\nvar splice = arrayProto.splice;\n\n/**\n * Removes `key` and its value from the list cache.\n *\n * @private\n * @name delete\n * @memberOf ListCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction listCacheDelete(key) {\n  var data = this.__data__,\n      index = assocIndexOf(data, key);\n\n  if (index < 0) {\n    return false;\n  }\n  var lastIndex = data.length - 1;\n  if (index == lastIndex) {\n    data.pop();\n  } else {\n    splice.call(data, index, 1);\n  }\n  --this.size;\n  return true;\n}\n\nmodule.exports = listCacheDelete;\n","var assocIndexOf = require('./_assocIndexOf');\n\n/**\n * Gets the list cache value for `key`.\n *\n * @private\n * @name get\n * @memberOf ListCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction listCacheGet(key) {\n  var data = this.__data__,\n      index = assocIndexOf(data, key);\n\n  return index < 0 ? undefined : data[index][1];\n}\n\nmodule.exports = listCacheGet;\n","var assocIndexOf = require('./_assocIndexOf');\n\n/**\n * Checks if a list cache value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf ListCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction listCacheHas(key) {\n  return assocIndexOf(this.__data__, key) > -1;\n}\n\nmodule.exports = listCacheHas;\n","var assocIndexOf = require('./_assocIndexOf');\n\n/**\n * Sets the list cache `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf ListCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the list cache instance.\n */\nfunction listCacheSet(key, value) {\n  var data = this.__data__,\n      index = assocIndexOf(data, key);\n\n  if (index < 0) {\n    ++this.size;\n    data.push([key, value]);\n  } else {\n    data[index][1] = value;\n  }\n  return this;\n}\n\nmodule.exports = listCacheSet;\n","var listCacheClear = require('./_listCacheClear'),\n    listCacheDelete = require('./_listCacheDelete'),\n    listCacheGet = require('./_listCacheGet'),\n    listCacheHas = require('./_listCacheHas'),\n    listCacheSet = require('./_listCacheSet');\n\n/**\n * Creates an list cache object.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction ListCache(entries) {\n  var index = -1,\n      length = entries == null ? 0 : entries.length;\n\n  this.clear();\n  while (++index < length) {\n    var entry = entries[index];\n    this.set(entry[0], entry[1]);\n  }\n}\n\n// Add methods to `ListCache`.\nListCache.prototype.clear = listCacheClear;\nListCache.prototype['delete'] = listCacheDelete;\nListCache.prototype.get = listCacheGet;\nListCache.prototype.has = listCacheHas;\nListCache.prototype.set = listCacheSet;\n\nmodule.exports = ListCache;\n","var getNative = require('./_getNative'),\n    root = require('./_root');\n\n/* Built-in method references that are verified to be native. */\nvar Map = getNative(root, 'Map');\n\nmodule.exports = Map;\n","var Hash = require('./_Hash'),\n    ListCache = require('./_ListCache'),\n    Map = require('./_Map');\n\n/**\n * Removes all key-value entries from the map.\n *\n * @private\n * @name clear\n * @memberOf MapCache\n */\nfunction mapCacheClear() {\n  this.size = 0;\n  this.__data__ = {\n    'hash': new Hash,\n    'map': new (Map || ListCache),\n    'string': new Hash\n  };\n}\n\nmodule.exports = mapCacheClear;\n","/**\n * Checks if `value` is suitable for use as unique object key.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is suitable, else `false`.\n */\nfunction isKeyable(value) {\n  var type = typeof value;\n  return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')\n    ? (value !== '__proto__')\n    : (value === null);\n}\n\nmodule.exports = isKeyable;\n","var isKeyable = require('./_isKeyable');\n\n/**\n * Gets the data for `map`.\n *\n * @private\n * @param {Object} map The map to query.\n * @param {string} key The reference key.\n * @returns {*} Returns the map data.\n */\nfunction getMapData(map, key) {\n  var data = map.__data__;\n  return isKeyable(key)\n    ? data[typeof key == 'string' ? 'string' : 'hash']\n    : data.map;\n}\n\nmodule.exports = getMapData;\n","var getMapData = require('./_getMapData');\n\n/**\n * Removes `key` and its value from the map.\n *\n * @private\n * @name delete\n * @memberOf MapCache\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction mapCacheDelete(key) {\n  var result = getMapData(this, key)['delete'](key);\n  this.size -= result ? 1 : 0;\n  return result;\n}\n\nmodule.exports = mapCacheDelete;\n","var getMapData = require('./_getMapData');\n\n/**\n * Gets the map value for `key`.\n *\n * @private\n * @name get\n * @memberOf MapCache\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction mapCacheGet(key) {\n  return getMapData(this, key).get(key);\n}\n\nmodule.exports = mapCacheGet;\n","var getMapData = require('./_getMapData');\n\n/**\n * Checks if a map value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf MapCache\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction mapCacheHas(key) {\n  return getMapData(this, key).has(key);\n}\n\nmodule.exports = mapCacheHas;\n","var getMapData = require('./_getMapData');\n\n/**\n * Sets the map `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf MapCache\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the map cache instance.\n */\nfunction mapCacheSet(key, value) {\n  var data = getMapData(this, key),\n      size = data.size;\n\n  data.set(key, value);\n  this.size += data.size == size ? 0 : 1;\n  return this;\n}\n\nmodule.exports = mapCacheSet;\n","var mapCacheClear = require('./_mapCacheClear'),\n    mapCacheDelete = require('./_mapCacheDelete'),\n    mapCacheGet = require('./_mapCacheGet'),\n    mapCacheHas = require('./_mapCacheHas'),\n    mapCacheSet = require('./_mapCacheSet');\n\n/**\n * Creates a map cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction MapCache(entries) {\n  var index = -1,\n      length = entries == null ? 0 : entries.length;\n\n  this.clear();\n  while (++index < length) {\n    var entry = entries[index];\n    this.set(entry[0], entry[1]);\n  }\n}\n\n// Add methods to `MapCache`.\nMapCache.prototype.clear = mapCacheClear;\nMapCache.prototype['delete'] = mapCacheDelete;\nMapCache.prototype.get = mapCacheGet;\nMapCache.prototype.has = mapCacheHas;\nMapCache.prototype.set = mapCacheSet;\n\nmodule.exports = MapCache;\n","var MapCache = require('./_MapCache');\n\n/** Error message constants. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/**\n * Creates a function that memoizes the result of `func`. If `resolver` is\n * provided, it determines the cache key for storing the result based on the\n * arguments provided to the memoized function. By default, the first argument\n * provided to the memoized function is used as the map cache key. The `func`\n * is invoked with the `this` binding of the memoized function.\n *\n * **Note:** The cache is exposed as the `cache` property on the memoized\n * function. Its creation may be customized by replacing the `_.memoize.Cache`\n * constructor with one whose instances implement the\n * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)\n * method interface of `clear`, `delete`, `get`, `has`, and `set`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to have its output memoized.\n * @param {Function} [resolver] The function to resolve the cache key.\n * @returns {Function} Returns the new memoized function.\n * @example\n *\n * var object = { 'a': 1, 'b': 2 };\n * var other = { 'c': 3, 'd': 4 };\n *\n * var values = _.memoize(_.values);\n * values(object);\n * // => [1, 2]\n *\n * values(other);\n * // => [3, 4]\n *\n * object.a = 2;\n * values(object);\n * // => [1, 2]\n *\n * // Modify the result cache.\n * values.cache.set(object, ['a', 'b']);\n * values(object);\n * // => ['a', 'b']\n *\n * // Replace `_.memoize.Cache`.\n * _.memoize.Cache = WeakMap;\n */\nfunction memoize(func, resolver) {\n  if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {\n    throw new TypeError(FUNC_ERROR_TEXT);\n  }\n  var memoized = function() {\n    var args = arguments,\n        key = resolver ? resolver.apply(this, args) : args[0],\n        cache = memoized.cache;\n\n    if (cache.has(key)) {\n      return cache.get(key);\n    }\n    var result = func.apply(this, args);\n    memoized.cache = cache.set(key, result) || cache;\n    return result;\n  };\n  memoized.cache = new (memoize.Cache || MapCache);\n  return memoized;\n}\n\n// Expose `MapCache`.\nmemoize.Cache = MapCache;\n\nmodule.exports = memoize;\n","var memoize = require('./memoize');\n\n/** Used as the maximum memoize cache size. */\nvar MAX_MEMOIZE_SIZE = 500;\n\n/**\n * A specialized version of `_.memoize` which clears the memoized function's\n * cache when it exceeds `MAX_MEMOIZE_SIZE`.\n *\n * @private\n * @param {Function} func The function to have its output memoized.\n * @returns {Function} Returns the new memoized function.\n */\nfunction memoizeCapped(func) {\n  var result = memoize(func, function(key) {\n    if (cache.size === MAX_MEMOIZE_SIZE) {\n      cache.clear();\n    }\n    return key;\n  });\n\n  var cache = result.cache;\n  return result;\n}\n\nmodule.exports = memoizeCapped;\n","var memoizeCapped = require('./_memoizeCapped');\n\n/** Used to match property names within property paths. */\nvar rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2)\\]|(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))/g;\n\n/** Used to match backslashes in property paths. */\nvar reEscapeChar = /\\\\(\\\\)?/g;\n\n/**\n * Converts `string` to a property path array.\n *\n * @private\n * @param {string} string The string to convert.\n * @returns {Array} Returns the property path array.\n */\nvar stringToPath = memoizeCapped(function(string) {\n  var result = [];\n  if (string.charCodeAt(0) === 46 /* . */) {\n    result.push('');\n  }\n  string.replace(rePropName, function(match, number, quote, subString) {\n    result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));\n  });\n  return result;\n});\n\nmodule.exports = stringToPath;\n","/**\n * A specialized version of `_.map` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n  var index = -1,\n      length = array == null ? 0 : array.length,\n      result = Array(length);\n\n  while (++index < length) {\n    result[index] = iteratee(array[index], index, array);\n  }\n  return result;\n}\n\nmodule.exports = arrayMap;\n","var Symbol = require('./_Symbol'),\n    arrayMap = require('./_arrayMap'),\n    isArray = require('./isArray'),\n    isSymbol = require('./isSymbol');\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n    symbolToString = symbolProto ? symbolProto.toString : undefined;\n\n/**\n * The base implementation of `_.toString` which doesn't convert nullish\n * values to empty strings.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {string} Returns the string.\n */\nfunction baseToString(value) {\n  // Exit early for strings to avoid a performance hit in some environments.\n  if (typeof value == 'string') {\n    return value;\n  }\n  if (isArray(value)) {\n    // Recursively convert values (susceptible to call stack limits).\n    return arrayMap(value, baseToString) + '';\n  }\n  if (isSymbol(value)) {\n    return symbolToString ? symbolToString.call(value) : '';\n  }\n  var result = (value + '');\n  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\nmodule.exports = baseToString;\n","var baseToString = require('./_baseToString');\n\n/**\n * Converts `value` to a string. An empty string is returned for `null`\n * and `undefined` values. The sign of `-0` is preserved.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n * @example\n *\n * _.toString(null);\n * // => ''\n *\n * _.toString(-0);\n * // => '-0'\n *\n * _.toString([1, 2, 3]);\n * // => '1,2,3'\n */\nfunction toString(value) {\n  return value == null ? '' : baseToString(value);\n}\n\nmodule.exports = toString;\n","var isArray = require('./isArray'),\n    isKey = require('./_isKey'),\n    stringToPath = require('./_stringToPath'),\n    toString = require('./toString');\n\n/**\n * Casts `value` to a path array if it's not one.\n *\n * @private\n * @param {*} value The value to inspect.\n * @param {Object} [object] The object to query keys on.\n * @returns {Array} Returns the cast property path array.\n */\nfunction castPath(value, object) {\n  if (isArray(value)) {\n    return value;\n  }\n  return isKey(value, object) ? [value] : stringToPath(toString(value));\n}\n\nmodule.exports = castPath;\n","var isSymbol = require('./isSymbol');\n\n/** Used as references for various `Number` constants. */\nvar INFINITY = 1 / 0;\n\n/**\n * Converts `value` to a string key if it's not a string or symbol.\n *\n * @private\n * @param {*} value The value to inspect.\n * @returns {string|symbol} Returns the key.\n */\nfunction toKey(value) {\n  if (typeof value == 'string' || isSymbol(value)) {\n    return value;\n  }\n  var result = (value + '');\n  return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;\n}\n\nmodule.exports = toKey;\n","var castPath = require('./_castPath'),\n    toKey = require('./_toKey');\n\n/**\n * The base implementation of `_.get` without support for default values.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @returns {*} Returns the resolved value.\n */\nfunction baseGet(object, path) {\n  path = castPath(path, object);\n\n  var index = 0,\n      length = path.length;\n\n  while (object != null && index < length) {\n    object = object[toKey(path[index++])];\n  }\n  return (index && index == length) ? object : undefined;\n}\n\nmodule.exports = baseGet;\n","var baseGet = require('./_baseGet');\n\n/**\n * Gets the value at `path` of `object`. If the resolved value is\n * `undefined`, the `defaultValue` is returned in its place.\n *\n * @static\n * @memberOf _\n * @since 3.7.0\n * @category Object\n * @param {Object} object The object to query.\n * @param {Array|string} path The path of the property to get.\n * @param {*} [defaultValue] The value returned for `undefined` resolved values.\n * @returns {*} Returns the resolved value.\n * @example\n *\n * var object = { 'a': [{ 'b': { 'c': 3 } }] };\n *\n * _.get(object, 'a[0].b.c');\n * // => 3\n *\n * _.get(object, ['a', '0', 'b', 'c']);\n * // => 3\n *\n * _.get(object, 'a.b.c', 'default');\n * // => 'default'\n */\nfunction get(object, path, defaultValue) {\n  var result = object == null ? undefined : baseGet(object, path);\n  return result === undefined ? defaultValue : result;\n}\n\nmodule.exports = get;\n","/**\n * Checks for a numeric match within a certain tolerance.\n *\n * @param {number} value1\n * @param {number} value2\n * @param {number} tolerance\n */\nexport function checkMatch(value1, value2, tolerance) {\n    return value1 - tolerance <= value2 && value2 <= value1 + tolerance;\n}\n//# sourceMappingURL=checkMatch.js.map","export function getLinkDim(link) {\n    return link.experimentType === '1d' ? 1 : 2;\n}\n//# sourceMappingURL=getLinkDim.js.map","import { getLinkDim } from './getLinkDim';\nexport function getLinkDelta(link) {\n    if (!link.pseudo) {\n        return getLinkDim(link) === 1\n            ? link.signal.delta\n            : link.axis === 'x'\n                ? link.signal.x.delta\n                : link.signal.y.delta;\n    }\n}\n//# sourceMappingURL=getLinkDelta.js.map","import { getLinkDelta } from './getLinkDelta';\nexport function getCorrelationDelta(correlation) {\n    if (correlation.link.length > 0)\n        return getLinkDelta(correlation.link[0]);\n}\n//# sourceMappingURL=getCorrelationDelta.js.map","import { checkMatch } from '../general/checkMatch';\nimport { getCorrelationDelta } from '../general/getCorrelationDelta';\n/**\n * Sets proton counts from DEPT90 signals and DEPT135/edited HSQC signals.\n *\n * @param {Values} correlations\n * @param {Array<{ delta: number }>} signals90\n * @param {Array<{ delta: number; sign?: number }>} signals135\n * @param {number} toleranceAtomType\n */\nexport function setProtonsCount(correlations, signals90, signals135, toleranceAtomType) {\n    // eslint-disable-next-line @typescript-eslint/prefer-for-of\n    for (let i = 0; i < correlations.length; i++) {\n        const correlation = correlations[i];\n        if (correlation.edited.protonsCount) {\n            // do not overwrite a manually edited value\n            continue;\n        }\n        const correlationDelta = getCorrelationDelta(correlation);\n        const match = [-1, -1];\n        for (let k = 0; k < signals90.length; k++) {\n            if (\n            // signals90[k].sign === 1 &&\n            correlationDelta !== undefined &&\n                checkMatch(correlationDelta, signals90[k].delta, toleranceAtomType)) {\n                match[0] = k;\n                break;\n            }\n        }\n        for (let k = 0; k < signals135.length; k++) {\n            if (correlationDelta !== undefined &&\n                checkMatch(correlationDelta, signals135[k].delta, toleranceAtomType)) {\n                match[1] = k;\n                break;\n            }\n        }\n        if (match[0] >= 0) {\n            // signal match in DEPT90\n            // CH\n            correlation.protonsCount = [1];\n            continue;\n        }\n        // no signal match in DEPT90\n        if (match[1] >= 0) {\n            // signal match in DEPT135\n            if (signals135[match[1]].sign === 1) {\n                // positive signal\n                if (signals90.length > 0) {\n                    // in case of both DEPT90 and DEPT135 are given\n                    // CH3\n                    correlation.protonsCount = [3];\n                }\n                else {\n                    // in case of DEPT135 is given only\n                    // CH or CH3\n                    correlation.protonsCount = [1, 3];\n                }\n            }\n            else {\n                // negative signal\n                // CH2\n                correlation.protonsCount = [2];\n            }\n        }\n        else if (signals135.length > 0) {\n            // no signal match in both spectra\n            // qC\n            correlation.protonsCount = [0];\n        }\n        else {\n            // no information\n            correlation.protonsCount = [];\n        }\n    }\n    return correlations;\n}\n//# sourceMappingURL=setProtonsCount.js.map","import lodashGet from 'lodash/get';\nimport { getCorrelationsByAtomType } from '../general/getCorrelationsByAtomType';\nimport { setProtonsCount } from './setProtonsCount';\n/**\n * Sets proton counts from DEPT90 signals and DEPT135 signals.\n *\n * @param {Values} correlations\n * @param {Experiment1DSignals} signalsDEPT\n * @param {Tolerance} tolerance\n * @param {string} atomType\n */\nexport function setProtonsCountFromDEPT(correlations, signalsDEPT, tolerance, atomType) {\n    const correlationsAtomType = getCorrelationsByAtomType(correlations, atomType).filter((correlation) => !correlation.pseudo);\n    const signalsDEPT90 = lodashGet(signalsDEPT, '90', [])\n        .filter((signalDEPT90) => signalDEPT90.atomType === atomType)\n        .map((signalDEPT90) => signalDEPT90.signal);\n    const signalsDEPT135 = lodashGet(signalsDEPT, '135', [])\n        .filter((signalDEPT135) => signalDEPT135.atomType === atomType)\n        .map((signalDEPT135) => signalDEPT135.signal);\n    setProtonsCount(correlationsAtomType, signalsDEPT90, signalsDEPT135, tolerance[atomType]);\n    return correlations;\n}\n//# sourceMappingURL=setProtonsCountFromDEPT.js.map","import lodashGet from 'lodash/get';\nimport { setProtonsCount } from './setProtonsCount';\n/**\n * Sets proton counts from edited HSQC signals.\n *\n * @param {Values} correlations\n * @param {Experiment2DSignals} signals2D\n * @param {Tolerance} tolerance\n * @param {string} heavyAtomType\n */\nexport function setProtonsCountFromEditedHSQC(correlations, signals2D, tolerance, heavyAtomType) {\n    const correlationsAtomTypeHSQC = correlations.filter((correlation) => !correlation.pseudo && correlation.atomType === heavyAtomType);\n    const signalsEditedHSQC = lodashGet(signals2D, 'hsqc', [])\n        .filter((signal2D) => signal2D.atomType[1] === heavyAtomType && signal2D.signal.sign !== 0)\n        .map((signal2D) => {\n        return { delta: signal2D.signal.y.delta, sign: signal2D.signal.sign };\n    });\n    setProtonsCount(correlationsAtomTypeHSQC, [], signalsEditedHSQC, tolerance[heavyAtomType]);\n    return correlations;\n}\n//# sourceMappingURL=setProtonsCountFromEditedHSQC.js.map","import { setProtonsCountFromDEPT } from './setProtonsCountFromDEPT';\nimport { setProtonsCountFromEditedHSQC } from './setProtonsCountFromEditedHSQC';\n/**\n * Sets proton counts from DEPT90 and/or DEPT135/edited HSQC signals, depending on what spectra data is given.\n *\n * @param {Values} correlations\n * @param {Experiment1DSignals} signalsDEPT\n * @param {Experiment2DSignals} signals2D\n * @param {Tolerance} tolerance\n */\nexport function setProtonsCountFromData(correlations, signalsDEPT, signals2D, tolerance) {\n    const heavyAtomTypes = [];\n    correlations.forEach((correlation) => {\n        if (!correlation.pseudo &&\n            correlation.atomType !== 'H' &&\n            !heavyAtomTypes.includes(correlation.atomType)) {\n            heavyAtomTypes.push(correlation.atomType);\n            if (Object.keys(signalsDEPT).length > 0) {\n                setProtonsCountFromDEPT(correlations, signalsDEPT, tolerance, correlation.atomType);\n            }\n            else {\n                setProtonsCountFromEditedHSQC(correlations, signals2D, tolerance, correlation.atomType);\n            }\n        }\n    });\n    return correlations;\n}\n//# sourceMappingURL=setProtonsCountFromData.js.map","/**\n * Get all different experiments from spectra data.\n *\n * @param {Spectra} spectraData\n */\nexport function getExperiments(spectraData) {\n    if (!spectraData)\n        return {};\n    const experiments = {};\n    for (const spectrum of spectraData) {\n        if (spectrum.info.isFid)\n            continue;\n        if (!experiments[`${spectrum.info.dimension}D`]) {\n            experiments[`${spectrum.info.dimension}D`] = {};\n        }\n        const experiment = spectrum.info.experiment;\n        if (!experiments[`${spectrum.info.dimension}D`][`${experiment}`]) {\n            experiments[`${spectrum.info.dimension}D`][`${experiment}`] = [];\n        }\n        experiments[`${spectrum.info.dimension}D`][`${experiment}`].push(spectrum);\n    }\n    return experiments;\n}\n//# sourceMappingURL=getExperiments.js.map","/**\n * Returns the atom type from nucleus.\n * @param {string} nucleus\n */\nexport function getAtomTypeFromNucleus(nucleus) {\n    return nucleus.length > 0 ? nucleus.split(/\\d+/)[1] : '';\n}\n//# sourceMappingURL=getAtomTypeFromNucleus.js.map","import lodashGet from 'lodash/get';\nimport { getAtomTypeFromNucleus } from '../general/getAtomTypeFromNucleus';\n/**\n * Add experiment of certain type to experiments.\n *\n * @param {Experiments} experiments\n * @param {ExperimentsType} experimentsType\n * @param {string} type\n * @param {boolean} checkAtomType\n * @param {string} experimentKey\n */\nexport function addToExperiments(experiments, experimentsType, type, checkAtomType, experimentKey) {\n    const _experiments = lodashGet(experiments, `${type}`, []) // don't consider DEPT etc. here\n        .filter((_experiment) => {\n        const hasValues = lodashGet(_experiment, type.includes('1D') ? 'ranges.values' : 'zones.values', []).length > 0;\n        return checkAtomType\n            ? getAtomTypeFromNucleus(_experiment.info.nucleus) ===\n                experimentKey && hasValues\n            : hasValues;\n    });\n    if (_experiments.length > 0) {\n        experimentsType[experimentKey] = _experiments;\n    }\n}\n//# sourceMappingURL=addToExperiments.js.map","import lodashGet from 'lodash/get';\nimport { getAtomTypeFromNucleus } from '../general/getAtomTypeFromNucleus';\nimport { addToExperiments } from './addToExperiments';\n/**\n * Get \"plain\" 1D experiments containing ranges, i.e. without DEPT etc..\n *\n * @param {Spectra} spectraData\n */\nexport function getExperiments1D(experiments) {\n    const _experiments1D = {};\n    lodashGet(experiments, '1D.1d', [])\n        .map((experiment) => getAtomTypeFromNucleus(experiment.info.nucleus))\n        .forEach((atomType) => {\n        addToExperiments(experiments, _experiments1D, '1D.1d', true, atomType);\n    });\n    return _experiments1D;\n}\n//# sourceMappingURL=getExperiments1D.js.map","import lodashGet from 'lodash/get';\nimport { addToExperiments } from './addToExperiments';\n/**\n * Get \"extra\" 1D experiments containing ranges, e.g. DEPT.\n *\n * @param {Spectra} spectraData\n */\nexport function getExperiments1DExtra(experiments) {\n    const _experiments1DExtra = {};\n    Object.keys(lodashGet(experiments, `1D`, {}))\n        .filter((experimentType) => experimentType !== '1d') // don't consider \"plain\" 1D experiments here\n        .forEach((experimentType) => {\n        addToExperiments(experiments, _experiments1DExtra, `1D.${experimentType}`, false, experimentType);\n    });\n    return _experiments1DExtra;\n}\n//# sourceMappingURL=getExperiments1DExtra.js.map","import lodashGet from 'lodash/get';\nimport { addToExperiments } from './addToExperiments';\n/**\n * Get 2D experiments containing zones.\n *\n * @param {Spectra} spectraData\n */\nexport function getExperiments2D(experiments) {\n    const _experiments2D = {};\n    Object.keys(lodashGet(experiments, '2D', {})).forEach((experimentType) => {\n        addToExperiments(experiments, _experiments2D, `2D.${experimentType}`, false, experimentType);\n    });\n    return _experiments2D;\n}\n//# sourceMappingURL=getExperiments2D.js.map","const allowedSignalKinds = ['signal'];\nexport { allowedSignalKinds };\n//# sourceMappingURL=allowedSignalKinds.js.map","import { allowedSignalKinds } from '../../constants/allowedSignalKinds';\nimport { checkMatch } from '../general/checkMatch';\n/**\n * Get all different 1D signals from experiments with allowed signal kinds in \"signalKindsToInclude\".\n *\n * @param {ExperimentsType} experiments1D\n */\nexport function getSignals1D(experiments1D) {\n    // store valid signals from 1D experiments\n    const signals1DByAtomType = {};\n    for (const atomType in experiments1D) {\n        const signals = [];\n        const experiment = experiments1D[`${atomType}`] || [];\n        if (experiment.length === 0)\n            continue;\n        const index = 0;\n        const spectrum1D = experiment[index];\n        for (const range of spectrum1D.ranges.values) {\n            for (const signal of range.signals) {\n                if (!signal.kind || !allowedSignalKinds.includes(signal.kind))\n                    continue;\n                if (!checkExistence(signal, signals)) {\n                    signals.push({\n                        experimentType: '1d',\n                        experimentID: spectrum1D.id,\n                        integration: signal.integration\n                            ? signal.integration\n                            : range.integration,\n                        atomType,\n                        signal: { ...signal },\n                    });\n                }\n            }\n        }\n        signals1DByAtomType[atomType] = signals;\n    }\n    return signals1DByAtomType;\n}\nfunction checkExistence(current, group) {\n    for (const element of group) {\n        if (checkMatch(element.signal.delta, current.delta, 0.0)) {\n            return true;\n        }\n    }\n    return false;\n}\n//# sourceMappingURL=getSignals1D.js.map","var ListCache = require('./_ListCache');\n\n/**\n * Removes all key-value entries from the stack.\n *\n * @private\n * @name clear\n * @memberOf Stack\n */\nfunction stackClear() {\n  this.__data__ = new ListCache;\n  this.size = 0;\n}\n\nmodule.exports = stackClear;\n","/**\n * Removes `key` and its value from the stack.\n *\n * @private\n * @name delete\n * @memberOf Stack\n * @param {string} key The key of the value to remove.\n * @returns {boolean} Returns `true` if the entry was removed, else `false`.\n */\nfunction stackDelete(key) {\n  var data = this.__data__,\n      result = data['delete'](key);\n\n  this.size = data.size;\n  return result;\n}\n\nmodule.exports = stackDelete;\n","/**\n * Gets the stack value for `key`.\n *\n * @private\n * @name get\n * @memberOf Stack\n * @param {string} key The key of the value to get.\n * @returns {*} Returns the entry value.\n */\nfunction stackGet(key) {\n  return this.__data__.get(key);\n}\n\nmodule.exports = stackGet;\n","/**\n * Checks if a stack value for `key` exists.\n *\n * @private\n * @name has\n * @memberOf Stack\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction stackHas(key) {\n  return this.__data__.has(key);\n}\n\nmodule.exports = stackHas;\n","var ListCache = require('./_ListCache'),\n    Map = require('./_Map'),\n    MapCache = require('./_MapCache');\n\n/** Used as the size to enable large array optimizations. */\nvar LARGE_ARRAY_SIZE = 200;\n\n/**\n * Sets the stack `key` to `value`.\n *\n * @private\n * @name set\n * @memberOf Stack\n * @param {string} key The key of the value to set.\n * @param {*} value The value to set.\n * @returns {Object} Returns the stack cache instance.\n */\nfunction stackSet(key, value) {\n  var data = this.__data__;\n  if (data instanceof ListCache) {\n    var pairs = data.__data__;\n    if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {\n      pairs.push([key, value]);\n      this.size = ++data.size;\n      return this;\n    }\n    data = this.__data__ = new MapCache(pairs);\n  }\n  data.set(key, value);\n  this.size = data.size;\n  return this;\n}\n\nmodule.exports = stackSet;\n","var ListCache = require('./_ListCache'),\n    stackClear = require('./_stackClear'),\n    stackDelete = require('./_stackDelete'),\n    stackGet = require('./_stackGet'),\n    stackHas = require('./_stackHas'),\n    stackSet = require('./_stackSet');\n\n/**\n * Creates a stack cache object to store key-value pairs.\n *\n * @private\n * @constructor\n * @param {Array} [entries] The key-value pairs to cache.\n */\nfunction Stack(entries) {\n  var data = this.__data__ = new ListCache(entries);\n  this.size = data.size;\n}\n\n// Add methods to `Stack`.\nStack.prototype.clear = stackClear;\nStack.prototype['delete'] = stackDelete;\nStack.prototype.get = stackGet;\nStack.prototype.has = stackHas;\nStack.prototype.set = stackSet;\n\nmodule.exports = Stack;\n","/**\n * A specialized version of `_.forEach` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\nfunction arrayEach(array, iteratee) {\n  var index = -1,\n      length = array == null ? 0 : array.length;\n\n  while (++index < length) {\n    if (iteratee(array[index], index, array) === false) {\n      break;\n    }\n  }\n  return array;\n}\n\nmodule.exports = arrayEach;\n","var getNative = require('./_getNative');\n\nvar defineProperty = (function() {\n  try {\n    var func = getNative(Object, 'defineProperty');\n    func({}, '', {});\n    return func;\n  } catch (e) {}\n}());\n\nmodule.exports = defineProperty;\n","var defineProperty = require('./_defineProperty');\n\n/**\n * The base implementation of `assignValue` and `assignMergeValue` without\n * value checks.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction baseAssignValue(object, key, value) {\n  if (key == '__proto__' && defineProperty) {\n    defineProperty(object, key, {\n      'configurable': true,\n      'enumerable': true,\n      'value': value,\n      'writable': true\n    });\n  } else {\n    object[key] = value;\n  }\n}\n\nmodule.exports = baseAssignValue;\n","var baseAssignValue = require('./_baseAssignValue'),\n    eq = require('./eq');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignValue(object, key, value) {\n  var objValue = object[key];\n  if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n      (value === undefined && !(key in object))) {\n    baseAssignValue(object, key, value);\n  }\n}\n\nmodule.exports = assignValue;\n","var assignValue = require('./_assignValue'),\n    baseAssignValue = require('./_baseAssignValue');\n\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\nfunction copyObject(source, props, object, customizer) {\n  var isNew = !object;\n  object || (object = {});\n\n  var index = -1,\n      length = props.length;\n\n  while (++index < length) {\n    var key = props[index];\n\n    var newValue = customizer\n      ? customizer(object[key], source[key], key, object, source)\n      : undefined;\n\n    if (newValue === undefined) {\n      newValue = source[key];\n    }\n    if (isNew) {\n      baseAssignValue(object, key, newValue);\n    } else {\n      assignValue(object, key, newValue);\n    }\n  }\n  return object;\n}\n\nmodule.exports = copyObject;\n","/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n  var index = -1,\n      result = Array(n);\n\n  while (++index < n) {\n    result[index] = iteratee(index);\n  }\n  return result;\n}\n\nmodule.exports = baseTimes;\n","var baseGetTag = require('./_baseGetTag'),\n    isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]';\n\n/**\n * The base implementation of `_.isArguments`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n */\nfunction baseIsArguments(value) {\n  return isObjectLike(value) && baseGetTag(value) == argsTag;\n}\n\nmodule.exports = baseIsArguments;\n","var baseIsArguments = require('./_baseIsArguments'),\n    isObjectLike = require('./isObjectLike');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n *  else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nvar isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n  return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n    !propertyIsEnumerable.call(value, 'callee');\n};\n\nmodule.exports = isArguments;\n","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n  return false;\n}\n\nmodule.exports = stubFalse;\n","var root = require('./_root'),\n    stubFalse = require('./stubFalse');\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;\n\n/**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\nvar isBuffer = nativeIsBuffer || stubFalse;\n\nmodule.exports = isBuffer;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n  var type = typeof value;\n  length = length == null ? MAX_SAFE_INTEGER : length;\n\n  return !!length &&\n    (type == 'number' ||\n      (type != 'symbol' && reIsUint.test(value))) &&\n        (value > -1 && value % 1 == 0 && value < length);\n}\n\nmodule.exports = isIndex;\n","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n  return typeof value == 'number' &&\n    value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nmodule.exports = isLength;\n","var baseGetTag = require('./_baseGetTag'),\n    isLength = require('./isLength'),\n    isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n    arrayTag = '[object Array]',\n    boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    errorTag = '[object Error]',\n    funcTag = '[object Function]',\n    mapTag = '[object Map]',\n    numberTag = '[object Number]',\n    objectTag = '[object Object]',\n    regexpTag = '[object RegExp]',\n    setTag = '[object Set]',\n    stringTag = '[object String]',\n    weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n    dataViewTag = '[object DataView]',\n    float32Tag = '[object Float32Array]',\n    float64Tag = '[object Float64Array]',\n    int8Tag = '[object Int8Array]',\n    int16Tag = '[object Int16Array]',\n    int32Tag = '[object Int32Array]',\n    uint8Tag = '[object Uint8Array]',\n    uint8ClampedTag = '[object Uint8ClampedArray]',\n    uint16Tag = '[object Uint16Array]',\n    uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values of typed arrays. */\nvar typedArrayTags = {};\ntypedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\ntypedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\ntypedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\ntypedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\ntypedArrayTags[uint32Tag] = true;\ntypedArrayTags[argsTag] = typedArrayTags[arrayTag] =\ntypedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\ntypedArrayTags[dataViewTag] = typedArrayTags[dateTag] =\ntypedArrayTags[errorTag] = typedArrayTags[funcTag] =\ntypedArrayTags[mapTag] = typedArrayTags[numberTag] =\ntypedArrayTags[objectTag] = typedArrayTags[regexpTag] =\ntypedArrayTags[setTag] = typedArrayTags[stringTag] =\ntypedArrayTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.isTypedArray` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n */\nfunction baseIsTypedArray(value) {\n  return isObjectLike(value) &&\n    isLength(value.length) && !!typedArrayTags[baseGetTag(value)];\n}\n\nmodule.exports = baseIsTypedArray;\n","/**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\nfunction baseUnary(func) {\n  return function(value) {\n    return func(value);\n  };\n}\n\nmodule.exports = baseUnary;\n","var freeGlobal = require('./_freeGlobal');\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Detect free variable `process` from Node.js. */\nvar freeProcess = moduleExports && freeGlobal.process;\n\n/** Used to access faster Node.js helpers. */\nvar nodeUtil = (function() {\n  try {\n    // Use `util.types` for Node.js 10+.\n    var types = freeModule && freeModule.require && freeModule.require('util').types;\n\n    if (types) {\n      return types;\n    }\n\n    // Legacy `process.binding('util')` for Node.js < 10.\n    return freeProcess && freeProcess.binding && freeProcess.binding('util');\n  } catch (e) {}\n}());\n\nmodule.exports = nodeUtil;\n","var baseIsTypedArray = require('./_baseIsTypedArray'),\n    baseUnary = require('./_baseUnary'),\n    nodeUtil = require('./_nodeUtil');\n\n/* Node.js helper references. */\nvar nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n/**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\nvar isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\nmodule.exports = isTypedArray;\n","var baseTimes = require('./_baseTimes'),\n    isArguments = require('./isArguments'),\n    isArray = require('./isArray'),\n    isBuffer = require('./isBuffer'),\n    isIndex = require('./_isIndex'),\n    isTypedArray = require('./isTypedArray');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\nfunction arrayLikeKeys(value, inherited) {\n  var isArr = isArray(value),\n      isArg = !isArr && isArguments(value),\n      isBuff = !isArr && !isArg && isBuffer(value),\n      isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n      skipIndexes = isArr || isArg || isBuff || isType,\n      result = skipIndexes ? baseTimes(value.length, String) : [],\n      length = result.length;\n\n  for (var key in value) {\n    if ((inherited || hasOwnProperty.call(value, key)) &&\n        !(skipIndexes && (\n           // Safari 9 has enumerable `arguments.length` in strict mode.\n           key == 'length' ||\n           // Node.js 0.10 has enumerable non-index properties on buffers.\n           (isBuff && (key == 'offset' || key == 'parent')) ||\n           // PhantomJS 2 has enumerable non-index properties on typed arrays.\n           (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n           // Skip index properties.\n           isIndex(key, length)\n        ))) {\n      result.push(key);\n    }\n  }\n  return result;\n}\n\nmodule.exports = arrayLikeKeys;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n  var Ctor = value && value.constructor,\n      proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n  return value === proto;\n}\n\nmodule.exports = isPrototype;\n","/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n  return function(arg) {\n    return func(transform(arg));\n  };\n}\n\nmodule.exports = overArg;\n","var overArg = require('./_overArg');\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeKeys = overArg(Object.keys, Object);\n\nmodule.exports = nativeKeys;\n","var isPrototype = require('./_isPrototype'),\n    nativeKeys = require('./_nativeKeys');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeys(object) {\n  if (!isPrototype(object)) {\n    return nativeKeys(object);\n  }\n  var result = [];\n  for (var key in Object(object)) {\n    if (hasOwnProperty.call(object, key) && key != 'constructor') {\n      result.push(key);\n    }\n  }\n  return result;\n}\n\nmodule.exports = baseKeys;\n","var isFunction = require('./isFunction'),\n    isLength = require('./isLength');\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n  return value != null && isLength(value.length) && !isFunction(value);\n}\n\nmodule.exports = isArrayLike;\n","var arrayLikeKeys = require('./_arrayLikeKeys'),\n    baseKeys = require('./_baseKeys'),\n    isArrayLike = require('./isArrayLike');\n\n/**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n *   this.a = 1;\n *   this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\nfunction keys(object) {\n  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);\n}\n\nmodule.exports = keys;\n","var copyObject = require('./_copyObject'),\n    keys = require('./keys');\n\n/**\n * The base implementation of `_.assign` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\nfunction baseAssign(object, source) {\n  return object && copyObject(source, keys(source), object);\n}\n\nmodule.exports = baseAssign;\n","/**\n * This function is like\n * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * except that it includes inherited enumerable properties.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction nativeKeysIn(object) {\n  var result = [];\n  if (object != null) {\n    for (var key in Object(object)) {\n      result.push(key);\n    }\n  }\n  return result;\n}\n\nmodule.exports = nativeKeysIn;\n","var isObject = require('./isObject'),\n    isPrototype = require('./_isPrototype'),\n    nativeKeysIn = require('./_nativeKeysIn');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeysIn(object) {\n  if (!isObject(object)) {\n    return nativeKeysIn(object);\n  }\n  var isProto = isPrototype(object),\n      result = [];\n\n  for (var key in object) {\n    if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n      result.push(key);\n    }\n  }\n  return result;\n}\n\nmodule.exports = baseKeysIn;\n","var arrayLikeKeys = require('./_arrayLikeKeys'),\n    baseKeysIn = require('./_baseKeysIn'),\n    isArrayLike = require('./isArrayLike');\n\n/**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n *   this.a = 1;\n *   this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\nfunction keysIn(object) {\n  return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);\n}\n\nmodule.exports = keysIn;\n","var copyObject = require('./_copyObject'),\n    keysIn = require('./keysIn');\n\n/**\n * The base implementation of `_.assignIn` without support for multiple sources\n * or `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\nfunction baseAssignIn(object, source) {\n  return object && copyObject(source, keysIn(source), object);\n}\n\nmodule.exports = baseAssignIn;\n","var root = require('./_root');\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined,\n    allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;\n\n/**\n * Creates a clone of  `buffer`.\n *\n * @private\n * @param {Buffer} buffer The buffer to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Buffer} Returns the cloned buffer.\n */\nfunction cloneBuffer(buffer, isDeep) {\n  if (isDeep) {\n    return buffer.slice();\n  }\n  var length = buffer.length,\n      result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);\n\n  buffer.copy(result);\n  return result;\n}\n\nmodule.exports = cloneBuffer;\n","/**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\nfunction copyArray(source, array) {\n  var index = -1,\n      length = source.length;\n\n  array || (array = Array(length));\n  while (++index < length) {\n    array[index] = source[index];\n  }\n  return array;\n}\n\nmodule.exports = copyArray;\n","/**\n * A specialized version of `_.filter` for arrays without support for\n * iteratee shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {Array} Returns the new filtered array.\n */\nfunction arrayFilter(array, predicate) {\n  var index = -1,\n      length = array == null ? 0 : array.length,\n      resIndex = 0,\n      result = [];\n\n  while (++index < length) {\n    var value = array[index];\n    if (predicate(value, index, array)) {\n      result[resIndex++] = value;\n    }\n  }\n  return result;\n}\n\nmodule.exports = arrayFilter;\n","/**\n * This method returns a new empty array.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {Array} Returns the new empty array.\n * @example\n *\n * var arrays = _.times(2, _.stubArray);\n *\n * console.log(arrays);\n * // => [[], []]\n *\n * console.log(arrays[0] === arrays[1]);\n * // => false\n */\nfunction stubArray() {\n  return [];\n}\n\nmodule.exports = stubArray;\n","var arrayFilter = require('./_arrayFilter'),\n    stubArray = require('./stubArray');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols;\n\n/**\n * Creates an array of the own enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\nvar getSymbols = !nativeGetSymbols ? stubArray : function(object) {\n  if (object == null) {\n    return [];\n  }\n  object = Object(object);\n  return arrayFilter(nativeGetSymbols(object), function(symbol) {\n    return propertyIsEnumerable.call(object, symbol);\n  });\n};\n\nmodule.exports = getSymbols;\n","var copyObject = require('./_copyObject'),\n    getSymbols = require('./_getSymbols');\n\n/**\n * Copies own symbols of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\nfunction copySymbols(source, object) {\n  return copyObject(source, getSymbols(source), object);\n}\n\nmodule.exports = copySymbols;\n","/**\n * Appends the elements of `values` to `array`.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {Array} values The values to append.\n * @returns {Array} Returns `array`.\n */\nfunction arrayPush(array, values) {\n  var index = -1,\n      length = values.length,\n      offset = array.length;\n\n  while (++index < length) {\n    array[offset + index] = values[index];\n  }\n  return array;\n}\n\nmodule.exports = arrayPush;\n","var overArg = require('./_overArg');\n\n/** Built-in value references. */\nvar getPrototype = overArg(Object.getPrototypeOf, Object);\n\nmodule.exports = getPrototype;\n","var arrayPush = require('./_arrayPush'),\n    getPrototype = require('./_getPrototype'),\n    getSymbols = require('./_getSymbols'),\n    stubArray = require('./stubArray');\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeGetSymbols = Object.getOwnPropertySymbols;\n\n/**\n * Creates an array of the own and inherited enumerable symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of symbols.\n */\nvar getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {\n  var result = [];\n  while (object) {\n    arrayPush(result, getSymbols(object));\n    object = getPrototype(object);\n  }\n  return result;\n};\n\nmodule.exports = getSymbolsIn;\n","var copyObject = require('./_copyObject'),\n    getSymbolsIn = require('./_getSymbolsIn');\n\n/**\n * Copies own and inherited symbols of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy symbols from.\n * @param {Object} [object={}] The object to copy symbols to.\n * @returns {Object} Returns `object`.\n */\nfunction copySymbolsIn(source, object) {\n  return copyObject(source, getSymbolsIn(source), object);\n}\n\nmodule.exports = copySymbolsIn;\n","var arrayPush = require('./_arrayPush'),\n    isArray = require('./isArray');\n\n/**\n * The base implementation of `getAllKeys` and `getAllKeysIn` which uses\n * `keysFunc` and `symbolsFunc` to get the enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @param {Function} symbolsFunc The function to get the symbols of `object`.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction baseGetAllKeys(object, keysFunc, symbolsFunc) {\n  var result = keysFunc(object);\n  return isArray(object) ? result : arrayPush(result, symbolsFunc(object));\n}\n\nmodule.exports = baseGetAllKeys;\n","var baseGetAllKeys = require('./_baseGetAllKeys'),\n    getSymbols = require('./_getSymbols'),\n    keys = require('./keys');\n\n/**\n * Creates an array of own enumerable property names and symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction getAllKeys(object) {\n  return baseGetAllKeys(object, keys, getSymbols);\n}\n\nmodule.exports = getAllKeys;\n","var baseGetAllKeys = require('./_baseGetAllKeys'),\n    getSymbolsIn = require('./_getSymbolsIn'),\n    keysIn = require('./keysIn');\n\n/**\n * Creates an array of own and inherited enumerable property names and\n * symbols of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names and symbols.\n */\nfunction getAllKeysIn(object) {\n  return baseGetAllKeys(object, keysIn, getSymbolsIn);\n}\n\nmodule.exports = getAllKeysIn;\n","var getNative = require('./_getNative'),\n    root = require('./_root');\n\n/* Built-in method references that are verified to be native. */\nvar DataView = getNative(root, 'DataView');\n\nmodule.exports = DataView;\n","var getNative = require('./_getNative'),\n    root = require('./_root');\n\n/* Built-in method references that are verified to be native. */\nvar Promise = getNative(root, 'Promise');\n\nmodule.exports = Promise;\n","var getNative = require('./_getNative'),\n    root = require('./_root');\n\n/* Built-in method references that are verified to be native. */\nvar Set = getNative(root, 'Set');\n\nmodule.exports = Set;\n","var getNative = require('./_getNative'),\n    root = require('./_root');\n\n/* Built-in method references that are verified to be native. */\nvar WeakMap = getNative(root, 'WeakMap');\n\nmodule.exports = WeakMap;\n","var DataView = require('./_DataView'),\n    Map = require('./_Map'),\n    Promise = require('./_Promise'),\n    Set = require('./_Set'),\n    WeakMap = require('./_WeakMap'),\n    baseGetTag = require('./_baseGetTag'),\n    toSource = require('./_toSource');\n\n/** `Object#toString` result references. */\nvar mapTag = '[object Map]',\n    objectTag = '[object Object]',\n    promiseTag = '[object Promise]',\n    setTag = '[object Set]',\n    weakMapTag = '[object WeakMap]';\n\nvar dataViewTag = '[object DataView]';\n\n/** Used to detect maps, sets, and weakmaps. */\nvar dataViewCtorString = toSource(DataView),\n    mapCtorString = toSource(Map),\n    promiseCtorString = toSource(Promise),\n    setCtorString = toSource(Set),\n    weakMapCtorString = toSource(WeakMap);\n\n/**\n * Gets the `toStringTag` of `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nvar getTag = baseGetTag;\n\n// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.\nif ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||\n    (Map && getTag(new Map) != mapTag) ||\n    (Promise && getTag(Promise.resolve()) != promiseTag) ||\n    (Set && getTag(new Set) != setTag) ||\n    (WeakMap && getTag(new WeakMap) != weakMapTag)) {\n  getTag = function(value) {\n    var result = baseGetTag(value),\n        Ctor = result == objectTag ? value.constructor : undefined,\n        ctorString = Ctor ? toSource(Ctor) : '';\n\n    if (ctorString) {\n      switch (ctorString) {\n        case dataViewCtorString: return dataViewTag;\n        case mapCtorString: return mapTag;\n        case promiseCtorString: return promiseTag;\n        case setCtorString: return setTag;\n        case weakMapCtorString: return weakMapTag;\n      }\n    }\n    return result;\n  };\n}\n\nmodule.exports = getTag;\n","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Initializes an array clone.\n *\n * @private\n * @param {Array} array The array to clone.\n * @returns {Array} Returns the initialized clone.\n */\nfunction initCloneArray(array) {\n  var length = array.length,\n      result = new array.constructor(length);\n\n  // Add properties assigned by `RegExp#exec`.\n  if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {\n    result.index = array.index;\n    result.input = array.input;\n  }\n  return result;\n}\n\nmodule.exports = initCloneArray;\n","var root = require('./_root');\n\n/** Built-in value references. */\nvar Uint8Array = root.Uint8Array;\n\nmodule.exports = Uint8Array;\n","var Uint8Array = require('./_Uint8Array');\n\n/**\n * Creates a clone of `arrayBuffer`.\n *\n * @private\n * @param {ArrayBuffer} arrayBuffer The array buffer to clone.\n * @returns {ArrayBuffer} Returns the cloned array buffer.\n */\nfunction cloneArrayBuffer(arrayBuffer) {\n  var result = new arrayBuffer.constructor(arrayBuffer.byteLength);\n  new Uint8Array(result).set(new Uint8Array(arrayBuffer));\n  return result;\n}\n\nmodule.exports = cloneArrayBuffer;\n","var cloneArrayBuffer = require('./_cloneArrayBuffer');\n\n/**\n * Creates a clone of `dataView`.\n *\n * @private\n * @param {Object} dataView The data view to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned data view.\n */\nfunction cloneDataView(dataView, isDeep) {\n  var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;\n  return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);\n}\n\nmodule.exports = cloneDataView;\n","/** Used to match `RegExp` flags from their coerced string values. */\nvar reFlags = /\\w*$/;\n\n/**\n * Creates a clone of `regexp`.\n *\n * @private\n * @param {Object} regexp The regexp to clone.\n * @returns {Object} Returns the cloned regexp.\n */\nfunction cloneRegExp(regexp) {\n  var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));\n  result.lastIndex = regexp.lastIndex;\n  return result;\n}\n\nmodule.exports = cloneRegExp;\n","var Symbol = require('./_Symbol');\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;\n\n/**\n * Creates a clone of the `symbol` object.\n *\n * @private\n * @param {Object} symbol The symbol object to clone.\n * @returns {Object} Returns the cloned symbol object.\n */\nfunction cloneSymbol(symbol) {\n  return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};\n}\n\nmodule.exports = cloneSymbol;\n","var cloneArrayBuffer = require('./_cloneArrayBuffer');\n\n/**\n * Creates a clone of `typedArray`.\n *\n * @private\n * @param {Object} typedArray The typed array to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the cloned typed array.\n */\nfunction cloneTypedArray(typedArray, isDeep) {\n  var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;\n  return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);\n}\n\nmodule.exports = cloneTypedArray;\n","var cloneArrayBuffer = require('./_cloneArrayBuffer'),\n    cloneDataView = require('./_cloneDataView'),\n    cloneRegExp = require('./_cloneRegExp'),\n    cloneSymbol = require('./_cloneSymbol'),\n    cloneTypedArray = require('./_cloneTypedArray');\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    mapTag = '[object Map]',\n    numberTag = '[object Number]',\n    regexpTag = '[object RegExp]',\n    setTag = '[object Set]',\n    stringTag = '[object String]',\n    symbolTag = '[object Symbol]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n    dataViewTag = '[object DataView]',\n    float32Tag = '[object Float32Array]',\n    float64Tag = '[object Float64Array]',\n    int8Tag = '[object Int8Array]',\n    int16Tag = '[object Int16Array]',\n    int32Tag = '[object Int32Array]',\n    uint8Tag = '[object Uint8Array]',\n    uint8ClampedTag = '[object Uint8ClampedArray]',\n    uint16Tag = '[object Uint16Array]',\n    uint32Tag = '[object Uint32Array]';\n\n/**\n * Initializes an object clone based on its `toStringTag`.\n *\n * **Note:** This function only supports cloning values with tags of\n * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.\n *\n * @private\n * @param {Object} object The object to clone.\n * @param {string} tag The `toStringTag` of the object to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneByTag(object, tag, isDeep) {\n  var Ctor = object.constructor;\n  switch (tag) {\n    case arrayBufferTag:\n      return cloneArrayBuffer(object);\n\n    case boolTag:\n    case dateTag:\n      return new Ctor(+object);\n\n    case dataViewTag:\n      return cloneDataView(object, isDeep);\n\n    case float32Tag: case float64Tag:\n    case int8Tag: case int16Tag: case int32Tag:\n    case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:\n      return cloneTypedArray(object, isDeep);\n\n    case mapTag:\n      return new Ctor;\n\n    case numberTag:\n    case stringTag:\n      return new Ctor(object);\n\n    case regexpTag:\n      return cloneRegExp(object);\n\n    case setTag:\n      return new Ctor;\n\n    case symbolTag:\n      return cloneSymbol(object);\n  }\n}\n\nmodule.exports = initCloneByTag;\n","var isObject = require('./isObject');\n\n/** Built-in value references. */\nvar objectCreate = Object.create;\n\n/**\n * The base implementation of `_.create` without support for assigning\n * properties to the created object.\n *\n * @private\n * @param {Object} proto The object to inherit from.\n * @returns {Object} Returns the new object.\n */\nvar baseCreate = (function() {\n  function object() {}\n  return function(proto) {\n    if (!isObject(proto)) {\n      return {};\n    }\n    if (objectCreate) {\n      return objectCreate(proto);\n    }\n    object.prototype = proto;\n    var result = new object;\n    object.prototype = undefined;\n    return result;\n  };\n}());\n\nmodule.exports = baseCreate;\n","var baseCreate = require('./_baseCreate'),\n    getPrototype = require('./_getPrototype'),\n    isPrototype = require('./_isPrototype');\n\n/**\n * Initializes an object clone.\n *\n * @private\n * @param {Object} object The object to clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneObject(object) {\n  return (typeof object.constructor == 'function' && !isPrototype(object))\n    ? baseCreate(getPrototype(object))\n    : {};\n}\n\nmodule.exports = initCloneObject;\n","var getTag = require('./_getTag'),\n    isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar mapTag = '[object Map]';\n\n/**\n * The base implementation of `_.isMap` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n */\nfunction baseIsMap(value) {\n  return isObjectLike(value) && getTag(value) == mapTag;\n}\n\nmodule.exports = baseIsMap;\n","var baseIsMap = require('./_baseIsMap'),\n    baseUnary = require('./_baseUnary'),\n    nodeUtil = require('./_nodeUtil');\n\n/* Node.js helper references. */\nvar nodeIsMap = nodeUtil && nodeUtil.isMap;\n\n/**\n * Checks if `value` is classified as a `Map` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a map, else `false`.\n * @example\n *\n * _.isMap(new Map);\n * // => true\n *\n * _.isMap(new WeakMap);\n * // => false\n */\nvar isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;\n\nmodule.exports = isMap;\n","var getTag = require('./_getTag'),\n    isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar setTag = '[object Set]';\n\n/**\n * The base implementation of `_.isSet` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n */\nfunction baseIsSet(value) {\n  return isObjectLike(value) && getTag(value) == setTag;\n}\n\nmodule.exports = baseIsSet;\n","var baseIsSet = require('./_baseIsSet'),\n    baseUnary = require('./_baseUnary'),\n    nodeUtil = require('./_nodeUtil');\n\n/* Node.js helper references. */\nvar nodeIsSet = nodeUtil && nodeUtil.isSet;\n\n/**\n * Checks if `value` is classified as a `Set` object.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a set, else `false`.\n * @example\n *\n * _.isSet(new Set);\n * // => true\n *\n * _.isSet(new WeakSet);\n * // => false\n */\nvar isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;\n\nmodule.exports = isSet;\n","var Stack = require('./_Stack'),\n    arrayEach = require('./_arrayEach'),\n    assignValue = require('./_assignValue'),\n    baseAssign = require('./_baseAssign'),\n    baseAssignIn = require('./_baseAssignIn'),\n    cloneBuffer = require('./_cloneBuffer'),\n    copyArray = require('./_copyArray'),\n    copySymbols = require('./_copySymbols'),\n    copySymbolsIn = require('./_copySymbolsIn'),\n    getAllKeys = require('./_getAllKeys'),\n    getAllKeysIn = require('./_getAllKeysIn'),\n    getTag = require('./_getTag'),\n    initCloneArray = require('./_initCloneArray'),\n    initCloneByTag = require('./_initCloneByTag'),\n    initCloneObject = require('./_initCloneObject'),\n    isArray = require('./isArray'),\n    isBuffer = require('./isBuffer'),\n    isMap = require('./isMap'),\n    isObject = require('./isObject'),\n    isSet = require('./isSet'),\n    keys = require('./keys'),\n    keysIn = require('./keysIn');\n\n/** Used to compose bitmasks for cloning. */\nvar CLONE_DEEP_FLAG = 1,\n    CLONE_FLAT_FLAG = 2,\n    CLONE_SYMBOLS_FLAG = 4;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n    arrayTag = '[object Array]',\n    boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    errorTag = '[object Error]',\n    funcTag = '[object Function]',\n    genTag = '[object GeneratorFunction]',\n    mapTag = '[object Map]',\n    numberTag = '[object Number]',\n    objectTag = '[object Object]',\n    regexpTag = '[object RegExp]',\n    setTag = '[object Set]',\n    stringTag = '[object String]',\n    symbolTag = '[object Symbol]',\n    weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n    dataViewTag = '[object DataView]',\n    float32Tag = '[object Float32Array]',\n    float64Tag = '[object Float64Array]',\n    int8Tag = '[object Int8Array]',\n    int16Tag = '[object Int16Array]',\n    int32Tag = '[object Int32Array]',\n    uint8Tag = '[object Uint8Array]',\n    uint8ClampedTag = '[object Uint8ClampedArray]',\n    uint16Tag = '[object Uint16Array]',\n    uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values supported by `_.clone`. */\nvar cloneableTags = {};\ncloneableTags[argsTag] = cloneableTags[arrayTag] =\ncloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =\ncloneableTags[boolTag] = cloneableTags[dateTag] =\ncloneableTags[float32Tag] = cloneableTags[float64Tag] =\ncloneableTags[int8Tag] = cloneableTags[int16Tag] =\ncloneableTags[int32Tag] = cloneableTags[mapTag] =\ncloneableTags[numberTag] = cloneableTags[objectTag] =\ncloneableTags[regexpTag] = cloneableTags[setTag] =\ncloneableTags[stringTag] = cloneableTags[symbolTag] =\ncloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =\ncloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;\ncloneableTags[errorTag] = cloneableTags[funcTag] =\ncloneableTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.clone` and `_.cloneDeep` which tracks\n * traversed objects.\n *\n * @private\n * @param {*} value The value to clone.\n * @param {boolean} bitmask The bitmask flags.\n *  1 - Deep clone\n *  2 - Flatten inherited properties\n *  4 - Clone symbols\n * @param {Function} [customizer] The function to customize cloning.\n * @param {string} [key] The key of `value`.\n * @param {Object} [object] The parent object of `value`.\n * @param {Object} [stack] Tracks traversed objects and their clone counterparts.\n * @returns {*} Returns the cloned value.\n */\nfunction baseClone(value, bitmask, customizer, key, object, stack) {\n  var result,\n      isDeep = bitmask & CLONE_DEEP_FLAG,\n      isFlat = bitmask & CLONE_FLAT_FLAG,\n      isFull = bitmask & CLONE_SYMBOLS_FLAG;\n\n  if (customizer) {\n    result = object ? customizer(value, key, object, stack) : customizer(value);\n  }\n  if (result !== undefined) {\n    return result;\n  }\n  if (!isObject(value)) {\n    return value;\n  }\n  var isArr = isArray(value);\n  if (isArr) {\n    result = initCloneArray(value);\n    if (!isDeep) {\n      return copyArray(value, result);\n    }\n  } else {\n    var tag = getTag(value),\n        isFunc = tag == funcTag || tag == genTag;\n\n    if (isBuffer(value)) {\n      return cloneBuffer(value, isDeep);\n    }\n    if (tag == objectTag || tag == argsTag || (isFunc && !object)) {\n      result = (isFlat || isFunc) ? {} : initCloneObject(value);\n      if (!isDeep) {\n        return isFlat\n          ? copySymbolsIn(value, baseAssignIn(result, value))\n          : copySymbols(value, baseAssign(result, value));\n      }\n    } else {\n      if (!cloneableTags[tag]) {\n        return object ? value : {};\n      }\n      result = initCloneByTag(value, tag, isDeep);\n    }\n  }\n  // Check for circular references and return its corresponding clone.\n  stack || (stack = new Stack);\n  var stacked = stack.get(value);\n  if (stacked) {\n    return stacked;\n  }\n  stack.set(value, result);\n\n  if (isSet(value)) {\n    value.forEach(function(subValue) {\n      result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));\n    });\n  } else if (isMap(value)) {\n    value.forEach(function(subValue, key) {\n      result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));\n    });\n  }\n\n  var keysFunc = isFull\n    ? (isFlat ? getAllKeysIn : getAllKeys)\n    : (isFlat ? keysIn : keys);\n\n  var props = isArr ? undefined : keysFunc(value);\n  arrayEach(props || value, function(subValue, key) {\n    if (props) {\n      key = subValue;\n      subValue = value[key];\n    }\n    // Recursively populate clone (susceptible to call stack limits).\n    assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));\n  });\n  return result;\n}\n\nmodule.exports = baseClone;\n","var baseClone = require('./_baseClone');\n\n/** Used to compose bitmasks for cloning. */\nvar CLONE_DEEP_FLAG = 1,\n    CLONE_SYMBOLS_FLAG = 4;\n\n/**\n * This method is like `_.clone` except that it recursively clones `value`.\n *\n * @static\n * @memberOf _\n * @since 1.0.0\n * @category Lang\n * @param {*} value The value to recursively clone.\n * @returns {*} Returns the deep cloned value.\n * @see _.clone\n * @example\n *\n * var objects = [{ 'a': 1 }, { 'b': 2 }];\n *\n * var deep = _.cloneDeep(objects);\n * console.log(deep[0] === objects[0]);\n * // => false\n */\nfunction cloneDeep(value) {\n  return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);\n}\n\nmodule.exports = cloneDeep;\n","/** Used to stand-in for `undefined` hash values. */\nvar HASH_UNDEFINED = '__lodash_hash_undefined__';\n\n/**\n * Adds `value` to the array cache.\n *\n * @private\n * @name add\n * @memberOf SetCache\n * @alias push\n * @param {*} value The value to cache.\n * @returns {Object} Returns the cache instance.\n */\nfunction setCacheAdd(value) {\n  this.__data__.set(value, HASH_UNDEFINED);\n  return this;\n}\n\nmodule.exports = setCacheAdd;\n","/**\n * Checks if `value` is in the array cache.\n *\n * @private\n * @name has\n * @memberOf SetCache\n * @param {*} value The value to search for.\n * @returns {number} Returns `true` if `value` is found, else `false`.\n */\nfunction setCacheHas(value) {\n  return this.__data__.has(value);\n}\n\nmodule.exports = setCacheHas;\n","var MapCache = require('./_MapCache'),\n    setCacheAdd = require('./_setCacheAdd'),\n    setCacheHas = require('./_setCacheHas');\n\n/**\n *\n * Creates an array cache object to store unique values.\n *\n * @private\n * @constructor\n * @param {Array} [values] The values to cache.\n */\nfunction SetCache(values) {\n  var index = -1,\n      length = values == null ? 0 : values.length;\n\n  this.__data__ = new MapCache;\n  while (++index < length) {\n    this.add(values[index]);\n  }\n}\n\n// Add methods to `SetCache`.\nSetCache.prototype.add = SetCache.prototype.push = setCacheAdd;\nSetCache.prototype.has = setCacheHas;\n\nmodule.exports = SetCache;\n","/**\n * A specialized version of `_.some` for arrays without support for iteratee\n * shorthands.\n *\n * @private\n * @param {Array} [array] The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n *  else `false`.\n */\nfunction arraySome(array, predicate) {\n  var index = -1,\n      length = array == null ? 0 : array.length;\n\n  while (++index < length) {\n    if (predicate(array[index], index, array)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nmodule.exports = arraySome;\n","/**\n * Checks if a `cache` value for `key` exists.\n *\n * @private\n * @param {Object} cache The cache to query.\n * @param {string} key The key of the entry to check.\n * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.\n */\nfunction cacheHas(cache, key) {\n  return cache.has(key);\n}\n\nmodule.exports = cacheHas;\n","var SetCache = require('./_SetCache'),\n    arraySome = require('./_arraySome'),\n    cacheHas = require('./_cacheHas');\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n    COMPARE_UNORDERED_FLAG = 2;\n\n/**\n * A specialized version of `baseIsEqualDeep` for arrays with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Array} array The array to compare.\n * @param {Array} other The other array to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `array` and `other` objects.\n * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n */\nfunction equalArrays(array, other, bitmask, customizer, equalFunc, stack) {\n  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n      arrLength = array.length,\n      othLength = other.length;\n\n  if (arrLength != othLength && !(isPartial && othLength > arrLength)) {\n    return false;\n  }\n  // Check that cyclic values are equal.\n  var arrStacked = stack.get(array);\n  var othStacked = stack.get(other);\n  if (arrStacked && othStacked) {\n    return arrStacked == other && othStacked == array;\n  }\n  var index = -1,\n      result = true,\n      seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;\n\n  stack.set(array, other);\n  stack.set(other, array);\n\n  // Ignore non-index properties.\n  while (++index < arrLength) {\n    var arrValue = array[index],\n        othValue = other[index];\n\n    if (customizer) {\n      var compared = isPartial\n        ? customizer(othValue, arrValue, index, other, array, stack)\n        : customizer(arrValue, othValue, index, array, other, stack);\n    }\n    if (compared !== undefined) {\n      if (compared) {\n        continue;\n      }\n      result = false;\n      break;\n    }\n    // Recursively compare arrays (susceptible to call stack limits).\n    if (seen) {\n      if (!arraySome(other, function(othValue, othIndex) {\n            if (!cacheHas(seen, othIndex) &&\n                (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {\n              return seen.push(othIndex);\n            }\n          })) {\n        result = false;\n        break;\n      }\n    } else if (!(\n          arrValue === othValue ||\n            equalFunc(arrValue, othValue, bitmask, customizer, stack)\n        )) {\n      result = false;\n      break;\n    }\n  }\n  stack['delete'](array);\n  stack['delete'](other);\n  return result;\n}\n\nmodule.exports = equalArrays;\n","/**\n * Converts `map` to its key-value pairs.\n *\n * @private\n * @param {Object} map The map to convert.\n * @returns {Array} Returns the key-value pairs.\n */\nfunction mapToArray(map) {\n  var index = -1,\n      result = Array(map.size);\n\n  map.forEach(function(value, key) {\n    result[++index] = [key, value];\n  });\n  return result;\n}\n\nmodule.exports = mapToArray;\n","/**\n * Converts `set` to an array of its values.\n *\n * @private\n * @param {Object} set The set to convert.\n * @returns {Array} Returns the values.\n */\nfunction setToArray(set) {\n  var index = -1,\n      result = Array(set.size);\n\n  set.forEach(function(value) {\n    result[++index] = value;\n  });\n  return result;\n}\n\nmodule.exports = setToArray;\n","var Symbol = require('./_Symbol'),\n    Uint8Array = require('./_Uint8Array'),\n    eq = require('./eq'),\n    equalArrays = require('./_equalArrays'),\n    mapToArray = require('./_mapToArray'),\n    setToArray = require('./_setToArray');\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1,\n    COMPARE_UNORDERED_FLAG = 2;\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    errorTag = '[object Error]',\n    mapTag = '[object Map]',\n    numberTag = '[object Number]',\n    regexpTag = '[object RegExp]',\n    setTag = '[object Set]',\n    stringTag = '[object String]',\n    symbolTag = '[object Symbol]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n    dataViewTag = '[object DataView]';\n\n/** Used to convert symbols to primitives and strings. */\nvar symbolProto = Symbol ? Symbol.prototype : undefined,\n    symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;\n\n/**\n * A specialized version of `baseIsEqualDeep` for comparing objects of\n * the same `toStringTag`.\n *\n * **Note:** This function only supports comparing values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {string} tag The `toStringTag` of the objects to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {\n  switch (tag) {\n    case dataViewTag:\n      if ((object.byteLength != other.byteLength) ||\n          (object.byteOffset != other.byteOffset)) {\n        return false;\n      }\n      object = object.buffer;\n      other = other.buffer;\n\n    case arrayBufferTag:\n      if ((object.byteLength != other.byteLength) ||\n          !equalFunc(new Uint8Array(object), new Uint8Array(other))) {\n        return false;\n      }\n      return true;\n\n    case boolTag:\n    case dateTag:\n    case numberTag:\n      // Coerce booleans to `1` or `0` and dates to milliseconds.\n      // Invalid dates are coerced to `NaN`.\n      return eq(+object, +other);\n\n    case errorTag:\n      return object.name == other.name && object.message == other.message;\n\n    case regexpTag:\n    case stringTag:\n      // Coerce regexes to strings and treat strings, primitives and objects,\n      // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring\n      // for more details.\n      return object == (other + '');\n\n    case mapTag:\n      var convert = mapToArray;\n\n    case setTag:\n      var isPartial = bitmask & COMPARE_PARTIAL_FLAG;\n      convert || (convert = setToArray);\n\n      if (object.size != other.size && !isPartial) {\n        return false;\n      }\n      // Assume cyclic values are equal.\n      var stacked = stack.get(object);\n      if (stacked) {\n        return stacked == other;\n      }\n      bitmask |= COMPARE_UNORDERED_FLAG;\n\n      // Recursively compare objects (susceptible to call stack limits).\n      stack.set(object, other);\n      var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);\n      stack['delete'](object);\n      return result;\n\n    case symbolTag:\n      if (symbolValueOf) {\n        return symbolValueOf.call(object) == symbolValueOf.call(other);\n      }\n  }\n  return false;\n}\n\nmodule.exports = equalByTag;\n","var getAllKeys = require('./_getAllKeys');\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1;\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqualDeep` for objects with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} stack Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalObjects(object, other, bitmask, customizer, equalFunc, stack) {\n  var isPartial = bitmask & COMPARE_PARTIAL_FLAG,\n      objProps = getAllKeys(object),\n      objLength = objProps.length,\n      othProps = getAllKeys(other),\n      othLength = othProps.length;\n\n  if (objLength != othLength && !isPartial) {\n    return false;\n  }\n  var index = objLength;\n  while (index--) {\n    var key = objProps[index];\n    if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {\n      return false;\n    }\n  }\n  // Check that cyclic values are equal.\n  var objStacked = stack.get(object);\n  var othStacked = stack.get(other);\n  if (objStacked && othStacked) {\n    return objStacked == other && othStacked == object;\n  }\n  var result = true;\n  stack.set(object, other);\n  stack.set(other, object);\n\n  var skipCtor = isPartial;\n  while (++index < objLength) {\n    key = objProps[index];\n    var objValue = object[key],\n        othValue = other[key];\n\n    if (customizer) {\n      var compared = isPartial\n        ? customizer(othValue, objValue, key, other, object, stack)\n        : customizer(objValue, othValue, key, object, other, stack);\n    }\n    // Recursively compare objects (susceptible to call stack limits).\n    if (!(compared === undefined\n          ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))\n          : compared\n        )) {\n      result = false;\n      break;\n    }\n    skipCtor || (skipCtor = key == 'constructor');\n  }\n  if (result && !skipCtor) {\n    var objCtor = object.constructor,\n        othCtor = other.constructor;\n\n    // Non `Object` object instances with different constructors are not equal.\n    if (objCtor != othCtor &&\n        ('constructor' in object && 'constructor' in other) &&\n        !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n          typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n      result = false;\n    }\n  }\n  stack['delete'](object);\n  stack['delete'](other);\n  return result;\n}\n\nmodule.exports = equalObjects;\n","var Stack = require('./_Stack'),\n    equalArrays = require('./_equalArrays'),\n    equalByTag = require('./_equalByTag'),\n    equalObjects = require('./_equalObjects'),\n    getTag = require('./_getTag'),\n    isArray = require('./isArray'),\n    isBuffer = require('./isBuffer'),\n    isTypedArray = require('./isTypedArray');\n\n/** Used to compose bitmasks for value comparisons. */\nvar COMPARE_PARTIAL_FLAG = 1;\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n    arrayTag = '[object Array]',\n    objectTag = '[object Object]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqual` for arrays and objects which performs\n * deep comparisons and tracks traversed objects enabling objects with circular\n * references to be compared.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.\n * @param {Function} customizer The function to customize comparisons.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Object} [stack] Tracks traversed `object` and `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {\n  var objIsArr = isArray(object),\n      othIsArr = isArray(other),\n      objTag = objIsArr ? arrayTag : getTag(object),\n      othTag = othIsArr ? arrayTag : getTag(other);\n\n  objTag = objTag == argsTag ? objectTag : objTag;\n  othTag = othTag == argsTag ? objectTag : othTag;\n\n  var objIsObj = objTag == objectTag,\n      othIsObj = othTag == objectTag,\n      isSameTag = objTag == othTag;\n\n  if (isSameTag && isBuffer(object)) {\n    if (!isBuffer(other)) {\n      return false;\n    }\n    objIsArr = true;\n    objIsObj = false;\n  }\n  if (isSameTag && !objIsObj) {\n    stack || (stack = new Stack);\n    return (objIsArr || isTypedArray(object))\n      ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)\n      : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);\n  }\n  if (!(bitmask & COMPARE_PARTIAL_FLAG)) {\n    var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n        othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n    if (objIsWrapped || othIsWrapped) {\n      var objUnwrapped = objIsWrapped ? object.value() : object,\n          othUnwrapped = othIsWrapped ? other.value() : other;\n\n      stack || (stack = new Stack);\n      return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);\n    }\n  }\n  if (!isSameTag) {\n    return false;\n  }\n  stack || (stack = new Stack);\n  return equalObjects(object, other, bitmask, customizer, equalFunc, stack);\n}\n\nmodule.exports = baseIsEqualDeep;\n","var baseIsEqualDeep = require('./_baseIsEqualDeep'),\n    isObjectLike = require('./isObjectLike');\n\n/**\n * The base implementation of `_.isEqual` which supports partial comparisons\n * and tracks traversed objects.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {boolean} bitmask The bitmask flags.\n *  1 - Unordered comparison\n *  2 - Partial comparison\n * @param {Function} [customizer] The function to customize comparisons.\n * @param {Object} [stack] Tracks traversed `value` and `other` objects.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n */\nfunction baseIsEqual(value, other, bitmask, customizer, stack) {\n  if (value === other) {\n    return true;\n  }\n  if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {\n    return value !== value && other !== other;\n  }\n  return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);\n}\n\nmodule.exports = baseIsEqual;\n","var baseIsEqual = require('./_baseIsEqual');\n\n/**\n * Performs a deep comparison between two values to determine if they are\n * equivalent.\n *\n * **Note:** This method supports comparing arrays, array buffers, booleans,\n * date objects, error objects, maps, numbers, `Object` objects, regexes,\n * sets, strings, symbols, and typed arrays. `Object` objects are compared\n * by their own, not inherited, enumerable properties. Functions and DOM\n * nodes are compared by strict equality, i.e. `===`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.isEqual(object, other);\n * // => true\n *\n * object === other;\n * // => false\n */\nfunction isEqual(value, other) {\n  return baseIsEqual(value, other);\n}\n\nmodule.exports = isEqual;\n","export function isEditedHSQC(experiment) {\n    // detection whether experiment is an edited HSQC\n    return experiment.info.pulseSequence.includes('hsqced');\n}\n//# sourceMappingURL=isEditedHSQC.js.map","import lodashCloneDeep from 'lodash/cloneDeep';\nimport lodashIsEqual from 'lodash/isEqual';\nimport { allowedSignalKinds } from '../../constants/allowedSignalKinds';\nimport { checkMatch } from '../general/checkMatch';\nimport { getAtomTypeFromNucleus } from '../general/getAtomTypeFromNucleus';\nimport { isEditedHSQC } from '../general/isEditedHSQC';\n/**\n * Get all different 2D signals from experiments with allowed signal kinds in \"signalKindsToInclude\".\n *\n * @param {ExperimentsType} experiments1D\n */\nexport function getSignals2D(experiments2D) {\n    // store valid signals from 2D experiments\n    const _signals2D = {};\n    Object.keys(experiments2D).forEach((experimentType) => {\n        const _signals = [];\n        // for now we use the first occurring spectrum only, for each experiment type (current loop) and nuclei combination\n        const indices = [];\n        const nuclei = [];\n        experiments2D[experimentType].forEach((_experiment, i) => {\n            const experiment = _experiment;\n            if (!nuclei.some((_nuclei) => lodashIsEqual(_nuclei, experiment.info.nucleus))) {\n                nuclei.push(experiment.info.nucleus);\n                indices.push(i);\n            }\n        });\n        indices.forEach((index) => {\n            const spectrum2D = experiments2D[experimentType][index];\n            const atomType = spectrum2D.info.nucleus.map((nucleus) => getAtomTypeFromNucleus(nucleus));\n            const __signals = spectrum2D.zones.values\n                .map((zone) => zone.signals.filter((signal) => signal.kind && allowedSignalKinds.includes(signal.kind)))\n                .flat();\n            __signals.forEach((signal) => {\n                if (!_signals.some((_signal) => checkMatch(_signal.signal.x.delta, signal.x.delta, 0.0) &&\n                    checkMatch(_signal.signal.y.delta, signal.y.delta, 0.0))) {\n                    _signals.push({\n                        experimentType,\n                        experimentID: spectrum2D.id,\n                        atomType,\n                        // @TODO here we assume that only one peak exists for the signal and its intensity indicates the sign\n                        signal: {\n                            ...lodashCloneDeep(signal),\n                            sign: isEditedHSQC(spectrum2D) && signal.peaks\n                                ? signal.peaks[0].z >= 0\n                                    ? 1\n                                    : -1\n                                : 0,\n                        },\n                    });\n                }\n            });\n        });\n        _signals2D[experimentType] = _signals;\n    });\n    return _signals2D;\n}\n//# sourceMappingURL=getSignals2D.js.map","import lodashCloneDeep from 'lodash/cloneDeep';\nimport { allowedSignalKinds } from '../../constants/allowedSignalKinds';\nimport { checkMatch } from '../general/checkMatch';\nimport { getAtomTypeFromNucleus } from '../general/getAtomTypeFromNucleus';\n/**\n * Get all DEPT signals from experiments with allowed signal kinds in \"signalKindsToInclude\".\n *\n * @param {ExperimentsType} experiments1DExtra\n */\nexport function getSignalsDEPT(experiments1DExtra) {\n    // store valid signals from 1D extra experiments, e.g. DEPT, APT\n    const _signalsDEPT = {};\n    // store valid signals from 2D experiments\n    Object.keys(experiments1DExtra)\n        .filter((experimentType) => experimentType === 'dept')\n        .forEach((experimentType) => experiments1DExtra[experimentType].forEach((_experimentDEPT) => {\n        const experimentDEPT = _experimentDEPT;\n        const _signals = [];\n        const match = experimentDEPT.info.pulseSequence.match(/\\d/g);\n        if (match) {\n            const mode = match.reduce((_mode, digit) => _mode + digit);\n            const atomType = getAtomTypeFromNucleus(experimentDEPT.info.nucleus);\n            const __signals = experimentDEPT.ranges.values\n                .map((range) => range.signals\n                .filter((signal) => signal.kind && allowedSignalKinds.includes(signal.kind))\n                .map((signal) => {\n                return { ...signal, sign: range.absolute > 0 ? 1 : -1 };\n            }))\n                .flat();\n            __signals.forEach((signal) => {\n                if (!_signals.some((_signal) => checkMatch(_signal.signal.delta, signal.delta, 0.0))) {\n                    _signals.push({\n                        experimentType,\n                        experimentID: experimentDEPT.id,\n                        mode,\n                        atomType,\n                        signal: lodashCloneDeep(signal),\n                    });\n                }\n            });\n            _signalsDEPT[mode] = _signals;\n        }\n    }));\n    return _signalsDEPT;\n}\n//# sourceMappingURL=getSignalsDEPT.js.map","import { getExperiments } from '../experiment/getExperiments';\nimport { getExperiments1D } from '../experiment/getExperiments1D';\nimport { getExperiments1DExtra } from '../experiment/getExperiments1DExtra';\nimport { getExperiments2D } from '../experiment/getExperiments2D';\nimport { getSignals1D } from './getSignals1D';\nimport { getSignals2D } from './getSignals2D';\nimport { getSignalsDEPT } from './getSignalsDEPT';\n// general remark for all experiment types:\n// build an array of experiments, because one could have more than\n// one spectrum in spectra list for one atom type or experiment type\n/**\n * Get all signals from experiments with allowed signal kinds in \"signalKindsToInclude\".\n *\n * @param {Spectra} spectraData\n */\nexport function getSignals(spectraData) {\n    const experiments = getExperiments(spectraData);\n    const experiments1D = getExperiments1D(experiments);\n    const experiments1DExtra = getExperiments1DExtra(experiments);\n    const experiments2D = getExperiments2D(experiments);\n    const signals1D = getSignals1D(experiments1D);\n    const signals2D = getSignals2D(experiments2D);\n    const signalsDEPT = getSignalsDEPT(experiments1DExtra);\n    return {\n        signals1D,\n        signals2D,\n        signalsDEPT,\n    };\n}\n//# sourceMappingURL=getSignals.js.map","const BASE62 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst LENGTH = 8;\nexport function generateID() {\n    let id = '';\n    for (let i = 0; i < LENGTH; i++) {\n        id += BASE62.charAt(Math.floor(Math.random() * 62));\n    }\n    return id;\n}\n//# sourceMappingURL=generateID.js.map","import { generateID } from '../general/generateID';\n/**\n * Builds a link object with some existing default values.\n *\n * @param {LinkOptions} options\n */\nexport function buildLink(options) {\n    return {\n        id: options.id || generateID(),\n        experimentType: options.experimentType,\n        experimentID: options.experimentID,\n        atomType: options.atomType,\n        signal: options.signal,\n        axis: options.axis,\n        match: options.match || [],\n        experimentLabel: options.experimentLabel || '',\n        pseudo: options.pseudo || false,\n        edited: options.edited || {},\n    };\n}\n//# sourceMappingURL=buildLink.js.map","export function findLinkedCorrelationsBySignalID(correlations, signalID) {\n    return correlations.filter((_correlation) => _correlation.link.some((_link) => _link.signal.id === signalID));\n}\n//# sourceMappingURL=findLinkedCorrelationsBySignalID.js.map","import lodashIsEqual from 'lodash/isEqual';\n/**\n * Checks whether a correlation contains a link by id search.\n *\n * @param {Correlation} correlation\n * @param {Link} link\n */\nexport function containsLink(correlation, link) {\n    return correlation.link.some((_link) => _link.experimentType === link.experimentType &&\n        _link.experimentID === link.experimentID &&\n        lodashIsEqual(_link.atomType, link.atomType) &&\n        _link.signal.id === link.signal.id &&\n        _link.axis === link.axis);\n}\n//# sourceMappingURL=containsLink.js.map","/**\n * Checks whether a correlation has links.\n *\n * @param {Correlation} correlation\n */\nexport function hasLinks(correlation) {\n    return correlation.link.length > 0;\n}\n//# sourceMappingURL=hasLinks.js.map","import { addLink, buildCorrelation } from '../..';\nimport { containsLink } from '../correlation/containsLink';\nimport { hasLinks } from '../correlation/hasLinks';\nexport function addSignal(matchedCorrelationIndices, atomType, link, correlations) {\n    if (matchedCorrelationIndices.length === 0) {\n        // in case of no signal match -> add new signal from 2D\n        const newCorrelation = buildCorrelation({\n            atomType,\n        });\n        addLink(newCorrelation, link);\n        const pseudoIndex = correlations.findIndex((correlation) => correlation.atomType === atomType &&\n            correlation.pseudo &&\n            !hasLinks(correlation));\n        if (pseudoIndex >= 0) {\n            correlations[pseudoIndex] = newCorrelation;\n        }\n        else {\n            correlations.push(newCorrelation);\n        }\n    }\n    else if (!containsLink(correlations[matchedCorrelationIndices[0]], link)) {\n        // if allowed then add links from 2D data in first match only\n        addLink(correlations[matchedCorrelationIndices[0]], link);\n    }\n}\n//# sourceMappingURL=addSignal.js.map","import { buildLink } from '../correlation/buildLink';\nimport { checkMatch } from '../general/checkMatch';\nimport { findLinkedCorrelationsBySignalID } from '../general/findLinkedCorrelationsBySignalID';\nimport { getCorrelationDelta } from '../general/getCorrelationDelta';\nimport { addSignal } from './addSignal';\n/**\n * Adds new correlations from 1D and 2D data or adds links to already existing ones.\n *\n * @param {Values} correlations\n * * @param {Experiment1DSignals} signals1D\n * @param {Experiment2DSignals} signals2D\n * @param {Tolerance} tolerance\n */\nexport function addFromData(correlations, signals1D, signals2D, tolerance) {\n    // remove non-pseudo correlation objects without links\n    correlations = correlations.filter((correlation) => correlation.link.length > 0 || correlation.pseudo);\n    // add from 1D data\n    Object.keys(signals1D).forEach((atomType) => {\n        signals1D[atomType].forEach((signal1D) => {\n            const linkedCorrelations = findLinkedCorrelationsBySignalID(correlations, signal1D.signal.id || '');\n            if (linkedCorrelations.length === 0) {\n                const matchedCorrelationIndices = correlations\n                    .map((correlation, k) => {\n                    const correlationDelta = getCorrelationDelta(correlation);\n                    return !correlation.pseudo &&\n                        correlation.atomType === atomType &&\n                        correlationDelta !== undefined &&\n                        checkMatch(correlationDelta, signal1D.signal.delta, tolerance[atomType])\n                        ? k\n                        : -1;\n                })\n                    .filter((index) => index >= 0)\n                    .filter((index, i, a) => a.indexOf(index) === i);\n                const link = buildLink({\n                    experimentType: signal1D.experimentType,\n                    experimentID: signal1D.experimentID,\n                    signal: signal1D.signal,\n                    atomType: [atomType],\n                });\n                addSignal(matchedCorrelationIndices, atomType, link, correlations);\n            }\n        });\n    });\n    // add from 2D\n    // add potential new correlations and push new links via shift matches between 1D vs. 2D and 2D vs. 2D\n    Object.keys(signals2D).forEach((experimentType) => signals2D[experimentType].forEach((signal2D) => {\n        const linkedCorrelations = findLinkedCorrelationsBySignalID(correlations, signal2D.signal.id || '');\n        if (linkedCorrelations.length === 0) {\n            signal2D.atomType.forEach((atomType, dim) => {\n                const axis = dim === 0 ? 'x' : 'y';\n                const matchedCorrelationIndices = correlations\n                    .map((correlation, k) => {\n                    const correlationDelta = getCorrelationDelta(correlation);\n                    return !correlation.pseudo &&\n                        correlation.atomType === atomType &&\n                        correlationDelta !== undefined &&\n                        checkMatch(correlationDelta, signal2D.signal[axis].delta, tolerance[atomType])\n                        ? k\n                        : -1;\n                })\n                    .filter((index) => index >= 0)\n                    .filter((index, i, a) => a.indexOf(index) === i);\n                const link = buildLink({\n                    experimentType: signal2D.experimentType,\n                    experimentID: signal2D.experimentID,\n                    signal: signal2D.signal,\n                    axis,\n                    atomType: signal2D.atomType,\n                });\n                addSignal(matchedCorrelationIndices, atomType, link, correlations);\n            });\n        }\n    }));\n    return correlations;\n}\n//# sourceMappingURL=addFromData.js.map","import { generateID } from '../general/generateID';\n/**\n * Builds a correlation object with some existing default values.\n *\n * @param {CorrelationOptions} options\n */\nexport function buildCorrelation(options) {\n    return {\n        id: options.id || generateID(),\n        atomType: options.atomType,\n        label: options.label || {},\n        link: options.link || [],\n        equivalence: options.equivalence || 1,\n        attachment: options.attachment || {},\n        protonsCount: options.protonsCount || [],\n        hybridization: options.hybridization || [],\n        pseudo: options.pseudo || false,\n        edited: options.edited || {},\n    };\n}\n//# sourceMappingURL=buildCorrelation.js.map","import { buildCorrelation } from '../../correlation/buildCorrelation';\nimport { getCorrelationsByAtomType } from '../../general/getCorrelationsByAtomType';\nexport function addPseudoCorrelations(correlations, atoms) {\n    for (const atomType in atoms) {\n        const atomTypeCount = getCorrelationsByAtomType(correlations, atomType).reduce((sum, correlation) => sum + correlation.equivalence, 0);\n        // add missing pseudo correlations\n        for (let i = atomTypeCount; i < atoms[atomType]; i++) {\n            correlations.push(buildCorrelation({\n                atomType,\n                pseudo: true,\n            }));\n        }\n    }\n    return correlations;\n}\n//# sourceMappingURL=addPseudoCorrelations.js.map","/**\n * Removes a link by id search.\n *\n * @param {Correlation} correlation\n * @param {string} id\n */\nexport function removeLink(correlation, id) {\n    correlation.link = correlation.link.filter((_link) => _link.id !== id);\n    return correlation;\n}\n//# sourceMappingURL=removeLink.js.map","/**\n * Removes a match index from a link.\n *\n * @param {Link} link\n * @param {number} index\n */\nexport function removeMatch(link, index) {\n    const indexOf = link.match.indexOf(index);\n    if (indexOf >= 0) {\n        link.match.splice(indexOf, 1);\n    }\n    return link;\n}\n//# sourceMappingURL=removeMatch.js.map","import { hasLinks } from '../../correlation/hasLinks';\nimport { removeLink } from '../../correlation/removeLink';\nimport { removeMatch } from '../../correlation/removeMatch';\nimport { getCorrelationIndex } from '../../general/getCorrelationIndex';\nimport { getCorrelationsByAtomType } from '../../general/getCorrelationsByAtomType';\nexport function checkPseudoCorrelations(correlations, atoms) {\n    for (const atomType in atoms) {\n        // consider also pseudo correlations\n        const correlationsAtomType = getCorrelationsByAtomType(correlations, atomType);\n        if (correlationsAtomType.length > atoms[atomType]) {\n            // remove pseudo correlations which are out of limit and not linked\n            const pseudoCorrelationsAtomType = correlationsAtomType.filter((correlation) => correlation.pseudo &&\n                correlation.equivalence === 1 &&\n                !hasLinks(correlation));\n            for (let i = correlationsAtomType.length - 1; i >= atoms[atomType]; i--) {\n                if (pseudoCorrelationsAtomType.length === 0) {\n                    break;\n                }\n                const pseudoCorrelationToRemove = pseudoCorrelationsAtomType.pop();\n                if (pseudoCorrelationToRemove) {\n                    correlations.splice(correlations.indexOf(pseudoCorrelationToRemove), 1);\n                }\n            }\n        }\n    }\n    // check for deleted links and correct proton counts if no HSQC link exists\n    for (const pseudoCorrelation of correlations) {\n        if (!pseudoCorrelation.pseudo ||\n            pseudoCorrelation.equivalence > 1 ||\n            hasLinks(pseudoCorrelation)) {\n            continue;\n        }\n        // remove wrong (old) match indices and empty links\n        const linksToRemove = [];\n        const pseudoCorrelationIndex = getCorrelationIndex(correlations, pseudoCorrelation);\n        for (const pseudoLink of pseudoCorrelation.link) {\n            for (const matchIndex of pseudoLink.match) {\n                if (!correlations[matchIndex] ||\n                    !correlations[matchIndex].link.some((_link) => _link.match.includes(pseudoCorrelationIndex))) {\n                    removeMatch(pseudoLink, matchIndex);\n                }\n            }\n            if (pseudoLink.match.length === 0) {\n                linksToRemove.push(pseudoLink);\n            }\n        }\n        for (const pseudoLink of linksToRemove) {\n            removeLink(pseudoCorrelation, pseudoLink.id);\n        }\n        // correct protons count if no HSQC link was found anymore and the field was not edited manually\n        if (!pseudoCorrelation.edited.protonsCount &&\n            !pseudoCorrelation.link.some((pseudoLink) => pseudoLink.experimentType === 'hsqc')) {\n            pseudoCorrelation.protonsCount = [];\n        }\n    }\n    // filter out correlations with unknown atom types from previous molecular formula\n    return Object.keys(atoms).length > 0\n        ? correlations.filter((correlation) => Object.keys(atoms).includes(correlation.atomType))\n        : correlations;\n}\n//# sourceMappingURL=checkPseudoCorrelations.js.map","import { hasLinks } from '../../correlation/hasLinks';\nimport { getCorrelationsByAtomType } from '../../general/getCorrelationsByAtomType';\nexport function replacePseudoCorrelationsByEquivalences(correlations, atoms) {\n    for (const atomType in atoms) {\n        // remove pseudo correlations to be replaced by equivalences, starting at the end\n        const correlationsAtomType = getCorrelationsByAtomType(correlations, atomType);\n        const validCorrelationsAtomType = correlationsAtomType.filter((correlation) => !correlation.pseudo ||\n            correlation.equivalence > 1 ||\n            hasLinks(correlation));\n        const atomTypeEquivalencesCount = validCorrelationsAtomType.reduce((sum, correlation) => sum + (correlation.equivalence - 1), 0);\n        const pseudoCorrelationsAtomType = correlationsAtomType.filter((correlation) => correlation.pseudo &&\n            !validCorrelationsAtomType.some((validCorrelation) => validCorrelation.id === correlation.id));\n        for (let i = 0; i <\n            correlationsAtomType.length -\n                (atoms[atomType] - atomTypeEquivalencesCount); i++) {\n            if (pseudoCorrelationsAtomType.length === 0) {\n                break;\n            }\n            const pseudoCorrelationToRemove = pseudoCorrelationsAtomType.pop();\n            if (pseudoCorrelationToRemove) {\n                correlations.splice(correlations.indexOf(pseudoCorrelationToRemove), 1);\n            }\n        }\n    }\n    return correlations;\n}\n//# sourceMappingURL=replacePseudoCorrelationsByEquivalences.js.map","import { getAtomCounts } from '../../general/getAtomCounts';\nimport { addPseudoCorrelations } from './addPseudoCorrelations';\nimport { checkPseudoCorrelations } from './checkPseudoCorrelations';\nimport { replacePseudoCorrelationsByEquivalences } from './replacePseudoCorrelationsByEquivalences';\n/**\n * Adds pseudo correlations if needed, checks for replacement\n * by equivalent atoms and cleanup.\n * @param {Values} correlations\n * @param {string} mf\n */\nexport function updatePseudoCorrelations(correlations, mf) {\n    const atoms = getAtomCounts(mf);\n    if (Object.keys(atoms).length === 0) {\n        correlations = correlations.filter((correlation) => !correlation.pseudo);\n    }\n    // add pseudo correlations\n    correlations = addPseudoCorrelations(correlations, atoms);\n    // remove pseudo correlations to be replaced by equivalences\n    correlations = replacePseudoCorrelationsByEquivalences(correlations, atoms);\n    // remove pseudo correlations which are out of limit, clean up links and proton counts\n    correlations = checkPseudoCorrelations(correlations, atoms);\n    return correlations;\n}\n//# sourceMappingURL=updatePseudoCorrelations.js.map","import lodashGet from 'lodash/get';\nimport { removeLink } from '../..';\n/**\n * Removes non-pseudo correlations which signal id can not be found or have no links anymore.\n *\n * @param {Values} values\n * @param {Experiment1DSignals} signals1D\n * @param {Experiment2DSignals} signals2D\n */\nexport function removeObsoleteLinksAndNotLinkedCorrelations(correlations, signals1D, signals2D) {\n    const _correlations = correlations.filter((correlation) => !correlation.pseudo);\n    const removeList = _correlations.slice();\n    _correlations.forEach((correlation) => {\n        for (const link of correlation.link) {\n            if (link.experimentType === '1d') {\n                // search in 1D data\n                if (lodashGet(signals1D, link.atomType[0], []).some((signal1D) => signal1D.signal.id === link.signal.id)) {\n                    const index = removeList.indexOf(correlation);\n                    if (index >= 0) {\n                        removeList.splice(index, 1);\n                    }\n                }\n                else if (!link.pseudo) {\n                    // remove obsolete link to not anymore existing signal\n                    removeLink(correlation, link.id);\n                }\n            }\n            else if (lodashGet(signals2D, `${link.experimentType}`, []).some((signal2D) => signal2D.signal.id === link.signal.id)) {\n                // search in 2D data\n                const index = removeList.indexOf(correlation);\n                if (index >= 0) {\n                    removeList.splice(index, 1);\n                }\n            }\n            else if (!link.pseudo) {\n                // remove obsolete link to not anymore existing signal\n                removeLink(correlation, link.id);\n            }\n        }\n    });\n    removeList.forEach((correlation) => {\n        const index = correlations.indexOf(correlation); // in case we already removed previously\n        if (index >= 0) {\n            correlations.splice(index, 1);\n        }\n    });\n    return correlations;\n}\n//# sourceMappingURL=removeObsoleteLinksAndNotLinkedCorrelations.js.map","/**\n * Checks whether an atom type key in attachments already exists.\n *\n * @param {Correlation} correlation\n * @param {string} atomType\n */\nexport function hasAttachmentAtomType(correlation, atomType) {\n    return Boolean(correlation.attachment[atomType] &&\n        correlation.attachment[atomType].length > 0);\n}\n//# sourceMappingURL=hasAttachmentAtomType.js.map","import { hasAttachmentAtomType } from './hasAttachmentAtomType';\n/**\n * Creates an attachment array for a certain atom type in a correlation.\n *\n * @param {Correlation} correlation\n * @param {string} atomType\n */\nexport function addAttachmentAtomType(correlation, atomType) {\n    if (!hasAttachmentAtomType(correlation, atomType)) {\n        correlation.attachment[atomType] = [];\n    }\n    return correlation;\n}\n//# sourceMappingURL=addAttachmentAtomType.js.map","import { addAttachmentAtomType } from './addAttachmentAtomType';\n/**\n * Adds an attachment for a certain atom type to a correlation.\n *\n * @param {Correlation} correlation\n * @param {string} atomType\n * @param {number} attachment\n */\nexport function addAttachment(correlation, atomType, attachment) {\n    addAttachmentAtomType(correlation, atomType);\n    if (!correlation.attachment[atomType].includes(attachment)) {\n        correlation.attachment[atomType].push(attachment);\n    }\n    return correlation;\n}\n//# sourceMappingURL=addAttachment.js.map","/**\n * Removes all attachments of a correlation.\n *\n * @param {Correlation} correlation\n */\nexport function removeAttachments(correlation) {\n    correlation.attachment = {};\n    return correlation;\n}\n//# sourceMappingURL=removeAttachments.js.map","import { addAttachment } from '../correlation/addAttachment';\nimport { hasAttachmentAtomType } from '../correlation/hasAttachmentAtomType';\nimport { removeAttachments } from '../correlation/removeAttachments';\n/**\n * Sets the attachment information (indices of attached atoms).\n * And from that, the equivalence value for protons can be set too.\n *\n * @param {Values} values\n */\nexport function setAttachmentsAndProtonEquivalences(correlations) {\n    // update attachment information between heavy atoms and protons via HSQC or HMQC\n    for (const correlation of correlations) {\n        // remove previous set attachments\n        removeAttachments(correlation);\n        // add attachments\n        const linksFiltered = correlation.link.filter((link) => link.experimentType === 'hsqc' || link.experimentType === 'hmqc');\n        for (const link of linksFiltered) {\n            const otherAtomType = link.atomType[link.axis === 'x' ? 1 : 0];\n            for (let matchIndex of link.match) {\n                addAttachment(correlation, otherAtomType, matchIndex);\n            }\n        }\n    }\n    // set previously set equivalences of protons to 0\n    for (const correlation of correlations) {\n        if (correlation.atomType === 'H') {\n            correlation.equivalence = 0;\n        }\n    }\n    // reset previously set proton equivalences and set new ones\n    // check heavy atoms with an unambiguous protons count\n    for (const correlation of correlations) {\n        if (correlation.atomType !== 'H' &&\n            correlation.protonsCount.length === 1 &&\n            hasAttachmentAtomType(correlation, 'H')) {\n            const { equivalence, protonsCount } = correlation;\n            let equivalences = 1;\n            if (protonsCount[0] === 3) {\n                equivalences = 3;\n            }\n            else if (protonsCount[0] === 2) {\n                equivalences = 2;\n            }\n            const sharedEquivalences = (equivalence * equivalences) / correlation.attachment.H.length;\n            for (const attachedProtonIndex of correlation.attachment.H) {\n                correlations[attachedProtonIndex].equivalence += sharedEquivalences;\n            }\n        }\n    }\n    // set unchanged equivalence of protons back to 1\n    for (const correlation of correlations) {\n        if (correlation.atomType === 'H' && correlation.equivalence === 0) {\n            correlation.equivalence = 1;\n        }\n    }\n    return correlations;\n}\n//# sourceMappingURL=setAttachmentsAndProtonEquivalences.js.map","import lodashGet from 'lodash/get';\n/**\n * Sets the origin (default) label for each correlation, e.g. C1 or H2, depending on its order.\n *\n * @param {Values} values\n */\nexport function setLabels(correlations) {\n    const atomTypeCounts = {};\n    correlations.forEach((correlation) => {\n        if (!lodashGet(atomTypeCounts, correlation.atomType, false)) {\n            atomTypeCounts[correlation.atomType] = 0;\n        }\n        atomTypeCounts[correlation.atomType]++;\n        correlation.label.origin = `${correlation.atomType}${atomTypeCounts[correlation.atomType]}`;\n    });\n    return correlations;\n}\n//# sourceMappingURL=setLabels.js.map","/**\n * Adds an index to the match array of a link.\n *\n * @param {Link} link\n * @param {number} index\n */\nexport function addMatch(link, index) {\n    if (!link.match.includes(index)) {\n        link.match.push(index);\n    }\n    return link;\n}\n//# sourceMappingURL=addMatch.js.map","/**\n * Removes all match indices in a link.\n *\n * @param {Link} link\n */\nexport function removeMatches(link) {\n    link.match = [];\n    return link;\n}\n//# sourceMappingURL=removeMatches.js.map","import lodashIsEqual from 'lodash/isEqual';\nimport { addMatch } from '../correlation/addMatch';\nimport { removeLink } from '../correlation/removeLink';\nimport { removeMatches } from '../correlation/removeMatches';\nimport { getCorrelationIndex } from '../general/getCorrelationIndex';\nimport { getCorrelationsByAtomType } from '../general/getCorrelationsByAtomType';\n/**\n * Sets the match indices for each link within a correlation.\n *\n * @param {Values} values\n */\nexport function setMatches(correlations) {\n    correlations.forEach((correlation) => {\n        correlation.link.forEach((link) => {\n            // remove previously added matches\n            removeMatches(link);\n            // add matches\n            const otherAtomType = link.axis === 'x' ? link.atomType[1] : link.atomType[0];\n            getCorrelationsByAtomType(correlations, otherAtomType).forEach((correlationOtherAtomType) => {\n                if (correlation.id !== correlationOtherAtomType.id) {\n                    const correlationIndexOtherAtomType = getCorrelationIndex(correlations, correlationOtherAtomType);\n                    correlationOtherAtomType.link.forEach((linkOtherAtomType) => {\n                        // check for correlation match and avoid possible duplicates\n                        if (linkOtherAtomType.experimentType === link.experimentType &&\n                            linkOtherAtomType.experimentID === link.experimentID &&\n                            lodashIsEqual(linkOtherAtomType.atomType, link.atomType) &&\n                            linkOtherAtomType.signal.id === link.signal.id &&\n                            linkOtherAtomType.axis !== link.axis) {\n                            addMatch(link, correlationIndexOtherAtomType);\n                        }\n                    });\n                }\n            });\n        });\n    });\n    // remove links without any matches\n    correlations.forEach((correlation) => {\n        const linksToRemove = correlation.link.filter((link) => {\n            var _a;\n            return link.match.length === 0 &&\n                link.experimentType !== '1d' &&\n                !((_a = link.edited) === null || _a === void 0 ? void 0 : _a.moved);\n        });\n        linksToRemove.forEach((link) => removeLink(correlation, link.id));\n    });\n    return correlations;\n}\n//# sourceMappingURL=setMatches.js.map","import { getCorrelationDelta } from '../general/getCorrelationDelta';\nimport { getCorrelationsByAtomType } from '../general/getCorrelationsByAtomType';\n/**\n * Sorts the correlations according to its atom type value and signal delta.\n *\n * @param {Values} values\n */\nexport function sortCorrelations(correlations) {\n    const compareAtomTypes = (atomType1, atomType2) => {\n        // C and H highest priority\n        if (atomType1 === 'C') {\n            return -1;\n        }\n        if (atomType2 === 'C') {\n            return 1;\n        }\n        if (atomType1 === 'H') {\n            return -1;\n        }\n        if (atomType2 === 'H') {\n            return 1;\n        }\n        // alphabetical sort\n        if (atomType1 < atomType2) {\n            return -1;\n        }\n        if (atomType1 > atomType2) {\n            return 1;\n        }\n        return 0;\n    };\n    const compareCorrelations = (corr1, corr2) => {\n        if (!corr1.pseudo &&\n            !corr2.pseudo &&\n            corr1.link.length > 0 &&\n            corr2.link.length > 0) {\n            const corr1Delta = getCorrelationDelta(corr1);\n            const corr2Delta = getCorrelationDelta(corr2);\n            if (corr1Delta !== undefined && corr2Delta !== undefined) {\n                if (corr1Delta < corr2Delta) {\n                    return -1;\n                }\n                else if (corr1Delta > corr2Delta) {\n                    return 1;\n                }\n            }\n        }\n        if (!corr1.pseudo && corr2.pseudo) {\n            return -1;\n        }\n        if (corr1.pseudo && !corr2.pseudo) {\n            return 1;\n        }\n        if (corr1.label.origin < corr2.label.origin) {\n            return -1;\n        }\n        if (corr1.label.origin > corr2.label.origin) {\n            return 1;\n        }\n        return 0;\n    };\n    let sortedCorrelations = [];\n    const atomTypes = correlations\n        .map((correlation) => correlation.atomType)\n        .filter((atomType, i, a) => a.indexOf(atomType) === i);\n    atomTypes.sort(compareAtomTypes);\n    atomTypes.forEach((atomType) => {\n        const correlationsAtomType = getCorrelationsByAtomType(correlations, atomType);\n        correlationsAtomType.sort(compareCorrelations);\n        sortedCorrelations = sortedCorrelations.concat(correlationsAtomType);\n    });\n    return sortedCorrelations;\n}\n//# sourceMappingURL=sortCorrelations.js.map","import { setProtonsCountFromData } from '../protonsCount/setProtonsCountFromData';\nimport { getSignals } from '../signals/getSignals';\nimport { addFromData } from './addFromData';\nimport { updatePseudoCorrelations } from './pseudo/updatePseudoCorrelations';\nimport { removeObsoleteLinksAndNotLinkedCorrelations } from './removeObsoleteLinksAndNotLinkedCorrelations';\nimport { setAttachmentsAndProtonEquivalences } from './setAttachmentsAndProtonEquivalences';\nimport { setLabels } from './setLabels';\nimport { setMatches } from './setMatches';\nimport { sortCorrelations } from './sortCorrelations';\n/**\n * Builds the correlation data values from given input spectra and options.\n * @param {Spectra} spectra\n * @param {Options} options\n */\nexport function buildValues(spectra, options) {\n    const { tolerance = {}, mf = '', values: prevValues = [] } = options;\n    const signals = getSignals(spectra);\n    let _correlations = prevValues ? prevValues.slice() : [];\n    if (options.skipDataUpdate !== true) {\n        // remove obsolete links/correlations\n        _correlations = removeObsoleteLinksAndNotLinkedCorrelations(_correlations, signals.signals1D, signals.signals2D);\n        // add signals from either 1D or 2D if not already existing as correlation\n        // if a signal already exists then add a link within matched correlation\n        _correlations = addFromData(_correlations, signals.signals1D, signals.signals2D, tolerance);\n    }\n    else {\n        // in case an external movement has led to en empty link array within a correlation\n        _correlations = _correlations.filter((correlation) => correlation.link.length > 0 || correlation.pseudo);\n    }\n    // set the number of attached protons via DEPT or edited HSQC\n    _correlations = setProtonsCountFromData(_correlations, signals.signalsDEPT, signals.signals2D, tolerance);\n    // sort by atom type and shift value\n    _correlations = sortCorrelations(_correlations);\n    // link signals via matches to same 2D signal: e.g. 13C -> HSQC <- 1H\n    setMatches(_correlations);\n    // set attachments via HSQC or HMQC\n    setAttachmentsAndProtonEquivalences(_correlations);\n    // update pseudo correlation\n    _correlations = updatePseudoCorrelations(_correlations, mf);\n    // set labels\n    setLabels(_correlations);\n    return _correlations;\n}\n//# sourceMappingURL=buildValues.js.map","import { buildState } from '../utilities/build/buildState';\nimport { buildValues } from '../utilities/build/buildValues';\n/**\n * Builds the correlation data from spectra data and some options.\n *\n * @param {Spectra} spectra\n * @param {Options} options\n */\nexport function buildCorrelationData(spectra, options) {\n    const values = spectra ? buildValues(spectra, options) : [];\n    delete options.values;\n    delete options.skipDataUpdate;\n    return {\n        values,\n        options,\n        state: buildState(values, options.mf || ''),\n    };\n}\n//# sourceMappingURL=buildCorrelationData.js.map","/**\n * Adds a link to a correlation.\n *\n * @param {Correlation} correlation\n * @param {Link} link\n */\nexport function addLink(correlation, link) {\n    correlation.link.push(link);\n    return correlation;\n}\n//# sourceMappingURL=addLink.js.map","import { getCorrelationDelta } from 'nmr-correlation';\nexport function createMapPossibleAssignment(expandMap, props) {\n    const { restrictionByCS, predictions, targets } = props;\n    const { tolerance: toleranceCS, chemicalShiftRestriction } = restrictionByCS;\n    const atomTypes = Object.keys(predictions);\n    for (const atomType of atomTypes) {\n        let errorAbs = toleranceCS[atomType];\n        let predictionByAtomType = predictions[atomType];\n        let targetByAtomType = targets[atomType];\n        if (!expandMap[atomType])\n            expandMap[atomType] = {};\n        for (const diaID in predictionByAtomType) {\n            let prediction = predictionByAtomType[diaID];\n            expandMap[atomType][diaID] = [];\n            if (targetByAtomType) {\n                for (const targetID in targetByAtomType) {\n                    let target = targetByAtomType[targetID];\n                    const { nbAtoms, protonsCount: protonsCountFromPrediction } = prediction;\n                    const { integration, protonsCount } = target;\n                    const couldBeAssigned = !integration\n                        ? true\n                        : atomType === 'H'\n                            ? nbAtoms - integration < 1\n                            : protonsCount.length > 0\n                                ? protonsCount.some((count) => protonsCountFromPrediction === count)\n                                : true;\n                    if (couldBeAssigned) {\n                        if (!chemicalShiftRestriction ||\n                            typeof prediction.delta === 'undefined') {\n                            // Chemical shift is not a restriction\n                            expandMap[atomType][diaID].push(targetID);\n                        }\n                        else {\n                            let targetDelta = getCorrelationDelta(target);\n                            if (targetDelta === undefined) {\n                                throw new Error(`Correlation has not delta`);\n                            }\n                            let distAfterLimit = Math.abs(prediction.delta - targetDelta - errorAbs);\n                            if (distAfterLimit < 4 * errorAbs) {\n                                expandMap[atomType][diaID].push(targetID);\n                            }\n                        }\n                    }\n                }\n            }\n            expandMap[atomType][diaID].push('*');\n        }\n    }\n    return expandMap;\n}\n//# sourceMappingURL=createMapPossibleAssignment.js.map","function groupCarbonTargetByIntegrationZone(activeDomainOnTarget, targets, correlations) {\n    let targetID = activeDomainOnTarget[0];\n    let { H: attachments = [] } = targets[targetID].attachment;\n    let targetByIntegral = [\n        { targetIDs: [targetID], attachments: new Set(attachments) },\n    ];\n    for (let i = 1; i < activeDomainOnTarget.length; i++) {\n        let targetID = activeDomainOnTarget[i];\n        let target = targets[targetID];\n        let { H: attachments = [] } = target.attachment;\n        let alone = true;\n        for (let group of targetByIntegral) {\n            const pertain = attachments.some((attachment) => group.attachments.has(attachment));\n            if (pertain) {\n                alone = false;\n                group.targetIDs.push(targetID);\n                for (let attachment of attachments) {\n                    group.attachments.add(attachment);\n                }\n                break;\n            }\n        }\n        if (alone) {\n            targetByIntegral.push({\n                targetIDs: [targetID],\n                attachments: new Set(attachments),\n            });\n        }\n    }\n    return targetByIntegral.map((t) => ({\n        atomType: 'C',\n        targetIDs: t.targetIDs,\n        integration: correlations\n            ? Array.from(t.attachments).reduce((sum, index) => {\n                return correlations[index].integration + sum;\n            }, 0)\n            : 0,\n    }));\n}\nexport default groupCarbonTargetByIntegrationZone;\n//# sourceMappingURL=groupCarbonTargetByIntegrationZone.js.map","import { getCorrelationDelta } from 'nmr-correlation';\nimport groupCarbonTargetByIntegrationZone from './groupCarbonTargetByIntegrationZone';\nexport function partialScore(partial, props) {\n    const { diaIDPeerPossibleAssignment, infoByAtomTypes, restrictionByCS, predictions, targets, correlations, } = props;\n    const { tolerance: toleranceCS, useChemicalShiftScore } = restrictionByCS;\n    let totalStarts = 0;\n    let totalPartial = 0;\n    let partialInverse = {};\n    let activeDomainOnPrediction = {};\n    const atomTypes = Object.keys(partial);\n    for (const atomType of atomTypes) {\n        let countStars = 0;\n        const { nbAllowedUnAssigned } = infoByAtomTypes[atomType];\n        const currentPartialInverse = {};\n        const partialAssignment = partial[atomType] || [];\n        partialInverse[atomType] = currentPartialInverse;\n        activeDomainOnPrediction[atomType] = [];\n        totalPartial += partialAssignment.length;\n        for (let i = 0; i < partialAssignment.length; i++) {\n            const targetID = partialAssignment[i];\n            if (targetID && targetID !== '*') {\n                activeDomainOnPrediction[atomType].push(i);\n                if (!currentPartialInverse[targetID]) {\n                    currentPartialInverse[targetID] = [];\n                }\n                currentPartialInverse[targetID].push(diaIDPeerPossibleAssignment[atomType][i]);\n            }\n            if (targetID === '*')\n                countStars++;\n        }\n        if (countStars > nbAllowedUnAssigned)\n            return 0;\n        totalStarts += countStars;\n    }\n    const activeDomainOnTarget = {};\n    for (const atomType in partialInverse) {\n        activeDomainOnTarget[atomType] = Object.keys(partialInverse[atomType]);\n    }\n    const valuesActiveDomainOnTarget = Object.values(activeDomainOnTarget);\n    if (valuesActiveDomainOnTarget.reduce((sum, e) => (e.length === 0 ? sum + 1 : sum), 0) === valuesActiveDomainOnTarget.length) {\n        return 0;\n    }\n    const getPredictionByDiaID = getPrediction.bind({}, predictions);\n    // check the integration\n    const targetByIntegral = [];\n    for (const atomType in partial) {\n        if (atomType === 'C' && activeDomainOnTarget[atomType].length > 0) {\n            targetByIntegral.push(...groupCarbonTargetByIntegrationZone(activeDomainOnTarget[atomType], targets[atomType], correlations));\n        }\n        else {\n            for (let targetID of activeDomainOnTarget[atomType]) {\n                targetByIntegral.push({\n                    atomType,\n                    targetIDs: [targetID],\n                    integration: targets.H[targetID].integration,\n                });\n            }\n        }\n    }\n    for (const group of targetByIntegral) {\n        const { integration, atomType } = group;\n        if (integration === undefined || isNaN(integration))\n            continue;\n        let total = 0;\n        for (let targetID of group.targetIDs) {\n            let targetToSource = partialInverse[atomType][targetID];\n            for (const diaID of targetToSource) {\n                const { prediction, atomType: atomOfPrediction } = getPredictionByDiaID(diaID);\n                if (atomType === atomOfPrediction)\n                    total += prediction.allHydrogens;\n            }\n        }\n        if (total - integration >= 5) {\n            return 0;\n        }\n    }\n    //chemical shift score\n    let count = 1;\n    let chemicalShiftScore = 1;\n    if (useChemicalShiftScore) {\n        chemicalShiftScore = 0;\n        count = 0;\n        for (const atomType of Object.keys(partial)) {\n            const partialPeerAtomType = partial[atomType];\n            const targetsPeerAtomType = targets[atomType];\n            for (let index = 0; index < partialPeerAtomType.length; index++) {\n                const targetID = partialPeerAtomType[index];\n                if (targetID && targetID !== '*') {\n                    count++;\n                    let diaID = diaIDPeerPossibleAssignment[atomType][index];\n                    let source = predictions[atomType][diaID];\n                    let target = targetsPeerAtomType[targetID];\n                    let error = toleranceCS[atomType];\n                    // if (source.error) {\n                    //   error = Math.max(source.error, toleranceCS);\n                    // }\n                    if (typeof source.delta === 'undefined') {\n                        // Chemical shift is not a restriction\n                        chemicalShiftScore += 1;\n                    }\n                    else {\n                        const targetDelta = getCorrelationDelta(target);\n                        if (targetDelta === undefined) {\n                            throw new Error('correlation has not delta');\n                        }\n                        let diff = Math.abs(source.delta - targetDelta);\n                        if (diff < error) {\n                            //@TODO: check for a better discriminant\n                            chemicalShiftScore += 1;\n                        }\n                        else {\n                            diff = Math.abs(diff - error);\n                            chemicalShiftScore += (-0.25 / error) * diff + 1;\n                        }\n                    }\n                }\n            }\n        }\n        if (count > 0) {\n            chemicalShiftScore /= count;\n        }\n    }\n    let scoreOn2D = 0;\n    if (howManyActived(activeDomainOnTarget) > 1) {\n        let andConstrains = {};\n        let activeDomain = [];\n        for (const atomType of Object.keys(activeDomainOnPrediction)) {\n            activeDomain = activeDomain.concat(activeDomainOnPrediction[atomType].map((e) => ({ index: e, atomType })));\n        }\n        for (let i = 0; i < activeDomain.length; i++) {\n            const { atomType: atomTypeI, index: indexI } = activeDomain[i];\n            const predictionI = predictions[atomTypeI][diaIDPeerPossibleAssignment[atomTypeI][indexI]];\n            for (let j = i + 1; j < activeDomain.length; j++) {\n                const { atomType: atomTypeJ, index: indexJ } = activeDomain[j];\n                const predictionJ = predictions[atomTypeJ][diaIDPeerPossibleAssignment[atomTypeJ][indexJ]];\n                let pathLength = predictionI.pathLength[predictionJ.diaIDIndex];\n                let isPossible = pathLength < 5;\n                let partialI = partial[atomTypeI][indexI];\n                let partialJ = partial[atomTypeJ][indexJ];\n                if (!partialI || !partialJ)\n                    continue;\n                let keyOnTargertMap = partialI > partialJ\n                    ? `${partialJ} ${partialI}`\n                    : `${partialI} ${partialJ}`;\n                let areLinked = checkLinking({\n                    from: {\n                        targetID: partialI,\n                        atomType: atomTypeI,\n                    },\n                    to: {\n                        targetID: partialJ,\n                        atomType: atomTypeJ,\n                    },\n                }, targets);\n                let partialScore2D = isPossible\n                    ? areLinked\n                        ? 1\n                        : 0\n                    : !areLinked\n                        ? 1\n                        : 0;\n                andConstrains[keyOnTargertMap] = andConstrains[keyOnTargertMap]\n                    ? Math.max(andConstrains[keyOnTargertMap], partialScore2D)\n                    : partialScore2D;\n            }\n        }\n        let sumAnd = 0;\n        for (let key in andConstrains) {\n            sumAnd += andConstrains[key];\n        }\n        scoreOn2D =\n            sumAnd / ((activeDomain.length * (activeDomain.length - 1)) / 2);\n    }\n    const penaltyByStarts = totalStarts / totalPartial;\n    if (chemicalShiftScore === 0)\n        return scoreOn2D - penaltyByStarts;\n    if (scoreOn2D === 0)\n        return chemicalShiftScore - penaltyByStarts;\n    return (chemicalShiftScore + scoreOn2D) / 2 - penaltyByStarts;\n}\nfunction checkLinking(partials, correlations) {\n    const { from, to } = partials;\n    if (from.targetID === to.targetID)\n        return true;\n    let correlationI = correlations[from.atomType][from.targetID];\n    let correlationJ = correlations[to.atomType][to.targetID];\n    for (const linkJ of correlationJ.link) {\n        for (const link of correlationI.link) {\n            if (link.signal.id === linkJ.signal.id)\n                return true;\n        }\n    }\n    return false;\n}\nfunction getPrediction(predictions, diaID) {\n    const atomTypes = Object.keys(predictions);\n    for (const atomType of atomTypes) {\n        const predictionByAtomType = predictions[atomType];\n        if (!predictionByAtomType)\n            throw new Error(`prediction by ${atomType}`);\n        if (predictionByAtomType[diaID]) {\n            return { atomType, prediction: predictionByAtomType[diaID] };\n        }\n    }\n    throw new Error(`There is not prediction for ${diaID}`);\n}\nfunction howManyActived(actived) {\n    let sum = 0;\n    for (const atom in actived) {\n        sum += actived[atom].length;\n    }\n    return sum;\n}\n//# sourceMappingURL=partialScore.js.map","import { partialScore } from './partialScore';\nexport function exploreTree(props, infoByAtomTypes, partial, store) {\n    const { currentAtomTypes, restrictionByCS, timeout, timeStart, maxSolutions, targets, predictions, correlations, lowerBoundScore, possibleAssignmentMap, diaIDPeerPossibleAssignment, } = props;\n    const currentDate = new Date();\n    if (currentDate.getTime() - timeStart > timeout) {\n        new Error('timeout expired');\n        return store;\n    }\n    for (const atomType of currentAtomTypes) {\n        const { currentIndex, nSources } = infoByAtomTypes[atomType];\n        if (currentIndex >= nSources - 1 &&\n            partial[atomType][currentIndex] !== null) {\n            continue;\n        }\n        const diaID = diaIDPeerPossibleAssignment[atomType][currentIndex];\n        const possibleAssignments = possibleAssignmentMap[atomType][diaID];\n        for (let targetID of possibleAssignments) {\n            partial[atomType][currentIndex] = targetID;\n            let score = partialScore(partial, {\n                diaIDPeerPossibleAssignment,\n                infoByAtomTypes,\n                restrictionByCS,\n                predictions,\n                correlations,\n                targets,\n            });\n            if (score === 0) {\n                continue;\n            }\n            if (isLastOne(currentAtomTypes, infoByAtomTypes) &&\n                score >= lowerBoundScore) {\n                addSolution(store, { predictions, partial, score, maxSolutions });\n            }\n            else {\n                const newInfo = JSON.parse(JSON.stringify(infoByAtomTypes));\n                newInfo[atomType].currentIndex += 1;\n                exploreTree({\n                    currentAtomTypes,\n                    restrictionByCS,\n                    timeout,\n                    timeStart,\n                    maxSolutions,\n                    targets,\n                    predictions,\n                    correlations,\n                    lowerBoundScore,\n                    possibleAssignmentMap,\n                    diaIDPeerPossibleAssignment,\n                }, newInfo, JSON.parse(JSON.stringify(partial)), store);\n            }\n        }\n    }\n}\nfunction addSolution(store, props) {\n    let { score, maxSolutions, partial, predictions } = props;\n    score /= doubleAssignmentPenalty(partial, predictions);\n    let solution = {\n        assignment: JSON.parse(JSON.stringify(partial)),\n        score,\n    };\n    if (store.nSolutions >= maxSolutions) {\n        if (solution.score > store.solutions.last().score) {\n            store.solutions.pollLast();\n            store.solutions.add(solution);\n        }\n    }\n    else {\n        store.solutions.add(solution);\n        store.nSolutions++;\n    }\n}\nfunction isLastOne(currentAtomTypes, infoByAtomTypes) {\n    let lastOne = true;\n    for (const atomType of currentAtomTypes) {\n        const { currentIndex, nSources } = infoByAtomTypes[atomType];\n        lastOne = lastOne && currentIndex >= nSources - 1;\n    }\n    return lastOne;\n}\nfunction doubleAssignmentPenalty(partial, predictions) {\n    let nbDoubleAssignment = 0;\n    for (const atomType in predictions) {\n        const nbSources = Object.keys(predictions[atomType]).length;\n        let assignments = new Set(partial[atomType]);\n        nbDoubleAssignment += nbSources - assignments.size;\n    }\n    return nbDoubleAssignment > 0 ? 2 * nbDoubleAssignment : 1;\n}\n//# sourceMappingURL=exploreTree.js.map","export function isSpectraData1D(spectrum) {\n    return 'ranges' in spectrum;\n}\n//# sourceMappingURL=isSpectraData1D.js.map","import { isSpectraData1D } from './isSpectraData1D';\nexport function searchIndices(signalId, spectra) {\n    for (let spectrumIndex = 0; spectrumIndex < spectra.length; spectrumIndex++) {\n        const spectrum = spectra[spectrumIndex];\n        const data = isSpectraData1D(spectrum) ? spectrum.ranges : spectrum.zones;\n        for (let elementIndex = 0; elementIndex < data.length; elementIndex++) {\n            const signals = data[elementIndex].signals || [];\n            for (let signalIndex = 0; signalIndex < signals.length; signalIndex++) {\n                if (signalId === signals[signalIndex].id) {\n                    return { spectrumIndex, signalIndex, elementIndex };\n                }\n            }\n        }\n    }\n    throw new Error(`There is not a signal with ${signalId} ID`);\n}\n//# sourceMappingURL=searchIndices.js.map","import TreeSet from 'ml-tree-set';\nimport { getConnectivityMatrix } from 'openchemlib-utils';\nimport { predictCarbon } from '../../../prediction/predictCarbon';\nimport { predictProton } from '../../../prediction/predictProton';\nimport { createMapPossibleAssignment, } from './createMapPossibleAssignment';\nimport { exploreTree } from './exploreTree';\nimport { isSpectraData1D } from './isSpectraData1D';\nimport { searchIndices } from './searchIndices';\nconst comparator = (a, b) => {\n    return b.score - a.score;\n};\nconst predictor = { H: predictProton, C: predictCarbon };\nfunction checkNMRSignal1D(signals) {\n    const keys = [\n        'nbAtoms',\n        'diaIDs',\n        'atoms',\n    ];\n    for (const signal of signals) {\n        for (let key of keys) {\n            if (!signal[key])\n                throw new Error(`property ${key} does not exist`);\n        }\n    }\n}\nexport const getAllHydrogens = {\n    C: (m, i) => m.getAllHydrogens(i),\n    H: () => 1,\n};\nexport async function buildAssignments(props) {\n    const { spectra, molecule, restrictionByCS, timeout, minScore, nbAllowedUnAssigned = {}, maxSolutions, correlations, assignmentOrder, predictionOptions, predictions: inputPrediction = {}, targets, } = props;\n    let date = new Date();\n    let timeStart = date.getTime();\n    let lowerBoundScore = minScore;\n    let store = {\n        solutions: new TreeSet(comparator),\n        nSolutions: 0,\n    };\n    const pathLengthMatrix = getConnectivityMatrix(molecule, {\n        pathLength: true,\n    });\n    let infoByAtomType = {};\n    const predictions = {};\n    let possibleAssignmentMap = {};\n    let diaIDPeerPossibleAssignment = {};\n    for (const atomTypesToPredict of assignmentOrder) {\n        for (const atomType of atomTypesToPredict) {\n            const options = predictionOptions[atomType];\n            const predictedSignals = inputPrediction[atomType];\n            let { joinedSignals } = predictedSignals\n                ? { joinedSignals: predictedSignals }\n                : await predictor[atomType](molecule, options);\n            checkNMRSignal1D(joinedSignals);\n            if (!predictions[atomType])\n                predictions[atomType] = {};\n            let totalHydrogens = 0;\n            for (let prediction of joinedSignals) {\n                const diaID = prediction.diaIDs[0];\n                const index = prediction.atoms[0];\n                const allHydrogens = getAllHydrogens[atomType](molecule, index);\n                totalHydrogens += prediction.nbAtoms * allHydrogens;\n                predictions[atomType][diaID] = {\n                    ...prediction,\n                    diaIDIndex: index,\n                    allHydrogens: prediction.nbAtoms * allHydrogens,\n                    protonsCount: allHydrogens,\n                    pathLength: pathLengthMatrix[index],\n                };\n            }\n            for (let diaID in predictions[atomType]) {\n                predictions[atomType][diaID].allHydrogens *= 100 / totalHydrogens;\n            }\n            infoByAtomType[atomType] = {\n                nSources: joinedSignals.length,\n                currentIndex: 0,\n                nbAllowedUnAssigned: nbAllowedUnAssigned[atomType] || 0,\n            };\n        }\n        possibleAssignmentMap = createMapPossibleAssignment(possibleAssignmentMap, {\n            restrictionByCS,\n            predictions,\n            targets,\n        });\n        diaIDPeerPossibleAssignment = {};\n        for (const atomType in possibleAssignmentMap) {\n            diaIDPeerPossibleAssignment[atomType] = Object.keys(possibleAssignmentMap[atomType]);\n        }\n        let sourceOfPartials = getSourceOfPartials(store, infoByAtomType, atomTypesToPredict);\n        store = {\n            solutions: new TreeSet(comparator),\n            nSolutions: 0,\n        };\n        for (let partial of sourceOfPartials) {\n            exploreTree({\n                currentAtomTypes: atomTypesToPredict,\n                restrictionByCS,\n                timeout,\n                timeStart,\n                targets,\n                predictions,\n                correlations,\n                maxSolutions,\n                lowerBoundScore,\n                possibleAssignmentMap,\n                diaIDPeerPossibleAssignment,\n            }, infoByAtomType, partial, store);\n        }\n    }\n    return annotateSpectraData({\n        store,\n        spectra,\n        diaIDPeerPossibleAssignment,\n        targets,\n    });\n}\nfunction annotateSpectraData(input) {\n    var _a;\n    const { store, spectra, diaIDPeerPossibleAssignment, targets } = input;\n    const { solutions } = store;\n    const mapSignalId = {};\n    const atomTypes = Object.keys(targets);\n    for (const atomType of atomTypes) {\n        const targetByAtomType = targets[atomType];\n        for (const targetId in targetByAtomType) {\n            let target = targetByAtomType[targetId];\n            for (const link of target.link) {\n                const signalId = link.signal.id;\n                if (mapSignalId[signalId])\n                    continue;\n                mapSignalId[link.signal.id] = searchIndices(signalId, spectra);\n            }\n        }\n    }\n    const result = [];\n    for (let solution of solutions.elements) {\n        const spectraResult = JSON.parse(JSON.stringify(spectra));\n        const { assignment, score } = solution;\n        const atomTypes = Object.keys(assignment);\n        for (const atomType of atomTypes) {\n            const targetByAtomType = targets[atomType];\n            const assignmentPeerAtomType = assignment[atomType];\n            for (let index = 0; index < assignmentPeerAtomType.length; index++) {\n                const targetID = assignmentPeerAtomType[index];\n                if (targetID === '*' || !targetID)\n                    continue;\n                const target = targetByAtomType[targetID];\n                const diaId = diaIDPeerPossibleAssignment[atomType][index];\n                for (let link of target.link) {\n                    const { spectrumIndex, elementIndex, signalIndex } = mapSignalId[link.signal.id];\n                    const spectrum = spectraResult[spectrumIndex];\n                    if (isSpectraData1D(spectrum)) {\n                        let { ranges } = spectrum;\n                        let range = ranges[elementIndex];\n                        let signal = range.signals[signalIndex];\n                        if (!signal.diaIDs)\n                            signal.diaIDs = [];\n                        signal.diaIDs.push(diaId);\n                    }\n                    else {\n                        const axis = link.axis;\n                        const signal = spectrum.zones[elementIndex].signals[signalIndex];\n                        if (!signal[axis].diaIDs)\n                            signal[axis].diaIDs = [];\n                        (_a = signal[axis].diaIDs) === null || _a === void 0 ? void 0 : _a.push(diaId);\n                    }\n                }\n            }\n        }\n        result.push({\n            score,\n            assignment: spectraResult,\n        });\n    }\n    return result;\n}\nfunction getSourceOfPartials(store, infoByAtomType, currentAtoms) {\n    return store.nSolutions > 0\n        ? store.solutions.elements.map((e) => {\n            let currentAssignment = e.assignment;\n            for (const atom of currentAtoms) {\n                currentAssignment[atom] = fillPartial(infoByAtomType[atom].nSources);\n            }\n            return currentAssignment;\n        })\n        : initializePartials(infoByAtomType, currentAtoms);\n}\nfunction initializePartials(infoByAtomType, currentAtoms) {\n    const partial = {};\n    const atomsType = Object.keys(infoByAtomType);\n    for (const atom of atomsType) {\n        const value = currentAtoms.includes(atom) ? null : '*';\n        partial[atom] = fillPartial(infoByAtomType[atom].nSources, value);\n    }\n    return [partial];\n}\nfunction fillPartial(nSources, value = null) {\n    const partial = new Array(nSources);\n    for (let i = 0; i < nSources; i++) {\n        partial[i] = value;\n    }\n    return partial;\n}\n//# sourceMappingURL=buildAssignments.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport { isSpectraData1D } from './isSpectraData1D';\nexport function checkIDs(input = []) {\n    let inputClone = JSON.parse(JSON.stringify(input));\n    let spectra = [];\n    for (const spectraData of inputClone) {\n        if (!('info' in spectraData)) {\n            throw new Error('each spectrum should contain info properties with nucleus information');\n        }\n        const { info, id } = spectraData;\n        if (isSpectraData1D(spectraData)) {\n            let ranges = addIDs(spectraData.ranges);\n            spectra.push({ id, info, ranges });\n        }\n        else {\n            let data = addIDs(spectraData.zones);\n            spectra.push({ id, info, zones: data });\n        }\n    }\n    return spectra;\n}\nexport function hasIDs(data) {\n    for (const element of data) {\n        if (!element.id)\n            throw new Error('A range/zone has not an ID');\n        for (let signal of element.signals || []) {\n            if (!signal.id)\n                throw new Error('A signal has not an ID');\n        }\n    }\n}\nexport function addIDs(data) {\n    for (const element of data) {\n        if (!element.id)\n            element.id = generateID();\n        for (let signal of element.signals || []) {\n            if (!signal.id)\n                signal.id = generateID();\n        }\n    }\n    hasIDs(data);\n    return data;\n}\n//# sourceMappingURL=checkIDs.js.map","import { isSpectraData1D } from './isSpectraData1D';\nexport function formatData(input = []) {\n    let inputClone = JSON.parse(JSON.stringify(input));\n    let spectra = [];\n    for (const spectraData of inputClone) {\n        const { id, info } = spectraData;\n        if (isSpectraData1D(spectraData)) {\n            const ranges = rescaleIntegration({\n                id,\n                info,\n                ranges: spectraData.ranges,\n            });\n            spectra.push({ id, info, ranges: { values: ranges } });\n        }\n        else {\n            spectra.push({ id, info, zones: { values: spectraData.zones } });\n        }\n    }\n    return spectra;\n}\nfunction rescaleIntegration(spectrum) {\n    if (spectrum.info.nucleus !== '1H')\n        return spectrum.ranges;\n    let totalIntegration = spectrum.ranges.reduce((total, range) => (range.integration ? total + range.integration : total), 0);\n    for (let range of spectrum.ranges) {\n        if (range.integration) {\n            range.integration *= 100 / totalIntegration;\n            if (range.signals) {\n                const totalSignalIntegration = range.signals.reduce((total, signal) => signal.integration ? total + signal.integration : total, 0);\n                for (let signal of range.signals) {\n                    if (signal.integration) {\n                        signal.integration *= range.integration / totalSignalIntegration;\n                    }\n                    else {\n                        signal.integration = range.integration;\n                    }\n                }\n            }\n        }\n    }\n    return spectrum.ranges;\n}\n//# sourceMappingURL=formatData.js.map","export function getIntegrationOfAttachedProtons(target, correlations) {\n    const { H: attachment = [] } = target.attachment;\n    let integration = 0;\n    for (const match of attachment) {\n        const correlation = correlations[match];\n        integration += Number(correlation.link[0].signal.integration);\n    }\n    return integration;\n}\n//# sourceMappingURL=getIntegrationOfAttachedProtons.js.map","import { buildCorrelationData } from 'nmr-correlation';\nimport { formatData } from './formatData';\nimport { getIntegrationOfAttachedProtons } from './getIntegrationOfAttachedProtons';\nexport function getTargetsAndCorrelations(spectra, options = {}) {\n    //add indirect links, if a carbon C1 is attached to a proton H1 that correlating\n    //with carbon C2, so the carbon C1 and C2 are also correlating\n    const { tolerance = { C: 0.25, H: 0.05 } } = options;\n    const spectraData = formatData(spectra);\n    const { values: correlations } = buildCorrelationData(spectraData, {\n        tolerance,\n    });\n    let targets = {};\n    for (const correlation of correlations) {\n        if (correlation.pseudo)\n            continue;\n        const { id: targetID, atomType } = correlation;\n        if (!targets[atomType])\n            targets[atomType] = {};\n        targets[atomType][targetID] = correlation;\n        if (atomType === 'H') {\n            targets[atomType][targetID].integration =\n                correlation.link[0].signal.integration;\n        }\n        else {\n            targets[atomType][targetID].integration = getIntegrationOfAttachedProtons(correlation, correlations);\n        }\n    }\n    return {\n        targets,\n        correlations,\n    };\n}\n//# sourceMappingURL=getTargetsAndCorrelations.js.map","/**\n * if hsqc is present in experimentTypes we can just predict 13C\n * spectrum and try to assign the carbons first.\n * @param {*} correlations\n * @param {*} justAssign\n */\nfunction getWorkFlow(correlations, justAssign = []) {\n    const experimentTypes = extractExperimentType(correlations);\n    const { hasHSQC, types } = experimentTypes;\n    if (justAssign.length > 0) {\n        return { assignmentOrder: justAssign, experimentTypes };\n    }\n    const assignmentOrder = [];\n    if (hasHSQC) {\n        assignmentOrder.push(['C'], ['H']);\n    }\n    else {\n        assignmentOrder.push(types.filter((type) => type === 'H' || type === 'C'));\n    }\n    return { assignmentOrder, experimentTypes };\n}\nexport default getWorkFlow;\nfunction extractExperimentType(correlations) {\n    const types = [];\n    for (const correlation of correlations) {\n        let experimentType = correlation.experimentType;\n        if (experimentType === '1d') {\n            experimentType = `${correlation.atomType.toUpperCase()}`;\n        }\n        if (!types.includes(experimentType)) {\n            types.push(experimentType);\n        }\n        for (const link of correlation.link) {\n            experimentType = link.experimentType;\n            if (experimentType === '1d') {\n                experimentType = `${link.atomType[0].toUpperCase()}`;\n            }\n            if (!types.includes(experimentType)) {\n                types.push(experimentType);\n            }\n        }\n    }\n    return {\n        types,\n        hasProton: types.includes('H'),\n        hasCarbon: types.includes('C'),\n        hasHSQC: types.includes('hsqc'),\n    };\n}\n//# sourceMappingURL=getWorkFlow.js.map","import { addDiastereotopicMissingChirality } from 'openchemlib-utils';\nimport { buildAssignments, } from './utils/getAssignment/buildAssignments';\nimport { checkIDs } from './utils/getAssignment/checkIDs';\nimport { getTargetsAndCorrelations } from './utils/getAssignment/getTargetsAndCorrelations';\nimport getWorkFlow from './utils/getAssignment/getWorkFlow';\nexport async function getAssignments(input, options = {}) {\n    let { restrictionByCS = {}, justAssign, minScore = 0.01, maxSolutions = 10, nbAllowedUnAssigned, timeout = 6000, predictionOptions = {}, predictions = {}, correlation: correlationOptions = {}, } = options;\n    const { tolerance = { H: 0.2, C: 1 }, useChemicalShiftScore = false, chemicalShiftRestriction = true, } = restrictionByCS;\n    const molecule = input.molecule;\n    if (!molecule)\n        throw new Error('It is needed a molecule to assign');\n    molecule.addImplicitHydrogens();\n    addDiastereotopicMissingChirality(molecule);\n    const spectra = checkIDs(input.spectra);\n    const { targets, correlations } = getTargetsAndCorrelations(spectra, correlationOptions);\n    const { assignmentOrder } = getWorkFlow(correlations, justAssign);\n    const solutions = await buildAssignments({\n        restrictionByCS: {\n            tolerance,\n            useChemicalShiftScore,\n            chemicalShiftRestriction,\n        },\n        spectra,\n        molecule,\n        timeout,\n        minScore,\n        maxSolutions,\n        assignmentOrder,\n        nbAllowedUnAssigned,\n        correlations,\n        targets,\n        predictionOptions,\n        predictions,\n    });\n    return solutions;\n}\n//# sourceMappingURL=getAssignments.js.map","/**\n * Return\n * @param {*} signal\n */\nexport function signalMultiplicityPattern(signal) {\n    let js = signal.js;\n    let pattern = '';\n    if (js && js.length > 0) {\n        for (let coupling of js) {\n            pattern += coupling.multiplicity;\n        }\n    }\n    else if (signal.delta) {\n        pattern = 's';\n    }\n    else {\n        pattern = 'm';\n    }\n    return pattern;\n}\n//# sourceMappingURL=signalMultiplicityPattern.js.map","import { signalJoinCouplings } from '../signal/signalJoinCouplings';\nimport { signalMultiplicityPattern } from '../signal/signalMultiplicityPattern';\nconst globalOptions = {\n    h: {\n        nucleus: '1H',\n        nbDecimalDelta: 2,\n        nbDecimalJ: 1,\n        observedFrequency: 400,\n    },\n    c: {\n        nucleus: '13C',\n        nbDecimalDelta: 1,\n        nbDecimalJ: 1,\n        observedFrequency: 100,\n    },\n    f: {\n        nucleus: '19F',\n        nbDecimalDelta: 2,\n        nbDecimalJ: 1,\n        observedFrequency: 400,\n    },\n};\nexport function rangesToACS(ranges, options = {}) {\n    if (!options.nucleus)\n        options.nucleus = '1H';\n    const nucleus = options.nucleus.toLowerCase().replace(/[0-9]/g, '');\n    const defaultOptions = globalOptions[nucleus];\n    options = {\n        ...defaultOptions,\n        ascending: false,\n        format: 'IMJA',\n        ...options,\n    };\n    ranges = JSON.parse(JSON.stringify(ranges));\n    if (options.ascending === true) {\n        ranges.sort((a, b) => {\n            const fromA = Math.min(a.from, a.to);\n            const fromB = Math.min(b.from, b.to);\n            return fromA - fromB;\n        });\n    }\n    let acsString = formatAcs(ranges, options);\n    if (acsString.length > 0)\n        acsString += '.';\n    return acsString;\n}\nfunction formatAcs(ranges, options) {\n    let acs = spectroInformation(options);\n    if (acs.length === 0)\n        acs = 'δ ';\n    const acsRanges = [];\n    for (const range of ranges) {\n        if (uselessKind(range.kind, options.filter))\n            continue;\n        pushDelta(range, acsRanges, options);\n    }\n    if (acsRanges.length > 0) {\n        return acs + acsRanges.join(', ');\n    }\n    else {\n        return '';\n    }\n}\nfunction spectroInformation(options) {\n    const parenthesis = [];\n    let strings = `${formatNucleus(options.nucleus)} NMR`;\n    if (options.solvent) {\n        parenthesis.push(formatMF(options.solvent));\n    }\n    if (options.observedFrequency) {\n        parenthesis.push(`${(options.observedFrequency * 1).toFixed(0)} MHz`);\n    }\n    if (parenthesis.length > 0) {\n        strings += ` (${parenthesis.join(', ')}): δ `;\n    }\n    else {\n        strings += ': δ ';\n    }\n    return strings;\n}\nfunction pushDelta(range, acsRanges, options) {\n    let strings = '';\n    let parenthesis = [];\n    const fromTo = [range.from, range.to];\n    if (range.signals) {\n        range.signals = range.signals.filter((signal) => !uselessKind(signal.kind, options.filter));\n    }\n    if (range.signals && range.signals.length > 0) {\n        let signals = range.signals;\n        if (signals.length > 1) {\n            if (options.ascending === true) {\n                signals.sort((a, b) => {\n                    return a.delta - b.delta;\n                });\n            }\n            strings += `${Math.min(...fromTo).toFixed(options.nbDecimalDelta)}-${Math.max(...fromTo).toFixed(options.nbDecimalDelta)}`;\n            strings += ` (${getIntegral(range, options)}`;\n            for (let signal of signals) {\n                parenthesis = [];\n                if (signal.delta !== undefined) {\n                    strings = appendSeparator(strings);\n                    strings += signal.delta.toFixed(options.nbDecimalDelta);\n                }\n                const range = {\n                    from: Number.MIN_SAFE_INTEGER,\n                    to: Number.MAX_SAFE_INTEGER,\n                };\n                switchFormat(range, signal, parenthesis, options);\n                if (parenthesis.length > 0)\n                    strings += ` (${parenthesis.join(', ')})`;\n            }\n            strings += ')';\n        }\n        else {\n            parenthesis = [];\n            if (signals[0].delta !== undefined) {\n                strings += signals[0].delta.toFixed(options.nbDecimalDelta);\n                switchFormat(range, signals[0], parenthesis, options);\n                if (parenthesis.length > 0)\n                    strings += ` (${parenthesis.join(', ')})`;\n            }\n            else {\n                strings += `${Math.min(...fromTo).toFixed(options.nbDecimalDelta)}-${Math.max(...fromTo).toFixed(options.nbDecimalDelta)}`;\n                switchFormat(range, signals[0], parenthesis, options);\n                if (parenthesis.length > 0)\n                    strings += ` (${parenthesis})`;\n            }\n        }\n    }\n    else {\n        strings += `${Math.min(...fromTo).toFixed(options.nbDecimalDelta)}-${Math.max(...fromTo).toFixed(options.nbDecimalDelta)}`;\n        const signal = {};\n        switchFormat(range, signal, parenthesis, options);\n        if (parenthesis.length > 0)\n            strings += ` (${parenthesis.join(', ')})`;\n    }\n    acsRanges.push(strings);\n}\nfunction getIntegral(range, options) {\n    let integration = '';\n    if (range.pubIntegral) {\n        integration = String(range.pubIntegral);\n    }\n    else if (range.integration) {\n        const { nucleus } = options;\n        integration = range.integration.toFixed(0) + nucleus[nucleus.length - 1];\n    }\n    return integration;\n}\nfunction pushIntegral(range, parenthesis, options) {\n    let integration = getIntegral(range, options);\n    if (integration.length > 0)\n        parenthesis.push(integration);\n}\nfunction pushmultiplicityFromSignal(signal, parenthesis) {\n    let multiplicity = signal.multiplicity;\n    if (!multiplicity) {\n        let joinedCouplings = signalJoinCouplings(signal, {\n            tolerance: 0.05,\n            ignoreDiaIDs: true,\n        });\n        multiplicity = signalMultiplicityPattern(joinedCouplings);\n    }\n    if (multiplicity.length > 0)\n        parenthesis.push(multiplicity);\n}\nfunction switchFormat(range, signal, parenthesis, options) {\n    for (const char of options.format) {\n        switch (char.toUpperCase()) {\n            case 'I':\n                pushIntegral(range, parenthesis, options);\n                break;\n            case 'M':\n                pushmultiplicityFromSignal(signal, parenthesis);\n                break;\n            case 'A':\n                pushAssignment(signal, parenthesis);\n                break;\n            case 'J':\n                pushCoupling(signal, parenthesis, options);\n                break;\n            default:\n                throw new Error(`Unknow format letter: ${char}`);\n        }\n    }\n}\nfunction formatMF(mf) {\n    return mf.replace(/(?<num>[0-9]+)/g, '<sub>$<num></sub>');\n}\nfunction formatNucleus(nucleus) {\n    return nucleus.replace(/(?<num>[0-9]+)/g, '<sup>$<num></sup>');\n}\nfunction appendSeparator(strings) {\n    if (strings.length > 0 && !/ $/.exec(strings) && !/\\($/.exec(strings)) {\n        strings += ', ';\n    }\n    return strings;\n}\nfunction formatAssignment(assignment) {\n    assignment = assignment.replace(/(?<num>[0-9]+)/g, '<sub>$<num></sub>');\n    assignment = assignment.replace(/\"(?<i>[^\"]*)\"/g, '<i>$<i></i>');\n    return assignment;\n}\nfunction pushCoupling(signal, parenthesis, options) {\n    if (Array.isArray(signal.js) && signal.js.length > 0) {\n        signal.js.sort((a, b) => {\n            return b.coupling - a.coupling;\n        });\n        let values = [];\n        for (let j of signal.js) {\n            if (j.coupling !== undefined) {\n                values.push(j.coupling.toFixed(options.nbDecimalJ));\n            }\n        }\n        if (values.length > 0) {\n            parenthesis.push(`<i>J</i> = ${values.join(', ')} Hz`);\n        }\n    }\n}\nfunction pushAssignment(signal, parenthesis) {\n    if (signal.assignment) {\n        parenthesis.push(formatAssignment(signal.assignment));\n    }\n}\nfunction uselessKind(kind = '', filter = true) {\n    kind = kind.toLowerCase();\n    if (filter && (kind === 'impurity' || kind === 'solvent'))\n        return true;\n    return false;\n}\n//# sourceMappingURL=rangesToACS.js.map","import { couplingPatterns } from '../constants/couplingPatterns';\nexport function addDummySignals(signals) {\n    let newSignals = JSON.parse(JSON.stringify(signals));\n    let nextAtomToAssign = signals.reduce((nextAtomToAssign, signal) => {\n        const { atoms = [] } = signal;\n        return Math.max(...atoms) > nextAtomToAssign\n            ? Math.max(...atoms)\n            : nextAtomToAssign;\n    }, 0) + 1;\n    signals.forEach((signal, s) => {\n        const { js: jCouplings = [], atoms: signalAssignment = [nextAtomToAssign++], } = signal;\n        let { newCouplings, tempSignals } = checkCouplings(jCouplings, newSignals, signalAssignment, nextAtomToAssign + signals.length);\n        if (tempSignals.length > 0)\n            newSignals.push(...tempSignals);\n        newSignals[s].js = newCouplings;\n        newSignals[s].atoms = signalAssignment;\n    });\n    return newSignals.sort((a, b) => a.delta - b.delta);\n}\nfunction checkCouplings(jCouplings, signals, signalAssignment, nextAtomToAssign) {\n    let tempSignals = [];\n    const newCouplings = jCouplings.reduce((newCouplings, jCoupling) => {\n        const { atoms = [], multiplicity, coupling } = jCoupling;\n        if (atoms.length === 0) {\n            if (coupling && multiplicity) {\n                let tempCouplings = [];\n                const nbLinks = couplingPatterns.indexOf(multiplicity);\n                for (let i = 0; i < nbLinks; i++) {\n                    nextAtomToAssign++;\n                    tempCouplings.push({\n                        coupling,\n                        atoms: [nextAtomToAssign],\n                    });\n                    tempSignals.push(formatSignal(coupling, [nextAtomToAssign], signalAssignment));\n                }\n            }\n            else {\n                newCouplings.push(jCoupling);\n            }\n        }\n        return newCouplings;\n    }, []);\n    return { newCouplings, tempSignals };\n}\nfunction formatSignal(coupling, newSignalAssignment, signalAssignment) {\n    return {\n        delta: 100000,\n        atoms: newSignalAssignment,\n        js: [\n            {\n                coupling,\n                atoms: signalAssignment,\n            },\n        ],\n    };\n}\n//# sourceMappingURL=addDummySignals.js.map","import { addDummySignals } from './addDummySignals';\nimport { signalsToXY } from './signalsToXY';\n/**\n * Create the xy object from an array of 1D signals.\n * @param signals Array of signals with assigned or unassigned couplings.\n */\nexport function hackSignalsToXY(signals, options = {}) {\n    let newSignals = addDummySignals(signals);\n    return signalsToXY(newSignals, options);\n}\n//# sourceMappingURL=hackSignalsToXY.js.map","import { xSequentialFill } from 'ml-spectra-processing';\nimport { SpectrumGenerator } from 'spectrum-generator';\nimport { hackSignalsToXY } from '../signals/hackSignalsToXY';\nfunction checkForSignals(ranges) {\n    for (let range of ranges) {\n        if (!range.signals)\n            throw new Error('range has not signals');\n    }\n}\nconst defaultFromTo = (nucleus = '') => {\n    switch (nucleus.toUpperCase()) {\n        case '13C':\n            return { from: -5, to: 206 };\n        default:\n            return { from: -0.5, to: 10.5 };\n    }\n};\nexport function rangesToXY(ranges, options = {}) {\n    checkForSignals(ranges);\n    let { frequency = 400, lineWidth = 1, nbPoints = 16 * 1024, shape = { kind: 'gaussian' }, } = options;\n    const addSpectrum = (a, b) => {\n        for (let i = 0; i < nbPoints; i++) {\n            a[i] += b[i];\n        }\n    };\n    const { from, to } = getFromTo(ranges, options);\n    const spectrumOptions = {\n        to,\n        from,\n        nbPoints,\n        shape,\n        lineWidth,\n        frequency,\n    };\n    let spectrum = new Float64Array(nbPoints);\n    for (const range of ranges) {\n        const { integration, signals = [] } = range;\n        const { multiplicity: rangeMulplicity = '' } = range;\n        if (rangeMulplicity === 'm' && signals.length < 1) {\n            const { from, to } = range;\n            signals.push({\n                delta: (from + to) / 2,\n                multiplicity: 'm',\n            });\n        }\n        let rangeSpectrum = new Float64Array(nbPoints);\n        for (const signal of signals) {\n            const { multiplicity } = signal;\n            let signalSpectrum = multiplicity === 'm' || multiplicity === 'b' || multiplicity === 'br s'\n                ? broadPeakOrMultipletSpectrum([signal], spectrumOptions).y\n                : hackSignalsToXY([signal], spectrumOptions).y;\n            normalizeSpectrum(signalSpectrum, [signal]);\n            addSpectrum(rangeSpectrum, signalSpectrum);\n        }\n        if (range.integration) {\n            normalizeSpectrum(rangeSpectrum, signals, { integration });\n        }\n        addSpectrum(spectrum, rangeSpectrum);\n    }\n    return {\n        x: xSequentialFill({ from, to, size: nbPoints }),\n        y: spectrum,\n    };\n}\nfunction broadPeakOrMultipletSpectrum(signals, options = {}) {\n    const { lineWidth, frequency } = options;\n    const spectrumGenerator = new SpectrumGenerator(options);\n    const broadWidth = (lineWidth * 3) / frequency;\n    for (let signal of signals) {\n        const { multiplicity, delta, integration = 1 } = signal;\n        if (multiplicity === 'b' || multiplicity === 'br s') {\n            spectrumGenerator.addPeak({\n                x: delta,\n                y: integration,\n                width: broadWidth,\n            });\n        }\n        else {\n            const peaks = peaksOfMultiplet(delta, {\n                lineWidth,\n                frequency,\n            });\n            spectrumGenerator.addPeaks(peaks);\n        }\n    }\n    return spectrumGenerator.getSpectrum();\n}\nfunction peaksOfMultiplet(delta, options) {\n    const { frequency, lineWidth, intensities = [1, 2, 5, 4, 5, 7, 5, 4, 5, 2, 1], } = options;\n    const lineWidthPpm = lineWidth / frequency;\n    const spaceBetweenPeaks = lineWidthPpm * 1.5;\n    const peaks = [];\n    const firstPeakPosition = delta - (spaceBetweenPeaks * intensities.length) / 2;\n    for (let i = 0; i < intensities.length; i++) {\n        peaks.push({\n            x: firstPeakPosition + spaceBetweenPeaks * i,\n            y: intensities[i],\n            width: lineWidthPpm,\n        });\n    }\n    return peaks;\n}\nfunction normalizeSpectrum(spectrum, signals, options = {}) {\n    const { integration = signals.reduce((acc, signal) => {\n        const { integration = 1 } = signal;\n        return acc + integration;\n    }, 0), } = options;\n    const sum = spectrum.reduce((acc, element) => acc + element, 0);\n    if (sum !== 0) {\n        const norma = (integration / sum) * 1e6;\n        for (let i = 0; i < spectrum.length; i++) {\n            spectrum[i] *= norma;\n        }\n    }\n}\nfunction getFromTo(ranges, options) {\n    const { from: defaultFrom, to: defaultTo } = defaultFromTo(options.nucleus);\n    let rangesFrom = Number.MAX_SAFE_INTEGER;\n    let rangesTo = Number.MIN_SAFE_INTEGER;\n    for (const range of ranges) {\n        for (const signal of range.signals || []) {\n            if (rangesFrom > signal.delta)\n                rangesFrom = signal.delta;\n            if (rangesTo < signal.delta)\n                rangesTo = signal.delta;\n        }\n    }\n    const { from = Math.min(rangesFrom - 0.5, defaultFrom), to = Math.max(rangesTo + 0.5, defaultTo), } = options;\n    return { from, to };\n}\n//# sourceMappingURL=rangesToXY.js.map","import direct from 'ml-direct';\nexport function directOptimization(data, sumOfShapes, options) {\n    const { minValues, maxValues, directOptions = {} } = options;\n    const objectiveFunction = getObjectiveFunction(data, sumOfShapes);\n    const result = direct(objectiveFunction, minValues, maxValues, directOptions);\n    const { optima } = result;\n    return {\n        error: result.minFunctionValue,\n        iterations: result.iterations,\n        parameterValues: optima[0],\n    };\n}\nfunction getObjectiveFunction(data, sumOfShapes) {\n    const { x, y } = data;\n    const nbPoints = x.length;\n    return (parameters) => {\n        const fct = sumOfShapes(parameters);\n        let error = 0;\n        for (let i = 0; i < nbPoints; i++) {\n            error += Math.pow(y[i] - fct(x[i]), 2);\n        }\n        return error;\n    };\n}\n//# sourceMappingURL=directOptimization.js.map","export const defaultParameters = {\n    delta: {\n        init: (data) => data.signal.delta,\n        min: (data) => data.signal.delta - data.shape.fwhm * 2,\n        max: (data) => data.signal.delta + data.shape.fwhm * 2,\n        gradientDifference: () => 2e-3,\n    },\n    intensity: {\n        init: (data) => data.signal.intensity || 1,\n        min: () => 0,\n        max: () => 1.5,\n        gradientDifference: () => 1e-3,\n    },\n    fwhm: {\n        init: (data) => data.shape.fwhm,\n        min: (data) => data.shape.fwhm * 0.25,\n        max: (data) => data.shape.fwhm * 4,\n        gradientDifference: (data) => data.shape.fwhm * 2e-3,\n    },\n    mu: {\n        init: (data) => data.shape.mu || 0.5,\n        min: () => 0,\n        max: () => 1,\n        gradientDifference: () => 0.01,\n    },\n    coupling: {\n        init: (data) => data.jCoupling.coupling,\n        min: (data) => data.jCoupling.coupling * 0.8,\n        max: (data) => data.jCoupling.coupling * 1.2,\n        gradientDifference: () => 0.01,\n    },\n};\n//# sourceMappingURL=defaultParameters.js.map","import { addDummySignals } from '../addDummySignals';\nimport { signalsToSpinSystem } from '../simulation/signalsToSpinSystem';\nimport { simulateXYPeaks } from '../simulation/simulateXYPeaks';\nimport { splitSpinSystem } from '../simulation/splitSpinSystem';\nexport function signalsToPointXY(signals, options) {\n    const { frequency, maxClusterSize = 1 } = options;\n    const completeSignalSet = addDummySignals(signals);\n    const spinSystem = signalsToSpinSystem(completeSignalSet);\n    spinSystem.clusters = splitSpinSystem(spinSystem, {\n        frequency,\n        maxClusterSize,\n    });\n    const pointsXY = simulateXYPeaks(spinSystem, options).filter((point) => point.x < 1000);\n    const maxIntensity = pointsXY.reduce((max, peak) => (peak.y > max ? peak.y : max), Number.MIN_SAFE_INTEGER);\n    for (const point of pointsXY) {\n        point.y /= maxIntensity;\n    }\n    return pointsXY;\n}\n//# sourceMappingURL=signalsToPointXY.js.map","import { getShape1D } from 'ml-peak-shape-generator';\nimport { xyFindClosestPoint } from 'ml-spectra-processing';\nimport { defaultParameters } from './defaultParameters';\nimport { signalsToPointXY } from './signalsToPointXY';\nconst properties = ['init', 'min', 'max', 'gradientDifference'];\nexport function getInternalSignals(data, signals, minMaxY, options) {\n    var _a, _b;\n    let index = 0;\n    let internalSignals = [];\n    const { shape: shapeAsOption = { kind: 'gaussian' }, baseline: shiftValue = minMaxY.min, lineWidth = 1, frequency, } = options;\n    const normalizedSignals = normalizeSignals({\n        signals,\n        data,\n        shiftValue,\n        frequency,\n        range: minMaxY.range,\n    });\n    for (const signal of normalizedSignals) {\n        const { shape = { ...shapeAsOption } } = signal;\n        if (!shape.fwhm) {\n            shape.fwhm = lineWidth;\n        }\n        shape.fwhm /= frequency;\n        const shapeFct = getShape1D(shape);\n        const parameters = [\n            'delta',\n            'intensity',\n            ...shapeFct.getParameters(),\n        ];\n        const propertiesValues = {\n            min: [],\n            max: [],\n            init: [],\n            gradientDifference: [],\n        };\n        for (const parameter of parameters) {\n            for (const property of properties) {\n                propertiesValues[property].push(getPropertyValue({\n                    signal,\n                    frequency,\n                    parameter,\n                    property,\n                    minMaxY,\n                    shapeFct,\n                }));\n            }\n        }\n        for (const jCoupling of signal.js || []) {\n            for (const property of properties) {\n                const parameter = 'coupling';\n                let generalParameterValue = (_b = (_a = options === null || options === void 0 ? void 0 : options.parameters) === null || _a === void 0 ? void 0 : _a[parameter]) === null || _b === void 0 ? void 0 : _b[property];\n                if (generalParameterValue) {\n                    if (typeof generalParameterValue === 'number') {\n                        propertiesValues[property].push(getNormalizedValue(generalParameterValue, parameter, property, minMaxY, frequency, options.baseline));\n                    }\n                    else {\n                        let value = generalParameterValue({ jCoupling });\n                        propertiesValues[property].push(getNormalizedValue(value, parameter, property, minMaxY, frequency, options.baseline));\n                    }\n                }\n                if (!defaultParameters[parameter]) {\n                    throw new Error(`No default parameter for ${parameter}`);\n                }\n                const defaultParameterValues = defaultParameters[parameter][property];\n                propertiesValues[property].push(defaultParameterValues({ jCoupling }));\n            }\n        }\n        const fromIndex = index;\n        const toIndex = fromIndex + parameters.length - 1;\n        const fromIndexCoupling = toIndex + 1;\n        const toIndexCoupling = fromIndexCoupling + signal.js.length - 1;\n        index += toIndexCoupling - fromIndex + 1;\n        internalSignals.push({\n            shape: shape,\n            shapeFct,\n            signal,\n            parameters,\n            propertiesValues,\n            fromIndex,\n            toIndex,\n            fromIndexCoupling,\n            toIndexCoupling,\n        });\n    }\n    return internalSignals;\n}\nfunction normalizeSignals(options) {\n    const { signals, data, frequency, shiftValue, range } = options;\n    const getMaxIntensity = (signal) => {\n        const peaks = signalsToPointXY([signal], { frequency, maxClusterSize: 1 });\n        const biggestPeak = peaks.reduce((biggest, peak) => (peak.y > biggest.y ? peak : biggest), peaks[0]);\n        const { y: maxIntensity } = xyFindClosestPoint(data, biggestPeak.x);\n        return maxIntensity;\n    };\n    return signals.map((signal) => {\n        const { intensity = getMaxIntensity(signal) } = signal;\n        return {\n            ...signal,\n            js: signal.js || [],\n            intensity: (intensity - shiftValue) / range,\n        };\n    });\n}\nfunction getPropertyValue(options) {\n    var _a, _b, _c, _d;\n    const { signal, frequency, parameter, property, minMaxY, shapeFct } = options;\n    // check if the property is specified in the signal\n    let propertyValue = (_b = (_a = signal === null || signal === void 0 ? void 0 : signal.parameters) === null || _a === void 0 ? void 0 : _a[parameter]) === null || _b === void 0 ? void 0 : _b[property];\n    if (propertyValue) {\n        return getNormalizedValue(propertyValue, parameter, property, minMaxY, frequency, options.baseline);\n    }\n    // check if there are some global option, it could be a number or a callback\n    let generalParameterValue = (_d = (_c = options === null || options === void 0 ? void 0 : options.parameters) === null || _c === void 0 ? void 0 : _c[parameter]) === null || _d === void 0 ? void 0 : _d[property];\n    if (generalParameterValue) {\n        if (typeof generalParameterValue === 'number') {\n            return getNormalizedValue(generalParameterValue, parameter, property, minMaxY, frequency, options.baseline);\n        }\n        else {\n            let value = generalParameterValue(signal);\n            return getNormalizedValue(value, parameter, property, minMaxY, frequency, options.baseline);\n        }\n    }\n    // we just need to take the default parameters\n    if (!defaultParameters[parameter]) {\n        throw new Error(`No default parameter for ${parameter}`);\n    }\n    const defaultParameterValues = defaultParameters[parameter][property];\n    return defaultParameterValues({ signal, shape: shapeFct });\n}\nfunction getNormalizedValue(value, parameter, property, minMaxY, frequency, baseline) {\n    if (parameter === 'intensity') {\n        if (property === 'gradientDifference') {\n            return value;\n        }\n        else {\n            return baseline !== undefined\n                ? (value - baseline) / minMaxY.range\n                : (value - minMaxY.min) / minMaxY.range;\n        }\n    }\n    else if (parameter === 'fwhm') {\n        return value / frequency;\n    }\n    return value;\n}\n//# sourceMappingURL=getInternalSignals.js.map","import { signalsToPointXY } from './signalsToPointXY';\nconst defaultSimulationOptions = {\n    maxClusterSize: 1,\n};\nexport function getSumOfShapes(internalSignals, options) {\n    const simulationOptions = { ...defaultSimulationOptions, ...options };\n    return function sumOfShapes(parameters) {\n        const peaks = [];\n        for (const internalSignal of internalSignals) {\n            const delta = parameters[internalSignal.fromIndex];\n            const intensity = parameters[internalSignal.fromIndex + 1];\n            for (let i = 2; i < internalSignal.parameters.length; i++) {\n                //@ts-expect-error Not simply to solve the issue\n                internalSignal.shapeFct[internalSignal.parameters[i]] =\n                    parameters[internalSignal.fromIndex + i];\n            }\n            const couplings = internalSignal.signal.js;\n            for (let i = 0; i < couplings.length; i++) {\n                couplings[i].coupling =\n                    parameters[internalSignal.fromIndexCoupling + i];\n            }\n            const currentPeaks = signalsToPointXY([\n                {\n                    delta,\n                    js: couplings,\n                },\n            ], simulationOptions);\n            peaks.push(...currentPeaks.map((peak) => {\n                return { intensity, shape: internalSignal.shapeFct, ...peak };\n            }));\n        }\n        return (currentX) => {\n            let totalY = 0;\n            for (let peak of peaks) {\n                const { x, y, intensity, shape } = peak;\n                totalY += y * intensity * shape.fct(currentX - x);\n            }\n            return totalY;\n        };\n    };\n}\n//# sourceMappingURL=getSumOfShapes.js.map","import { v4 } from '@lukeed/uuid';\nimport { levenbergMarquardt } from 'ml-levenberg-marquardt';\nimport { getShape1D } from 'ml-peak-shape-generator';\nimport { xMinMaxValues } from 'ml-spectra-processing';\nimport { directOptimization } from './optimization/directOptimization';\nimport { getInternalSignals, } from './optimization/getInternalSignals';\nimport { getSumOfShapes } from './optimization/getSumOfShapes';\nimport { signalsToPointXY, } from './optimization/signalsToPointXY';\nconst defaultLMOptimizationOptions = {\n    damping: 1.5,\n    maxIterations: 100,\n    errorTolerance: 1e-8,\n};\nconst defaultDirectOptimizationOptions = {\n    iterations: 25,\n};\nexport function optimizeSignals(data, signals, options) {\n    const { optimization = {}, simulation: simulationOptions, ...restOptions } = options;\n    let temp = xMinMaxValues(data.y);\n    const minMaxY = { ...temp, range: temp.max - temp.min };\n    const internalSignals = getInternalSignals(data, signals, minMaxY, {\n        frequency: simulationOptions.frequency,\n        ...restOptions,\n    });\n    const { baseline: shiftValue = minMaxY.min } = options;\n    let normalizedY = new Float64Array(data.y.length);\n    for (let i = 0; i < data.y.length; i++) {\n        normalizedY[i] = (data.y[i] - shiftValue) / minMaxY.range;\n    }\n    const nbParams = internalSignals[internalSignals.length - 1].toIndexCoupling + 1;\n    const minValues = new Float64Array(nbParams);\n    const maxValues = new Float64Array(nbParams);\n    const initialValues = new Float64Array(nbParams);\n    const gradientDifferences = new Float64Array(nbParams);\n    let index = 0;\n    for (const internalSignal of internalSignals) {\n        for (let i = 0; i < internalSignal.parameters.length; i++) {\n            minValues[index] = internalSignal.propertiesValues.min[i];\n            maxValues[index] = internalSignal.propertiesValues.max[i];\n            initialValues[index] = internalSignal.propertiesValues.init[i];\n            gradientDifferences[index++] =\n                internalSignal.propertiesValues.gradientDifference[i];\n        }\n        for (let i = internalSignal.parameters.length; i < internalSignal.parameters.length + internalSignal.signal.js.length; i++) {\n            minValues[index] = internalSignal.propertiesValues.min[i];\n            maxValues[index] = internalSignal.propertiesValues.max[i];\n            initialValues[index] = internalSignal.propertiesValues.init[i];\n            gradientDifferences[index++] =\n                internalSignal.propertiesValues.gradientDifference[i];\n        }\n    }\n    const sumOfShapes = getSumOfShapes(internalSignals, simulationOptions);\n    const { kind, options: optimizationOptions } = optimization;\n    const [algorithm, defaultOptimizationOptions] = kind === 'direct'\n        ? [directOptimization, defaultDirectOptimizationOptions]\n        : [levenbergMarquardt, defaultLMOptimizationOptions];\n    let fitted = algorithm({ x: data.x, y: normalizedY }, sumOfShapes, {\n        minValues,\n        maxValues,\n        initialValues,\n        gradientDifference: gradientDifferences,\n        ...defaultOptimizationOptions,\n        ...optimizationOptions,\n    });\n    const fittedValues = fitted.parameterValues;\n    const newSignals = [];\n    for (const internalSignal of internalSignals) {\n        const { fromIndexCoupling } = internalSignal;\n        const js = internalSignal.signal.js.map((jCoupling, i) => {\n            jCoupling.coupling = fittedValues[fromIndexCoupling + i];\n            return jCoupling;\n        });\n        const delta = fittedValues[internalSignal.fromIndex];\n        const pointXYs = signalsToPointXY([{ delta, js }], simulationOptions);\n        const intensity = fittedValues[internalSignal.fromIndex + 1] * minMaxY.range + shiftValue;\n        const newPeaks = [];\n        for (const { x, y } of pointXYs) {\n            const peak = {\n                id: v4(),\n                x,\n                y: intensity * y,\n                width: 0,\n                shape: { ...internalSignal.shape },\n            };\n            for (let i = 2; i < internalSignal.parameters.length; i++) {\n                //@ts-expect-error should be fixed once\n                peak.shape[internalSignal.parameters[i]] =\n                    fittedValues[internalSignal.fromIndex + i];\n            }\n            peak.shape.fwhm *= simulationOptions.frequency;\n            peak.width = getShape1D(peak.shape).fwhmToWidth(peak.shape.fwhm);\n            newPeaks.push(peak);\n        }\n        newSignals.push({\n            delta,\n            js,\n            shape: { ...newPeaks[0].shape },\n            intensity,\n            peaks: newPeaks,\n        });\n    }\n    return newSignals;\n}\n//# sourceMappingURL=optimizeSignals.js.map","/**\n * pure function that applies a window function to the input data.\n */\nexport function applyWindow(data, options) {\n    const dataLength = data.length;\n    const { windowData, start = 0, length = dataLength, pointsToShift = 0, output = new Float64Array(data), } = options;\n    const firstEndPoint = Math.min(start + length, dataLength - pointsToShift);\n    for (let i = start, j = 0; i < firstEndPoint; i++) {\n        output[i] *= windowData[j++];\n    }\n    for (let i = dataLength - 1, j = 0; i > dataLength - pointsToShift - 1; i--) {\n        output[i] *= windowData[j++];\n    }\n    return output;\n}\n//# sourceMappingURL=applyWindow.js.map","export function exponential(options) {\n    const { lb, dw } = options;\n    const coefExp = -lb * Math.PI * dw;\n    return (i) => Math.exp(coefExp * i);\n}\n//# sourceMappingURL=exponential.js.map","export function lorentzToGauss(options) {\n    const { dw, length, gaussianHz = 0, exponentialHz = 0, center = 0 } = options;\n    if (center > 1 || center < 0) {\n        throw new Error('The center of gaussian shape should be inside of the window function: 0 - 1');\n    }\n    const C5 = Math.pow(0.6 * Math.PI * gaussianHz * dw, 2);\n    const C2 = center * (length - 1);\n    const C6 = Math.PI * dw * exponentialHz;\n    return (i) => Math.exp(i * C6 - Math.pow(C2 - i, 2) * C5);\n}\n//# sourceMappingURL=lorentzToGauss.js.map","import { exponential } from './shapes/exponential';\nimport { lorentzToGauss } from './shapes/lorentzToGauss';\nexport function getFunction(shape) {\n    const { kind, options } = shape;\n    switch (kind) {\n        case 'exponential':\n            return exponential(options);\n        case 'lorentzToGauss':\n            return lorentzToGauss(options);\n        default:\n            throw Error(`Unknown distribution ${kind}`);\n    }\n}\n//# sourceMappingURL=getFunction.js.map","/**\n * generate and scale the data of a window function\n */\nexport function getData(func, length) {\n    const data = new Float64Array(length);\n    let max = Number.MIN_SAFE_INTEGER;\n    for (let i = 0; i < length; i++) {\n        const value = func(i);\n        data[i] = value;\n        if (value > max)\n            max = value;\n    }\n    for (let i = 0; i < length; i++)\n        data[i] /= max;\n    return data;\n}\n//# sourceMappingURL=getData.js.map","import { applyWindow } from './applyWindow';\nimport { getFunction } from './getFunction';\nimport { getData } from './utils/getData';\nexport function compose(shapeOptions) {\n    const { length: dataLength, shapes = [] } = shapeOptions;\n    let data = new Float64Array(dataLength).fill(1);\n    shapes.forEach((options) => {\n        const { shape, start = 0 } = options;\n        const { options: shapeOptions } = shape;\n        const length = 'length' in shapeOptions ? shapeOptions.length : dataLength - start;\n        const windowData = getData(getFunction(shape), length);\n        applyWindow(data, {\n            windowData,\n            length,\n            start,\n            output: data,\n        });\n    });\n    return data;\n}\n//# sourceMappingURL=compose.js.map","import { applyWindow } from './applyWindow';\nimport { compose } from './compose';\nexport function apodization(data, options) {\n    const { compose: composeOptions, pointsToShift } = options;\n    const windowData = compose(composeOptions);\n    const applyWindowOptions = {\n        windowData,\n        pointsToShift,\n    };\n    const re = applyWindow(data.re, applyWindowOptions);\n    const im = applyWindow(data.im, applyWindowOptions);\n    return { re, im, windowData };\n}\n//# sourceMappingURL=apodization.js.map","import { xSequentialFill } from 'ml-spectra-processing';\nimport { apodization } from '../apodization/apodization';\nimport { signalsToSpinSystem } from './simulation/signalsToSpinSystem';\nimport { simulateXYPeaks } from './simulation/simulateXYPeaks';\nimport { splitSpinSystem } from './simulation/splitSpinSystem';\nconst twoPi = Math.PI * 2;\n/**\n * it use the chemical shifts and the coupling between them in order to generate a FID.\n * It does not propagate the hamiltonian of the spin system, instead it simulate all the\n * frequencies in the spectrum (including second order) and add all the waves in a real and\n * imaginary parts, that is why the couplings should be assigned in order to generate the spin system.\n */\nexport function signalsToFID(signals, options) {\n    const { lb = 1, from = 0, to = 10, nbPoints = 1024, frequency = 400, maxClusterSize = 8, } = options;\n    let spinSystem = signalsToSpinSystem(signals);\n    spinSystem.clusters = splitSpinSystem(spinSystem, {\n        frequency,\n        maxClusterSize,\n    });\n    const peaks = simulateXYPeaks(spinSystem, { frequency });\n    const re = new Float64Array(nbPoints);\n    const im = new Float64Array(nbPoints);\n    const sw = Math.abs(to - from);\n    const adquisitionTime = nbPoints / (sw * frequency);\n    const time = xSequentialFill({\n        size: nbPoints,\n        from: 0,\n        to: adquisitionTime,\n    });\n    for (const peak of peaks) {\n        const { x, y } = peak;\n        const cs = x * frequency * twoPi;\n        for (let i = 0; i < nbPoints; i++) {\n            re[i] += y * Math.cos(cs * time[i]);\n            im[i] += y * Math.sin(cs * time[i]);\n        }\n    }\n    const { windowData, ...result } = apodization({ re, im }, {\n        pointsToShift: 0,\n        compose: {\n            length: nbPoints,\n            shapes: [\n                {\n                    start: 0,\n                    shape: {\n                        kind: 'exponential',\n                        options: {\n                            dw: adquisitionTime / (nbPoints - 1),\n                            lb,\n                        },\n                    },\n                },\n            ],\n        },\n    });\n    return result;\n}\n//# sourceMappingURL=signalsToFID.js.map","export function splitParenthesis(part) {\n    const match = / *(?<before>[^(]*?) *\\( *(?<inside>.*?) *\\) *(?<after>.*?) */.exec(part);\n    if (!match) {\n        return { before: part, inside: '', after: '' };\n    }\n    return match.groups;\n}\n//# sourceMappingURL=splitParenthesis.js.map","export function splitPatterns(multiplet) {\n    if (/^\\s*$/.exec(multiplet))\n        return [];\n    let result = multiplet.match(/ *(quint|hex|sept|hept|oct|nona|non|s|d|t|q|h|o|n) */g);\n    if (result)\n        return result.map((entry) => entry.trim());\n    return [multiplet];\n}\n//# sourceMappingURL=splitPatterns.js.map","import { rangeFromSignal } from './rangeFromSignal';\nimport { splitParenthesis } from './splitParenthesis';\nimport { splitPatterns } from './splitPatterns';\nexport function resurrectRange(part, options = {}) {\n    const { nucleus = '1h', frequency = 400 } = options;\n    const split = splitParenthesis(part);\n    if (!split.before)\n        return;\n    const beforeMatch = /.*?(?<from>-?[0-9.]+)-?(?<to>-?[0-9.]*).*/.exec(split.before);\n    if (!beforeMatch || !beforeMatch.groups)\n        return;\n    const isARange = beforeMatch.groups.to !== '';\n    const from = Number(beforeMatch.groups.from);\n    const to = isARange ? Number(beforeMatch.groups.to) : from;\n    const insideParts = split.inside.split(/ *, */);\n    let signal = { delta: NaN, js: [] };\n    let range = { from, to, signals: [signal] };\n    const integrationParts = insideParts.filter((part) => part.match(/^[0-9]+H$/));\n    if (integrationParts.length === 1) {\n        range.integration = Number(integrationParts[0].replace('H', ''));\n    }\n    const multiplicityParts = insideParts.filter((part) => part.match(/^[a-zA-Z]+$/));\n    if (multiplicityParts.length === 1) {\n        const multiplicity = multiplicityParts[0];\n        if (multiplicity === 'm') {\n            if (isARange) {\n                // a real range\n                signal.delta = (from + to) / 2;\n                signal.multiplicity = multiplicity;\n            }\n            else {\n                // a complex signal\n                signal.delta = from;\n                signal.multiplicity = multiplicity;\n            }\n        }\n        else if (!isARange) {\n            // a complex signal\n            signal.delta = from;\n            signal.multiplicity = multiplicity;\n        }\n    }\n    const jCouplings = insideParts\n        .filter((part) => part.match(/(Hz|J|^[0-9.]+$)/))\n        .map((jCoupling) => Number(jCoupling.replace(/[^0-9.]/g, '')));\n    const multiplicities = splitPatterns(signal.multiplicity || '');\n    if (multiplicities.length === jCouplings.length) {\n        for (let i = 0; i < multiplicities.length; i++) {\n            if (!signal.js) {\n                throw new Error('signal has not js');\n            }\n            signal.js.push({\n                coupling: jCouplings[i],\n                multiplicity: multiplicities[i],\n            });\n        }\n    }\n    if (range.from === range.to) {\n        range = { ...range, ...rangeFromSignal(signal, { nucleus, frequency }) };\n    }\n    return range;\n}\n//# sourceMappingURL=resurrectRange.js.map","import { resurrectRange } from './resurrectRange';\nimport { splitParenthesis } from './splitParenthesis';\nexport function resurrect(acsString) {\n    const data = {\n        experiment: {},\n        ranges: [],\n        acsString,\n        normalized: acsString\n            .replace(/[\\r\\n\\t]/g, ' ')\n            .replace(/[;:]/g, ',')\n            .replace(/\\}/g, ')')\n            .replace(/\\{/g, '(')\n            .replace(/[\\u2011\\u2012\\u2013\\u2014\\u2015\\u2212]/g, '-'),\n    };\n    createParts(data);\n    parseParts(data);\n    return data;\n}\nfunction parseParts(data) {\n    for (const part of data.parts) {\n        if (part.toLowerCase().includes('nmr')) {\n            processExperiment(data, part);\n        }\n        else {\n            const { frequency, nucleus } = data.experiment;\n            const range = resurrectRange(part, { frequency, nucleus });\n            if (range)\n                data.ranges.push(range);\n        }\n    }\n}\nfunction processExperiment(data, part) {\n    const split = splitParenthesis(part);\n    const before = split.before\n        .replace(/[ -]*nmr[ -]*/i, '')\n        .replace(/[ -]/g, '');\n    if (/^[0-9]+[A-Z][a-z]?$/.exec(before)) {\n        // 36Cl, 1H, 13C, ...\n        data.experiment.nucleus = before;\n    }\n    if (/^[A-Z][a-z]?[0-9]+$/.exec(before)) {\n        // Cl35, H1, C13, ...\n        data.experiment.nucleus = before.replace(/^([A-Z][a-z]?)([0-9]+)$/, '$2$1');\n    }\n    if (split.inside) {\n        // some frequency and solvent ???\n        const insideParts = split.inside.split(/[,]/);\n        const frequencyParts = insideParts.filter((part) => /[0-9]{2}/.exec(part));\n        if (frequencyParts.length) {\n            const frequency = frequencyParts[0].replace(/[^0-9]/g, '');\n            if (frequency.length > 1)\n                data.experiment.frequency = Number(frequency);\n        }\n        const solventParts = insideParts.filter((part) => !part.match(/[0-9]{2}/));\n        if (solventParts.length) {\n            data.experiment.solvent = solventParts[0];\n        }\n    }\n}\nfunction createParts(data) {\n    const parts = data.normalized\n        .split(/\\)(?![^()]*\\))/)\n        .map((part) => part.replace(/^\\s*(.*?)\\s*$/, '$1'))\n        .filter((part) => part)\n        .map((part) => `${part})`)\n        .map((part) => part.split(/[,;](?![^()]*\\))/))\n        .flat()\n        .map((part) => part.replace(/^\\s*(.*?)\\s*$/, '$1'))\n        .filter((part) => part);\n    data.parts = parts;\n}\n//# sourceMappingURL=resurrect.js.map","import { convertWidth } from './convertWidth';\nexport function convertWidthToHz(peaks, options) {\n    return convertWidth(peaks, { ...options, convertTo: 'hz' });\n}\n//# sourceMappingURL=convertWidthToHz.js.map","import { gsd, optimizePeaks, joinBroadPeaks, setShape, } from 'ml-gsd';\nimport { xyExtract, xNoiseSanPlot, xAbsoluteMedian, } from 'ml-spectra-processing';\nimport { convertWidthToHz } from '../peaks/util/convertWidthToHz';\nexport function xyAutoPeaksPicking(data, options) {\n    const { from, to, frequency, noiseLevel, thresholdFactor = 3, minMaxRatio = 0.05, broadRatio = 0.00025, useSanPlot = false, smoothY = true, optimize = false, factorLimits = 4, realTopDetection = true, shape = { kind: 'gaussian' }, optimization = { kind: 'lm' }, broadWidth = 0.25, sgOptions = {}, direction = 'positive', } = options;\n    let pointsPerHz = 1 / frequency / (data.x[1] - data.x[0]);\n    // we can consider a peak with of 0.5 Hz for the windowSize\n    let ws = Math.max(Math.round(pointsPerHz / 2), 5);\n    const { windowSize = ws - (ws % 2) + 1, polynomial = 3 } = sgOptions;\n    if (data.x.length < windowSize)\n        return [];\n    if (from !== undefined && to !== undefined) {\n        data = xyExtract(data, { zones: [{ from, to }] });\n    }\n    const cutOff = getCutOff(data.y, { noiseLevel, useSanPlot, thresholdFactor });\n    let getPeakOptions = {\n        shape,\n        frequency,\n        broadWidth,\n        optimize,\n        factorLimits,\n        maxCriteria: true,\n        sgOptions: { windowSize, polynomial },\n        minMaxRatio,\n        broadRatio,\n        noiseLevel: cutOff.positive,\n        smoothY,\n        optimization,\n        realTopDetection,\n    };\n    switch (direction) {\n        case 'positive': {\n            return getPeakList(data, getPeakOptions);\n        }\n        case 'negative': {\n            return getNegativePeaks(data, cutOff, getPeakOptions);\n        }\n        case 'both': {\n            return [\n                ...getPeakList(data, getPeakOptions),\n                ...getNegativePeaks(data, cutOff, getPeakOptions),\n            ];\n        }\n        default: {\n            const unHandled = direction;\n            // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n            throw Error(`Unknown distribution ${unHandled}`);\n        }\n    }\n}\nfunction getNegativePeaks(data, cutOff, getPeakOptions) {\n    getPeakOptions.noiseLevel = cutOff.negative;\n    getPeakOptions.maxCriteria = false;\n    return getPeakList(data, getPeakOptions);\n}\nfunction getPeakList(data, options) {\n    const { shape, frequency, broadWidth, optimize, maxCriteria, factorLimits, sgOptions, minMaxRatio, broadRatio, noiseLevel, smoothY, optimization, realTopDetection, } = options;\n    const peaks = gsd(data, {\n        sgOptions,\n        maxCriteria,\n        minMaxRatio,\n        noiseLevel,\n        smoothY,\n        realTopDetection,\n    });\n    const peakList = setShape(peaks, { output: peaks, shape });\n    const newPeaks = broadWidth\n        ? joinBroadPeaks(peakList, {\n            broadRatio,\n            broadWidth,\n            shape,\n            optimization,\n        }).map(toNMRPeak1DStructure)\n        : peakList.map(toNMRPeak1DStructure);\n    return convertWidthToHz(optimize\n        ? optimizePeaks(data, newPeaks, {\n            shape,\n            factorLimits,\n            optimization,\n        }).map(toNMRPeak1DStructure)\n        : newPeaks, { frequency });\n}\nfunction getCutOff(data, options) {\n    const { noiseLevel, useSanPlot, thresholdFactor } = options;\n    const formatResult = (noiseLevel) => typeof noiseLevel === 'number'\n        ? { positive: noiseLevel, negative: -noiseLevel }\n        : noiseLevel;\n    if (noiseLevel) {\n        return formatResult(noiseLevel);\n    }\n    else {\n        return useSanPlot\n            ? xNoiseSanPlot(data, { factorStd: thresholdFactor })\n            : formatResult(xAbsoluteMedian(data) * thresholdFactor);\n    }\n}\nfunction toNMRPeak1DStructure(peak) {\n    const { id, shape, x, y, width } = peak;\n    return {\n        id,\n        x,\n        y,\n        width,\n        shape,\n    };\n}\n//# sourceMappingURL=xyAutoPeaksPicking.js.map","import { v4 as generateID } from '@lukeed/uuid';\nexport function joinRanges(ranges) {\n    ranges.sort((a, b) => a.from - b.from);\n    for (let i = 0; i < ranges.length - 1; i++) {\n        const currentRange = ranges[i];\n        const nextRange = ranges[i + 1];\n        if (currentRange.to > nextRange.from) {\n            currentRange.id = generateID();\n            currentRange.to = Math.max(nextRange.to, currentRange.to);\n            if (currentRange.signals && nextRange.signals) {\n                currentRange.signals = currentRange.signals.concat(nextRange.signals);\n            }\n            if (currentRange.integration !== undefined) {\n                currentRange.integration += nextRange.integration || 0;\n            }\n            ranges.splice(i + 1, 1);\n            i--;\n        }\n    }\n    return ranges;\n}\n//# sourceMappingURL=joinRanges.js.map","/*\n * This library implements the J analyser described by Cobas et al in the paper:\n * A two-stage approach to automatic determination of 1H NMR coupling constants\n */\nconst patterns = ['s', 'd', 't', 'q', 'quint', 'h', 'sept', 'o', 'n'];\nlet symRatio = 1.5;\nlet maxErrorIter1 = 2.5; // Hz\nlet maxErrorIter2 = 1; // Hz\nlet jAxisKeys = { jAxis: 'x', intensity: 'intensity' };\nfunction checkSignalForCompilePattern(signal) {\n    if (!('symRank' in signal)) {\n        throw new Error('Internal error, symRank was not calculated');\n    }\n    if (!('mask' in signal)) {\n        throw new Error('Internal Error, mask was not added');\n    }\n}\nexport default {\n    /**\n     * The compilation process implements at the first stage a normalization procedure described by Golotvin et al.\n     * embedding in peak-component-counting method described by Hoyes et al.\n     * @param {object} signal\n     * @private\n     */\n    compilePattern: (inputSignal, options = {}) => {\n        let { jAxisKey = jAxisKeys } = options;\n        // checkForPeaks(inputSignal);\n        // const signal = JSON.parse(JSON.stringify(inputSignal));\n        // 1.1 symmetrize\n        // It will add a set of peaks(signal.peaksComp) to the signal that will be used during\n        // the compilation process. The unit of those peaks will be in Hz\n        const signal = symmetrizeChoiseBest(inputSignal, {\n            maxError: maxErrorIter1,\n            iteration: 1,\n            jAxisKey,\n        });\n        signal.multiplicity = 'm';\n        signal.asymmetric = true;\n        //asserts the signal has all needed\n        checkSignalForCompilePattern(signal);\n        // Is the signal symmetric?\n        if (signal.symRank >= 0.95 && signal.peaksComp.length < 32) {\n            signal.asymmetric = false;\n            let P1, n2, maxFlagged;\n            let k = 1;\n            let jCouplings = [];\n            // Loop over the possible number of coupling contributing to the multiplet\n            for (let n = 0; n < 9; n++) {\n                // 1.2 Normalize. It makes a deep copy of the peaks before to modify them.\n                let peaks = normalize(signal, n);\n                let validPattern = false; // It will change to true, when we find the good patter\n                // Lets check if the signal could be a singulet.\n                if (peaks.length === 1 && n === 0) {\n                    validPattern = true;\n                }\n                else if (peaks.length <= 1) {\n                    continue;\n                }\n                // 1.3 Establish a range for the Heights Hi [peaks.intensity*0.85,peaks.intensity*1.15];\n                let ranges = getRanges(peaks);\n                n2 = Math.pow(2, n);\n                // 1.4 Find a combination of integer heights Hi, one from each Si, that sums to 2^n.\n                let heights = null;\n                let counter = 1;\n                while (!validPattern &&\n                    (heights = getNextCombination(ranges, n2)) !== null &&\n                    counter < 400) {\n                    // 2.1 Number the components of the multiplet consecutively from 1 to 2n,\n                    // starting at peak 1\n                    let numbering = new Array(heights.length);\n                    k = 1;\n                    for (let i = 0; i < heights.length; i++) {\n                        numbering[i] = new Array(heights[i]);\n                        for (let j = 0; j < heights[i]; j++) {\n                            numbering[i][j] = k++;\n                        }\n                    }\n                    jCouplings = []; // The array to store the detected j-coupling\n                    // 2.2 Set j = 1; J1 = P2 - P1. Flag components 1 and 2 as accounted for.\n                    let j = 1;\n                    jCouplings.push(peaks[1].x - peaks[0].x);\n                    P1 = peaks[0].x;\n                    numbering[0].splice(0, 1); // Flagged\n                    numbering[1].splice(0, 1); // Flagged\n                    k = 1;\n                    let nFlagged = 2;\n                    maxFlagged = Math.pow(2, n) - 1;\n                    while (jCouplings.length < n &&\n                        nFlagged < maxFlagged &&\n                        k < peaks.length) {\n                        counter += 1;\n                        // 4.1. Increment j. Set k to the number of the first unflagged component.\n                        j++;\n                        while (k < peaks.length && numbering[k].length === 0) {\n                            k++;\n                        }\n                        if (k < peaks.length) {\n                            // 4.2 Jj = Pk - P1.\n                            jCouplings.push(peaks[k].x - peaks[0].x);\n                            // Flag component k and, for each sum of the...\n                            numbering[k].splice(0, 1); // Flageed\n                            nFlagged++;\n                            // Flag the other components of the multiplet\n                            for (let u = 2; u <= j; u++) {\n                                let jSum = 0;\n                                for (let i = 0; i < u; i++) {\n                                    jSum += jCouplings[i];\n                                }\n                                for (let i = 1; i < numbering.length; i++) {\n                                    // Maybe 0.25 Hz is too much?\n                                    if (Math.abs(peaks[i].x - (P1 + jSum)) < 0.25) {\n                                        numbering[i].splice(0, 1); // Flageed\n                                        nFlagged++;\n                                        break;\n                                    }\n                                }\n                            }\n                        }\n                    }\n                    // Calculate the ideal patter by using the extracted j-couplings\n                    let pattern = idealPattern(jCouplings);\n                    // Compare the ideal pattern with the proposed intensities.\n                    // All the intensities have to match to accept the multiplet\n                    validPattern = true;\n                    for (let i = 0; i < pattern.length; i++) {\n                        if (pattern[i].intensity !== heights[i]) {\n                            validPattern = false;\n                        }\n                    }\n                }\n                // If we found a valid pattern we should inform about the pattern.\n                if (validPattern) {\n                    updateSignal(signal, jCouplings);\n                }\n            }\n        }\n        // Before to return, change the units of peaksComp from Hz to PPM again\n        for (let peakComp of signal.peaksComp) {\n            peakComp.x /= signal.observe;\n            peakComp.width *= signal.observe;\n        }\n        return signal;\n    },\n};\n/**\n * @private\n * update the signal\n * @param {*} signal\n * @param {*} jCouplings\n */\nfunction updateSignal(signal, jCouplings) {\n    // Update the limits of the signal\n    let peaks = signal.peaksComp; // Always in Hz\n    let nbPeaks = peaks.length;\n    signal.startX = peaks[0].x / signal.observe - peaks[0].width;\n    signal.stopX =\n        peaks[nbPeaks - 1].x / signal.observe + peaks[nbPeaks - 1].width;\n    signal.integralData.from = peaks[0].x / signal.observe - peaks[0].width * 3;\n    signal.integralData.to =\n        peaks[nbPeaks - 1].x / signal.observe + peaks[nbPeaks - 1].width * 3;\n    // Compile the pattern and format the constant couplings\n    signal.maskPattern = signal.mask2;\n    signal.multiplicity = abstractPattern(signal, jCouplings);\n    signal.pattern = signal.multiplicity; // Our library depends on this parameter, but it is old\n}\n/**\n * Returns the multiplet in the compact format\n * @param {object} signal\n * @param {object} jCouplings\n * @return {String}\n * @private\n */\nfunction abstractPattern(signal, jCouplings) {\n    let tol = 0.05;\n    let pattern = '';\n    let cont = 1;\n    let newNmrJs = [];\n    if (jCouplings && jCouplings.length > 0) {\n        jCouplings.sort((a, b) => {\n            return b - a;\n        });\n        for (let i = 0; i < jCouplings.length - 1; i++) {\n            if (Math.abs(jCouplings[i] - jCouplings[i + 1]) < tol) {\n                cont++;\n            }\n            else {\n                newNmrJs.push({\n                    coupling: Math.abs(jCouplings[i]),\n                    multiplicity: patterns[cont],\n                });\n                pattern += patterns[cont];\n                cont = 1;\n            }\n        }\n        let index = jCouplings.length - 1;\n        newNmrJs.push({\n            coupling: Math.abs(jCouplings[index]),\n            multiplicity: patterns[cont],\n        });\n        pattern += patterns[cont];\n        signal.nmrJs = newNmrJs;\n    }\n    else {\n        pattern = 's';\n        if (Math.abs(signal.startX - signal.stopX) * signal.observe > 16) {\n            pattern = 'br s';\n        }\n    }\n    return pattern;\n}\n/**\n * This function creates an ideal pattern from the given J-couplings\n * @private\n * @param {Array} jCouplings\n * @return {*[]}\n * @private\n */\nfunction idealPattern(jCouplings) {\n    let hsum = Math.pow(2, jCouplings.length);\n    let pattern = [{ x: 0, intensity: hsum }];\n    // To split the initial height\n    for (const jc of jCouplings) {\n        for (let j = pattern.length - 1; j >= 0; j--) {\n            pattern.push({\n                x: pattern[j].x + jc / 2,\n                intensity: pattern[j].intensity / 2,\n            });\n            pattern[j].x = pattern[j].x - jc / 2;\n            pattern[j].intensity = pattern[j].intensity / 2;\n        }\n    }\n    // To sum the heights in the same positions\n    pattern.sort((a, b) => {\n        return a.x - b.x;\n    });\n    for (let j = pattern.length - 2; j >= 0; j--) {\n        if (Math.abs(pattern[j].x - pattern[j + 1].x) < 0.1) {\n            pattern[j].intensity += pattern[j + 1].intensity;\n            pattern.splice(j + 1, 1);\n        }\n    }\n    return pattern;\n}\n/**\n * Find a combination of integer heights Hi, one from each Si, that sums to 2n.\n * @param {object} ranges\n * @param {Number} value\n * @return {*}\n * @private\n */\nfunction getNextCombination(ranges, value) {\n    let half = Math.ceil(ranges.values.length * 0.5);\n    let lng = ranges.values.length;\n    let sum = 0;\n    let ok;\n    while (sum !== value) {\n        // Update the indexes to point at the next possible combination\n        ok = false;\n        while (!ok) {\n            ok = true;\n            ranges.currentIndex[ranges.active]++;\n            if (ranges.currentIndex[ranges.active] >=\n                ranges.values[ranges.active].length) {\n                // In this case, there is no more possible combinations\n                if (ranges.active + 1 === half) {\n                    return null;\n                }\n                else {\n                    // If this happens we need to try the next active peak\n                    ranges.currentIndex[ranges.active] = 0;\n                    ok = false;\n                    ranges.active++;\n                }\n            }\n            else {\n                ranges.active = 0;\n            }\n        }\n        // Sum the heights for this combination\n        sum = 0;\n        for (let i = 0; i < half; i++) {\n            sum += ranges.values[i][ranges.currentIndex[i]] * 2;\n        }\n        if (ranges.values.length % 2 !== 0) {\n            sum -= ranges.values[half - 1][ranges.currentIndex[half - 1]];\n        }\n    }\n    // If the sum is equal to the expected value, fill the array to return\n    if (sum === value) {\n        let heights = new Array(lng);\n        for (let i = 0; i < half; i++) {\n            heights[i] = ranges.values[i][ranges.currentIndex[i]];\n            heights[lng - i - 1] = ranges.values[i][ranges.currentIndex[i]];\n        }\n        return heights;\n    }\n    return null;\n}\n/**\n * This function generates the possible values that each peak can contribute\n * to the multiplet.\n * @param {Array} peaks Array of objects with peaks information {intensity}\n * @return {{values: Array, currentIndex: Array, active: number}}\n * @private\n */\nfunction getRanges(peaks) {\n    let ranges = new Array(peaks.length);\n    let currentIndex = new Array(peaks.length);\n    let min, max;\n    ranges[0] = [1];\n    ranges[peaks.length - 1] = [1];\n    currentIndex[0] = -1;\n    currentIndex[peaks.length - 1] = 0;\n    for (let i = 1; i < peaks.length - 1; i++) {\n        min = Math.round(peaks[i].intensity * 0.85);\n        max = Math.round(peaks[i].intensity * 1.15);\n        ranges[i] = [];\n        for (let j = min; j <= max; j++) {\n            ranges[i].push(j);\n        }\n        currentIndex[i] = 0;\n    }\n    return { values: ranges, currentIndex, active: 0 };\n}\n/**\n * Performs a symmetrization of the signal by using different aproximations to the center.\n * It will return the result of the symmetrization that removes less peaks from the signal\n * @param {object} signal\n * @param {Number} maxError\n * @param {Number} iteration\n * @return {*}\n * @private\n */\nfunction symmetrizeChoiseBest(signal, options) {\n    let { maxError, iteration, jAxisKey = jAxisKeys } = options;\n    //make a clone of signal\n    let newSignal1 = symmetrize(signal, maxError, iteration, jAxisKey);\n    if (!newSignal1.peaksComp) {\n        throw new Error('internal peaksComp was not created');\n    }\n    let tmpPeaks = newSignal1.peaksComp;\n    let tmpMask = newSignal1.mask;\n    let cs = signal.delta;\n    signal.delta =\n        (signal.peaks[0].x + signal.peaks[signal.peaks.length - 1].x) / 2;\n    let newSignal2 = symmetrize(signal, maxError, iteration, jAxisKey);\n    if (!newSignal2.peaksComp) {\n        throw new Error('internal peaksComp was not created');\n    }\n    if (newSignal2.peaksComp.length > tmpPeaks.length) {\n        return newSignal2;\n    }\n    signal.delta = cs;\n    signal.peaksComp = tmpPeaks;\n    signal.mask = tmpMask;\n    return newSignal1;\n}\n/**\n * This function will return a set of symmetric peaks that will\n * be the enter point for the patter compilation process.\n * @param {object} signal\n * @param {Number} maxError\n * @param {Number} iteration\n * @return {Number}\n * @private\n */\nfunction symmetrize(signalInput, maxError, iteration, key) {\n    let { jAxis, intensity } = key;\n    const newSignal = JSON.parse(JSON.stringify(signalInput));\n    // Before to symmetrize we need to keep only the peaks that possibly conforms the multiplete\n    let max, min, avg, ratio, avgWidth;\n    let peaks = new Array(newSignal.peaks.length);\n    // Make a deep copy of the peaks and convert PPM ot HZ\n    for (let i = 0; i < peaks.length; i++) {\n        let peak = newSignal.peaks[i];\n        peaks[i] = {\n            x: peak[jAxis] * newSignal.observe,\n            intensity: peak[intensity],\n            width: peak.width / newSignal.observe,\n        };\n    }\n    // Join the peaks that are closer than 0.25 Hz\n    for (let i = peaks.length - 2; i >= 0; i--) {\n        if (Math.abs(peaks[i].x - peaks[i + 1].x) < 0.25) {\n            peaks[i].x =\n                peaks[i].x * peaks[i].intensity +\n                    peaks[i + 1].x * peaks[i + 1].intensity;\n            peaks[i].intensity = peaks[i].intensity + peaks[i + 1].intensity;\n            peaks[i].x /= peaks[i].intensity;\n            peaks[i].intensity /= 2;\n            peaks[i].width += peaks[i + 1].width;\n            peaks.splice(i + 1, 1);\n        }\n    }\n    newSignal.peaksComp = peaks;\n    let nbPeaks = peaks.length;\n    let mask = new Array(nbPeaks);\n    newSignal.mask = mask;\n    let left = 0;\n    let right = peaks.length - 1;\n    let cs = newSignal.delta * newSignal.observe;\n    let middle = [(peaks[0].x + peaks[nbPeaks - 1].x) / 2, 1];\n    maxError = error(Math.abs(cs - middle[0]));\n    let heightSum = 0;\n    // We try to symmetrize the extreme peaks. We consider as candidates for symmetricing those which have\n    // ratio smaller than 3\n    for (let i = 0; i < nbPeaks; i++) {\n        mask[i] = true;\n        // heightSum += signal.peaks[i].intensity;\n        heightSum += peaks[i].intensity;\n    }\n    while (left <= right) {\n        mask[left] = true;\n        mask[right] = true;\n        if (left === right) {\n            if (nbPeaks > 2 && Math.abs(peaks[left].x - cs) > maxError) {\n                mask[left] = false;\n            }\n        }\n        else {\n            max = Math.max(peaks[left].intensity, peaks[right].intensity);\n            min = Math.min(peaks[left].intensity, peaks[right].intensity);\n            ratio = max / min;\n            if (ratio > symRatio) {\n                if (peaks[left].intensity === min) {\n                    mask[left] = false;\n                    right++;\n                }\n                else {\n                    mask[right] = false;\n                    left--;\n                }\n            }\n            else {\n                let diffL = Math.abs(peaks[left].x - cs);\n                let diffR = Math.abs(peaks[right].x - cs);\n                if (Math.abs(diffL - diffR) < maxError) {\n                    avg = Math.min(peaks[left].intensity, peaks[right].intensity);\n                    avgWidth = Math.min(peaks[left].width, peaks[right].width);\n                    peaks[left].intensity = avg;\n                    peaks[right].intensity = avg;\n                    peaks[left].width = avgWidth;\n                    peaks[right].width = avgWidth;\n                    middle = [\n                        middle[0] + (peaks[right].x + peaks[left].x) / 2,\n                        middle[1] + 1,\n                    ];\n                }\n                else if (Math.max(diffL, diffR) === diffR) {\n                    mask[right] = false;\n                    left--;\n                }\n                else {\n                    mask[left] = false;\n                    right++;\n                }\n            }\n        }\n        left++;\n        right--;\n        // Only alter cs if it is the first iteration of the sym process.\n        if (iteration === 1) {\n            cs = chemicalShift(peaks, mask);\n            // There is not more available peaks\n            if (isNaN(cs)) {\n                newSignal.symRank = 0;\n                return newSignal;\n            }\n        }\n        maxError = error(Math.abs(cs - middle[0] / middle[1]));\n    }\n    // To remove the weak peaks and recalculate the cs\n    for (let i = nbPeaks - 1; i >= 0; i--) {\n        if (mask[i] === false) {\n            peaks.splice(i, 1);\n        }\n    }\n    cs = chemicalShift(peaks);\n    if (isNaN(cs)) {\n        newSignal.symRank = 0;\n        return newSignal;\n    }\n    newSignal.delta = cs / newSignal.observe;\n    // Now, the peak should be symmetric in heights, but we need to know if it is symmetric in x\n    let symFactor = 0;\n    let weight = 0;\n    if (peaks.length > 1) {\n        for (let i = Math.ceil(peaks.length / 2) - 1; i >= 0; i--) {\n            symFactor +=\n                ((3 +\n                    Math.min(Math.abs(peaks[i].x - cs), Math.abs(peaks[peaks.length - 1 - i].x - cs))) /\n                    (3 +\n                        Math.max(Math.abs(peaks[i].x - cs), Math.abs(peaks[peaks.length - 1 - i].x - cs)))) *\n                    peaks[i].intensity;\n            weight += peaks[i].intensity;\n        }\n        symFactor /= weight;\n    }\n    else if (peaks.length === 1) {\n        symFactor = 1;\n    }\n    let newSumHeights = 0;\n    for (const peak of peaks) {\n        newSumHeights += peak.intensity;\n    }\n    symFactor -= ((heightSum - newSumHeights) / heightSum) * 0.12; // Removed peaks penalty\n    // Sometimes we need a second opinion after the first symmetrization.\n    if (symFactor > 0.8 && symFactor < 0.97 && iteration < 2) {\n        return symmetrize(newSignal, maxErrorIter2, 2, key);\n    }\n    else if (peaks.length > 1) {\n        // Center the given pattern at cs and symmetrize x\n        let dxi;\n        for (let i = Math.ceil(peaks.length / 2) - 1; i >= 0; i--) {\n            dxi = (peaks[i].x - peaks[peaks.length - 1 - i].x) / 2.0;\n            peaks[i].x = cs + dxi;\n            peaks[peaks.length - 1 - i].x = cs - dxi;\n        }\n    }\n    newSignal.symRank = symFactor;\n    return newSignal;\n}\n/**\n * Error validator\n * @param {Number} value\n * @return {Number}\n * @private\n */\nfunction error(value) {\n    let maxError = value * 2.5;\n    if (maxError < 0.75) {\n        maxError = 0.75;\n    }\n    if (maxError > 3) {\n        maxError = 3;\n    }\n    return maxError;\n}\n/**\n * @private\n * 2 stages normalizarion of the peaks heights to Math.pow(2,n).\n * Creates a new mask with the peaks that could contribute to the multiplete\n * @param {object} signal\n * @param {Number} n\n * @return {*}\n */\nfunction normalize(signal, n) {\n    // Perhaps this is slow\n    let peaks = JSON.parse(JSON.stringify(signal.peaksComp));\n    let norm = 0;\n    let norm2 = 0;\n    for (let peak of peaks) {\n        norm += peak.intensity;\n    }\n    norm = Math.pow(2, n) / norm;\n    signal.mask2 = signal.mask.slice();\n    let index = signal.mask2.length - 1;\n    for (let i = peaks.length - 1; i >= 0; i--) {\n        peaks[i].intensity *= norm;\n        while (index >= 0 && !signal.mask2[index]) {\n            index--;\n        }\n        if (peaks[i].intensity < 0.75) {\n            peaks.splice(i, 1);\n            signal.mask2[index] = false;\n        }\n        else {\n            norm2 += peaks[i].intensity;\n        }\n        index--;\n    }\n    norm2 = Math.pow(2, n) / norm2;\n    for (let i = peaks.length - 1; i >= 0; i--) {\n        peaks[i].intensity *= norm2;\n    }\n    return peaks;\n}\n/**\n * @private\n * Calculates the chemical shift as the weighted sum of the peaks\n * @param {Array} peaks\n * @param {Array} mask\n * @return {Number}\n */\nfunction chemicalShift(peaks, mask = []) {\n    let sum = 0;\n    let cs = 0;\n    let area;\n    if (mask.length > 0) {\n        for (let i = 0; i < peaks.length; i++) {\n            if (mask[i]) {\n                area = getArea(peaks[i]);\n                sum += area;\n                cs += area * peaks[i].x;\n            }\n        }\n    }\n    else {\n        for (let peak of peaks) {\n            area = getArea(peak);\n            sum += area;\n            cs += area * peak.x;\n        }\n    }\n    return cs / sum;\n}\n/**\n * Return the area of a Lorentzian function\n * @param {object} peak - object with peak information\n * @return {Number}\n * @private\n */\nfunction getArea(peak) {\n    return Math.abs(peak.intensity * peak.width * 1.57); // 1.772453851);\n}\n//# sourceMappingURL=jAnalyzer.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport { xyIntegration } from 'ml-spectra-processing';\nimport { joinRanges } from '../ranges/utils/joinRanges';\nimport jAnalyzer from '../signals/utils/jAnalyzer';\nfunction checkSignalAfterCompilePattern(signal) {\n    // if (!signal.symRank)\n    //   throw new Error('Internal error, symRank was not calculated');\n    if (!signal.mask)\n        throw new Error('Internal Error, mask was not added');\n    if (!signal.mask2)\n        throw new Error('Internal Error, mask2 was not added');\n    if (!signal.maskPattern) {\n        throw new Error('Internal Error, maskPattern was not added');\n    }\n}\nconst assignSignal = (peak, frequency, nucleus) => {\n    return {\n        id: generateID(),\n        delta: NaN,\n        nbPeaks: 1,\n        kind: 'signal',\n        startX: peak.x - peak.width / frequency,\n        stopX: peak.x + peak.width / frequency,\n        observe: frequency,\n        nucleus,\n        integralData: {\n            from: peak.x - (peak.width * 3) / frequency,\n            to: peak.x + (peak.width * 3) / frequency,\n            value: 0,\n        },\n        peaks: [\n            {\n                x: peak.x,\n                intensity: peak.y,\n                width: peak.width,\n            },\n        ],\n    };\n};\n/**\n * This function clustering peaks and calculate the integration value for each range from the peak list returned from extractPeaks function.\n */\nexport function peaksToRanges(data, peakList, options = {}) {\n    let { integrationSum = 100, joinOverlapRanges = true, clean = 0.4, compile = true, integralType = 'sum', frequency = 400, frequencyCluster = 16, keepPeaks = false, nucleus = '1H', } = options;\n    let signalOptions = {\n        integrationSum,\n        integralType,\n        frequencyCluster,\n        frequency,\n        nucleus,\n    };\n    if (peakList.length === 0)\n        return [];\n    if (data.x[0] > data.x[1]) {\n        data.x = data.x.reverse();\n        data.y = data.y.reverse();\n    }\n    let signals = detectSignals(data, peakList, signalOptions);\n    if (clean) {\n        for (let i = 0; i < signals.length; i++) {\n            if (Math.abs(signals[i].integralData.value) < clean) {\n                signals.splice(i, 1);\n            }\n        }\n    }\n    if (compile) {\n        let nHi, sum;\n        for (let i = 0; i < signals.length; i++) {\n            signals[i] = jAnalyzer.compilePattern(signals[i]);\n            let signal = signals[i];\n            if (signal.maskPattern &&\n                signal.multiplicity !== 'm' &&\n                signal.multiplicity !== '') {\n                checkSignalAfterCompilePattern(signal);\n                // Create a new signal with the removed peaks\n                nHi = 0;\n                sum = 0;\n                let peaksO = [];\n                for (let j = signal.maskPattern.length - 1; j >= 0; j--) {\n                    sum += computeArea(signal.peaks[j], frequency);\n                    if (!signal.maskPattern[j]) {\n                        let peakR = signal.peaks.splice(j, 1)[0];\n                        peaksO.push({\n                            x: peakR.x,\n                            y: peakR.intensity,\n                            width: peakR.width,\n                        });\n                        signal.mask.splice(j, 1);\n                        signal.mask2.splice(j, 1);\n                        signal.maskPattern.splice(j, 1);\n                        signal.nbPeaks--;\n                        nHi += computeArea(peakR, frequency);\n                    }\n                }\n                if (peaksO.length > 0) {\n                    nHi = (nHi * signal.integralData.value) / sum;\n                    signal.integralData.value -= nHi;\n                    let peaks1 = [];\n                    for (let j = peaksO.length - 1; j >= 0; j--) {\n                        peaks1.push(peaksO[j]);\n                    }\n                    signalOptions.integrationSum = Math.abs(nHi);\n                    let ranges = detectSignals(data, peaks1, signalOptions);\n                    for (const range of ranges) {\n                        signals.push(range);\n                    }\n                }\n            }\n        }\n        // it was a updateIntegrals function.\n        updateIntegration(signals, integrationSum);\n    }\n    signals.sort((a, b) => {\n        return b.delta - a.delta;\n    });\n    if (clean) {\n        for (let i = signals.length - 1; i >= 0; i--) {\n            if (Math.abs(signals[i].integralData.value) < clean) {\n                signals.splice(i, 1);\n            }\n        }\n    }\n    let ranges = [];\n    for (let i = 0; i < signals.length; i++) {\n        let signal = signals[i];\n        const range = {\n            id: generateID(),\n            from: signal.integralData.from,\n            to: signal.integralData.to,\n            integration: signal.integralData.value,\n        };\n        const signalResult = {\n            delta: signal.delta,\n            kind: signal.kind || 'signal',\n            multiplicity: signal.multiplicity,\n        };\n        if (keepPeaks) {\n            signalResult.peaks = signal.peaks.map((peak) => {\n                const newResult = {\n                    y: peak.intensity,\n                    ...peak,\n                };\n                delete newResult.intensity;\n                return newResult;\n            });\n        }\n        if (signal.nmrJs) {\n            signalResult.js = signal.nmrJs;\n        }\n        range.signals = [signalResult];\n        ranges[i] = range;\n    }\n    if (joinOverlapRanges)\n        ranges = joinRanges(ranges);\n    return ranges;\n}\n/**\n * Extract the signals from the peakList and the given spectrum.\n * @param {object} data - spectra data\n * @param {array} peakList - nmr signals\n * @param {object} [options = {}]\n * @param {number} [options.integrationSum='100'] - Number of hydrogens or some number to normalize the integration data, If it's zero return the absolute integration value\n * @param {string} [options.integralType='sum'] - option to chose between approx area with peaks or the sum of the points of given range\n * @param {number} [options.frequencyCluster=16] - distance limit to clustering the peaks.\n * range = frequencyCluster / observeFrequency -> Peaks withing this range are considered to belongs to the same signal1D\n * @param {string} [options.nucleus='1H'] - - Nucleus\n * @param {String} [options.frequency = 400] - Observed frequency\n * @return {array} nmr signals\n * @private\n */\nexport function detectSignals(data, peakList, options = {}) {\n    let { integrationSum = 100, integralType = 'sum', frequencyCluster = 16, frequency = 400, nucleus = '1H', } = options;\n    let signal1D = assignSignal(peakList[0], frequency, nucleus);\n    let peaks;\n    let signals = [];\n    let prevPeak = { x: Number.MIN_SAFE_INTEGER };\n    frequencyCluster /= frequency;\n    for (const peak of peakList) {\n        if (Math.abs(peak.x - prevPeak.x) > frequencyCluster) {\n            signal1D = assignSignal(peak, frequency, nucleus);\n            if (peak.kind)\n                signal1D.kind = peak.kind;\n            signals.push(signal1D);\n        }\n        else {\n            let tmp = peak.x + peak.width / frequency;\n            signal1D.stopX = Math.max(signal1D.stopX, tmp);\n            signal1D.startX = Math.min(signal1D.startX, tmp);\n            signal1D.nbPeaks++;\n            signal1D.peaks.push({\n                x: peak.x,\n                intensity: peak.y,\n                width: peak.width,\n            });\n            signal1D.integralData.from = Math.min(signal1D.integralData.from, peak.x - (peak.width * 3) / frequency);\n            signal1D.integralData.to = Math.max(signal1D.integralData.to, peak.x + (peak.width * 3) / frequency);\n            if (peak.kind)\n                signal1D.kind = peak.kind;\n        }\n        prevPeak = peak;\n    }\n    for (let signal of signals) {\n        peaks = signal.peaks;\n        let integration = signal.integralData;\n        let chemicalShift = 0;\n        let integralPeaks = 0;\n        for (const peak of peaks) {\n            let area = computeArea(peak, frequency);\n            chemicalShift += peak.x * area;\n            integralPeaks += area;\n        }\n        signal.delta = chemicalShift / integralPeaks;\n        if (integralType === 'sum') {\n            integration.value = xyIntegration(data, {\n                from: integration.from,\n                to: integration.to,\n            });\n        }\n        else {\n            integration.value = integralPeaks;\n        }\n    }\n    if (integrationSum > 0) {\n        updateIntegration(signals, integrationSum);\n    }\n    return signals;\n}\n/**\n * Return the area of a Lorentzian function\n * @private\n */\nfunction computeArea(peak, frequency) {\n    return Math.abs(((peak.intensity * peak.width) / frequency) * 1.57); // todo add an option with this value: 1.772453851\n}\n/**\n * update the integration Values\n * @param signals\n * @param integrationSum\n */\nfunction updateIntegration(signals, integrationSum) {\n    let sumIntegral = 0;\n    let sumObserved = 0;\n    for (const signal of signals) {\n        sumObserved += Math.abs(Math.round(signal.integralData.value));\n    }\n    if (sumObserved !== integrationSum) {\n        sumIntegral = integrationSum / sumObserved;\n        for (const signal of signals) {\n            signal.integralData.value *= sumIntegral;\n        }\n    }\n}\n//# sourceMappingURL=peaksToRanges.js.map","import { peaksFilterImpurities } from '../peaks/peaksFilterImpurities';\nimport { peaksToRanges } from '../peaks/peaksToRanges';\nimport { xyAutoPeaksPicking } from './xyAutoPeaksPicking';\n/**\n * Detect peaks, optimize parameters and compile multiplicity if required.\n */\nexport function xyAutoRangesPicking(data, options) {\n    let peaks = xyAutoPeaksPicking(data, options.peakPicking);\n    peaks = peaksFilterImpurities(peaks, options.impurities);\n    return peaksToRanges(data, peaks, options.ranges);\n}\n//# sourceMappingURL=xyAutoRangesPicking.js.map","import { optimizePeaks } from 'ml-gsd';\nimport { convertWidthToHz } from '../peaks/util/convertWidthToHz';\nimport { convertWidthToPPM } from '../peaks/util/convertWidthToPPM';\nexport function xyPeaksOptimization(data, peaks, options) {\n    const { frequency } = options;\n    const newPeaks = convertWidthToPPM(peaks, { frequency });\n    const optimizedPeaks = optimizePeaks(data, newPeaks, options);\n    const result = convertWidthToHz(optimizedPeaks, {\n        frequency,\n        output: optimizedPeaks,\n    });\n    return result;\n}\n//# sourceMappingURL=xyPeaksOptimization.js.map","/**\n * Fast Fourier Transform module\n * 1D-FFT/IFFT, 2D-FFT/IFFT (radix-2)\n */\nvar FFT = (function(){\n  var FFT;  \n  \n  if(typeof exports !== 'undefined') {\n    FFT = exports;   // for CommonJS\n  } else {\n    FFT = {};\n  }\n  \n  var version = {\n    release: '0.3.0',\n    date: '2013-03'\n  };\n  FFT.toString = function() {\n    return \"version \" + version.release + \", released \" + version.date;\n  };\n\n  // core operations\n  var _n = 0,          // order\n      _bitrev = null,  // bit reversal table\n      _cstb = null;    // sin/cos table\n\n  var core = {\n    init : function(n) {\n      if(n !== 0 && (n & (n - 1)) === 0) {\n        _n = n;\n        core._initArray();\n        core._makeBitReversalTable();\n        core._makeCosSinTable();\n      } else {\n        throw new Error(\"init: radix-2 required\");\n      }\n    },\n    // 1D-FFT\n    fft1d : function(re, im) {\n      core.fft(re, im, 1);\n    },\n    // 1D-IFFT\n    ifft1d : function(re, im) {\n      var n = 1/_n;\n      core.fft(re, im, -1);\n      for(var i=0; i<_n; i++) {\n        re[i] *= n;\n        im[i] *= n;\n      }\n    },\n     // 1D-IFFT\n    bt1d : function(re, im) {\n      core.fft(re, im, -1);\n    },\n    // 2D-FFT Not very useful if the number of rows have to be equal to cols\n    fft2d : function(re, im) {\n      var tre = [],\n          tim = [],\n          i = 0;\n      // x-axis\n      for(var y=0; y<_n; y++) {\n        i = y*_n;\n        for(var x1=0; x1<_n; x1++) {\n          tre[x1] = re[x1 + i];\n          tim[x1] = im[x1 + i];\n        }\n        core.fft1d(tre, tim);\n        for(var x2=0; x2<_n; x2++) {\n          re[x2 + i] = tre[x2];\n          im[x2 + i] = tim[x2];\n        }\n      }\n      // y-axis\n      for(var x=0; x<_n; x++) {\n        for(var y1=0; y1<_n; y1++) {\n          i = x + y1*_n;\n          tre[y1] = re[i];\n          tim[y1] = im[i];\n        }\n        core.fft1d(tre, tim);\n        for(var y2=0; y2<_n; y2++) {\n          i = x + y2*_n;\n          re[i] = tre[y2];\n          im[i] = tim[y2];\n        }\n      }\n    },\n    // 2D-IFFT\n    ifft2d : function(re, im) {\n      var tre = [],\n          tim = [],\n          i = 0;\n      // x-axis\n      for(var y=0; y<_n; y++) {\n        i = y*_n;\n        for(var x1=0; x1<_n; x1++) {\n          tre[x1] = re[x1 + i];\n          tim[x1] = im[x1 + i];\n        }\n        core.ifft1d(tre, tim);\n        for(var x2=0; x2<_n; x2++) {\n          re[x2 + i] = tre[x2];\n          im[x2 + i] = tim[x2];\n        }\n      }\n      // y-axis\n      for(var x=0; x<_n; x++) {\n        for(var y1=0; y1<_n; y1++) {\n          i = x + y1*_n;\n          tre[y1] = re[i];\n          tim[y1] = im[i];\n        }\n        core.ifft1d(tre, tim);\n        for(var y2=0; y2<_n; y2++) {\n          i = x + y2*_n;\n          re[i] = tre[y2];\n          im[i] = tim[y2];\n        }\n      }\n    },\n    // core operation of FFT\n    fft : function(re, im, inv) {\n      var d, h, ik, m, tmp, wr, wi, xr, xi,\n          n4 = _n >> 2;\n      // bit reversal\n      for(var l=0; l<_n; l++) {\n        m = _bitrev[l];\n        if(l < m) {\n          tmp = re[l];\n          re[l] = re[m];\n          re[m] = tmp;\n          tmp = im[l];\n          im[l] = im[m];\n          im[m] = tmp;\n        }\n      }\n      // butterfly operation\n      for(var k=1; k<_n; k<<=1) {\n        h = 0;\n        d = _n/(k << 1);\n        for(var j=0; j<k; j++) {\n          wr = _cstb[h + n4];\n          wi = inv*_cstb[h];\n          for(var i=j; i<_n; i+=(k<<1)) {\n            ik = i + k;\n            xr = wr*re[ik] + wi*im[ik];\n            xi = wr*im[ik] - wi*re[ik];\n            re[ik] = re[i] - xr;\n            re[i] += xr;\n            im[ik] = im[i] - xi;\n            im[i] += xi;\n          }\n          h += d;\n        }\n      }\n    },\n    // initialize the array (supports TypedArray)\n    _initArray : function() {\n      if(typeof Uint32Array !== 'undefined') {\n        _bitrev = new Uint32Array(_n);\n      } else {\n        _bitrev = [];\n      }\n      if(typeof Float64Array !== 'undefined') {\n        _cstb = new Float64Array(_n*1.25);\n      } else {\n        _cstb = [];\n      }\n    },\n    // zero padding\n    _paddingZero : function() {\n      // TODO\n    },\n    // makes bit reversal table\n    _makeBitReversalTable : function() {\n      var i = 0,\n          j = 0,\n          k = 0;\n      _bitrev[0] = 0;\n      while(++i < _n) {\n        k = _n >> 1;\n        while(k <= j) {\n          j -= k;\n          k >>= 1;\n        }\n        j += k;\n        _bitrev[i] = j;\n      }\n    },\n    // makes trigonometiric function table\n    _makeCosSinTable : function() {\n      var n2 = _n >> 1,\n          n4 = _n >> 2,\n          n8 = _n >> 3,\n          n2p4 = n2 + n4,\n          t = Math.sin(Math.PI/_n),\n          dc = 2*t*t,\n          ds = Math.sqrt(dc*(2 - dc)),\n          c = _cstb[n4] = 1,\n          s = _cstb[0] = 0;\n      t = 2*dc;\n      for(var i=1; i<n8; i++) {\n        c -= dc;\n        dc += t*c;\n        s += ds;\n        ds -= t*s;\n        _cstb[i] = s;\n        _cstb[n4 - i] = c;\n      }\n      if(n8 !== 0) {\n        _cstb[n8] = Math.sqrt(0.5);\n      }\n      for(var j=0; j<n4; j++) {\n        _cstb[n2 - j]  = _cstb[j];\n      }\n      for(var k=0; k<n2p4; k++) {\n        _cstb[k + n2] = -_cstb[k];\n      }\n    }\n  };\n  // aliases (public APIs)\n  var apis = ['init', 'fft1d', 'ifft1d', 'fft2d', 'ifft2d'];\n  for(var i=0; i<apis.length; i++) {\n    FFT[apis[i]] = core[apis[i]];\n  }\n  FFT.bt = core.bt1d;\n  FFT.fft = core.fft1d;\n  FFT.ifft = core.ifft1d;\n  \n  return FFT;\n}).call(this);\n","'use strict'\n\nvar FFT = require('./fftlib');\n\nvar FFTUtils= {\n    DEBUG : false,\n\n    /**\n     * Calculates the inverse of a 2D Fourier transform\n     *\n     * @param ft\n     * @param ftRows\n     * @param ftCols\n     * @return\n     */\n    ifft2DArray : function(ft, ftRows, ftCols){\n        var tempTransform = new Array(ftRows * ftCols);\n        var nRows = ftRows / 2;\n        var nCols = (ftCols - 1) * 2;\n        // reverse transform columns\n        FFT.init(nRows);\n        var tmpCols = {re: new Array(nRows), im: new Array(nRows)};\n        for (var iCol = 0; iCol < ftCols; iCol++) {\n            for (var iRow = nRows - 1; iRow >= 0; iRow--) {\n                tmpCols.re[iRow] = ft[(iRow * 2) * ftCols + iCol];\n                tmpCols.im[iRow] = ft[(iRow * 2 + 1) * ftCols + iCol];\n            }\n            //Unnormalized inverse transform\n            FFT.bt(tmpCols.re, tmpCols.im);\n            for (var iRow = nRows - 1; iRow >= 0; iRow--) {\n                tempTransform[(iRow * 2) * ftCols + iCol] = tmpCols.re[iRow];\n                tempTransform[(iRow * 2 + 1) * ftCols + iCol] = tmpCols.im[iRow];\n            }\n        }\n\n        // reverse row transform\n        var finalTransform = new Array(nRows * nCols);\n        FFT.init(nCols);\n        var tmpRows = {re: new Array(nCols), im: new Array(nCols)};\n        var scale = nCols * nRows;\n        for (var iRow = 0; iRow < ftRows; iRow += 2) {\n            tmpRows.re[0] = tempTransform[iRow * ftCols];\n            tmpRows.im[0] = tempTransform[(iRow + 1) * ftCols];\n            for (var iCol = 1; iCol < ftCols; iCol++) {\n                tmpRows.re[iCol] = tempTransform[iRow * ftCols + iCol];\n                tmpRows.im[iCol] = tempTransform[(iRow + 1) * ftCols + iCol];\n                tmpRows.re[nCols - iCol] = tempTransform[iRow * ftCols + iCol];\n                tmpRows.im[nCols - iCol] = -tempTransform[(iRow + 1) * ftCols + iCol];\n            }\n            //Unnormalized inverse transform\n            FFT.bt(tmpRows.re, tmpRows.im);\n\n            var indexB = (iRow / 2) * nCols;\n            for (var iCol = nCols - 1; iCol >= 0; iCol--) {\n                finalTransform[indexB + iCol] = tmpRows.re[iCol] / scale;\n            }\n        }\n        return finalTransform;\n    },\n    /**\n     * Calculates the fourier transform of a matrix of size (nRows,nCols) It is\n     * assumed that both nRows and nCols are a power of two\n     *\n     * On exit the matrix has dimensions (nRows * 2, nCols / 2 + 1) where the\n     * even rows contain the real part and the odd rows the imaginary part of the\n     * transform\n     * @param data\n     * @param nRows\n     * @param nCols\n     * @return\n     */\n    fft2DArray:function(data, nRows, nCols, opt) {\n        var options = Object.assign({},{inplace:true})\n        var ftCols = (nCols / 2 + 1);\n        var ftRows = nRows * 2;\n        var tempTransform = new Array(ftRows * ftCols);\n        FFT.init(nCols);\n        // transform rows\n        var tmpRows = {re: new Array(nCols), im: new Array(nCols)};\n        var row1 = {re: new Array(nCols), im: new Array(nCols)}\n        var row2 = {re: new Array(nCols), im: new Array(nCols)}\n        var index, iRow0, iRow1, iRow2, iRow3;\n        for (var iRow = 0; iRow < nRows / 2; iRow++) {\n            index = (iRow * 2) * nCols;\n            tmpRows.re = data.slice(index, index + nCols);\n\n            index = (iRow * 2 + 1) * nCols;\n            tmpRows.im = data.slice(index, index + nCols);\n\n            FFT.fft1d(tmpRows.re, tmpRows.im);\n\n            this.reconstructTwoRealFFT(tmpRows, row1, row2);\n            //Now lets put back the result into the output array\n            iRow0 = (iRow * 4) * ftCols;\n            iRow1 = (iRow * 4 + 1) * ftCols;\n            iRow2 = (iRow * 4 + 2) * ftCols;\n            iRow3 = (iRow * 4 + 3) * ftCols;\n            for (var k = ftCols - 1; k >= 0; k--) {\n                tempTransform[iRow0 + k] = row1.re[k];\n                tempTransform[iRow1 + k] = row1.im[k];\n                tempTransform[iRow2 + k] = row2.re[k];\n                tempTransform[iRow3 + k] = row2.im[k];\n            }\n        }\n\n        //console.log(tempTransform);\n        row1 = null;\n        row2 = null;\n        // transform columns\n        var finalTransform = new Array(ftRows * ftCols);\n\n        FFT.init(nRows);\n        var tmpCols = {re: new Array(nRows), im: new Array(nRows)};\n        for (var iCol = ftCols - 1; iCol >= 0; iCol--) {\n            for (var iRow = nRows - 1; iRow >= 0; iRow--) {\n                tmpCols.re[iRow] = tempTransform[(iRow * 2) * ftCols + iCol];\n                tmpCols.im[iRow] = tempTransform[(iRow * 2 + 1) * ftCols + iCol];\n                //TODO Chech why this happens\n                if(isNaN(tmpCols.re[iRow])){\n                    tmpCols.re[iRow]=0;\n                }\n                if(isNaN(tmpCols.im[iRow])){\n                    tmpCols.im[iRow]=0;\n                }\n            }\n            FFT.fft1d(tmpCols.re, tmpCols.im);\n            for (var iRow = nRows - 1; iRow >= 0; iRow--) {\n                finalTransform[(iRow * 2) * ftCols + iCol] = tmpCols.re[iRow];\n                finalTransform[(iRow * 2 + 1) * ftCols + iCol] = tmpCols.im[iRow];\n            }\n        }\n\n        //console.log(finalTransform);\n        return finalTransform;\n\n    },\n    /**\n     *\n     * @param fourierTransform\n     * @param realTransform1\n     * @param realTransform2\n     *\n     * Reconstructs the individual Fourier transforms of two simultaneously\n     * transformed series. Based on the Symmetry relationships (the asterisk\n     * denotes the complex conjugate)\n     *\n     * F_{N-n} = F_n^{*} for a purely real f transformed to F\n     *\n     * G_{N-n} = G_n^{*} for a purely imaginary g transformed to G\n     *\n     */\n    reconstructTwoRealFFT:function(fourierTransform, realTransform1, realTransform2) {\n        var length = fourierTransform.re.length;\n\n        // the components n=0 are trivial\n        realTransform1.re[0] = fourierTransform.re[0];\n        realTransform1.im[0] = 0.0;\n        realTransform2.re[0] = fourierTransform.im[0];\n        realTransform2.im[0] = 0.0;\n        var rm, rp, im, ip, j;\n        for (var i = length / 2; i > 0; i--) {\n            j = length - i;\n            rm = 0.5 * (fourierTransform.re[i] - fourierTransform.re[j]);\n            rp = 0.5 * (fourierTransform.re[i] + fourierTransform.re[j]);\n            im = 0.5 * (fourierTransform.im[i] - fourierTransform.im[j]);\n            ip = 0.5 * (fourierTransform.im[i] + fourierTransform.im[j]);\n            realTransform1.re[i] = rp;\n            realTransform1.im[i] = im;\n            realTransform1.re[j] = rp;\n            realTransform1.im[j] = -im;\n            realTransform2.re[i] = ip;\n            realTransform2.im[i] = -rm;\n            realTransform2.re[j] = ip;\n            realTransform2.im[j] = rm;\n        }\n    },\n\n    /**\n     * In place version of convolute 2D\n     *\n     * @param ftSignal\n     * @param ftFilter\n     * @param ftRows\n     * @param ftCols\n     * @return\n     */\n    convolute2DI:function(ftSignal, ftFilter, ftRows, ftCols) {\n        var re, im;\n        for (var iRow = 0; iRow < ftRows / 2; iRow++) {\n            for (var iCol = 0; iCol < ftCols; iCol++) {\n                //\n                re = ftSignal[(iRow * 2) * ftCols + iCol]\n                    * ftFilter[(iRow * 2) * ftCols + iCol]\n                    - ftSignal[(iRow * 2 + 1) * ftCols + iCol]\n                    * ftFilter[(iRow * 2 + 1) * ftCols + iCol];\n                im = ftSignal[(iRow * 2) * ftCols + iCol]\n                    * ftFilter[(iRow * 2 + 1) * ftCols + iCol]\n                    + ftSignal[(iRow * 2 + 1) * ftCols + iCol]\n                    * ftFilter[(iRow * 2) * ftCols + iCol];\n                //\n                ftSignal[(iRow * 2) * ftCols + iCol] = re;\n                ftSignal[(iRow * 2 + 1) * ftCols + iCol] = im;\n            }\n        }\n    },\n    /**\n     *\n     * @param data\n     * @param kernel\n     * @param nRows\n     * @param nCols\n     * @returns {*}\n     */\n    convolute:function(data, kernel, nRows, nCols, opt) {\n        var ftSpectrum = new Array(nCols * nRows);\n        for (var i = 0; i<nRows * nCols; i++) {\n            ftSpectrum[i] = data[i];\n        }\n\n        ftSpectrum = this.fft2DArray(ftSpectrum, nRows, nCols);\n\n\n        var dimR = kernel.length;\n        var dimC = kernel[0].length;\n        var ftFilterData = new Array(nCols * nRows);\n        for(var i = 0; i < nCols * nRows; i++) {\n            ftFilterData[i] = 0;\n        }\n\n        var iRow, iCol;\n        var shiftR = Math.floor((dimR - 1) / 2);\n        var shiftC = Math.floor((dimC - 1) / 2);\n        for (var ir = 0; ir < dimR; ir++) {\n            iRow = (ir - shiftR + nRows) % nRows;\n            for (var ic = 0; ic < dimC; ic++) {\n                iCol = (ic - shiftC + nCols) % nCols;\n                ftFilterData[iRow * nCols + iCol] = kernel[ir][ic];\n            }\n        }\n        ftFilterData = this.fft2DArray(ftFilterData, nRows, nCols);\n\n        var ftRows = nRows * 2;\n        var ftCols = nCols / 2 + 1;\n        this.convolute2DI(ftSpectrum, ftFilterData, ftRows, ftCols);\n\n        return this.ifft2DArray(ftSpectrum, ftRows, ftCols);\n    },\n\n\n    toRadix2:function(data, nRows, nCols) {\n        var i, j, irow, icol;\n        var cols = nCols, rows = nRows, prows=0, pcols=0;\n        if(!(nCols !== 0 && (nCols & (nCols - 1)) === 0)) {\n            //Then we have to make a pading to next radix2\n            cols = 0;\n            while((nCols>>++cols)!=0);\n            cols=1<<cols;\n            pcols = cols-nCols;\n        }\n        if(!(nRows !== 0 && (nRows & (nRows - 1)) === 0)) {\n            //Then we have to make a pading to next radix2\n            rows = 0;\n            while((nRows>>++rows)!=0);\n            rows=1<<rows;\n            prows = (rows-nRows)*cols;\n        }\n        if(rows==nRows&&cols==nCols)//Do nothing. Returns the same input!!! Be careful\n            return {data:data, rows:nRows, cols:nCols};\n\n        var output = new Array(rows*cols);\n        var shiftR = Math.floor((rows-nRows)/2)-nRows;\n        var shiftC = Math.floor((cols-nCols)/2)-nCols;\n\n        for( i = 0; i < rows; i++) {\n            irow = i*cols;\n            icol = ((i-shiftR) % nRows) * nCols;\n            for( j = 0; j < cols; j++) {\n                output[irow+j] = data[(icol+(j-shiftC) % nCols) ];\n            }\n        }\n        return {data:output, rows:rows, cols:cols};\n    },\n\n    /**\n     * Crop the given matrix to fit the corresponding number of rows and columns\n     */\n    crop:function(data, rows, cols, nRows, nCols, opt) {\n\n        if(rows == nRows && cols == nCols)//Do nothing. Returns the same input!!! Be careful\n            return data;\n\n        var options = Object.assign({}, opt);\n\n        var output = new Array(nCols*nRows);\n\n        var shiftR = Math.floor((rows-nRows)/2);\n        var shiftC = Math.floor((cols-nCols)/2);\n        var destinyRow, sourceRow, i, j;\n        for( i = 0; i < nRows; i++) {\n            destinyRow = i*nCols;\n            sourceRow = (i+shiftR)*cols;\n            for( j = 0;j < nCols; j++) {\n                output[destinyRow+j] = data[sourceRow+(j+shiftC)];\n            }\n        }\n\n        return output;\n    }\n}\n\nmodule.exports = FFTUtils;\n","'use strict';\n\nexports.FFTUtils = require(\"./FFTUtils\");\nexports.FFT = require('./fftlib');\n","export function matrix2Array(input) {\n  let inputData = input;\n  let nRows, nCols;\n  if (typeof input[0] !== 'number') {\n    nRows = input.length;\n    nCols = input[0].length;\n    inputData = new Array(nRows * nCols);\n    for (let i = 0; i < nRows; i++) {\n      for (let j = 0; j < nCols; j++) {\n        inputData[i * nCols + j] = input[i][j];\n      }\n    }\n  } else {\n    let tmp = Math.sqrt(input.length);\n    if (Number.isInteger(tmp)) {\n      nRows = tmp;\n      nCols = tmp;\n    }\n  }\n\n  return { data: inputData, rows: nRows, cols: nCols };\n}\n","import { FFTUtils } from 'ml-fft';\n\nimport { matrix2Array } from './util/matrix2Array';\n\nexport function convolutionFFT(input, kernel, opt) {\n  let tmp = matrix2Array(input);\n  let inputData = tmp.data;\n  let options = Object.assign(\n    { normalize: false, divisor: 1, rows: tmp.rows, cols: tmp.cols },\n    opt,\n  );\n\n  let nRows, nCols;\n  if (options.rows && options.cols) {\n    nRows = options.rows;\n    nCols = options.cols;\n  } else {\n    throw new Error(`Invalid number of rows or columns ${nRows} ${nCols}`);\n  }\n\n  let divisor = options.divisor;\n  let kHeight = kernel.length;\n  let kWidth = kernel[0].length;\n  if (options.normalize) {\n    divisor = 0;\n    for (let i = 0; i < kHeight; i++) {\n      for (let j = 0; j < kWidth; j++) divisor += kernel[i][j];\n    }\n  }\n  if (divisor === 0) {\n    throw new RangeError('convolution: The divisor is equal to zero');\n  }\n\n  let radix2Sized = FFTUtils.toRadix2(inputData, nRows, nCols);\n  let conv = FFTUtils.convolute(\n    radix2Sized.data,\n    kernel,\n    radix2Sized.rows,\n    radix2Sized.cols,\n  );\n  conv = FFTUtils.crop(conv, radix2Sized.rows, radix2Sized.cols, nRows, nCols);\n\n  if (divisor !== 0 && divisor !== 1) {\n    for (let i = 0; i < conv.length; i++) {\n      conv[i] /= divisor;\n    }\n  }\n\n  return conv;\n}\n","import { matrix2Array } from './util/matrix2Array';\n\nexport function convolutionDirect(input, kernel, opt) {\n  let tmp = matrix2Array(input);\n  let inputData = tmp.data;\n  let options = Object.assign(\n    { normalize: false, divisor: 1, rows: tmp.rows, cols: tmp.cols },\n    opt,\n  );\n\n  let nRows, nCols;\n  if (options.rows && options.cols) {\n    nRows = options.rows;\n    nCols = options.cols;\n  } else {\n    throw new Error(`Invalid number of rows or columns ${nRows} ${nCols}`);\n  }\n\n  let divisor = options.divisor;\n  let kHeight = kernel.length;\n  let kWidth = kernel[0].length;\n  let index, sum, kVal, row, col;\n  if (options.normalize) {\n    divisor = 0;\n    for (let i = 0; i < kHeight; i++) {\n      for (let j = 0; j < kWidth; j++) divisor += kernel[i][j];\n    }\n  }\n  if (divisor === 0) {\n    throw new RangeError('convolution: The divisor is equal to zero');\n  }\n\n  let output = new Array(nRows * nCols);\n\n  let hHeight = Math.floor(kHeight / 2);\n  let hWidth = Math.floor(kWidth / 2);\n\n  for (let y = 0; y < nRows; y++) {\n    for (let x = 0; x < nCols; x++) {\n      sum = 0;\n      for (let j = 0; j < kHeight; j++) {\n        for (let i = 0; i < kWidth; i++) {\n          kVal = kernel[kHeight - j - 1][kWidth - i - 1];\n          row = (y + j - hHeight + nRows) % nRows;\n          col = (x + i - hWidth + nCols) % nCols;\n          index = row * nCols + col;\n          sum += inputData[index] * kVal;\n        }\n      }\n      index = y * nCols + x;\n      output[index] = sum / divisor;\n    }\n  }\n  return output;\n}\n","'use strict';\n\n/**\n * @class DisjointSet\n */\nclass DisjointSet {\n    constructor() {\n        this.nodes = new Map();\n    }\n\n    /**\n     * Adds an element as a new set\n     * @param {*} value\n     * @return {DisjointSetNode} Object holding the element\n     */\n    add(value) {\n        var node = this.nodes.get(value);\n        if (!node) {\n            node = new DisjointSetNode(value);\n            this.nodes.set(value, node);\n        }\n        return node;\n    }\n\n    /**\n     * Merges the sets that contain x and y\n     * @param {DisjointSetNode} x\n     * @param {DisjointSetNode} y\n     */\n    union(x, y) {\n        const rootX = this.find(x);\n        const rootY = this.find(y);\n        if (rootX === rootY) {\n            return;\n        }\n        if (rootX.rank < rootY.rank) {\n            rootX.parent = rootY;\n        } else if (rootX.rank > rootY.rank) {\n            rootY.parent = rootX;\n        } else {\n            rootY.parent = rootX;\n            rootX.rank++;\n        }\n    }\n\n    /**\n     * Finds and returns the root node of the set that contains node\n     * @param {DisjointSetNode} node\n     * @return {DisjointSetNode}\n     */\n    find(node) {\n        var rootX = node;\n        while (rootX.parent !== null) {\n            rootX = rootX.parent;\n        }\n        var toUpdateX = node;\n        while (toUpdateX.parent !== null) {\n            var toUpdateParent = toUpdateX;\n            toUpdateX = toUpdateX.parent;\n            toUpdateParent.parent = rootX;\n        }\n        return rootX;\n    }\n\n    /**\n     * Returns true if x and y belong to the same set\n     * @param {DisjointSetNode} x\n     * @param {DisjointSetNode} y\n     */\n    connected(x, y) {\n        return this.find(x) === this.find(y);\n    }\n}\n\nmodule.exports = DisjointSet;\n\nfunction DisjointSetNode(value) {\n    this.value = value;\n    this.parent = null;\n    this.rank = 0;\n}\n","import DisjointSet from 'ml-disjoint-set';\n\nconst direction8X = [-1, -1, 0, 1, -1, 0, 1, 1];\nconst direction8Y = [0, -1, -1, -1, 1, 1, 1, 0];\nconst neighbours8 = [null, null, null, null, null, null, null, null];\n\nconst direction4X = [-1, 0, 1, 0];\nconst direction4Y = [0, -1, 0, 1];\nconst neighbours4 = [null, null, null, null];\n\nexport function drainLabelling(data, mask, options = {}) {\n  const { neighbours = 8, width, height } = options;\n\n  let directionX;\n  let directionY;\n  let neighboursList;\n  if (neighbours === 8) {\n    directionX = direction8X;\n    directionY = direction8Y;\n    neighboursList = neighbours8;\n  } else if (neighbours === 4) {\n    directionX = direction4X;\n    directionY = direction4Y;\n    neighboursList = neighbours4;\n  } else {\n    throw new RangeError(`unsupported neighbours count: ${neighbours}`);\n  }\n\n  let sorted = new Array(height * width);\n  for (let i = 0, index = 0; i < height; i++) {\n    for (let j = 0; j < width; j++, index++) {\n      sorted[index] = { value: data[index], row: i, col: j, mask: mask[index] };\n    }\n  }\n\n  sorted.sort((a, b) => a.value - b.value);\n\n  const size = mask.length;\n  const labels = new Array(size);\n  const pixels = new Int16Array(size);\n  const linked = new DisjointSet();\n\n  for (let i = 0, currentLabel = 1; i < mask.length; i++) {\n    let element = sorted[i];\n    if (!element.mask) continue;\n\n    let { row, col, value } = element;\n    let index = col + row * width;\n    let label = labels[index];\n    if (!label) {\n      labels[index] = linked.add(currentLabel++);\n    }\n\n    for (let k = 0; k < neighboursList.length; k++) {\n      let ii = col + directionX[k];\n      let jj = row + directionY[k];\n      if (ii >= 0 && jj >= 0 && ii < width && jj < height) {\n        let neighbor = labels[ii + jj * width];\n        if (!neighbor) {\n          let neighborValue = data[ii + jj * width];\n          if (value < neighborValue) {\n            labels[ii + jj * width] = labels[index];\n          }\n        }\n      }\n    }\n  }\n\n  for (let j = 0; j < height; j++) {\n    for (let i = 0; i < width; i++) {\n      let index = i + j * width;\n      if (mask[index]) {\n        pixels[index] = linked.find(labels[index]).value;\n      }\n    }\n  }\n  return pixels;\n}\n","import DisjointSet from 'ml-disjoint-set';\n\nconst direction4X = [-1, 0];\nconst direction4Y = [0, -1];\nconst neighbours4 = [null, null];\n\nconst direction8X = [-1, -1, 0, 1];\nconst direction8Y = [0, -1, -1, -1];\nconst neighbours8 = [null, null, null, null];\n\nexport function floodFillLabelling(mask, width, height, options) {\n  options = options || {};\n  const neighbours = options.neighbours || 8;\n\n  let directionX;\n  let directionY;\n  let neighboursList;\n  if (neighbours === 8) {\n    directionX = direction8X;\n    directionY = direction8Y;\n    neighboursList = neighbours8;\n  } else if (neighbours === 4) {\n    directionX = direction4X;\n    directionY = direction4Y;\n    neighboursList = neighbours4;\n  } else {\n    throw new RangeError(`unsupported neighbours count: ${neighbours}`);\n  }\n\n  const size = mask.length;\n  const labels = new Array(size);\n  const pixels = new Int16Array(size);\n  const linked = new DisjointSet();\n  let index;\n  let currentLabel = 1;\n  for (let j = 0; j < height; j++) {\n    for (let i = 0; i < width; i++) {\n      // true means out of background\n      let smallestNeighbor = null;\n      index = i + j * width;\n      if (mask[index]) {\n        for (let k = 0; k < neighboursList.length; k++) {\n          let ii = i + directionX[k];\n          let jj = j + directionY[k];\n          if (ii >= 0 && jj >= 0 && ii < width && jj < height) {\n            let neighbor = labels[ii + jj * width];\n            if (!neighbor) {\n              neighboursList[k] = null;\n            } else {\n              neighboursList[k] = neighbor;\n              if (\n                !smallestNeighbor ||\n                neighboursList[k].value < smallestNeighbor.value\n              ) {\n                smallestNeighbor = neighboursList[k];\n              }\n            }\n          }\n        }\n        if (!smallestNeighbor) {\n          labels[index] = linked.add(currentLabel++);\n        } else {\n          labels[index] = smallestNeighbor;\n          for (let k = 0; k < neighboursList.length; k++) {\n            if (neighboursList[k] && neighboursList[k] !== smallestNeighbor) {\n              linked.union(smallestNeighbor, neighboursList[k]);\n            }\n          }\n        }\n      }\n    }\n  }\n  for (let j = 0; j < height; j++) {\n    for (let i = 0; i < width; i++) {\n      index = i + j * width;\n      if (mask[index]) {\n        pixels[index] = linked.find(labels[index]).value;\n      }\n    }\n  }\n  return pixels;\n}\n","import * as convolution from 'ml-matrix-convolution';\n\nimport { drainLabelling } from './drainLabelling';\nimport { floodFillLabelling } from './floodFillLabelling';\n\nconst smallFilter = [\n  [0, 0, 1, 2, 2, 2, 1, 0, 0],\n  [0, 1, 4, 7, 7, 7, 4, 1, 0],\n  [1, 4, 5, 3, 0, 3, 5, 4, 1],\n  [2, 7, 3, -12, -23, -12, 3, 7, 2],\n  [2, 7, 0, -23, -40, -23, 0, 7, 2],\n  [2, 7, 3, -12, -23, -12, 3, 7, 2],\n  [1, 4, 5, 3, 0, 3, 5, 4, 1],\n  [0, 1, 3, 7, 7, 7, 3, 1, 0],\n  [0, 0, 1, 2, 2, 2, 1, 0, 0],\n];\n\n/**\n * Detects all the 2D-peaks in the given spectrum based on center of mass logic.\n * @param {Array<Array>} input - matrix to get the local maxima\n * @param {Object} [options = {}] - options of the method.\n * @param {Array<Array>} [options.nStdDev = 3] - number of times of the standard deviations for the noise level.Float64Array\n * @param {Array<Array>} [options.kernel] - kernel to the convolution step.\n * @param {string} [options.labelling = 'drain'] - select the labelling algorithm to assign pixels.\n * @param {Array<Array>} [options.originalData] - original data useful when the original matrix has values and the input matrix has absolute ones\n * @param {Array<Array>} [options.filteredData] - convoluted data, if it is defined the convolution step is skipped\n */\nexport function findPeaks2DRegion(input, options = {}) {\n  let {\n    nStdDev = 3,\n    kernel = smallFilter,\n    originalData = convolution.matrix2Array(input).data,\n    filteredData,\n    rows: nRows,\n    cols: nCols,\n    labelling = 'drain',\n  } = options;\n\n  let flatten = convolution.matrix2Array(input);\n  let data = flatten.data;\n\n  if (!nRows || !nCols) {\n    nRows = flatten.rows;\n    nCols = flatten.cols;\n  }\n\n  if (!nRows || !nCols) {\n    throw new Error(`Invalid number of rows or columns ${nRows} ${nCols}`);\n  }\n\n  let cs = filteredData;\n  if (!cs) cs = convolution.fft(data, kernel, options);\n\n  let threshold = 0;\n  for (let i = nCols * nRows - 2; i >= 0; i--) {\n    threshold += Math.pow(cs[i] - cs[i + 1], 2);\n  }\n  threshold = (-Math.sqrt(threshold) * nStdDev) / nRows;\n\n  let bitmask = new Uint16Array(nCols * nRows);\n  for (let i = cs.length - 1; i >= 0; i--) {\n    if (cs[i] < threshold) {\n      bitmask[i] = 1;\n    }\n  }\n\n  let pixels;\n  switch (labelling.toLowerCase()) {\n    case 'drain':\n      pixels = drainLabelling(cs, bitmask, {\n        neighbours: 8,\n        width: nCols,\n        height: nRows,\n      });\n      break;\n    case 'floodfill':\n      pixels = floodFillLabelling(bitmask, nCols, nRows, { neighbours: 8 });\n      break;\n    default:\n      throw new Error(`labelling ${labelling} does not support`);\n  }\n\n  return extractPeaks(pixels, {\n    data,\n    nCols,\n    originalData,\n  });\n}\n/**\n Detects all the 2D-peaks in the given spectrum based on the Max logic.\n amc\n */\nexport function findPeaks2DMax(input, options) {\n  let {\n    nStdDev = 3,\n    kernel = smallFilter,\n    originalData = convolution.matrix2Array(input).data,\n    rows: nRows,\n    cols: nCols,\n    filteredData,\n  } = options;\n\n  let flatten = convolution.matrix2Array(input);\n  let data = flatten.data;\n\n  if (!nRows || !nCols) {\n    nRows = flatten.rows;\n    nCols = flatten.cols;\n  }\n\n  if (!nRows || !nCols) {\n    throw new Error(`Invalid number of rows or columns ${nRows} ${nCols}`);\n  }\n\n  let cs = filteredData;\n  if (!cs) cs = convolution.fft(data, kernel, options);\n\n  let threshold = 0;\n  for (let i = nCols * nRows - 2; i >= 0; i--) {\n    threshold += Math.pow(cs[i] - cs[i + 1], 2);\n  }\n  threshold = (-Math.sqrt(threshold) * nStdDev) / nRows;\n\n  let rowI, colI;\n  let tmpIndex = 0;\n  let peakListMax = [];\n  for (let i = 0; i < cs.length; i++) {\n    if (cs[i] < threshold) {\n      //It is a peak?\n      rowI = Math.floor(i / nCols);\n      colI = i % nCols;\n      //Verifies if this point is a peak;\n      if (rowI > 0 && rowI + 1 < nRows && colI + 1 < nCols && colI > 0) {\n        //It is the minimum in the same row\n        if (cs[i] < cs[i + 1] && cs[i] < cs[i - 1]) {\n          //It is the minimum in the previous row\n          tmpIndex = (rowI - 1) * nCols + colI;\n          if (\n            cs[i] < cs[tmpIndex - 1] &&\n            cs[i] < cs[tmpIndex] &&\n            cs[i] < cs[tmpIndex + 1]\n          ) {\n            //It is the minimum in the next row\n            tmpIndex = (rowI + 1) * nCols + colI;\n            if (\n              cs[i] < cs[tmpIndex - 1] &&\n              cs[i] < cs[tmpIndex] &&\n              cs[i] < cs[tmpIndex + 1]\n            ) {\n              peakListMax.push({ x: colI, y: rowI, z: originalData[i] });\n            }\n          }\n        }\n      }\n    }\n  }\n  return peakListMax;\n}\n\nfunction extractPeaks(pixels, options) {\n  const { data, nCols, originalData } = options;\n  //How many different groups we have?\n  let labels = {};\n  let row, col, tmp;\n  for (let i = 0; i < pixels.length; i++) {\n    if (pixels[i] !== 0) {\n      col = i % nCols;\n      row = (i - col) / nCols;\n      if (labels[pixels[i]]) {\n        tmp = labels[pixels[i]];\n        tmp.x += col * data[i];\n        tmp.y += row * data[i];\n        tmp.z += originalData[i];\n        if (col < tmp.minX) tmp.minX = col;\n        if (col > tmp.maxX) tmp.maxX = col;\n        if (row < tmp.minY) tmp.minY = row;\n        if (row > tmp.maxY) tmp.maxY = row;\n      } else {\n        labels[pixels[i]] = {\n          x: col * data[i],\n          y: row * data[i],\n          z: originalData[i],\n          minX: col,\n          maxX: col,\n          minY: row,\n          maxY: row,\n        };\n      }\n    }\n  }\n  let keys = Object.keys(labels);\n  let peakList = new Array(keys.length);\n  for (let i = 0; i < keys.length; i++) {\n    peakList[i] = labels[keys[i]];\n    let zValue = Math.abs(peakList[i].z);\n    peakList[i].x /= zValue;\n    peakList[i].y /= zValue;\n  }\n\n  return peakList;\n}\n","import { v4 as generateID } from '@lukeed/uuid';\nconst { parse, stringify } = JSON;\nexport function addMissingIDs(peaks, options = {}) {\n    const { output = parse(stringify(peaks)) } = options;\n    for (const peak of output) {\n        if (!('id' in peak)) {\n            peak.id = generateID();\n        }\n    }\n    return output;\n}\n//# sourceMappingURL=addMissingIDs.js.map","import { levenbergMarquardt } from 'ml-levenberg-marquardt';\nimport { Gaussian2D } from 'ml-peak-shape-generator';\nconst direction8X = [-1, -1, -1, 0, 0, 1, 1, 1];\nconst direction8Y = [-1, 0, 1, -1, 1, -1, 0, 1];\nconst direction16X = [-2, -2, -2, -2, -2, -1, -1, 0, 0, 1, 1, 2, 2, 2, 2, 2];\nconst direction16Y = [-2, -1, 0, 1, 2, -2, 2, -2, 2, -2, 2, -2, -1, 0, 1, 2];\nexport function determineRealTop(peaks, options) {\n    let { nCols, absoluteData, originalData, minX, maxX, minY, maxY } = options;\n    for (let i = 0; i < peaks.length; i++) {\n        let xIndex = Math.round(peaks[i].x);\n        let yIndex = Math.round(peaks[i].y);\n        let currentIndex = xIndex + yIndex * nCols;\n        let { index, isMax } = determineMax(absoluteData, {\n            xIndex,\n            yIndex,\n            nCols,\n            shell: 1,\n        });\n        currentIndex = isMax\n            ? index\n            : determineMax(absoluteData, {\n                xIndex,\n                yIndex,\n                nCols,\n                shell: 2,\n            }).index;\n        let realTopCoordinates = fitGaussian(originalData, {\n            nCols,\n            index: currentIndex,\n            minY,\n            maxY,\n            minX,\n            maxX,\n        });\n        peaks[i] = Object.assign(peaks[i], realTopCoordinates);\n    }\n    return peaks;\n}\nfunction determineMax(data, options) {\n    let { xIndex, yIndex, shell, nCols } = options;\n    let currentIndex = xIndex + yIndex * nCols;\n    let [directionX, directionY] = shell > 1 ? [direction16X, direction16Y] : [direction8X, direction8Y];\n    let isMax = false;\n    for (let i = 0; i < directionX.length; i++) {\n        let c = xIndex + directionX[i];\n        let r = yIndex + directionY[i];\n        if (data[c + r * nCols] >= data[currentIndex]) {\n            isMax = true;\n            let candidateIndex = c + r * nCols;\n            for (let k = 0; k < direction8Y.length; k++) {\n                let nc = c + direction8X[k];\n                let nr = r + direction8Y[k];\n                if (data[nc + nr * nCols] > data[candidateIndex]) {\n                    isMax = false;\n                    break;\n                }\n            }\n            if (isMax) {\n                currentIndex = candidateIndex;\n            }\n        }\n    }\n    return { index: currentIndex, isMax };\n}\nfunction fitGaussian(data, options) {\n    let { nCols, index, minY, maxY, minX, maxX } = options;\n    let nRows = data.length / nCols;\n    let intervalX = (maxX - minX) / (nCols - 1);\n    let intervalY = (maxY - minY) / (nRows - 1);\n    let col = index % nCols;\n    let row = (index - col) / nCols;\n    let newCol = 1;\n    let newRow = 1;\n    let max = Number.MIN_SAFE_INTEGER;\n    let z = new Array(direction8X.length + 1);\n    let xAxis = new Array(direction8X.length + 1);\n    for (let i = -1, xi = 0; i < 2; i++) {\n        for (let j = -1; j < 2; j++, xAxis[xi] = xi++) {\n            let value = data[col + j + (row + i) * nCols];\n            if (max < value)\n                max = value;\n            z[newCol + j + (newRow + i) * 3] = value;\n        }\n    }\n    for (let i = 0; i < z.length; i++)\n        z[i] /= max;\n    let maxValues = [newCol + 1, newRow + 1, 1.5, 1, 1];\n    let minValues = [newCol - 1, newRow - 1, -1.5, 0.001, 0.001];\n    let initialValues = [newCol, newRow, z[newCol + newRow * 3], 0.2, 0.2];\n    let gradientDifference = [1e-4, 1e-4, 1e-3, 1e-3, 1e-3];\n    let func = paramGaussian2D(intervalX, intervalY, 3);\n    let pFit = levenbergMarquardt({ x: xAxis, y: z }, func, {\n        damping: 1.5,\n        maxIterations: 100,\n        errorTolerance: 1e-8,\n        initialValues,\n        gradientDifference,\n        maxValues,\n        minValues,\n    }).parameterValues;\n    return {\n        x: pFit[0] + col - 1,\n        y: pFit[1] + row - 1,\n        z: pFit[2] * max,\n    };\n}\nfunction paramGaussian2D(intervalX, intervalY, nCols) {\n    const gaussian2D = new Gaussian2D();\n    return (p) => {\n        return (t) => {\n            let nL = p.length / 5;\n            let result = 0;\n            let xIndex = t % nCols;\n            let yIndex = (t - xIndex) / nCols;\n            for (let i = 0; i < nL; i++) {\n                gaussian2D.fwhm = { x: p[i + 3 * nL], y: p[i + 4 * nL] };\n                result +=\n                    p[i + 2 * nL] *\n                        gaussian2D.fct((xIndex - p[i]) * intervalX, (yIndex - p[i + nL]) * intervalY);\n            }\n            return result;\n        };\n    };\n}\n//# sourceMappingURL=determineRealTop.js.map","export function getKernel(options = {}) {\n    let { sigma = 1.4, xLength = 9, yLength = 9 } = options;\n    let factor = -40 / laplacianOfGaussian(0, 0, sigma);\n    const xCenter = (xLength - 1) / 2;\n    const yCenter = (yLength - 1) / 2;\n    let matrix = new Array(xLength);\n    for (let x = 0; x < xLength; x++) {\n        matrix[x] = new Array(yLength);\n        for (let y = 0; y < yLength; y++) {\n            matrix[x][y] =\n                laplacianOfGaussian(x - xCenter, y - yCenter, sigma) * factor;\n        }\n    }\n    return matrix;\n}\nconst laplacianOfGaussian = (x, y, sigma) => {\n    let factor = -(Math.pow(x, 2) + Math.pow(y, 2)) / 2 / Math.pow(sigma, 2);\n    return -(1 / Math.PI / Math.pow(sigma, 4)) * (1 + factor) * Math.exp(factor);\n};\n//# sourceMappingURL=getKernel.js.map","let diagonalError = 0.05;\nlet tolerance = 0.05;\nexport function clean(peaks, threshold) {\n    let max = Number.NEGATIVE_INFINITY;\n    // double min = Double.MAX_VALUE;\n    for (let i = peaks.length - 1; i >= 0; i--) {\n        if (Math.abs(peaks[i].z) > max) {\n            max = Math.abs(peaks[i].z);\n        }\n    }\n    max *= threshold;\n    for (let i = peaks.length - 1; i >= 0; i--) {\n        if (Math.abs(peaks[i].z) < max) {\n            peaks.splice(i, 1);\n        }\n    }\n    return peaks;\n}\nexport function enhanceSymmetry(signals) {\n    let properties = initializeProperties(signals);\n    let output = signals.slice();\n    // First step of the optimization: Symmetry validation\n    let hits;\n    for (let i = output.length - 1; i >= 0; i--) {\n        let signal = output[i];\n        if (signal.peaks && signal.peaks.length > 1) {\n            properties[i][1]++;\n        }\n        if (properties[i][0] === 1) {\n            let index = exist(output, properties, signal, -1, true);\n            if (index >= 0) {\n                properties[i][1] += 2;\n                properties[index][1] += 2;\n            }\n        }\n    }\n    // Second step of the optimization: Diagonal image existence\n    for (let i = output.length - 1; i >= 0; i--) {\n        let signal = output[i];\n        if (properties[i][0] === 0) {\n            hits = checkCrossPeaks(output, properties, signal, true);\n            properties[i][1] += hits;\n            // checkCrossPeaks(output, properties, signal, false);\n        }\n    }\n    // Now, each peak have a score between 0 and 4, we can complete the patterns which\n    // contains peaks with high scores, and finally, we can remove peaks with scores 0 and 1\n    let count = 0;\n    for (let i = output.length - 1; i >= 0; i--) {\n        if (properties[i][0] !== 0 && properties[i][1] > 2) {\n            count++;\n            count += completeMissingIfNeeded(output, properties, output[i], properties[i]);\n        }\n        if (properties[i][1] >= 2 && properties[i][0] === 0) {\n            count++;\n        }\n    }\n    let toReturn = new Array(count);\n    count--;\n    for (let i = output.length - 1; i >= 0; i--) {\n        if ((properties[i][0] !== 0 && properties[i][1] > 2) ||\n            (properties[i][0] === 0 && properties[i][1] > 1)) {\n            toReturn[count--] = output[i];\n        }\n    }\n    return toReturn;\n}\n// export function alignDimensions(signals2D, references) {\n//   // For each reference dimension\n//   for (let i = 0; i < references.length; i++) {\n//     let ref = references[i];\n//     if (ref) {\n//       alignSingleDimension(signals2D, ref);\n//     }\n//   }\n// }\nfunction completeMissingIfNeeded(output, properties, thisSignal, thisProp) {\n    // Check for symmetry\n    let index = exist(output, properties, thisSignal, -thisProp[0], true);\n    let addedPeaks = 0;\n    let newSignal;\n    let tmpProp = null;\n    if (index < 0) {\n        // If this signal have no a symmetry image, we have to include it\n        newSignal = {\n            x: {\n                nucleus: thisSignal.x.nucleus,\n                resolution: thisSignal.x.resolution,\n                delta: thisSignal.y.delta,\n            },\n            y: {\n                nucleus: thisSignal.y.nucleus,\n                resolution: thisSignal.y.resolution,\n                delta: thisSignal.x.delta,\n            },\n            peaks: [{ x: thisSignal.y.delta, y: thisSignal.x.delta, z: 1 }],\n        };\n        output.push(newSignal);\n        tmpProp = [-thisProp[0], thisProp[1]];\n        properties.push(tmpProp);\n        addedPeaks++;\n    }\n    // Check for diagonal peaks\n    let signal;\n    let diagX = false;\n    let diagY = false;\n    for (let j = output.length - 1; j >= 0; j--) {\n        signal = output[j];\n        if (properties[j][0] === 0) {\n            if (Math.abs(signal.x.delta - thisSignal.x.delta) < diagonalError) {\n                diagX = true;\n            }\n            if (Math.abs(signal.y.delta - thisSignal.y.delta) < diagonalError) {\n                diagY = true;\n            }\n        }\n    }\n    if (!diagX) {\n        newSignal = {\n            x: {\n                delta: thisSignal.y.delta,\n                nucleus: thisSignal.x.nucleus,\n                resolution: thisSignal.x.resolution,\n            },\n            y: {\n                delta: thisSignal.x.delta,\n                nucleus: thisSignal.y.nucleus,\n                resolution: thisSignal.y.resolution,\n            },\n            peaks: [{ x: thisSignal.x.delta, y: thisSignal.x.delta, z: 1 }],\n        };\n        newSignal.peaks = [{ x: thisSignal.x.delta, y: thisSignal.x.delta, z: 1 }];\n        output.push(newSignal);\n        tmpProp = [0, thisProp[1]];\n        properties.push(tmpProp);\n        addedPeaks++;\n    }\n    if (!diagY) {\n        newSignal = {\n            x: {\n                delta: thisSignal.y.delta,\n                nucleus: thisSignal.x.nucleus,\n                resolution: thisSignal.x.resolution,\n            },\n            y: {\n                delta: thisSignal.y.delta,\n                nucleus: thisSignal.y.nucleus,\n                resolution: thisSignal.y.resolution,\n            },\n            peaks: [{ x: thisSignal.y.delta, y: thisSignal.y.delta, z: 1 }],\n        };\n        output.push(newSignal);\n        tmpProp = [0, thisProp[1]];\n        properties.push(tmpProp);\n        addedPeaks++;\n    }\n    return addedPeaks;\n}\n// Check for any diagonal peak that match this cross peak\nfunction checkCrossPeaks(output, properties, signal, updateProperties) {\n    let hits = 0;\n    let shift = signal.x.delta * 4;\n    let crossPeaksX = [];\n    let crossPeaksY = [];\n    let cross;\n    for (let i = output.length - 1; i >= 0; i--) {\n        cross = output[i];\n        if (properties[i][0] !== 0) {\n            if (Math.abs(cross.x.delta - signal.x.delta) < diagonalError) {\n                hits++;\n                if (updateProperties) {\n                    properties[i][1]++;\n                }\n                crossPeaksX.push(i);\n                shift += cross.x.delta;\n            }\n            else if (Math.abs(cross.y.delta - signal.y.delta) < diagonalError) {\n                hits++;\n                if (updateProperties) {\n                    properties[i][1]++;\n                }\n                crossPeaksY.push(i);\n                shift += cross.y.delta;\n            }\n        }\n    }\n    // Update found crossPeaks and diagonal peak\n    shift /= crossPeaksX.length + crossPeaksY.length + 4;\n    if (crossPeaksX.length > 0) {\n        for (let i = crossPeaksX.length - 1; i >= 0; i--) {\n            output[crossPeaksX[i]].x.delta = shift;\n        }\n    }\n    if (crossPeaksY.length > 0) {\n        for (let i = crossPeaksY.length - 1; i >= 0; i--) {\n            output[crossPeaksY[i]].y.delta = shift;\n        }\n    }\n    signal.x.delta = shift;\n    signal.y.delta = shift;\n    return hits;\n}\nfunction exist(output, properties, signal, type, symmetricSearch) {\n    for (let i = output.length - 1; i >= 0; i--) {\n        if (properties[i][0] === type) {\n            if (distanceTo(signal, output[i], symmetricSearch) < tolerance) {\n                if (!symmetricSearch) {\n                    let shiftX = (output[i].x.delta + signal.x.delta) / 2.0;\n                    let shiftY = (output[i].y.delta + signal.y.delta) / 2.0;\n                    output[i].x.delta = shiftX;\n                    output[i].y.delta = shiftY;\n                    signal.x.delta = shiftX;\n                    signal.y.delta = shiftY;\n                }\n                else {\n                    let shiftX = signal.x.delta;\n                    let shiftY = output[i].x.delta;\n                    output[i].y.delta = shiftX;\n                    signal.y.delta = shiftY;\n                }\n                return i;\n            }\n        }\n    }\n    return -1;\n}\n/**\n * Try to determine the position of each signal within the spectrum matrix.\n * Peaks could be of 3 types: upper diagonal, diagonal or under diagonal 1,0,-1\n * respectively.\n * @param {Array} signals\n * @return {*} A matrix containing the properties of each signal\n * @private\n */\nfunction initializeProperties(signals) {\n    let signalsProperties = new Array(signals.length);\n    for (let i = signals.length - 1; i >= 0; i--) {\n        signalsProperties[i] = [0, 0];\n        // We check if it is a diagonal peak\n        if (Math.abs(signals[i].x.delta - signals[i].y.delta) <= diagonalError) {\n            signalsProperties[i][1] = 1;\n            let shift = (signals[i].x.delta * 2 + signals[i].y.delta) / 3.0;\n            signals[i].x.delta = shift;\n            signals[i].y.delta = shift;\n        }\n        else if (signals[i].x.delta - signals[i].y.delta > 0) {\n            signalsProperties[i][0] = 1;\n        }\n        else {\n            signalsProperties[i][0] = -1;\n        }\n    }\n    return signalsProperties;\n}\n/**\n * This function calculates the distance between 2 nmr signals . If toImage is true,\n * it will interchange x by y in the distance calculation for the second signal.\n * @param {object} a\n * @param {object} b\n * @param {boolean} toImage\n * @return {number}\n * @private\n */\nfunction distanceTo(a, b, toImage) {\n    if (!toImage) {\n        return Math.sqrt(Math.pow(a.x.delta - b.x.delta, 2) + Math.pow(a.y.delta - b.y.delta, 2));\n    }\n    else {\n        return Math.sqrt(Math.pow(a.x.delta - b.y.delta, 2) + Math.pow(a.y.delta - b.x.delta, 2));\n    }\n}\n// type Signal2DWithHighlight = MakeMandatory<NMRSignal2D, '_highlight'>;\n// function checkHighlight(signals2D: NMRSignal2D[]): asserts signals2D is Signal2DwithHighlight[] {\n//   for (let signal of signals2D) {\n//     if (!signal._highlight) throw new Error('there is not _hightlight property');\n//     if (!signal.nucleusX) throw new Error('there is not nucleusX property');\n//     if (!signal.nucleusY) throw new Error('there is not nucleusY property')\n//   }\n// }\n// function alignSingleDimension(signals2D: NMRSignal2D[], references) {\n//   // For each 2D signal\n//   for (let i = 0; i < signals2D.length; i++) {\n//     let signal2D = signals2D[i];\n//     for (let j = 0; j < references.length; j++) {\n//       const center = (references[j].startX + references[j].stopX) / 2;\n//       const width = Math.abs(references[j].startX - references[j].stopX) / 2;\n//       if (signal2D.nucleusX === references[j].nucleus) {\n//         // The 2D peak overlaps with the 1D signal\n//         if (Math.abs(signal2D.x.delta - center) <= width) {\n//           signal2D._highlight.push(references[j]._highlight[0]);\n//         }\n//       }\n//       if (signal2D.nucleusY === references[j].nucleus) {\n//         if (Math.abs(signal2D.y.delta - center) <= width) {\n//           signal2D._highlight.push(references[j]._highlight[0]);\n//         }\n//       }\n//     }\n//   }\n// }\n//# sourceMappingURL=peakOptimizer.js.map","import { v4 as generateID } from '@lukeed/uuid';\nexport function formatZones(signals) {\n    let zones = [];\n    for (const signal of signals) {\n        let minMax1 = [Number.MAX_VALUE, 0];\n        let minMax2 = [Number.MAX_VALUE, 0];\n        for (const peak of signal.peaks || []) {\n            if (peak.minX < minMax1[0]) {\n                minMax1[0] = peak.minX;\n            }\n            if (peak.maxX > minMax1[1]) {\n                minMax1[1] = peak.maxX;\n            }\n            if (peak.minY < minMax2[0]) {\n                minMax2[0] = peak.minY;\n            }\n            if (peak.maxY > minMax2[1]) {\n                minMax2[1] = peak.maxY;\n            }\n        }\n        zones.push({\n            id: generateID(),\n            x: {\n                from: minMax1[0],\n                to: minMax1[1],\n            },\n            y: {\n                from: minMax2[0],\n                to: minMax2[1],\n            },\n            signals: [signal],\n        });\n    }\n    return zones;\n}\n//# sourceMappingURL=formatZone.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport { Matrix } from 'ml-matrix';\nimport * as convolution from 'ml-matrix-convolution';\nimport * as matrixPeakFinders from 'ml-matrix-peaks-finder';\nimport simpleClustering from 'ml-simple-clustering';\nimport { addMissingIDs } from '../peaks/util/addMissingIDs';\nimport { determineRealTop } from '../peaks/util/determineRealTop';\nimport { getKernel } from '../peaks/util/getKernel';\nimport * as PeakOptimizer from '../peaks/util/peakOptimizer';\nimport { formatZones } from './util/formatZone';\nconst smallFilter = [\n    [0, 0, 1, 2, 2, 2, 1, 0, 0],\n    [0, 1, 4, 7, 7, 7, 4, 1, 0],\n    [1, 4, 5, 3, 0, 3, 5, 4, 1],\n    [2, 7, 3, -12, -23, -12, 3, 7, 2],\n    [2, 7, 0, -23, -40, -23, 0, 7, 2],\n    [2, 7, 3, -12, -23, -12, 3, 7, 2],\n    [1, 4, 5, 3, 0, 3, 5, 4, 1],\n    [0, 1, 3, 7, 7, 7, 3, 1, 0],\n    [0, 0, 1, 2, 2, 2, 1, 0, 0],\n];\nexport function xyzAutoZonesPicking(spectraData, options) {\n    let { sizeToPad = 14, realTopDetection = true, thresholdFactor = 0.5, nuclei = ['1H', '1H'], observedFrequencies, enhanceSymmetry = false, clean = true, maxPercentCutOff = 0.03, tolerances = [24, 24], convolutionByFFT = true, kernel: kernelOptions, } = options;\n    if (!Array.isArray(observedFrequencies) &&\n        !ArrayBuffer.isView(observedFrequencies)) {\n        throw new Error('observedFrequencies is mandatory');\n    }\n    thresholdFactor = thresholdFactor === 0 ? 1 : Math.abs(thresholdFactor);\n    let nbPoints = spectraData.z[0].length;\n    let nbSubSpectra = spectraData.z.length;\n    if (nbSubSpectra < sizeToPad) {\n        spectraData = padData(spectraData, { width: sizeToPad });\n        nbPoints = spectraData.z[0].length;\n        nbSubSpectra = spectraData.z.length;\n    }\n    let absoluteData = new Float64Array(nbPoints * nbSubSpectra);\n    let originalData = new Float64Array(nbPoints * nbSubSpectra);\n    for (let iSubSpectra = 0; iSubSpectra < nbSubSpectra; iSubSpectra++) {\n        let spectrum = spectraData.z[iSubSpectra];\n        for (let iCol = 0; iCol < nbPoints; iCol++) {\n            let index = iSubSpectra * nbPoints + iCol;\n            absoluteData[index] = Math.abs(spectrum[iCol]);\n            originalData[index] = spectrum[iCol]; //@todo pensar si se puede evitar originalData\n        }\n    }\n    const kernel = kernelOptions ? getKernel(kernelOptions) : smallFilter;\n    let convolutedSpectrum = convolutionByFFT\n        ? convolution.fft(absoluteData, kernel, {\n            rows: nbSubSpectra,\n            cols: nbPoints,\n        })\n        : convolution.direct(absoluteData, kernel, {\n            rows: nbSubSpectra,\n            cols: nbPoints,\n        });\n    let peaksMC1 = matrixPeakFinders.findPeaks2DRegion(absoluteData, {\n        originalData,\n        filteredData: convolutedSpectrum,\n        rows: nbSubSpectra,\n        cols: nbPoints,\n        nStdDev: thresholdFactor,\n    });\n    if (clean) {\n        // Remove peaks with less than x% of the intensity of the highest peak\n        peaksMC1 = PeakOptimizer.clean(peaksMC1, maxPercentCutOff);\n    }\n    let signals = createSignals2D(addMissingIDs(peaksMC1), {\n        nRows: nbSubSpectra,\n        nCols: nbPoints,\n        minX: spectraData.minX,\n        maxX: spectraData.maxX,\n        minY: spectraData.minY,\n        maxY: spectraData.maxY,\n        absoluteData,\n        originalData,\n        tolerances,\n        nuclei,\n        observedFrequencies,\n        realTopDetection,\n    });\n    if (enhanceSymmetry) {\n        signals = PeakOptimizer.enhanceSymmetry(signals);\n    }\n    return formatZones(signals);\n}\nfunction createSignals2D(peaks, options) {\n    let { nCols, nRows, absoluteData, originalData, observedFrequencies, tolerances, nuclei, realTopDetection, minY, maxY, minX, maxX, } = options;\n    let [nucleusX, nucleusY] = nuclei;\n    let [toleranceX, toleranceY] = tolerances;\n    let [observeFrequencyX, observeFrequencyY] = observedFrequencies;\n    let dy = (maxY - minY) / (nRows - 1);\n    let dx = (maxX - minX) / (nCols - 1);\n    if (realTopDetection) {\n        peaks = determineRealTop(peaks, {\n            nCols,\n            absoluteData,\n            originalData,\n            minX,\n            maxX,\n            minY,\n            maxY,\n        });\n    }\n    for (let i = peaks.length - 1; i >= 0; i--) {\n        let { x, y } = peaks[i];\n        peaks[i].x = minX + dx * x;\n        peaks[i].y = minY + dy * y;\n        peaks[i].minX = minX + dx * peaks[i].minX;\n        peaks[i].minY = minY + dy * peaks[i].minY;\n        peaks[i].maxX = minX + dx * peaks[i].maxX;\n        peaks[i].maxY = minY + dy * peaks[i].maxY;\n        // Still having problems to correctly detect peaks on those areas. So I'm removing everything there.\n    }\n    // The connectivity matrix is an square and symmetric matrix, so we'll only store the upper diagonal in an\n    // array like form\n    let connectivity = [];\n    for (let i = 0; i < peaks.length; i++) {\n        for (let j = i; j < peaks.length; j++) {\n            if (Math.abs(peaks[i].x - peaks[j].x) * observeFrequencyX < toleranceX &&\n                Math.abs(peaks[i].y - peaks[j].y) * observeFrequencyY < toleranceY) {\n                // 24*24Hz We cannot distinguish peaks with less than 20 Hz of separation\n                connectivity.push(1);\n            }\n            else {\n                connectivity.push(0);\n            }\n        }\n    }\n    let clusters = simpleClustering(connectivity);\n    let signals = [];\n    if (clusters) {\n        for (const cluster of clusters) {\n            let signal = {\n                id: generateID(),\n                x: {\n                    delta: 0,\n                    nucleus: nucleusX,\n                    resolution: dx,\n                },\n                y: {\n                    delta: 0,\n                    nucleus: nucleusY,\n                    resolution: dy,\n                },\n            };\n            let peaks2D = [];\n            let sumZ = 0;\n            for (let jPeak = 0; jPeak < cluster.length; jPeak++) {\n                if (cluster[jPeak] === 1) {\n                    peaks2D.push(peaks[jPeak]);\n                    signal.x.delta += peaks[jPeak].x * peaks[jPeak].z;\n                    signal.y.delta += peaks[jPeak].y * peaks[jPeak].z;\n                    sumZ += peaks[jPeak].z;\n                }\n            }\n            signal.x.delta /= sumZ;\n            signal.y.delta /= sumZ;\n            signal.peaks = peaks2D;\n            signals.push(signal);\n        }\n    }\n    return signals;\n}\nfunction padData(spectraData, options) {\n    let { minX, maxX, minY, maxY } = spectraData;\n    const width = options.width;\n    let nbPoints = spectraData.z[0].length;\n    let nbSubSpectra = spectraData.z.length;\n    let yInterval = (maxY - minY) / (nbSubSpectra - 1);\n    let xInterval = (maxX - minX) / (nbPoints - 1);\n    let yDiff = width - nbSubSpectra;\n    let xDiff = Math.max(width - nbPoints, 0);\n    if (xDiff % 2)\n        xDiff++;\n    if (yDiff % 2)\n        yDiff++;\n    let xOffset = xDiff / 2;\n    let yOffset = yDiff / 2;\n    let newMatrix = Matrix.zeros(nbSubSpectra + yDiff, nbPoints + xDiff);\n    for (let i = 0; i < nbSubSpectra; i++) {\n        for (let j = 0; j < nbPoints; j++) {\n            newMatrix.set(i + yOffset, j + xOffset, spectraData.z[i][j]);\n        }\n    }\n    return {\n        z: newMatrix.to2DArray(),\n        minX: minX - xOffset * xInterval,\n        maxX: maxX + xOffset * xInterval,\n        minY: minY - yOffset * yInterval,\n        maxY: maxY + yOffset * yInterval,\n    };\n}\n//# sourceMappingURL=xyzAutoZonesPicking.js.map","import { v4 as generateID } from '@lukeed/uuid';\nimport simpleClustering from 'ml-simple-clustering';\nimport { addMissingIDs } from '../peaks/util/addMissingIDs';\nimport jAnalyzer from '../signals/utils/jAnalyzer';\nimport { formatZones } from './util/formatZone';\nconst { parse, stringify } = JSON;\nexport function xyzJResAnalyzer(signals, options = {}) {\n    let { reference = 0, getZones = false, referenceMaxShiftError = 0.08, tolerances = [10, 100], nuclei = ['1H', '1H'], observedFrequencies = [400, 400], jAnalyzer = {\n        jAxisKey: { jAxis: 'y', intensity: 'z' },\n    }, } = options;\n    let temporalSignals = compilePattern(signals, {\n        observedFrequencies,\n        tolerances,\n        nuclei,\n        jAnalyzer,\n    });\n    //check if the signal are symmetric around the reference\n    let signals2D = [];\n    for (const tempSignal of temporalSignals) {\n        let delta = tempSignal.y.delta;\n        if (Math.abs(delta - reference) > referenceMaxShiftError)\n            continue;\n        signals2D.push(tempSignal);\n    }\n    signals2D = addMissingIDs(signals2D);\n    return getZones ? formatZones(signals2D) : signals2D;\n}\nfunction compilePattern(signals, options) {\n    let { observedFrequencies, tolerances, nuclei, jAnalyzer: jAnalyzerOptions, } = options;\n    let signalOptions = {\n        observedFrequencies,\n        tolerances,\n        nuclei,\n        dx: signals[0].x.resolution,\n        dy: signals[0].y.resolution,\n    };\n    const defaultWidth = 0.02 * observedFrequencies[0];\n    const newSignals = parse(stringify(signals));\n    //adapt to 1D jAnalyzer\n    for (const signal of newSignals) {\n        let peaks = signal.peaks;\n        signal.nbPeaks = signal.peaks.length;\n        signal.multiplicity = '';\n        signal.pattern = '';\n        signal.delta1 = signal.shiftY;\n        signal.observe = observedFrequencies[1];\n        signal.integralData = {\n            from: Number.MAX_SAFE_INTEGER,\n            to: Number.MIN_SAFE_INTEGER,\n        };\n        for (const peak of peaks) {\n            if (!peak.width)\n                peak.width = defaultWidth;\n        }\n        peaks.sort((a, b) => a.y - b.y);\n    }\n    for (let i = 0; i < signals.length; i++) {\n        jAnalyzer.compilePattern(newSignals[i], jAnalyzerOptions);\n        if (newSignals[i].maskPattern &&\n            newSignals[i].multiplicity !== 'm' &&\n            newSignals[i].multiplicity !== '') {\n            // Create a new signal with the removed peaks\n            let peaksO = [];\n            for (let j = newSignals[i].maskPattern.length - 1; j >= 0; j--) {\n                if (newSignals[i].maskPattern[j] === false) {\n                    let peakR = newSignals[i].peaks.splice(j, 1)[0];\n                    peaksO.push(peakR);\n                    newSignals[i].mask.splice(j, 1);\n                    newSignals[i].mask2.splice(j, 1);\n                    newSignals[i].maskPattern.splice(j, 1);\n                    newSignals[i].nbPeaks--;\n                }\n            }\n            if (peaksO.length > 0) {\n                peaksO.reverse();\n                let signals2D = createSignals2D(peaksO, signalOptions);\n                for (const signal of signals2D) {\n                    newSignals.push(signal);\n                }\n            }\n        }\n    }\n    signals.sort((a, b) => {\n        return b.x.delta - a.x.delta;\n    });\n    return signals;\n}\nfunction createSignals2D(peaksInput, options) {\n    let { observedFrequencies, tolerances, nuclei, dx, dy } = options;\n    const peaks = parse(stringify(peaksInput));\n    let [nucleusX, nucleusY] = nuclei;\n    let [toleranceX, toleranceY] = tolerances;\n    let [observeFrequencyX, observeFrequencyY] = observedFrequencies;\n    // The connectivity matrix is an square and symmetric matrix, so we'll only store the upper diagonal in an\n    // array like form\n    let connectivity = [];\n    for (let i = 0; i < peaks.length; i++) {\n        for (let j = i; j < peaks.length; j++) {\n            if (Math.abs(peaks[i].x - peaks[j].x) * observeFrequencyX < toleranceX &&\n                Math.abs(peaks[i].y - peaks[j].y) * observeFrequencyY < toleranceY) {\n                // 24*24Hz We cannot distinguish peaks with less than 20 Hz of separation\n                connectivity.push(1);\n            }\n            else {\n                connectivity.push(0);\n            }\n        }\n    }\n    let clusters = simpleClustering(connectivity);\n    let signals = [];\n    if (clusters) {\n        for (let cluster of clusters) {\n            let signal = {\n                id: generateID(),\n                nucleusX,\n                nucleusY,\n                integralData: {\n                    from: Number.MAX_SAFE_INTEGER,\n                    to: Number.MIN_SAFE_INTEGER,\n                },\n                nbPeaks: 0,\n                multiplicity: '',\n                pattern: '',\n                observe: observeFrequencyY,\n                resolutionX: dx,\n                resolutionY: dy,\n                shiftX: 0,\n                shiftY: 0,\n            };\n            let peaks2D = [];\n            let minMax1 = [Number.MAX_VALUE, 0];\n            let minMax2 = [Number.MAX_VALUE, 0];\n            let sumZ = 0;\n            for (let jPeak = cluster.length - 1; jPeak >= 0; jPeak--) {\n                if (cluster[jPeak] === 1) {\n                    signal.nbPeaks++;\n                    if (!peaks[jPeak].width)\n                        peaks[jPeak].width = 0.02;\n                    peaks2D.push(peaks[jPeak]);\n                    signal.shiftX += peaks[jPeak].x * peaks[jPeak].z;\n                    signal.shiftY += peaks[jPeak].y * peaks[jPeak].z;\n                    sumZ += peaks[jPeak].z;\n                    if (peaks[jPeak].minX < minMax1[0]) {\n                        minMax1[0] = peaks[jPeak].minX;\n                    }\n                    if (peaks[jPeak].maxX > minMax1[1]) {\n                        minMax1[1] = peaks[jPeak].maxX;\n                    }\n                    if (peaks[jPeak].minY < minMax2[0]) {\n                        minMax2[0] = peaks[jPeak].minY;\n                    }\n                    if (peaks[jPeak].maxY > minMax2[1]) {\n                        minMax2[1] = peaks[jPeak].maxY;\n                    }\n                }\n            }\n            signal.fromTo = [\n                { from: minMax1[0], to: minMax1[1] },\n                { from: minMax2[0], to: minMax2[1] },\n            ];\n            signal.shiftX /= sumZ;\n            signal.shiftY /= sumZ;\n            signal.delta1 = signal.shiftY;\n            signal.peaks = peaks2D;\n            signals.push(signal);\n        }\n    }\n    return signals;\n}\n//# sourceMappingURL=xyzJResAnalyzer.js.map","import { fetch } from 'cross-fetch';\nimport { resurrectRange } from '../utilities/resurrectRange';\nexport async function getDatabase(url = 'https://docs.google.com/spreadsheets/d/1uwyq_L38PMRWCcT4If_EhPbHKyY3q_2tpjV8vr5_zh0/edit?usp=sharing', options = {}) {\n    const { format = 'tsv' } = options;\n    if (url.includes('google.com')) {\n        url = `https://googledocs.cheminfo.org/spreadsheets/d/${extractGoogleUUID(url)}/export?format=tsv`;\n    }\n    let parsed;\n    const response = await fetch(url);\n    switch (format) {\n        case 'tsv':\n            parsed = parseData(await response.text());\n            break;\n        case 'json':\n            parsed = await response.json();\n            break;\n        default:\n            throw new Error('unknown database format');\n    }\n    const results = [];\n    for (let line of parsed.data) {\n        const result = {\n            smiles: '',\n            solvent: '',\n            nucleus: '',\n            jcampURL: '',\n            names: [],\n            meta: {},\n            ranges: [],\n        };\n        for (let i = 0; i < line.length; i++) {\n            switch (parsed.kinds[i]) {\n                case 'smiles':\n                    result.smiles = line[i];\n                    break;\n                case 'solvent':\n                    result.solvent = line[i];\n                    break;\n                case 'nucleus':\n                    result.nucleus = line[i];\n                    break;\n                case 'jcampURL':\n                    result.jcampURL = line[i];\n                    break;\n                case 'name':\n                    if (result.names)\n                        result.names.push(line[i]);\n                    break;\n                case 'meta':\n                    if (result.meta)\n                        result.meta[parsed.labels[i]] = line[i];\n                    break;\n                case 'signal': {\n                    const range = resurrectRange(line[i]);\n                    if (range)\n                        result.ranges.push(range);\n                    break;\n                }\n                default:\n                    throw new Error(`Unknown column kind: ${parsed.kinds[i]}`);\n            }\n        }\n        results.push(result);\n    }\n    return results;\n}\nfunction extractGoogleUUID(url) {\n    return url.replace(/.*\\/(?<uuid>[^/]{20,50}).*/, '$<uuid>');\n}\nfunction parseData(text) {\n    const matrix = text\n        .split(/\\r?\\n/)\n        .filter((line) => !/^\\s*$/.exec(line))\n        .map((line) => line.split('\\t').map((cell) => cell.trim()));\n    const labels = matrix[0];\n    const kinds = matrix[1];\n    const data = matrix.slice(2);\n    return {\n        labels,\n        kinds,\n        data,\n    };\n}\n//# sourceMappingURL=getDatabase.js.map","export const carbonImpurities = [\n    {\n        names: ['acetic acid'],\n        smiles: 'CC(=O)O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 171.69,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 171.68625,\n                to: 171.69375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 20.13,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 20.12625,\n                to: 20.13375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['acetone'],\n        smiles: 'CC(=O)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 204.19,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 204.18625,\n                to: 204.19375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 30.17,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 30.16625,\n                to: 30.173750000000002,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['acetonitrile'],\n        smiles: 'CC#N',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 116.79,\n                        assignment: 'CN',\n                    },\n                ],\n                from: 116.78625000000001,\n                to: 116.79375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 0.45,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 0.44625000000000004,\n                to: 0.45375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['benzene'],\n        smiles: 'c1ccccc1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 128.84,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 128.83625,\n                to: 128.84375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['tert -butyl alcohol'],\n        smiles: 'CC(C)(C)O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 67.5,\n                        assignment: '(CH₃)₃C',\n                    },\n                ],\n                from: 67.49625,\n                to: 67.50375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 30.57,\n                        assignment: '(CH₃)₃C',\n                    },\n                ],\n                from: 30.56625,\n                to: 30.57375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['carbon dioxide'],\n        smiles: 'O=C=O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 125.69,\n                        assignment: 'CO₂',\n                    },\n                ],\n                from: 125.68625,\n                to: 125.69375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['carbon disulfide'],\n        smiles: 'S=C=S',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 193.37,\n                        assignment: 'CS₂',\n                    },\n                ],\n                from: 193.36625,\n                to: 193.37375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['carbon tetrachloride'],\n        smiles: 'ClC(Cl)(Cl)Cl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 96.89,\n                        assignment: 'CCl₄',\n                    },\n                ],\n                from: 96.88625,\n                to: 96.89375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['chloroform'],\n        smiles: 'ClC(Cl)Cl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 79.24,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 79.23625,\n                to: 79.24374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['18-crown-6'],\n        smiles: 'C1COCCOCCOCCOCCOCCO1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 71.34,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 71.33625,\n                to: 71.34375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['cyclohexane'],\n        smiles: 'C1CCCCC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 27.58,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 27.576249999999998,\n                to: 27.58375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['1,2-dichloroethane'],\n        smiles: 'ClCCCl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 44.64,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 44.636250000000004,\n                to: 44.64375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['dichloromethane'],\n        smiles: 'ClCCl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 54.67,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 54.666250000000005,\n                to: 54.67375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['diethyl ether'],\n        smiles: 'CCOCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 15.49,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 15.48625,\n                to: 15.49375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 66.14,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 66.13625,\n                to: 66.14375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['diglyme'],\n        smiles: 'COCCOCCOC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 58.72,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 58.71625,\n                to: 58.723749999999995,\n            },\n            {\n                signals: [\n                    {\n                        delta: 71.17,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 71.16625,\n                to: 71.17375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 72.72,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 72.71625,\n                to: 72.72375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['dimethylformamide'],\n        smiles: 'C(=O)N(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 161.96,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 161.95625,\n                to: 161.96375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 35.65,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 35.64625,\n                to: 35.653749999999995,\n            },\n            {\n                signals: [\n                    {\n                        delta: 30.7,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 30.69625,\n                to: 30.70375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['1,4-dioxane'],\n        smiles: 'C1COCCOC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 67.65,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 67.64625000000001,\n                to: 67.65375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['DME', 'diethyl ether'],\n        smiles: 'CCOCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 58.72,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 58.71625,\n                to: 58.723749999999995,\n            },\n            {\n                signals: [\n                    {\n                        delta: 72.58,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 72.57625,\n                to: 72.58375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['ethane'],\n        smiles: 'CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 6.79,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 6.78625,\n                to: 6.79375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['ethanol'],\n        smiles: 'CCO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 18.9,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 18.89625,\n                to: 18.90375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 57.6,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 57.596250000000005,\n                to: 57.60375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['ethyl acetate'],\n        smiles: 'CC(=O)CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 20.45,\n                        assignment: 'CH₃CO',\n                    },\n                ],\n                from: 20.44625,\n                to: 20.45375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 170.32,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 170.31625,\n                to: 170.32375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 60.3,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 60.29625,\n                to: 60.303749999999994,\n            },\n            {\n                signals: [\n                    {\n                        delta: 14.37,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.366249999999999,\n                to: 14.37375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['ethylene'],\n        smiles: 'C=C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 123.09,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 123.08625,\n                to: 123.09375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['ethylene glycol'],\n        smiles: 'OCCO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 64.35,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 64.34625,\n                to: 64.35374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['H grease'],\n        smiles: '',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 30.45,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 30.44625,\n                to: 30.45375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['hexamethylbenzene'],\n        smiles: 'CC1=C(C(=C(C(=C1C)C)C)C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 131.88,\n                        assignment: 'C',\n                    },\n                ],\n                from: 131.87625,\n                to: 131.88375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 16.71,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 16.70625,\n                to: 16.71375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['n-hexane'],\n        smiles: 'CCCCCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 14.22,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.21625,\n                to: 14.22375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 23.33,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 23.326249999999998,\n                to: 23.33375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 32.34,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 32.33625000000001,\n                to: 32.34375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['HMDSO'],\n        smiles: 'C[Si](C)(C)O[Si](C)(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 1.83,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 1.8262500000000002,\n                to: 1.83375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['HMPA'],\n        smiles: 'CN(C)P(=O)(N(C)C)N(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 36.89,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 36.886250000000004,\n                to: 36.89375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['imidazole'],\n        smiles: 'C1=CN=CN1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 135.72,\n                        assignment: 'CH(2)',\n                    },\n                ],\n                from: 135.71625,\n                to: 135.72375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 122.2,\n                        assignment: 'CH(4,5)',\n                    },\n                ],\n                from: 122.19625,\n                to: 122.20375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['methane'],\n        smiles: 'C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: -4.9,\n                        assignment: 'CH₄',\n                    },\n                ],\n                from: -4.9037500000000005,\n                to: -4.89625,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['methanol'],\n        smiles: 'CO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 49.64,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 49.636250000000004,\n                to: 49.64375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['nitromethane'],\n        smiles: 'C[N+](=O)[O-]',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 62.49,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 62.486250000000005,\n                to: 62.49375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['n-pentane'],\n        smiles: 'CCCCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 14.18,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.17625,\n                to: 14.18375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 23,\n                        assignment: 'CH₂(2,4)',\n                    },\n                ],\n                from: 22.99625,\n                to: 23.00375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 34.87,\n                        assignment: 'CH₂(3)',\n                    },\n                ],\n                from: 34.86625,\n                to: 34.873749999999994,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['propane'],\n        smiles: 'CCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 16.6,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 16.59625,\n                to: 16.60375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 16.82,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 16.81625,\n                to: 16.82375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['2-propanol'],\n        smiles: 'CC(O)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 25.7,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 25.69625,\n                to: 25.70375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 66.14,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 66.13625,\n                to: 66.14375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['propylene'],\n        smiles: 'CC=C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 19.27,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 19.26625,\n                to: 19.27375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 115.74,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 115.73625,\n                to: 115.74374999999999,\n            },\n            {\n                signals: [\n                    {\n                        delta: 134.02,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 134.01625,\n                to: 134.02375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['pyridine'],\n        smiles: 'C1=CC=NC=C1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 150.57,\n                        assignment: 'CH(2,6)',\n                    },\n                ],\n                from: 150.56625,\n                to: 150.57375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 124.08,\n                        assignment: 'CH(3,5)',\n                    },\n                ],\n                from: 124.07625,\n                to: 124.08375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 135.99,\n                        assignment: 'CH(4)',\n                    },\n                ],\n                from: 135.98625,\n                to: 135.99375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['pyrrole'],\n        smiles: 'C1=CNC=C1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 118.03,\n                        assignment: 'CH(2,5)',\n                    },\n                ],\n                from: 118.02625,\n                to: 118.03375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 107.74,\n                        assignment: 'CH(3,4)',\n                    },\n                ],\n                from: 107.73625,\n                to: 107.74374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['pyrrolidine'],\n        smiles: 'C1CCNC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 45.82,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 45.816250000000004,\n                to: 45.82375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 26.17,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 26.16625,\n                to: 26.173750000000002,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['silicone grease'],\n        smiles: '',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 1.2,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 1.19625,\n                to: 1.2037499999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['tetrahydrofuran'],\n        smiles: 'C1COCC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 68.03,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 68.02625,\n                to: 68.03375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 26.19,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 26.18625,\n                to: 26.19375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['toluene'],\n        smiles: 'Cc1ccccc1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 21.29,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 21.28625,\n                to: 21.29375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 138.24,\n                        assignment: 'C(1)',\n                    },\n                ],\n                from: 138.23625,\n                to: 138.24375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 129.47,\n                        assignment: 'CH(2,6)',\n                    },\n                ],\n                from: 129.46625,\n                to: 129.47375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 128.71,\n                        assignment: 'CH(3,5)',\n                    },\n                ],\n                from: 128.70625,\n                to: 128.71375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 125.84,\n                        assignment: 'CH(4)',\n                    },\n                ],\n                from: 125.83625,\n                to: 125.84375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['triethylamine'],\n        smiles: 'CCN(CC)CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 12.51,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 12.50625,\n                to: 12.51375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 47.18,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 47.17625,\n                to: 47.183749999999996,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'THF-d₈',\n    },\n    {\n        names: ['acetic acid'],\n        smiles: 'CC(=O)O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 175.85,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 175.84625,\n                to: 175.85375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 20.91,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 20.90625,\n                to: 20.91375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['acetone'],\n        smiles: 'CC(=O)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 206.78,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 206.77625,\n                to: 206.78375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 31,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 30.99625,\n                to: 31.00375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['acetonitrile'],\n        smiles: 'CC#N',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 116.92,\n                        assignment: 'CN',\n                    },\n                ],\n                from: 116.91625,\n                to: 116.92375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 2.03,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 2.0262499999999997,\n                to: 2.03375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['benzene'],\n        smiles: 'c1ccccc1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 128.68,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 128.67625,\n                to: 128.68375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['tert -butyl alcohol'],\n        smiles: 'CC(C)(C)O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 69.11,\n                        assignment: '(CH₃)₃C',\n                    },\n                ],\n                from: 69.10625,\n                to: 69.11375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 31.46,\n                        assignment: '(CH₃)₃C',\n                    },\n                ],\n                from: 31.45625,\n                to: 31.46375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['carbon dioxide'],\n        smiles: 'O=C=O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 125.26,\n                        assignment: 'CO₂',\n                    },\n                ],\n                from: 125.25625000000001,\n                to: 125.26375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['carbon disulfide'],\n        smiles: 'S=C=S',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 192.95,\n                        assignment: 'CS₂',\n                    },\n                ],\n                from: 192.94625,\n                to: 192.95374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['carbon tetrachloride'],\n        smiles: 'ClC(Cl)(Cl)Cl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 96.52,\n                        assignment: 'CCl₄',\n                    },\n                ],\n                from: 96.51625,\n                to: 96.52374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['chloroform'],\n        smiles: 'ClC(Cl)Cl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 77.99,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 77.98625,\n                to: 77.99374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['18-crown-6'],\n        smiles: 'C1COCCOCCOCCOCCOCCO1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 70.47,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 70.46625,\n                to: 70.47375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['cyclohexane'],\n        smiles: 'C1CCCCC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 27.38,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 27.37625,\n                to: 27.38375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['1,2-dichloroethane'],\n        smiles: 'ClCCCl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 44.35,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 44.346250000000005,\n                to: 44.35375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['dichloromethane'],\n        smiles: 'ClCCl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 54.24,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 54.236250000000005,\n                to: 54.24375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['diethyl ether'],\n        smiles: 'CCOCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 15.44,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 15.43625,\n                to: 15.44375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 66.11,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 66.10625,\n                to: 66.11375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['diglyme'],\n        smiles: 'COCCOCCOC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 58.95,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 58.946250000000006,\n                to: 58.95375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 70.7,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 70.69625,\n                to: 70.70375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 72.25,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 72.24625,\n                to: 72.25375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['dimethylformamide'],\n        smiles: 'C(=O)N(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 162.57,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 162.56625,\n                to: 162.57375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 36.56,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 36.556250000000006,\n                to: 36.56375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 31.39,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 31.38625,\n                to: 31.39375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['1,4-dioxane'],\n        smiles: 'C1COCCOC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 67.47,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 67.46625,\n                to: 67.47375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['DME', 'diethyl ether'],\n        smiles: 'CCOCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 59.02,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 59.01625000000001,\n                to: 59.02375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 72.24,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 72.23625,\n                to: 72.24374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['ethane'],\n        smiles: 'CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 6.91,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 6.90625,\n                to: 6.91375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['ethanol'],\n        smiles: 'CCO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 18.69,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 18.68625,\n                to: 18.69375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 58.57,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 58.566250000000004,\n                to: 58.57375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['ethyl acetate'],\n        smiles: 'CC(=O)CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 21.15,\n                        assignment: 'CH₃CO',\n                    },\n                ],\n                from: 21.14625,\n                to: 21.15375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 171.24,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 171.23625,\n                to: 171.24375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 60.63,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 60.626250000000006,\n                to: 60.63375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 14.37,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.366249999999999,\n                to: 14.37375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['ethylene'],\n        smiles: 'C=C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 123.2,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 123.19625,\n                to: 123.20375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['ethylene glycol'],\n        smiles: 'OCCO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 64.08,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 64.07625,\n                to: 64.08375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['H grease'],\n        smiles: '',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 30.14,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 30.13625,\n                to: 30.14375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['hexamethylbenzene'],\n        smiles: 'CC1=C(C(=C(C(=C1C)C)C)C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 132.09,\n                        assignment: 'C',\n                    },\n                ],\n                from: 132.08625,\n                to: 132.09375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 16.93,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 16.92625,\n                to: 16.93375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['n-hexane'],\n        smiles: 'CCCCCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 14.28,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.27625,\n                to: 14.28375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 23.07,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 23.06625,\n                to: 23.07375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 32.01,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 32.00625,\n                to: 32.013749999999995,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['HMDSO'],\n        smiles: 'C[Si](C)(C)O[Si](C)(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 1.96,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 1.95625,\n                to: 1.9637499999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['HMPA'],\n        smiles: 'CN(C)P(=O)(N(C)C)N(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 36.99,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 36.986250000000005,\n                to: 36.99375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['imidazole'],\n        smiles: 'C1=CN=CN1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 135.76,\n                        assignment: 'CH(2)',\n                    },\n                ],\n                from: 135.75625,\n                to: 135.76375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 122.16,\n                        assignment: 'CH(4,5)',\n                    },\n                ],\n                from: 122.15625,\n                to: 122.16375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['methane'],\n        smiles: 'C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: -4.33,\n                        assignment: 'CH₄',\n                    },\n                ],\n                from: -4.33375,\n                to: -4.32625,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['methanol'],\n        smiles: 'CO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 50.45,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 50.446250000000006,\n                to: 50.45375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['nitromethane'],\n        smiles: 'C[N+](=O)[O-]',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 63.03,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 63.026250000000005,\n                to: 63.03375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['n-pentane'],\n        smiles: 'CCCCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 14.24,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.23625,\n                to: 14.24375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 22.77,\n                        assignment: 'CH₂(2,4)',\n                    },\n                ],\n                from: 22.76625,\n                to: 22.77375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 34.57,\n                        assignment: 'CH₂(3)',\n                    },\n                ],\n                from: 34.566250000000004,\n                to: 34.57375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['propane'],\n        smiles: 'CCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 16.63,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 16.62625,\n                to: 16.63375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 16.63,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 16.62625,\n                to: 16.63375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['2-propanol'],\n        smiles: 'CC(O)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 25.43,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 25.42625,\n                to: 25.43375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 64.67,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 64.66625,\n                to: 64.67375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['propylene'],\n        smiles: 'CC=C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 19.47,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 19.46625,\n                to: 19.47375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 115.7,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 115.69625,\n                to: 115.70375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 134.21,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 134.20625,\n                to: 134.21375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['pyridine'],\n        smiles: 'C1=CC=NC=C1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 150.27,\n                        assignment: 'CH(2,6)',\n                    },\n                ],\n                from: 150.26625,\n                to: 150.27375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 124.06,\n                        assignment: 'CH(3,5)',\n                    },\n                ],\n                from: 124.05625,\n                to: 124.06375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 136.16,\n                        assignment: 'CH(4)',\n                    },\n                ],\n                from: 136.15625,\n                to: 136.16375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['pyrrole'],\n        smiles: 'C1=CNC=C1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 117.93,\n                        assignment: 'CH(2,5)',\n                    },\n                ],\n                from: 117.92625000000001,\n                to: 117.93375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 108.02,\n                        assignment: 'CH(3,4)',\n                    },\n                ],\n                from: 108.01625,\n                to: 108.02374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['pyrrolidine'],\n        smiles: 'C1CCNC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 47.02,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 47.01625000000001,\n                to: 47.02375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 25.83,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 25.826249999999998,\n                to: 25.83375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['silicone grease'],\n        smiles: '',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 1.22,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 1.21625,\n                to: 1.22375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['tetrahydrofuran'],\n        smiles: 'C1COCC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 68.16,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 68.15625,\n                to: 68.16375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 25.98,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 25.97625,\n                to: 25.98375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['toluene'],\n        smiles: 'Cc1ccccc1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 21.53,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 21.52625,\n                to: 21.53375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 138.36,\n                        assignment: 'C(1)',\n                    },\n                ],\n                from: 138.35625000000002,\n                to: 138.36375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 129.35,\n                        assignment: 'CH(2,6)',\n                    },\n                ],\n                from: 129.34625,\n                to: 129.35375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 128.54,\n                        assignment: 'CH(3,5)',\n                    },\n                ],\n                from: 128.53625,\n                to: 128.54375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 125.62,\n                        assignment: 'CH(4)',\n                    },\n                ],\n                from: 125.61625000000001,\n                to: 125.62375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['triethylamine'],\n        smiles: 'CCN(CC)CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 12.12,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 12.116249999999999,\n                to: 12.12375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 46.75,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 46.74625,\n                to: 46.75375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CD₂Cl₂',\n    },\n    {\n        names: ['acetic acid'],\n        smiles: 'CC(=O)O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 175.99,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 175.98625,\n                to: 175.99375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 20.81,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 20.80625,\n                to: 20.81375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['acetone'],\n        smiles: 'CC(=O)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 207.07,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 207.06625,\n                to: 207.07375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 30.92,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 30.91625,\n                to: 30.923750000000002,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['acetonitrile'],\n        smiles: 'CC#N',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 116.43,\n                        assignment: 'CN',\n                    },\n                ],\n                from: 116.42625000000001,\n                to: 116.43375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 1.89,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 1.88625,\n                to: 1.8937499999999998,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['benzene'],\n        smiles: 'c1ccccc1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 128.37,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 128.36625,\n                to: 128.37375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['tert -butyl alcohol'],\n        smiles: 'CC(C)(C)O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 69.15,\n                        assignment: '(CH₃)₃C',\n                    },\n                ],\n                from: 69.14625000000001,\n                to: 69.15375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 31.25,\n                        assignment: '(CH₃)₃C',\n                    },\n                ],\n                from: 31.24625,\n                to: 31.25375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['carbon dioxide'],\n        smiles: 'O=C=O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 124.99,\n                        assignment: 'CO₂',\n                    },\n                ],\n                from: 124.98625,\n                to: 124.99374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['carbon disulfide'],\n        smiles: 'S=C=S',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 192.83,\n                        assignment: 'CS₂',\n                    },\n                ],\n                from: 192.82625000000002,\n                to: 192.83375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['carbon tetrachloride'],\n        smiles: 'ClC(Cl)(Cl)Cl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 96.34,\n                        assignment: 'CCl₄',\n                    },\n                ],\n                from: 96.33625,\n                to: 96.34375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['chloroform'],\n        smiles: 'ClC(Cl)Cl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 77.36,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 77.35625,\n                to: 77.36375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['18-crown-6'],\n        smiles: 'C1COCCOCCOCCOCCOCCO1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 70.55,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 70.54625,\n                to: 70.55375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['cyclohexane'],\n        smiles: 'C1CCCCC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 26.94,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 26.93625,\n                to: 26.94375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['1,2-dichloroethane'],\n        smiles: 'ClCCCl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 43.5,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 43.49625,\n                to: 43.50375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['dichloromethane'],\n        smiles: 'ClCCl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 53.52,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 53.51625000000001,\n                to: 53.52375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['diethyl ether'],\n        smiles: 'CCOCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 15.2,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 15.19625,\n                to: 15.20375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 65.91,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 65.90625,\n                to: 65.91375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['diglyme'],\n        smiles: 'COCCOCCOC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 59.01,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 59.00625,\n                to: 59.013749999999995,\n            },\n            {\n                signals: [\n                    {\n                        delta: 70.51,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 70.50625000000001,\n                to: 70.51375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 71.9,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 71.89625000000001,\n                to: 71.90375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['dimethylformamide'],\n        smiles: 'C(=O)N(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 162.62,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 162.61625,\n                to: 162.62375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 36.5,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 36.49625,\n                to: 36.50375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 31.45,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 31.44625,\n                to: 31.45375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['1,4-dioxane'],\n        smiles: 'C1COCCOC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 67.14,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 67.13625,\n                to: 67.14375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['DME', 'diethyl ether'],\n        smiles: 'CCOCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 59.08,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 59.07625,\n                to: 59.083749999999995,\n            },\n            {\n                signals: [\n                    {\n                        delta: 71.84,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 71.83625,\n                to: 71.84375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['ethane'],\n        smiles: 'CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 6.89,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 6.8862499999999995,\n                to: 6.89375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['ethanol'],\n        smiles: 'CCO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 18.41,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 18.40625,\n                to: 18.41375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 58.28,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 58.276250000000005,\n                to: 58.28375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['ethyl acetate'],\n        smiles: 'CC(=O)CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 21.04,\n                        assignment: 'CH₃CO',\n                    },\n                ],\n                from: 21.03625,\n                to: 21.04375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 171.36,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 171.35625000000002,\n                to: 171.36375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 60.49,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 60.486250000000005,\n                to: 60.49375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 14.19,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.18625,\n                to: 14.19375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['ethylene'],\n        smiles: 'C=C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 123.13,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 123.12625,\n                to: 123.13374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['ethylene glycol'],\n        smiles: 'OCCO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 63.79,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 63.78625,\n                to: 63.793749999999996,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['H grease'],\n        smiles: '',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 29.71,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 29.70625,\n                to: 29.71375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['hexamethylbenzene'],\n        smiles: 'CC1=C(C(=C(C(=C1C)C)C)C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 132.21,\n                        assignment: 'C',\n                    },\n                ],\n                from: 132.20625,\n                to: 132.21375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 16.98,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 16.97625,\n                to: 16.98375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['n-hexane'],\n        smiles: 'CCCCCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 14.14,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.13625,\n                to: 14.14375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 22.7,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 22.69625,\n                to: 22.70375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 31.64,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 31.63625,\n                to: 31.64375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['HMDSO'],\n        smiles: 'C[Si](C)(C)O[Si](C)(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 1.97,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 1.96625,\n                to: 1.97375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['HMPA'],\n        smiles: 'CN(C)P(=O)(N(C)C)N(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 36.87,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 36.86625,\n                to: 36.873749999999994,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['imidazole'],\n        smiles: 'C1=CN=CN1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 135.38,\n                        assignment: 'CH(2)',\n                    },\n                ],\n                from: 135.37625,\n                to: 135.38375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 122,\n                        assignment: 'CH(4,5)',\n                    },\n                ],\n                from: 121.99625,\n                to: 122.00375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['methane'],\n        smiles: 'C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: -4.63,\n                        assignment: 'CH₄',\n                    },\n                ],\n                from: -4.63375,\n                to: -4.62625,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['methanol'],\n        smiles: 'CO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 50.41,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 50.40625,\n                to: 50.41374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['nitromethane'],\n        smiles: 'C[N+](=O)[O-]',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 62.5,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 62.49625,\n                to: 62.50375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['n-pentane'],\n        smiles: 'CCCCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 14.08,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.07625,\n                to: 14.08375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 22.38,\n                        assignment: 'CH₂(2,4)',\n                    },\n                ],\n                from: 22.37625,\n                to: 22.38375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 34.16,\n                        assignment: 'CH₂(3)',\n                    },\n                ],\n                from: 34.15625,\n                to: 34.16374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['propane'],\n        smiles: 'CCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 16.63,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 16.62625,\n                to: 16.63375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 16.37,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 16.36625,\n                to: 16.37375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['2-propanol'],\n        smiles: 'CC(O)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 25.14,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 25.13625,\n                to: 25.14375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 64.5,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 64.49625,\n                to: 64.50375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['propylene'],\n        smiles: 'CC=C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 19.5,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 19.49625,\n                to: 19.50375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 115.74,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 115.73625,\n                to: 115.74374999999999,\n            },\n            {\n                signals: [\n                    {\n                        delta: 133.91,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 133.90625,\n                to: 133.91375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['pyridine'],\n        smiles: 'C1=CC=NC=C1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 149.9,\n                        assignment: 'CH(2,6)',\n                    },\n                ],\n                from: 149.89625,\n                to: 149.90375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 123.75,\n                        assignment: 'CH(3,5)',\n                    },\n                ],\n                from: 123.74625,\n                to: 123.75375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 135.96,\n                        assignment: 'CH(4)',\n                    },\n                ],\n                from: 135.95625,\n                to: 135.96375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['pyrrole'],\n        smiles: 'C1=CNC=C1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 117.77,\n                        assignment: 'CH(2,5)',\n                    },\n                ],\n                from: 117.76625,\n                to: 117.77374999999999,\n            },\n            {\n                signals: [\n                    {\n                        delta: 107.98,\n                        assignment: 'CH(3,4)',\n                    },\n                ],\n                from: 107.97625000000001,\n                to: 107.98375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['pyrrolidine'],\n        smiles: 'C1CCNC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 46.93,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 46.92625,\n                to: 46.933749999999996,\n            },\n            {\n                signals: [\n                    {\n                        delta: 25.56,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 25.55625,\n                to: 25.56375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['silicone grease'],\n        smiles: '',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 1.19,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 1.18625,\n                to: 1.1937499999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['tetrahydrofuran'],\n        smiles: 'C1COCC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 67.97,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 67.96625,\n                to: 67.97375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 25.62,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 25.61625,\n                to: 25.62375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['toluene'],\n        smiles: 'Cc1ccccc1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 21.46,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 21.45625,\n                to: 21.46375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 137.89,\n                        assignment: 'C(1)',\n                    },\n                ],\n                from: 137.88625,\n                to: 137.89374999999998,\n            },\n            {\n                signals: [\n                    {\n                        delta: 129.07,\n                        assignment: 'CH(2,6)',\n                    },\n                ],\n                from: 129.06625,\n                to: 129.07375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 128.26,\n                        assignment: 'CH(3,5)',\n                    },\n                ],\n                from: 128.25625,\n                to: 128.26375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 125.33,\n                        assignment: 'CH(4)',\n                    },\n                ],\n                from: 125.32625,\n                to: 125.33375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['triethylamine'],\n        smiles: 'CCN(CC)CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 11.61,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 11.60625,\n                to: 11.61375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 46.25,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 46.24625,\n                to: 46.25375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'CDCl₃',\n    },\n    {\n        names: ['acetic acid'],\n        smiles: 'CC(=O)O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 175.3,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 175.29625000000001,\n                to: 175.30375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 20.27,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 20.26625,\n                to: 20.27375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['acetone'],\n        smiles: 'CC(=O)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 204,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 203.99625,\n                to: 204.00375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 30.03,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 30.02625,\n                to: 30.03375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['acetonitrile'],\n        smiles: 'CC#N',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 115.76,\n                        assignment: 'CN',\n                    },\n                ],\n                from: 115.75625000000001,\n                to: 115.76375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 0.03,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 0.02625,\n                to: 0.03375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['benzene'],\n        smiles: 'c1ccccc1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 128.57,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 128.56625,\n                to: 128.57375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['tert -butyl alcohol'],\n        smiles: 'CC(C)(C)O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 68.12,\n                        assignment: '(CH₃)₃C',\n                    },\n                ],\n                from: 68.11625000000001,\n                to: 68.12375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 30.49,\n                        assignment: '(CH₃)₃C',\n                    },\n                ],\n                from: 30.48625,\n                to: 30.49375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['carbon dioxide'],\n        smiles: 'O=C=O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 124.86,\n                        assignment: 'CO₂',\n                    },\n                ],\n                from: 124.85625,\n                to: 124.86375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['carbon disulfide'],\n        smiles: 'S=C=S',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 192.71,\n                        assignment: 'CS₂',\n                    },\n                ],\n                from: 192.70625,\n                to: 192.71375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['carbon tetrachloride'],\n        smiles: 'ClC(Cl)(Cl)Cl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 96.57,\n                        assignment: 'CCl₄',\n                    },\n                ],\n                from: 96.56625,\n                to: 96.57374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['chloroform'],\n        smiles: 'ClC(Cl)Cl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 77.89,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 77.88625,\n                to: 77.89375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['18-crown-6'],\n        smiles: 'C1COCCOCCOCCOCCOCCO1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 70.86,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 70.85625,\n                to: 70.86375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['cyclohexane'],\n        smiles: 'C1CCCCC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 27.31,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 27.30625,\n                to: 27.31375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['1,2-dichloroethane'],\n        smiles: 'ClCCCl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 43.4,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 43.39625,\n                to: 43.403749999999995,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['dichloromethane'],\n        smiles: 'ClCCl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 53.47,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 53.46625,\n                to: 53.473749999999995,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['diethyl ether'],\n        smiles: 'CCOCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 15.47,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 15.46625,\n                to: 15.47375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 65.94,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 65.93625,\n                to: 65.94375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['diglyme'],\n        smiles: 'COCCOCCOC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 58.62,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 58.61625,\n                to: 58.623749999999994,\n            },\n            {\n                signals: [\n                    {\n                        delta: 70.92,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 70.91625,\n                to: 70.92375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 72.39,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 72.38625,\n                to: 72.39375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['dimethylformamide'],\n        smiles: 'C(=O)N(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 161.93,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 161.92625,\n                to: 161.93375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 35.22,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 35.21625,\n                to: 35.223749999999995,\n            },\n            {\n                signals: [\n                    {\n                        delta: 30.64,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 30.63625,\n                to: 30.64375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['1,4-dioxane'],\n        smiles: 'C1COCCOC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 67.17,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 67.16625,\n                to: 67.17375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['DME', 'diethyl ether'],\n        smiles: 'CCOCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 58.63,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 58.626250000000006,\n                to: 58.63375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 72.25,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 72.24625,\n                to: 72.25375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['ethane'],\n        smiles: 'CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 6.94,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 6.93625,\n                to: 6.9437500000000005,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['ethanol'],\n        smiles: 'CCO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 18.78,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 18.77625,\n                to: 18.78375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 57.81,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 57.806250000000006,\n                to: 57.81375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['ethyl acetate'],\n        smiles: 'CC(=O)CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 20.46,\n                        assignment: 'CH₃CO',\n                    },\n                ],\n                from: 20.45625,\n                to: 20.46375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 170.02,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 170.01625,\n                to: 170.02375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 60.08,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 60.07625,\n                to: 60.083749999999995,\n            },\n            {\n                signals: [\n                    {\n                        delta: 14.23,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.22625,\n                to: 14.23375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['ethylene'],\n        smiles: 'C=C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 122.92,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 122.91625,\n                to: 122.92375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['ethylene glycol'],\n        smiles: 'OCCO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 64.29,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 64.28625000000001,\n                to: 64.29375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['H grease'],\n        smiles: '',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 30.31,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 30.30625,\n                to: 30.31375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['hexamethylbenzene'],\n        smiles: 'CC1=C(C(=C(C(=C1C)C)C)C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 131.72,\n                        assignment: 'C',\n                    },\n                ],\n                from: 131.71625,\n                to: 131.72375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 16.84,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 16.83625,\n                to: 16.84375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['n-hexane'],\n        smiles: 'CCCCCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 14.34,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.33625,\n                to: 14.34375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 23.12,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 23.11625,\n                to: 23.12375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 32.06,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 32.056250000000006,\n                to: 32.06375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['HMDSO'],\n        smiles: 'C[Si](C)(C)O[Si](C)(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 1.99,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 1.98625,\n                to: 1.99375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['HMPA'],\n        smiles: 'CN(C)P(=O)(N(C)C)N(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 36.8,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 36.79625,\n                to: 36.803749999999994,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['imidazole'],\n        smiles: 'C1=CN=CN1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 135.57,\n                        assignment: 'CH(2)',\n                    },\n                ],\n                from: 135.56625,\n                to: 135.57375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 122.13,\n                        assignment: 'CH(4,5)',\n                    },\n                ],\n                from: 122.12625,\n                to: 122.13374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['methane'],\n        smiles: 'C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: -4.34,\n                        assignment: 'CH₄',\n                    },\n                ],\n                from: -4.34375,\n                to: -4.33625,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['methanol'],\n        smiles: 'CO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 49.9,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 49.89625,\n                to: 49.903749999999995,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['nitromethane'],\n        smiles: 'C[N+](=O)[O-]',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 61.14,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 61.136250000000004,\n                to: 61.14375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['n-pentane'],\n        smiles: 'CCCCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 14.27,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.26625,\n                to: 14.27375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 22.79,\n                        assignment: 'CH₂(2,4)',\n                    },\n                ],\n                from: 22.78625,\n                to: 22.79375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 34.54,\n                        assignment: 'CH₂(3)',\n                    },\n                ],\n                from: 34.53625,\n                to: 34.543749999999996,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['propane'],\n        smiles: 'CCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 16.65,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 16.64625,\n                to: 16.65375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 16.63,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 16.62625,\n                to: 16.63375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['2-propanol'],\n        smiles: 'CC(O)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 25.24,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 25.23625,\n                to: 25.24375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 64.12,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 64.11625000000001,\n                to: 64.12375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['propylene'],\n        smiles: 'CC=C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 19.32,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 19.31625,\n                to: 19.32375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 115.89,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 115.88625,\n                to: 115.89375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 133.61,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 133.60625000000002,\n                to: 133.61375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['pyridine'],\n        smiles: 'C1=CC=NC=C1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 150.25,\n                        assignment: 'CH(2,6)',\n                    },\n                ],\n                from: 150.24625,\n                to: 150.25375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 123.46,\n                        assignment: 'CH(3,5)',\n                    },\n                ],\n                from: 123.45625,\n                to: 123.46374999999999,\n            },\n            {\n                signals: [\n                    {\n                        delta: 135.17,\n                        assignment: 'CH(4)',\n                    },\n                ],\n                from: 135.16625,\n                to: 135.17374999999998,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['pyrrole'],\n        smiles: 'C1=CNC=C1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 117.61,\n                        assignment: 'CH(2,5)',\n                    },\n                ],\n                from: 117.60625,\n                to: 117.61375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 108.15,\n                        assignment: 'CH(3,4)',\n                    },\n                ],\n                from: 108.14625000000001,\n                to: 108.15375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['pyrrolidine'],\n        smiles: 'C1CCNC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 47.12,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 47.11625,\n                to: 47.123749999999994,\n            },\n            {\n                signals: [\n                    {\n                        delta: 25.75,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 25.74625,\n                to: 25.75375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['silicone grease'],\n        smiles: '',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 1.37,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 1.3662500000000002,\n                to: 1.37375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['tetrahydrofuran'],\n        smiles: 'C1COCC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 67.75,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 67.74625,\n                to: 67.75375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 25.79,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 25.78625,\n                to: 25.79375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['toluene'],\n        smiles: 'Cc1ccccc1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 21.37,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 21.36625,\n                to: 21.37375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 137.84,\n                        assignment: 'C(1)',\n                    },\n                ],\n                from: 137.83625,\n                to: 137.84375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 129.33,\n                        assignment: 'CH(2,6)',\n                    },\n                ],\n                from: 129.32625000000002,\n                to: 129.33375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 128.51,\n                        assignment: 'CH(3,5)',\n                    },\n                ],\n                from: 128.50625,\n                to: 128.51375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 125.66,\n                        assignment: 'CH(4)',\n                    },\n                ],\n                from: 125.65625,\n                to: 125.66375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['triethylamine'],\n        smiles: 'CCN(CC)CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 12.39,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 12.38625,\n                to: 12.39375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 46.82,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 46.816250000000004,\n                to: 46.82375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'toluene- d₈',\n    },\n    {\n        names: ['acetic acid'],\n        smiles: 'CC(=O)O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 175.82,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 175.81625,\n                to: 175.82375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 20.37,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 20.36625,\n                to: 20.37375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['acetone'],\n        smiles: 'CC(=O)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 204.43,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 204.42625,\n                to: 204.43375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 30.14,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 30.13625,\n                to: 30.14375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['acetonitrile'],\n        smiles: 'CC#N',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 116.02,\n                        assignment: 'CN',\n                    },\n                ],\n                from: 116.01625,\n                to: 116.02374999999999,\n            },\n            {\n                signals: [\n                    {\n                        delta: 0.2,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 0.19625,\n                to: 0.20375000000000001,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['benzene'],\n        smiles: 'c1ccccc1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 128.62,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 128.61625,\n                to: 128.62375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['tert -butyl alcohol'],\n        smiles: 'CC(C)(C)O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 68.19,\n                        assignment: '(CH₃)₃C',\n                    },\n                ],\n                from: 68.18625,\n                to: 68.19375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 30.47,\n                        assignment: '(CH₃)₃C',\n                    },\n                ],\n                from: 30.46625,\n                to: 30.47375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['carbon dioxide'],\n        smiles: 'O=C=O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 124.76,\n                        assignment: 'CO₂',\n                    },\n                ],\n                from: 124.75625000000001,\n                to: 124.76375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['carbon disulfide'],\n        smiles: 'S=C=S',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 192.69,\n                        assignment: 'CS₂',\n                    },\n                ],\n                from: 192.68625,\n                to: 192.69375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['carbon tetrachloride'],\n        smiles: 'ClC(Cl)(Cl)Cl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 96.44,\n                        assignment: 'CCl₄',\n                    },\n                ],\n                from: 96.43625,\n                to: 96.44375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['chloroform'],\n        smiles: 'ClC(Cl)Cl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 77.79,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 77.78625000000001,\n                to: 77.79375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['18-crown-6'],\n        smiles: 'C1COCCOCCOCCOCCOCCO1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 70.59,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 70.58625,\n                to: 70.59375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['cyclohexane'],\n        smiles: 'C1CCCCC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 27.23,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 27.22625,\n                to: 27.23375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['1,2-dichloroethane'],\n        smiles: 'ClCCCl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 43.59,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 43.58625000000001,\n                to: 43.59375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['dichloromethane'],\n        smiles: 'ClCCl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 53.46,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 53.456250000000004,\n                to: 53.46375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['diethyl ether'],\n        smiles: 'CCOCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 15.46,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 15.45625,\n                to: 15.463750000000001,\n            },\n            {\n                signals: [\n                    {\n                        delta: 65.94,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 65.93625,\n                to: 65.94375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['diglyme'],\n        smiles: 'COCCOCCOC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 58.66,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 58.65625,\n                to: 58.66374999999999,\n            },\n            {\n                signals: [\n                    {\n                        delta: 70.87,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 70.86625000000001,\n                to: 70.87375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 72.35,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 72.34625,\n                to: 72.35374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['dimethylformamide'],\n        smiles: 'C(=O)N(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 162.13,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 162.12625,\n                to: 162.13375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 35.25,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 35.24625,\n                to: 35.25375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 30.72,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 30.71625,\n                to: 30.72375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['1,4-dioxane'],\n        smiles: 'C1COCCOC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 67.16,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 67.15625,\n                to: 67.16375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['DME', 'diethyl ether'],\n        smiles: 'CCOCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 58.68,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 58.67625,\n                to: 58.683749999999996,\n            },\n            {\n                signals: [\n                    {\n                        delta: 72.21,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 72.20625,\n                to: 72.21374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['ethane'],\n        smiles: 'CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 6.96,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 6.95625,\n                to: 6.96375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['ethanol'],\n        smiles: 'CCO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 18.72,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 18.71625,\n                to: 18.72375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 57.86,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 57.85625,\n                to: 57.863749999999996,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['ethyl acetate'],\n        smiles: 'CC(=O)CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 20.56,\n                        assignment: 'CH₃CO',\n                    },\n                ],\n                from: 20.55625,\n                to: 20.56375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 170.44,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 170.43625,\n                to: 170.44375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 60.21,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 60.206250000000004,\n                to: 60.21375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 14.19,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.18625,\n                to: 14.19375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['ethylene'],\n        smiles: 'C=C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 122.96,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 122.95625,\n                to: 122.96374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['ethylene glycol'],\n        smiles: 'OCCO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 64.34,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 64.33625,\n                to: 64.34375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['H grease'],\n        smiles: '',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 30.22,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 30.21625,\n                to: 30.22375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['hexamethylbenzene'],\n        smiles: 'CC1=C(C(=C(C(=C1C)C)C)C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 131.79,\n                        assignment: 'C',\n                    },\n                ],\n                from: 131.78625,\n                to: 131.79375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 16.95,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 16.94625,\n                to: 16.95375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['n-hexane'],\n        smiles: 'CCCCCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 14.32,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.31625,\n                to: 14.32375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 23.04,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 23.03625,\n                to: 23.04375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 31.96,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 31.95625,\n                to: 31.96375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['HMDSO'],\n        smiles: 'C[Si](C)(C)O[Si](C)(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 2.05,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 2.0462499999999997,\n                to: 2.05375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['HMPA'],\n        smiles: 'CN(C)P(=O)(N(C)C)N(C)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 36.88,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 36.876250000000006,\n                to: 36.88375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['imidazole'],\n        smiles: 'C1=CN=CN1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 135.76,\n                        assignment: 'CH(2)',\n                    },\n                ],\n                from: 135.75625,\n                to: 135.76375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 122.16,\n                        assignment: 'CH(4,5)',\n                    },\n                ],\n                from: 122.15625,\n                to: 122.16375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['methane'],\n        smiles: 'C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: -4.29,\n                        assignment: 'CH₄',\n                    },\n                ],\n                from: -4.29375,\n                to: -4.28625,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['methanol'],\n        smiles: 'CO',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 49.97,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 49.96625,\n                to: 49.973749999999995,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['nitromethane'],\n        smiles: 'C[N+](=O)[O-]',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 61.16,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 61.15625,\n                to: 61.16374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['n-pentane'],\n        smiles: 'CCCCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 14.25,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 14.24625,\n                to: 14.25375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 22.72,\n                        assignment: 'CH₂(2,4)',\n                    },\n                ],\n                from: 22.71625,\n                to: 22.72375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 34.45,\n                        assignment: 'CH₂(3)',\n                    },\n                ],\n                from: 34.446250000000006,\n                to: 34.45375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['propane'],\n        smiles: 'CCC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 16.66,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 16.65625,\n                to: 16.66375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 16.6,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 16.59625,\n                to: 16.60375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['2-propanol'],\n        smiles: 'CC(O)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 25.18,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 25.17625,\n                to: 25.18375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 64.23,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 64.22625000000001,\n                to: 64.23375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['propylene'],\n        smiles: 'CC=C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 19.38,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 19.37625,\n                to: 19.38375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 115.92,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 115.91625,\n                to: 115.92375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 133.69,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 133.68625,\n                to: 133.69375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['pyridine'],\n        smiles: 'C1=CC=NC=C1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 150.27,\n                        assignment: 'CH(2,6)',\n                    },\n                ],\n                from: 150.26625,\n                to: 150.27375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 123.58,\n                        assignment: 'CH(3,5)',\n                    },\n                ],\n                from: 123.57625,\n                to: 123.58375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 135.28,\n                        assignment: 'CH(4)',\n                    },\n                ],\n                from: 135.27625,\n                to: 135.28375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['pyrrole'],\n        smiles: 'C1=CNC=C1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 117.78,\n                        assignment: 'CH(2,5)',\n                    },\n                ],\n                from: 117.77625,\n                to: 117.78375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 108.21,\n                        assignment: 'CH(3,4)',\n                    },\n                ],\n                from: 108.20625,\n                to: 108.21374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['pyrrolidine'],\n        smiles: 'C1CCNC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 46.86,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 46.85625,\n                to: 46.863749999999996,\n            },\n            {\n                signals: [\n                    {\n                        delta: 25.65,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 25.64625,\n                to: 25.65375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['silicone grease'],\n        smiles: '',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 1.38,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 1.37625,\n                to: 1.3837499999999998,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['tetrahydrofuran'],\n        smiles: 'C1COCC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 67.8,\n                        assignment: 'CH₂(2,5)',\n                    },\n                ],\n                from: 67.79625,\n                to: 67.80375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 25.72,\n                        assignment: 'CH₂(3,4)',\n                    },\n                ],\n                from: 25.71625,\n                to: 25.72375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['toluene'],\n        smiles: 'Cc1ccccc1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 21.1,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 21.09625,\n                to: 21.10375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 137.91,\n                        assignment: 'C(1)',\n                    },\n                ],\n                from: 137.90625,\n                to: 137.91375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 129.33,\n                        assignment: 'CH(2,6)',\n                    },\n                ],\n                from: 129.32625000000002,\n                to: 129.33375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 128.56,\n                        assignment: 'CH(3,5)',\n                    },\n                ],\n                from: 128.55625,\n                to: 128.56375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 125.68,\n                        assignment: 'CH(4)',\n                    },\n                ],\n                from: 125.67625000000001,\n                to: 125.68375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['triethylamine'],\n        smiles: 'CCN(CC)CC',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 12.35,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 12.34625,\n                to: 12.35375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 46.77,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 46.76625000000001,\n                to: 46.77375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₆',\n    },\n    {\n        names: ['acetic acid'],\n        smiles: 'CC(=O)O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 175.67,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 175.66625,\n                to: 175.67374999999998,\n            },\n            {\n                signals: [\n                    {\n                        delta: 20.4,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 20.39625,\n                to: 20.40375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₅Cl',\n    },\n    {\n        names: ['acetone'],\n        smiles: 'CC(=O)C',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 204.83,\n                        assignment: 'CO',\n                    },\n                ],\n                from: 204.82625000000002,\n                to: 204.83375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 30.12,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 30.11625,\n                to: 30.12375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₅Cl',\n    },\n    {\n        names: ['acetonitrile'],\n        smiles: 'CC#N',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 115.93,\n                        assignment: 'CN',\n                    },\n                ],\n                from: 115.92625000000001,\n                to: 115.93375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 0.63,\n                        assignment: 'CH₃',\n                    },\n                ],\n                from: 0.62625,\n                to: 0.63375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₅Cl',\n    },\n    {\n        names: ['benzene'],\n        smiles: 'c1ccccc1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 128.38,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 128.37625,\n                to: 128.38375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₅Cl',\n    },\n    {\n        names: ['tert -butyl alcohol'],\n        smiles: 'CC(C)(C)O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 68.19,\n                        assignment: '(CH₃)₃C',\n                    },\n                ],\n                from: 68.18625,\n                to: 68.19375,\n            },\n            {\n                signals: [\n                    {\n                        delta: 31.13,\n                        assignment: '(CH₃)₃C',\n                    },\n                ],\n                from: 31.12625,\n                to: 31.13375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₅Cl',\n    },\n    {\n        names: ['carbon dioxide'],\n        smiles: 'O=C=O',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 126.08,\n                        assignment: 'CO₂',\n                    },\n                ],\n                from: 126.07625,\n                to: 126.08375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₅Cl',\n    },\n    {\n        names: ['carbon disulfide'],\n        smiles: 'S=C=S',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 192.49,\n                        assignment: 'CS₂',\n                    },\n                ],\n                from: 192.48625,\n                to: 192.49375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₅Cl',\n    },\n    {\n        names: ['carbon tetrachloride'],\n        smiles: 'ClC(Cl)(Cl)Cl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 96.38,\n                        assignment: 'CCl₄',\n                    },\n                ],\n                from: 96.37625,\n                to: 96.38374999999999,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₅Cl',\n    },\n    {\n        names: ['chloroform'],\n        smiles: 'ClC(Cl)Cl',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 77.67,\n                        assignment: 'CH',\n                    },\n                ],\n                from: 77.66625,\n                to: 77.67375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₅Cl',\n    },\n    {\n        names: ['18-crown-6'],\n        smiles: 'C1COCCOCCOCCOCCOCCO1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 70.55,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 70.54625,\n                to: 70.55375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₅Cl',\n    },\n    {\n        names: ['cyclohexane'],\n        smiles: 'C1CCCCC1',\n        ranges: [\n            {\n                signals: [\n                    {\n                        delta: 26.99,\n                        assignment: 'CH₂',\n                    },\n                ],\n                from: 26.98625,\n                to: 26.99375,\n            },\n        ],\n        nucleus: '13C',\n        solvent: 'C₆D₅Cl',\n    },\n    {\n        names: ['1,2-dichloroethane'],\n        smiles: 'ClCCCl',\n        ranges: [\n          