nmr-processing 9.5.0 → 9.5.1-pre.1684857934

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/lib/apodization/apodization.d.ts +9 -4
  2. package/lib/apodization/apodization.js +3 -1
  3. package/lib/apodization/apodization.js.map +1 -1
  4. package/lib/apodization/applyWindow.js.map +1 -1
  5. package/lib/apodization/compose.js.map +1 -1
  6. package/lib/apodization/getFunction.js +3 -0
  7. package/lib/apodization/getFunction.js.map +1 -1
  8. package/lib/apodization/shapes/WindowFunctions.d.ts +6 -1
  9. package/lib/apodization/shapes/sineBell.d.ts +27 -0
  10. package/lib/apodization/shapes/sineBell.js +17 -0
  11. package/lib/apodization/shapes/sineBell.js.map +1 -0
  12. package/lib/apodization/utils/getData.js.map +1 -1
  13. package/lib/filters/Data1D.d.ts +6 -0
  14. package/lib/{xyz/Data2D.js → filters/Data1D.js} +1 -1
  15. package/lib/filters/Data1D.js.map +1 -0
  16. package/lib/filters/Entry1D.d.ts +10 -0
  17. package/lib/filters/Entry1D.js +3 -0
  18. package/lib/filters/Entry1D.js.map +1 -0
  19. package/lib/filters/ExclusionZone.d.ts +5 -0
  20. package/lib/filters/ExclusionZone.js +3 -0
  21. package/lib/filters/ExclusionZone.js.map +1 -0
  22. package/lib/filters/Filters.d.ts +7 -0
  23. package/lib/filters/Filters.js +47 -0
  24. package/lib/filters/Filters.js.map +1 -0
  25. package/lib/filters/FiltersManager.d.ts +23 -0
  26. package/lib/filters/FiltersManager.js +130 -0
  27. package/lib/filters/FiltersManager.js.map +1 -0
  28. package/lib/filters/MatrixFilter.d.ts +39 -0
  29. package/lib/filters/MatrixFilter.js +3 -0
  30. package/lib/filters/MatrixFilter.js.map +1 -0
  31. package/lib/filters/MatrixOptions.d.ts +28 -0
  32. package/lib/filters/MatrixOptions.js +3 -0
  33. package/lib/filters/MatrixOptions.js.map +1 -0
  34. package/lib/filters/filter1d/apodization.d.ts +26 -0
  35. package/lib/filters/filter1d/apodization.js +77 -0
  36. package/lib/filters/filter1d/apodization.js.map +1 -0
  37. package/lib/filters/filter1d/baselineCorrection.d.ts +32 -0
  38. package/lib/filters/filter1d/baselineCorrection.js +61 -0
  39. package/lib/filters/filter1d/baselineCorrection.js.map +1 -0
  40. package/lib/filters/filter1d/digitalFilter.d.ts +15 -0
  41. package/lib/filters/filter1d/digitalFilter.js +47 -0
  42. package/lib/filters/filter1d/digitalFilter.js.map +1 -0
  43. package/lib/filters/filter1d/equallySpaced.d.ts +29 -0
  44. package/lib/filters/filter1d/equallySpaced.js +55 -0
  45. package/lib/filters/filter1d/equallySpaced.js.map +1 -0
  46. package/lib/filters/filter1d/exclusionZones.d.ts +11 -0
  47. package/lib/filters/filter1d/exclusionZones.js +35 -0
  48. package/lib/filters/filter1d/exclusionZones.js.map +1 -0
  49. package/lib/filters/filter1d/fft.d.ts +14 -0
  50. package/lib/filters/filter1d/fft.js +94 -0
  51. package/lib/filters/filter1d/fft.js.map +1 -0
  52. package/lib/filters/filter1d/phaseCorrection.d.ts +26 -0
  53. package/lib/filters/filter1d/phaseCorrection.js +81 -0
  54. package/lib/filters/filter1d/phaseCorrection.js.map +1 -0
  55. package/lib/filters/filter1d/shiftX.d.ts +16 -0
  56. package/lib/filters/filter1d/shiftX.js +30 -0
  57. package/lib/filters/filter1d/shiftX.js.map +1 -0
  58. package/lib/filters/filter1d/signalProcessing.d.ts +17 -0
  59. package/lib/filters/filter1d/signalProcessing.js +88 -0
  60. package/lib/filters/filter1d/signalProcessing.js.map +1 -0
  61. package/lib/filters/filter1d/utils/padDataToNextPowerOfTwo.d.ts +2 -0
  62. package/lib/filters/filter1d/utils/padDataToNextPowerOfTwo.js +41 -0
  63. package/lib/filters/filter1d/utils/padDataToNextPowerOfTwo.js.map +1 -0
  64. package/lib/filters/filter1d/zeroFilling.d.ts +18 -0
  65. package/lib/filters/filter1d/zeroFilling.js +68 -0
  66. package/lib/filters/filter1d/zeroFilling.js.map +1 -0
  67. package/lib/filters/filter2d/shiftX.d.ts +14 -0
  68. package/lib/filters/filter2d/shiftX.js +30 -0
  69. package/lib/filters/filter2d/shiftX.js.map +1 -0
  70. package/lib/filters/filter2d/shiftY.d.ts +14 -0
  71. package/lib/filters/filter2d/shiftY.js +30 -0
  72. package/lib/filters/filter2d/shiftY.js.map +1 -0
  73. package/lib/index.d.ts +2 -0
  74. package/lib/index.js +2 -0
  75. package/lib/index.js.map +1 -1
  76. package/lib/signals/signalsToFID.d.ts +3 -0
  77. package/lib/utilities/checkData2DFid.d.ts +3 -0
  78. package/lib/utilities/checkData2DFid.js +10 -0
  79. package/lib/utilities/checkData2DFid.js.map +1 -0
  80. package/lib/utilities/cloneData1D.d.ts +6 -0
  81. package/lib/utilities/cloneData1D.js +9 -0
  82. package/lib/utilities/cloneData1D.js.map +1 -0
  83. package/lib/utilities/cloneData2D.d.ts +2 -0
  84. package/lib/utilities/cloneData2D.js +28 -0
  85. package/lib/utilities/cloneData2D.js.map +1 -0
  86. package/lib/xyz/Entry2D.d.ts +10 -0
  87. package/lib/xyz/Entry2D.js +3 -0
  88. package/lib/xyz/Entry2D.js.map +1 -0
  89. package/lib/xyz/quadrature.d.ts +7 -0
  90. package/lib/xyz/quadrature.js +54 -0
  91. package/lib/xyz/quadrature.js.map +1 -0
  92. package/lib/xyz/util/fft2d/digitalFilter.d.ts +7 -0
  93. package/lib/xyz/util/fft2d/digitalFilter.js +20 -0
  94. package/lib/xyz/util/fft2d/digitalFilter.js.map +1 -0
  95. package/lib/xyz/util/fft2d/fftDirectDimension.d.ts +24 -0
  96. package/lib/xyz/util/fft2d/fftDirectDimension.js +57 -0
  97. package/lib/xyz/util/fft2d/fftDirectDimension.js.map +1 -0
  98. package/lib/xyz/util/fft2d/fftIndirectDimension.d.ts +23 -0
  99. package/lib/xyz/util/fft2d/fftIndirectDimension.js +72 -0
  100. package/lib/xyz/util/fft2d/fftIndirectDimension.js.map +1 -0
  101. package/lib/xyz/util/fft2d/removeDCOffset.d.ts +5 -0
  102. package/lib/xyz/util/fft2d/removeDCOffset.js +19 -0
  103. package/lib/xyz/util/fft2d/removeDCOffset.js.map +1 -0
  104. package/lib/xyz/util/fft2d/zeroFilling.d.ts +10 -0
  105. package/lib/xyz/util/fft2d/zeroFilling.js +29 -0
  106. package/lib/xyz/util/fft2d/zeroFilling.js.map +1 -0
  107. package/lib/xyz/util/padData.d.ts +5 -3
  108. package/lib/xyz/util/padData.js +7 -7
  109. package/lib/xyz/util/padData.js.map +1 -1
  110. package/lib/xyz/xyzAutoSignalsPicking.d.ts +2 -2
  111. package/lib/xyz/xyzAutoSignalsPicking.js.map +1 -1
  112. package/lib/xyz/xyzAutoZonesPicking.d.ts +2 -8
  113. package/lib/xyz/xyzAutoZonesPicking.js.map +1 -1
  114. package/lib/xyz/xyzBidimensionalFFT.d.ts +40 -0
  115. package/lib/xyz/xyzBidimensionalFFT.js +79 -0
  116. package/lib/xyz/xyzBidimensionalFFT.js.map +1 -0
  117. package/lib-esm/apodization/apodization.js +3 -1
  118. package/lib-esm/apodization/apodization.js.map +1 -1
  119. package/lib-esm/apodization/applyWindow.js.map +1 -1
  120. package/lib-esm/apodization/compose.js.map +1 -1
  121. package/lib-esm/apodization/getFunction.js +3 -0
  122. package/lib-esm/apodization/getFunction.js.map +1 -1
  123. package/lib-esm/apodization/shapes/sineBell.js +13 -0
  124. package/lib-esm/apodization/shapes/sineBell.js.map +1 -0
  125. package/lib-esm/apodization/utils/getData.js.map +1 -1
  126. package/lib-esm/filters/Data1D.js +2 -0
  127. package/lib-esm/filters/Data1D.js.map +1 -0
  128. package/lib-esm/filters/Entry1D.js +2 -0
  129. package/lib-esm/filters/Entry1D.js.map +1 -0
  130. package/lib-esm/filters/ExclusionZone.js +2 -0
  131. package/lib-esm/filters/ExclusionZone.js.map +1 -0
  132. package/lib-esm/filters/Filters.js +21 -0
  133. package/lib-esm/filters/Filters.js.map +1 -0
  134. package/lib-esm/filters/FiltersManager.js +124 -0
  135. package/lib-esm/filters/FiltersManager.js.map +1 -0
  136. package/lib-esm/filters/MatrixFilter.js +2 -0
  137. package/lib-esm/filters/MatrixFilter.js.map +1 -0
  138. package/lib-esm/filters/MatrixOptions.js +2 -0
  139. package/lib-esm/filters/MatrixOptions.js.map +1 -0
  140. package/lib-esm/filters/filter1d/apodization.js +70 -0
  141. package/lib-esm/filters/filter1d/apodization.js.map +1 -0
  142. package/lib-esm/filters/filter1d/baselineCorrection.js +52 -0
  143. package/lib-esm/filters/filter1d/baselineCorrection.js.map +1 -0
  144. package/lib-esm/filters/filter1d/digitalFilter.js +41 -0
  145. package/lib-esm/filters/filter1d/digitalFilter.js.map +1 -0
  146. package/lib-esm/filters/filter1d/equallySpaced.js +49 -0
  147. package/lib-esm/filters/filter1d/equallySpaced.js.map +1 -0
  148. package/lib-esm/filters/filter1d/exclusionZones.js +29 -0
  149. package/lib-esm/filters/filter1d/exclusionZones.js.map +1 -0
  150. package/lib-esm/filters/filter1d/fft.js +88 -0
  151. package/lib-esm/filters/filter1d/fft.js.map +1 -0
  152. package/lib-esm/filters/filter1d/phaseCorrection.js +75 -0
  153. package/lib-esm/filters/filter1d/phaseCorrection.js.map +1 -0
  154. package/lib-esm/filters/filter1d/shiftX.js +24 -0
  155. package/lib-esm/filters/filter1d/shiftX.js.map +1 -0
  156. package/lib-esm/filters/filter1d/signalProcessing.js +58 -0
  157. package/lib-esm/filters/filter1d/signalProcessing.js.map +1 -0
  158. package/lib-esm/filters/filter1d/utils/padDataToNextPowerOfTwo.js +37 -0
  159. package/lib-esm/filters/filter1d/utils/padDataToNextPowerOfTwo.js.map +1 -0
  160. package/lib-esm/filters/filter1d/zeroFilling.js +62 -0
  161. package/lib-esm/filters/filter1d/zeroFilling.js.map +1 -0
  162. package/lib-esm/filters/filter2d/shiftX.js +24 -0
  163. package/lib-esm/filters/filter2d/shiftX.js.map +1 -0
  164. package/lib-esm/filters/filter2d/shiftY.js +24 -0
  165. package/lib-esm/filters/filter2d/shiftY.js.map +1 -0
  166. package/lib-esm/index.js +2 -0
  167. package/lib-esm/index.js.map +1 -1
  168. package/lib-esm/utilities/checkData2DFid.js +6 -0
  169. package/lib-esm/utilities/checkData2DFid.js.map +1 -0
  170. package/lib-esm/utilities/cloneData1D.js +5 -0
  171. package/lib-esm/utilities/cloneData1D.js.map +1 -0
  172. package/lib-esm/utilities/cloneData2D.js +24 -0
  173. package/lib-esm/utilities/cloneData2D.js.map +1 -0
  174. package/lib-esm/xyz/Entry2D.js +2 -0
  175. package/lib-esm/xyz/Entry2D.js.map +1 -0
  176. package/lib-esm/xyz/quadrature.js +50 -0
  177. package/lib-esm/xyz/quadrature.js.map +1 -0
  178. package/lib-esm/xyz/util/fft2d/digitalFilter.js +16 -0
  179. package/lib-esm/xyz/util/fft2d/digitalFilter.js.map +1 -0
  180. package/lib-esm/xyz/util/fft2d/fftDirectDimension.js +50 -0
  181. package/lib-esm/xyz/util/fft2d/fftDirectDimension.js.map +1 -0
  182. package/lib-esm/xyz/util/fft2d/fftIndirectDimension.js +65 -0
  183. package/lib-esm/xyz/util/fft2d/fftIndirectDimension.js.map +1 -0
  184. package/lib-esm/xyz/util/fft2d/removeDCOffset.js +15 -0
  185. package/lib-esm/xyz/util/fft2d/removeDCOffset.js.map +1 -0
  186. package/lib-esm/xyz/util/fft2d/zeroFilling.js +25 -0
  187. package/lib-esm/xyz/util/fft2d/zeroFilling.js.map +1 -0
  188. package/lib-esm/xyz/util/padData.js +7 -4
  189. package/lib-esm/xyz/util/padData.js.map +1 -1
  190. package/lib-esm/xyz/xyzAutoSignalsPicking.js.map +1 -1
  191. package/lib-esm/xyz/xyzAutoZonesPicking.js.map +1 -1
  192. package/lib-esm/xyz/xyzBidimensionalFFT.js +75 -0
  193. package/lib-esm/xyz/xyzBidimensionalFFT.js.map +1 -0
  194. package/package.json +7 -2
  195. package/src/apodization/apodization.ts +6 -4
  196. package/src/apodization/applyWindow.ts +0 -1
  197. package/src/apodization/compose.ts +1 -0
  198. package/src/apodization/getFunction.ts +3 -0
  199. package/src/apodization/shapes/WindowFunctions.ts +7 -1
  200. package/src/apodization/shapes/sineBell.ts +41 -0
  201. package/src/apodization/utils/getData.ts +0 -1
  202. package/src/filters/Data1D.ts +7 -0
  203. package/src/filters/Entry1D.ts +11 -0
  204. package/src/filters/ExclusionZone.ts +5 -0
  205. package/src/filters/Filters.ts +24 -0
  206. package/src/filters/FiltersManager.ts +176 -0
  207. package/src/filters/MatrixFilter.ts +58 -0
  208. package/src/filters/MatrixOptions.ts +26 -0
  209. package/src/filters/filter1d/apodization.ts +90 -0
  210. package/src/filters/filter1d/baselineCorrection.ts +83 -0
  211. package/src/filters/filter1d/digitalFilter.ts +51 -0
  212. package/src/filters/filter1d/equallySpaced.ts +61 -0
  213. package/src/filters/filter1d/exclusionZones.ts +34 -0
  214. package/src/filters/filter1d/fft.ts +135 -0
  215. package/src/filters/filter1d/phaseCorrection.ts +118 -0
  216. package/src/filters/filter1d/shiftX.ts +31 -0
  217. package/src/filters/filter1d/signalProcessing.ts +79 -0
  218. package/src/filters/filter1d/utils/padDataToNextPowerOfTwo.ts +48 -0
  219. package/src/filters/filter1d/zeroFilling.ts +90 -0
  220. package/src/filters/filter2d/shiftX.ts +31 -0
  221. package/src/filters/filter2d/shiftY.ts +29 -0
  222. package/src/index.ts +3 -0
  223. package/src/utilities/checkData2DFid.ts +10 -0
  224. package/src/utilities/cloneData1D.ts +6 -0
  225. package/src/utilities/cloneData2D.ts +27 -0
  226. package/src/xyz/Entry2D.ts +12 -0
  227. package/src/xyz/quadrature.ts +68 -0
  228. package/src/xyz/util/fft2d/digitalFilter.ts +24 -0
  229. package/src/xyz/util/fft2d/fftDirectDimension.ts +111 -0
  230. package/src/xyz/util/fft2d/fftIndirectDimension.ts +123 -0
  231. package/src/xyz/util/fft2d/removeDCOffset.ts +19 -0
  232. package/src/xyz/util/fft2d/zeroFilling.ts +39 -0
  233. package/src/xyz/util/padData.ts +13 -7
  234. package/src/xyz/xyzAutoSignalsPicking.ts +2 -2
  235. package/src/xyz/xyzAutoZonesPicking.ts +3 -9
  236. package/src/xyz/xyzBidimensionalFFT.ts +122 -0
  237. package/lib/xyz/Data2D.d.ts +0 -7
  238. package/lib/xyz/Data2D.js.map +0 -1
  239. package/lib-esm/xyz/Data2D.js +0 -2
  240. package/lib-esm/xyz/Data2D.js.map +0 -1
  241. package/src/xyz/Data2D.ts +0 -7
@@ -0,0 +1,90 @@
1
+ import { apodization } from '../../apodization/apodization';
2
+ import { Entry1D } from '../Entry1D';
3
+ import { FilterDomainUpdateRules } from '../FiltersManager';
4
+
5
+ export const id = 'apodization';
6
+ export const name = 'Apodization';
7
+ export const DOMAIN_UPDATE_RULES: Readonly<FilterDomainUpdateRules> = {
8
+ updateXDomain: true,
9
+ updateYDomain: false,
10
+ };
11
+
12
+ export interface ApodizationOptions {
13
+ lineBroadening: number;
14
+ gaussBroadening: number;
15
+ lineBroadeningCenter: number;
16
+ }
17
+
18
+ export const defaultApodizationOptions: ApodizationOptions = {
19
+ lineBroadening: 1,
20
+ gaussBroadening: 0,
21
+ lineBroadeningCenter: 0,
22
+ };
23
+
24
+ export function apply(datum1D: Entry1D, options: ApodizationOptions) {
25
+ const newData = apodizationFilter(datum1D, options);
26
+
27
+ datum1D.data = {
28
+ ...datum1D.data,
29
+ re: newData.re as Float64Array,
30
+ im: newData.im as Float64Array,
31
+ };
32
+ }
33
+ export function isApplicable(datum1D: Entry1D) {
34
+ if (datum1D.info.isComplex && datum1D.info.isFid) return true;
35
+ return false;
36
+ }
37
+
38
+ export function reduce(previousValue: any, newValue: any) {
39
+ return {
40
+ once: true,
41
+ reduce: newValue,
42
+ };
43
+ }
44
+
45
+ export function apodizationFilter(
46
+ datum1D: Entry1D,
47
+ options: ApodizationOptions,
48
+ ) {
49
+ const { lineBroadening, gaussBroadening, lineBroadeningCenter } = options;
50
+ let grpdly = datum1D.info?.digitalFilter || 0;
51
+ let pointsToShift;
52
+ if (grpdly > 0) {
53
+ pointsToShift = Math.floor(grpdly);
54
+ } else {
55
+ pointsToShift = 0;
56
+ }
57
+
58
+ const re = datum1D.data.re;
59
+ const im = datum1D.data.im;
60
+ const t = datum1D.data.x;
61
+
62
+ const length = re.length;
63
+ const dw = (t[length - 1] - t[0]) / (length - 1); //REPLACE CONSTANT with calculated value... : for this we need AQ or DW to set it right...
64
+
65
+ return apodization(
66
+ { re, im },
67
+ {
68
+ pointsToShift,
69
+ compose: {
70
+ length,
71
+ shapes: [
72
+ {
73
+ start: 0,
74
+ shape: {
75
+ kind: 'lorentzToGauss',
76
+ options: {
77
+ length,
78
+ dw,
79
+ exponentialHz:
80
+ gaussBroadening > 0 ? lineBroadening : -lineBroadening,
81
+ gaussianHz: gaussBroadening,
82
+ center: lineBroadeningCenter,
83
+ },
84
+ },
85
+ },
86
+ ],
87
+ },
88
+ },
89
+ );
90
+ }
@@ -0,0 +1,83 @@
1
+ import airPLS from 'ml-airpls';
2
+ import baselineRegression from 'ml-baseline-correction-regression';
3
+ import { xyEquallySpaced } from 'ml-spectra-processing';
4
+
5
+ import { Entry1D } from '../Entry1D';
6
+ import { FilterDomainUpdateRules } from '../FiltersManager';
7
+
8
+ export const id = 'baselineCorrection';
9
+ export const name = 'Baseline correction';
10
+ export const DOMAIN_UPDATE_RULES: Readonly<FilterDomainUpdateRules> = {
11
+ updateXDomain: false,
12
+ updateYDomain: true,
13
+ };
14
+
15
+ export type BaselineAlgorithms = 'airpls' | 'polynomial';
16
+
17
+ export interface PolynomialOptions {
18
+ zones: Array<{ from: number; to: number; id: string }>;
19
+ algorithm: 'polynomial';
20
+ degree: number;
21
+ }
22
+
23
+ export interface AirplsOptions {
24
+ zones: Array<{ from: number; to: number; id: string }>;
25
+ algorithm: 'airpls';
26
+ maxIterations: number;
27
+ tolerance: number;
28
+ }
29
+
30
+ export type BaselineCorrectionOptions = PolynomialOptions | AirplsOptions;
31
+
32
+ export function apply(datum1D: Entry1D, options: BaselineCorrectionOptions) {
33
+ if (!isApplicable(datum1D)) {
34
+ throw new Error('baselineCorrection not applicable on this data');
35
+ }
36
+ const { algorithm } = options;
37
+ let { x, re } = datum1D.data;
38
+
39
+ let corrected;
40
+ switch (algorithm) {
41
+ case 'airpls':
42
+ corrected = airPLS(x, re, options).corrected;
43
+ break;
44
+ case 'polynomial':
45
+ {
46
+ const { degree, zones } = options;
47
+ let reduced = xyEquallySpaced(
48
+ { x, y: re },
49
+ { numberOfPoints: 4096, zones },
50
+ );
51
+ let result = baselineRegression(reduced.x, reduced.y, {
52
+ regressionOptions: degree,
53
+ });
54
+ let { regression } = result;
55
+ corrected = new Float64Array(x.length);
56
+ for (let i = 0; i < re.length; i++) {
57
+ corrected[i] = re[i] - regression.predict(x[i]);
58
+ }
59
+ }
60
+
61
+ break;
62
+ default:
63
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
64
+ throw new Error(`baselineCorrection: algorithm unknown: ${algorithm}`);
65
+ }
66
+
67
+ Object.assign(datum1D.data, { re: corrected });
68
+ }
69
+
70
+ export function isApplicable(datum1D: Entry1D) {
71
+ if (!datum1D.info.isFid) return true;
72
+ return false;
73
+ }
74
+
75
+ export function reduce(
76
+ previousValue: BaselineCorrectionOptions,
77
+ newValue: BaselineCorrectionOptions,
78
+ ) {
79
+ return {
80
+ once: true,
81
+ reduce: newValue,
82
+ };
83
+ }
@@ -0,0 +1,51 @@
1
+ import { Entry1D } from '../Entry1D';
2
+ import { FilterDomainUpdateRules } from '../FiltersManager';
3
+
4
+ export const id = 'digitalFilter';
5
+ export const name = 'Digital Filter';
6
+ export const DOMAIN_UPDATE_RULES: Readonly<FilterDomainUpdateRules> = {
7
+ updateXDomain: true,
8
+ updateYDomain: true,
9
+ };
10
+
11
+ /**
12
+ * Move points from the beginning to the end of FID and performs a first order phase correction
13
+ * @param {Datum1d} datum1d
14
+ */
15
+
16
+ export function apply(datum1D: Entry1D, options: any = {}) {
17
+ if (!isApplicable(datum1D)) {
18
+ throw new Error('Digital Filter is not applicable on this data');
19
+ }
20
+
21
+ let { digitalFilterValue = 0 } = options;
22
+ let re = new Float64Array(datum1D.data.re);
23
+ let im = new Float64Array(datum1D.data.im);
24
+
25
+ let pointsToShift = Math.floor(digitalFilterValue);
26
+
27
+ const skip = 0;
28
+ pointsToShift += 0;
29
+
30
+ const newRe = new Float64Array(re.length);
31
+ const newIm = new Float64Array(im.length);
32
+ newRe.set(re.slice(pointsToShift));
33
+ newRe.set(re.slice(skip, pointsToShift), re.length - pointsToShift);
34
+ newIm.set(im.slice(pointsToShift));
35
+ newIm.set(im.slice(skip, pointsToShift), im.length - pointsToShift);
36
+
37
+ datum1D.data.re = newRe;
38
+ datum1D.data.im = newIm;
39
+ }
40
+
41
+ export function isApplicable(datum1D: Entry1D) {
42
+ if (datum1D.info.isComplex && datum1D.info.isFid) return true;
43
+ return false;
44
+ }
45
+
46
+ export function reduce() {
47
+ return {
48
+ once: true,
49
+ reduce: undefined,
50
+ };
51
+ }
@@ -0,0 +1,61 @@
1
+ import { xyEquallySpaced } from 'ml-spectra-processing';
2
+
3
+ import { Entry1D } from '../Entry1D';
4
+
5
+ export const id = 'equallySpaced';
6
+ export const name = 'Equally spaced';
7
+
8
+ /**
9
+ * Equally Spaced
10
+ * **
11
+ * Function that returns a Number array of equally spaced numberOfPoints
12
+ * containing a representation of intensities of the spectra arguments x
13
+ * and y.
14
+ *
15
+ * The options parameter contains an object in the following form:
16
+ * from: starting point
17
+ * to: last point
18
+ * numberOfPoints: number of points between from and to
19
+ * variant: "slot" or "smooth" - smooth is the default option
20
+ *
21
+ * The slot variant consist that each point in the new array is calculated
22
+ * averaging the existing points between the slot that belongs to the current
23
+ * value. The smooth variant is the same but takes the integral of the range
24
+ * of the slot and divide by the step size between two points in the new array.
25
+ *
26
+ * @param {Array<{from:number;to:number}>} options.exclusions
27
+ */
28
+
29
+ export function apply(spectrum: Entry1D, options: any = {}) {
30
+ if (!isApplicable(spectrum)) {
31
+ throw new Error('Equally Spaced is not applicable on this data');
32
+ }
33
+ const { from, to, numberOfPoints, exclusions } = options;
34
+ const { x, re, im } = spectrum.data;
35
+ const XREdata = xyEquallySpaced(
36
+ { x, y: re },
37
+ { from, to, numberOfPoints, exclusions },
38
+ );
39
+
40
+ spectrum.data.x = XREdata.x;
41
+ spectrum.data.re = XREdata.y;
42
+ if (im) {
43
+ const XIMdata = xyEquallySpaced(
44
+ { x, y: re },
45
+ { from, to, numberOfPoints, exclusions },
46
+ );
47
+ spectrum.data.im = XIMdata.y;
48
+ }
49
+ }
50
+
51
+ export function isApplicable(spectrum: Entry1D) {
52
+ if (spectrum.info.isComplex && !spectrum.info.isFid) return true;
53
+ return false;
54
+ }
55
+
56
+ export function reduce() {
57
+ return {
58
+ once: false,
59
+ reduce: null,
60
+ };
61
+ }
@@ -0,0 +1,34 @@
1
+ import { xySetYValue, zonesNormalize } from 'ml-spectra-processing';
2
+
3
+ import { Entry1D } from '../Entry1D';
4
+ import { FilterDomainUpdateRules } from '../FiltersManager';
5
+
6
+ export const id = 'exclusionZones';
7
+ export const name = 'Exclusion zones';
8
+ export const DOMAIN_UPDATE_RULES: Readonly<FilterDomainUpdateRules> = {
9
+ updateXDomain: false,
10
+ updateYDomain: false,
11
+ };
12
+
13
+ export function apply(spectrum: Entry1D, zones = []) {
14
+ if (!isApplicable(spectrum)) {
15
+ throw new Error('Exclusion Zones filter not applicable on this data');
16
+ }
17
+ const { x, re, im } = spectrum.data;
18
+ spectrum.data.re = Float64Array.from(xySetYValue({ x, y: re }, { zones }).y);
19
+ spectrum.data.im = im
20
+ ? Float64Array.from(xySetYValue({ x, y: re }, { zones }).y)
21
+ : im;
22
+ }
23
+
24
+ export function isApplicable(spectrum: Entry1D) {
25
+ if (spectrum.info.isFt) return true;
26
+ return false;
27
+ }
28
+
29
+ export function reduce(previousValue: any, newValue: any) {
30
+ return {
31
+ once: true,
32
+ reduce: zonesNormalize(previousValue.concat(newValue)),
33
+ };
34
+ }
@@ -0,0 +1,135 @@
1
+ import {
2
+ DataReIm,
3
+ reimFFT,
4
+ reimPhaseCorrection,
5
+ xMean,
6
+ } from 'ml-spectra-processing';
7
+
8
+ import { Data1D } from '../Data1D';
9
+ import { Entry1D } from '../Entry1D';
10
+ import { FilterDomainUpdateRules } from '../FiltersManager';
11
+
12
+ import { padDataToNextPowerOfTwo } from './utils/padDataToNextPowerOfTwo';
13
+
14
+ export const id = 'fft';
15
+ export const name = 'FFT';
16
+ export const DOMAIN_UPDATE_RULES: Readonly<FilterDomainUpdateRules> = {
17
+ updateXDomain: true,
18
+ updateYDomain: true,
19
+ };
20
+
21
+ export function apply(datum1D: Entry1D) {
22
+ if (!isApplicable(datum1D)) {
23
+ throw new Error('fft not applicable on this data');
24
+ }
25
+
26
+ checkSameLength(datum1D);
27
+
28
+ let digitalFilterApplied = datum1D.filters.some(
29
+ (e) => e.name === 'digitalFilter' && e.flag,
30
+ );
31
+
32
+ const {
33
+ info: { aqMod },
34
+ } = datum1D;
35
+
36
+ if (aqMod === 1) {
37
+ removeDCOffset(datum1D, digitalFilterApplied);
38
+ }
39
+
40
+ if (!isPowerOfTwo(datum1D.data.x.length)) {
41
+ padDataToNextPowerOfTwo(datum1D, digitalFilterApplied);
42
+ }
43
+
44
+ const { data, info } = datum1D;
45
+ Object.assign(
46
+ data,
47
+ reimFFT(
48
+ {
49
+ re: data.re,
50
+ im: data.im,
51
+ },
52
+ { applyZeroShift: true },
53
+ ),
54
+ );
55
+
56
+ if (digitalFilterApplied) {
57
+ let { digitalFilter = 0 } = info;
58
+ let ph1 = (digitalFilter - Math.floor(digitalFilter)) * Math.PI * 2;
59
+ Object.assign(
60
+ data,
61
+ reimPhaseCorrection(data as DataReIm, 0, -ph1, { reverse: true }),
62
+ );
63
+ }
64
+
65
+ datum1D.data.x = generateXAxis(datum1D);
66
+ datum1D.info = { ...datum1D.info, isFid: false, isFt: true };
67
+ }
68
+
69
+ export function isApplicable(
70
+ datum1D: Entry1D,
71
+ ): datum1D is Entry1D & { data: Required<Data1D> } {
72
+ if (datum1D.info.isComplex && datum1D.info.isFid) return true;
73
+ return false;
74
+ }
75
+
76
+ export function reduce() {
77
+ return {
78
+ once: true,
79
+ reduce: undefined,
80
+ };
81
+ }
82
+
83
+ function generateXAxis(datum1D: Entry1D) {
84
+ const info = datum1D.info;
85
+ const baseFrequency = Number.parseFloat(info.baseFrequency);
86
+ const frequencyOffset = Number.parseFloat(info.frequencyOffset);
87
+ const spectralWidth = Number.parseFloat(info.spectralWidth);
88
+ const offset = frequencyOffset / baseFrequency;
89
+ let spectralHalfWidth = 0.5 * spectralWidth;
90
+ let nbPoints = datum1D.data.x.length;
91
+ let firstPoint = offset - spectralHalfWidth;
92
+ let dx = spectralWidth / (nbPoints - 1);
93
+ const xAxis = new Float64Array(nbPoints);
94
+ for (let i = 0; i < nbPoints; i++) {
95
+ xAxis[i] = firstPoint;
96
+ firstPoint += dx;
97
+ }
98
+ return xAxis;
99
+ }
100
+
101
+ function isPowerOfTwo(n: number) {
102
+ return n !== 0 && (n & (n - 1)) === 0;
103
+ }
104
+
105
+ function removeDCOffset(spectrum: Entry1D, digitalFilterApplied: boolean) {
106
+ let { digitalFilter = 0 } = digitalFilterApplied ? spectrum.info : {};
107
+ const data = spectrum.data;
108
+ const nbPoints = data.re.length;
109
+ const newRe = new Float64Array(data.re);
110
+ const newIm = new Float64Array(data.im);
111
+ const averageRe = xMean(
112
+ data.re.slice((nbPoints * 0.75) >> 0, nbPoints - digitalFilter),
113
+ );
114
+ const averageIm = xMean(
115
+ data.im.slice((nbPoints * 0.75) >> 0, nbPoints - digitalFilter),
116
+ );
117
+ for (
118
+ let i = digitalFilterApplied ? 0 : digitalFilter;
119
+ i < nbPoints - digitalFilter;
120
+ i++
121
+ ) {
122
+ newRe[i] -= averageRe;
123
+ newIm[i] -= averageIm;
124
+ }
125
+
126
+ Object.assign(spectrum.data, { re: newRe, im: newIm });
127
+ return spectrum;
128
+ }
129
+
130
+ function checkSameLength(spectrum: Entry1D) {
131
+ const { data } = spectrum;
132
+ if (data.x.length !== data.re.length || data.x.length !== data.im?.length) {
133
+ throw new Error('The length of data should be equal');
134
+ }
135
+ }
@@ -0,0 +1,118 @@
1
+ import {
2
+ reimAbsolute,
3
+ reimAutoPhaseCorrection,
4
+ reimPhaseCorrection,
5
+ } from 'ml-spectra-processing';
6
+
7
+ import { Data1D } from '../Data1D';
8
+ import { Entry1D } from '../Entry1D';
9
+ import { FilterDomainUpdateRules } from '../FiltersManager';
10
+
11
+ export const id = 'phaseCorrection';
12
+ export const name = 'Phase correction';
13
+ export const DOMAIN_UPDATE_RULES: Readonly<FilterDomainUpdateRules> = {
14
+ updateXDomain: false,
15
+ updateYDomain: false,
16
+ };
17
+ export interface PhaseCorrectionParameters {
18
+ ph0: number;
19
+ ph1: number;
20
+ absolute: boolean;
21
+ }
22
+
23
+ /**
24
+ *
25
+ * @param {Datum1d} datum1d
26
+ * @param {Object} [options={}]
27
+ * @param {number} [options.ph0=0]
28
+ * @param {number} [options.ph1=0]
29
+ */
30
+
31
+ export function apply(datum1D: Entry1D, options: any = {}) {
32
+ if (!isApplicable(datum1D)) {
33
+ throw new Error('phaseCorrection not applicable on this data');
34
+ }
35
+
36
+ const { absolute = false } = options;
37
+ const filter = datum1D.filters?.find((filter) => filter.name === id);
38
+
39
+ if (absolute) {
40
+ const { re, im } = datum1D.data;
41
+ datum1D.data.re = reimAbsolute({ re, im });
42
+ datum1D.data.im = new Float64Array(0);
43
+ if (filter) {
44
+ filter.value = { ...filter.value, ph0: 0, ph1: 0, absolute };
45
+ }
46
+ } else if ('ph0' in options && 'ph1' in options) {
47
+ let { ph0, ph1 } = options;
48
+ phaseCorrection(datum1D, { ph0, ph1 });
49
+ if (filter) {
50
+ filter.value = { ...filter.value, absolute };
51
+ }
52
+ } else {
53
+ let { ph0, ph1 } = autoPhaseCorrection(datum1D);
54
+ phaseCorrection(datum1D, { ph0, ph1 });
55
+ if (filter) {
56
+ filter.value = { ...filter.value, absolute, ph0, ph1 };
57
+ }
58
+ }
59
+ }
60
+
61
+ function phaseCorrection(
62
+ spectrum: Entry1D,
63
+ phaseValues: { ph0: number; ph1: number },
64
+ ) {
65
+ let { ph0, ph1 } = phaseValues;
66
+ ph0 *= Math.PI / 180;
67
+ ph1 *= Math.PI / 180;
68
+ spectrum.data = {
69
+ ...spectrum.data,
70
+ ...reimPhaseCorrection(spectrum.data, ph0, ph1, { reverse: true }),
71
+ };
72
+ }
73
+
74
+ interface AutoPhaseCorrectionOptions {
75
+ minRegSize?: number;
76
+ maxDistanceToJoin?: number;
77
+ magnitudeMode?: boolean;
78
+ factorNoise?: number;
79
+ reverse?: boolean;
80
+ }
81
+
82
+ function autoPhaseCorrection(
83
+ spectrum: Entry1D,
84
+ options: AutoPhaseCorrectionOptions = {},
85
+ ) {
86
+ const {
87
+ minRegSize = 5,
88
+ maxDistanceToJoin = 128,
89
+ magnitudeMode = true,
90
+ factorNoise = 5,
91
+ reverse = true,
92
+ } = options;
93
+
94
+ return reimAutoPhaseCorrection(spectrum.data as any, {
95
+ minRegSize,
96
+ maxDistanceToJoin,
97
+ magnitudeMode,
98
+ factorNoise,
99
+ reverse,
100
+ });
101
+ }
102
+
103
+ export function isApplicable(
104
+ spectrum: Entry1D,
105
+ ): spectrum is Entry1D & { data: Required<Data1D> } {
106
+ if (spectrum.info.isComplex && !spectrum.info.isFid) return true;
107
+ return false;
108
+ }
109
+
110
+ export function reduce(
111
+ previousValue: PhaseCorrectionParameters,
112
+ newValue: PhaseCorrectionParameters,
113
+ ) {
114
+ return {
115
+ once: true,
116
+ reduce: newValue,
117
+ };
118
+ }
@@ -0,0 +1,31 @@
1
+ import { Entry1D } from '../Entry1D';
2
+ import { FilterDomainUpdateRules } from '../FiltersManager';
3
+
4
+ /**
5
+ *
6
+ * @param {Object} datum1d
7
+ * @param {number} [shiftValue=0]
8
+ */
9
+
10
+ export const id = 'shiftX';
11
+ export const name = 'Shift X';
12
+
13
+ export const DOMAIN_UPDATE_RULES: Readonly<FilterDomainUpdateRules> = {
14
+ updateXDomain: true,
15
+ updateYDomain: false,
16
+ };
17
+
18
+ export function apply(datum1D: Entry1D, shiftValue = 0) {
19
+ datum1D.data.x = datum1D.data.x.map((val) => val + shiftValue);
20
+ }
21
+
22
+ export function isApplicable() {
23
+ return true;
24
+ }
25
+
26
+ export function reduce(previousValue: number, newValue: number) {
27
+ return {
28
+ once: true,
29
+ reduce: previousValue + newValue,
30
+ };
31
+ }
@@ -0,0 +1,79 @@
1
+ import * as Filters from 'ml-signal-processing';
2
+
3
+ import { MatrixOptions } from '../MatrixOptions';
4
+ import { Entry1D } from '../Entry1D';
5
+ import { FilterDomainUpdateRules } from '../FiltersManager';
6
+
7
+ export const id = 'signalProcessing';
8
+ export const name = 'Signal processing';
9
+
10
+ export const DOMAIN_UPDATE_RULES: Readonly<FilterDomainUpdateRules> = {
11
+ updateXDomain: true,
12
+ updateYDomain: true,
13
+ };
14
+
15
+ export function apply(spectrum: Entry1D, options: MatrixOptions) {
16
+ if (!isApplicable(spectrum)) {
17
+ throw new Error('Signal Processing is not applicable on this data');
18
+ }
19
+
20
+ spectrum.data = filterXY(spectrum, options);
21
+ }
22
+ export function isApplicable(spectrum: Entry1D) {
23
+ if (spectrum.info.isFt) return true;
24
+ return false;
25
+ }
26
+
27
+ export function reduce(previousValue: any, newValue: any) {
28
+ return {
29
+ once: true,
30
+ reduce: newValue,
31
+ };
32
+ }
33
+
34
+ export function filterXY(spectrum: Entry1D, options: MatrixOptions) {
35
+ let x = spectrum.data.x.slice(0);
36
+ let cloneX = spectrum.data.x.slice(0);
37
+ let re = spectrum.data.re.slice(0);
38
+ let im = spectrum.data.im?.slice(0);
39
+
40
+ const filters = options.filters.slice();
41
+
42
+ const {
43
+ range: { from, to },
44
+ numberOfPoints,
45
+ exclusionsZones: exclusions,
46
+ } = options;
47
+
48
+ filters.push({
49
+ name: 'equallySpaced',
50
+ options: { from, to, numberOfPoints, exclusions },
51
+ properties: {},
52
+ });
53
+
54
+ for (const filter of filters) {
55
+ // eslint-disable-next-line import/namespace
56
+ const filterFunction = Filters[filter.name];
57
+ if (!filterFunction) {
58
+ throw new Error(`Unknown filter: ${filter.name}`);
59
+ }
60
+
61
+ const filterOptions = filter?.options || {};
62
+
63
+ // @ts-expect-error some method have options and some other ones don't have any options
64
+ const realResult = filterFunction({ x, y: re }, filterOptions);
65
+ x = realResult.data.x as Float64Array;
66
+ re = realResult.data.y as Float64Array;
67
+
68
+ if (im) {
69
+ const imaginaryResult = filterFunction(
70
+ { x: cloneX, y: im },
71
+ // @ts-expect-error some method have options and some other ones don't have any options
72
+ filterOptions,
73
+ );
74
+ im = imaginaryResult.data.y as Float64Array;
75
+ }
76
+ }
77
+
78
+ return { x, re, im };
79
+ }