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,48 @@
1
+ import { xSequentialFill } from 'ml-spectra-processing';
2
+
3
+ import { Entry1D } from '../../Entry1D';
4
+
5
+ export function padDataToNextPowerOfTwo(
6
+ datum1D: Entry1D,
7
+ digitalFilterApplied: boolean,
8
+ ) {
9
+ const { x, re, im } = datum1D.data;
10
+ const size = nextPowerOfTwo(x.length);
11
+
12
+ let newRE = new Float64Array(size);
13
+ let newIM = new Float64Array(size);
14
+
15
+ const pointsToShift = getPointsToShift(datum1D);
16
+
17
+ newRE.set(re.slice(0, size - pointsToShift));
18
+ newIM.set(im.slice(0, size - pointsToShift));
19
+
20
+ if (pointsToShift > 0 && digitalFilterApplied) {
21
+ newRE.set(re.slice(re.length - pointsToShift), size - pointsToShift);
22
+ newIM.set(im.slice(re.length - pointsToShift), size - pointsToShift);
23
+ }
24
+
25
+ const newX = xSequentialFill({
26
+ from: x[0],
27
+ size,
28
+ step: x[1] - x[0],
29
+ }) as Float64Array;
30
+
31
+ datum1D.data = { ...datum1D.data, re: newRE, im: newIM, x: newX };
32
+ }
33
+
34
+ function getPointsToShift(datum1D: Entry1D) {
35
+ let grpdly = datum1D.info?.digitalFilter || 0;
36
+ return grpdly > 0 ? Math.floor(grpdly) : 0;
37
+ }
38
+
39
+ function nextPowerOfTwo(n: number) {
40
+ if (n === 0) return 1;
41
+ n--;
42
+ n |= n >> 1;
43
+ n |= n >> 2;
44
+ n |= n >> 4;
45
+ n |= n >> 8;
46
+ n |= n >> 16;
47
+ return n + 1;
48
+ }
@@ -0,0 +1,90 @@
1
+ import { Data1D } from '../Data1D';
2
+ import { Entry1D } from '../Entry1D';
3
+ import { FilterDomainUpdateRules } from '../FiltersManager';
4
+
5
+ export const id = 'zeroFilling';
6
+ export const name = 'Zero Filling';
7
+ export const DOMAIN_UPDATE_RULES: Readonly<FilterDomainUpdateRules> = {
8
+ updateXDomain: true,
9
+ updateYDomain: false,
10
+ };
11
+
12
+ export interface ZeroFillingOptions {
13
+ nbPoints?: number;
14
+ factor?: number;
15
+ }
16
+
17
+ export function apply(datum1D: Entry1D, options: ZeroFillingOptions) {
18
+ if (!isApplicable(datum1D)) {
19
+ throw new Error('zeroFilling not applicable on this data');
20
+ }
21
+
22
+ let { nbPoints, factor = 2 } = options;
23
+
24
+ if (!nbPoints) {
25
+ nbPoints = 2 ** Math.round(Math.log2(datum1D.data.x.length * factor));
26
+ const filter = datum1D.filters.find((filter) => filter.name === id);
27
+ if (filter) {
28
+ filter.value = { nbPoints };
29
+ }
30
+ }
31
+
32
+ let digitalFilterApplied = datum1D.filters.some(
33
+ (e) => e.name === 'digitalFilter' && e.flag,
34
+ );
35
+
36
+ let grpdly = datum1D.info?.digitalFilter || 0;
37
+ let pointsToShift;
38
+ if (grpdly > 0 && digitalFilterApplied) {
39
+ pointsToShift = Math.floor(grpdly);
40
+ } else {
41
+ pointsToShift = 0;
42
+ }
43
+
44
+ const { re, im, x } = datum1D.data;
45
+
46
+ let newRE = new Float64Array(nbPoints);
47
+ let newIM = new Float64Array(nbPoints);
48
+ let newX = new Float64Array(nbPoints);
49
+
50
+ const length = Math.min(nbPoints, re.length);
51
+
52
+ newRE.set(re.slice(0, length - pointsToShift));
53
+ newIM.set(im.slice(0, length - pointsToShift));
54
+ newX.set(x.slice(0, length - pointsToShift));
55
+
56
+ let diff = x[1] - x[0];
57
+ let currentX = x[length - pointsToShift - 1];
58
+ for (let i = length - pointsToShift; i < nbPoints; i++) {
59
+ currentX += diff;
60
+ newX[i] = currentX;
61
+ }
62
+
63
+ if (pointsToShift > 0 && pointsToShift < nbPoints) {
64
+ newRE.set(re.slice(re.length - pointsToShift), nbPoints - pointsToShift);
65
+ newIM.set(im.slice(re.length - pointsToShift), nbPoints - pointsToShift);
66
+ }
67
+
68
+ datum1D.data = { ...datum1D.data, re: newRE, im: newIM, x: newX };
69
+ }
70
+
71
+ export function isApplicable(
72
+ datum1D: Entry1D,
73
+ ): datum1D is Entry1D & { data: Required<Data1D> } {
74
+ if (datum1D.info.isComplex && datum1D.info.isFid) {
75
+ return true;
76
+ }
77
+ return false;
78
+ }
79
+
80
+ export function reduce(
81
+ _previousValue: ZeroFillingOptions,
82
+ newValue: ZeroFillingOptions,
83
+ ) {
84
+ delete newValue.factor;
85
+
86
+ return {
87
+ once: true,
88
+ reduce: newValue,
89
+ };
90
+ }
@@ -0,0 +1,31 @@
1
+ import { MinMaxContent } from 'cheminfo-types';
2
+
3
+ import { Entry2D } from '../../xyz/Entry2D';
4
+
5
+ export const id = 'shift2DX';
6
+ export const name = 'Shift 2D X';
7
+
8
+ /**
9
+ *
10
+ * @param {Object} datum2d
11
+ * @param {number} [shiftValue=0]
12
+ */
13
+
14
+ export function apply(datum2D: Entry2D, shiftValue = 0) {
15
+ const data: Record<string, MinMaxContent> = { ...datum2D.data };
16
+ for (const key in data) {
17
+ data[key].minX += shiftValue;
18
+ data[key].maxX += shiftValue;
19
+ }
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,29 @@
1
+ import { MinMaxContent } from 'cheminfo-types';
2
+
3
+ import { Entry2D } from '../../xyz/Entry2D';
4
+
5
+ export const id = 'shift2DY';
6
+ export const name = 'Shift 2D Y';
7
+ /**
8
+ *
9
+ * @param {Object} datum2d
10
+ * @param {number} [shiftValue=0]
11
+ */
12
+ export function apply(datum2D: Entry2D, shiftValue = 0) {
13
+ const data: Record<string, MinMaxContent> = { ...datum2D.data };
14
+ for (const key in data) {
15
+ data[key].minY += shiftValue;
16
+ data[key].maxY += shiftValue;
17
+ }
18
+ }
19
+
20
+ export function isApplicable() {
21
+ return true;
22
+ }
23
+
24
+ export function reduce(previousValue: number, newValue: number) {
25
+ return {
26
+ once: true,
27
+ reduce: previousValue + newValue,
28
+ };
29
+ }
package/src/index.ts CHANGED
@@ -40,6 +40,7 @@ export * from './xy/xyPeaksOptimization';
40
40
  export * from './xyz/xyzAutoZonesPicking';
41
41
  export * from './xyz/xyzAutoSignalsPicking';
42
42
  export * from './xyz/xyzJResAnalyzer';
43
+ export * from './xyz/xyzBidimensionalFFT';
43
44
 
44
45
  export * from './databases/getDatabase';
45
46
  export * from './databases/carbonImpurities';
@@ -58,6 +59,8 @@ export * from './multiplicity/checkMultiplet';
58
59
  export * from './multiplicity/checkMultiplicity';
59
60
  export * from './multiplicity/translateMultiplet';
60
61
 
62
+ export * from './filters/FiltersManager';
63
+
61
64
  export type { NMRSignal1D } from './signals/NMRSignal1D';
62
65
  export type { NMRSignal2D, Signal2DProjection } from './xyz/NMRSignal2D';
63
66
  export type { NMRRange } from './xy/NMRRange';
@@ -0,0 +1,10 @@
1
+ import { Data2D, Data2DFid } from 'cheminfo-types';
2
+
3
+ export type Data2DFidComplete = Required<Data2DFid>;
4
+ export function checkData2DFid(
5
+ data: Data2D,
6
+ ): asserts data is Data2DFidComplete {
7
+ if (!('re' in data && 'im' in data)) {
8
+ throw new Error('imaginary (im) data should exists');
9
+ }
10
+ }
@@ -0,0 +1,6 @@
1
+ import { Data1D } from '../filters/Data1D';
2
+
3
+ export function cloneData1D(datum: Data1D) {
4
+ const { x, re, im } = datum || { x: [], re: [], im: [] };
5
+ return { x: x.slice(), re: re.slice(), im: im?.slice() || null };
6
+ }
@@ -0,0 +1,27 @@
1
+ import { Data2D, Data2DFid, Data2DFt, MinMaxContent } from 'cheminfo-types';
2
+
3
+ export function cloneData2D(data: Data2D) {
4
+ const newData: any = {};
5
+
6
+ if (isData2DFt(data)) {
7
+ for (const key in data) {
8
+ addCloneData(newData, key, data[key as keyof Data2DFt]);
9
+ }
10
+ } else {
11
+ for (const key in data) {
12
+ addCloneData(newData, key, data[key as keyof Data2DFid]);
13
+ }
14
+ }
15
+ return newData;
16
+ }
17
+
18
+ function isData2DFt(data: Data2D): data is Data2DFt {
19
+ return 're' in data;
20
+ }
21
+
22
+ function addCloneData(newData: any, key: string, data?: MinMaxContent) {
23
+ if (data) {
24
+ const { z, ...other } = data;
25
+ newData[key] = { z: z.slice(), ...other };
26
+ }
27
+ }
@@ -0,0 +1,12 @@
1
+ import { Data2D } from 'cheminfo-types';
2
+
3
+ import { Filter } from '../filters/FiltersManager';
4
+
5
+ export interface Entry2D {
6
+ id?: string;
7
+ info: Record<string, any>;
8
+ originalInfo?: Record<string, any>;
9
+ data: Data2D;
10
+ originalData?: Data2D;
11
+ filters: Array<Filter>;
12
+ }
@@ -0,0 +1,68 @@
1
+ import { Data2D, DoubleArray } from 'cheminfo-types';
2
+ import { xAdd, xMultiply, xSubtract } from 'ml-spectra-processing';
3
+
4
+ import { checkData2DFid, Data2DFidComplete } from '../utilities/checkData2DFid';
5
+
6
+ export function quadrature(data: Data2D, options: { fnMode: string }) {
7
+ checkData2DFid(data);
8
+
9
+ const { fnMode } = options;
10
+
11
+ switch (fnMode) {
12
+ case 'ttpi':
13
+ return ttpiQuadrature(data);
14
+ case 'states':
15
+ return shrQuadrature(data);
16
+ case 'echo':
17
+ return echoQuadrature(data);
18
+ default:
19
+ return {
20
+ re: data.re.z,
21
+ im: data.im.z,
22
+ };
23
+ }
24
+ }
25
+
26
+ function echoQuadrature(data: Data2DFidComplete) {
27
+ const {
28
+ re: { z: reMatrix },
29
+ im: { z: imMatrix },
30
+ } = data;
31
+
32
+ const newRe: DoubleArray[] = [];
33
+ const newIm: DoubleArray[] = [];
34
+ for (let i = 0; i < reMatrix.length; i += 2) {
35
+ let reCosine = reMatrix[i];
36
+ let imCosine = imMatrix[i];
37
+ let reSine = reMatrix[i + 1];
38
+ let imSine = imMatrix[i + 1];
39
+
40
+ newRe.push(xSubtract(xMultiply(imSine, -1), imCosine));
41
+ newRe.push(xSubtract(reSine, reCosine));
42
+ newIm.push(xAdd(reSine, reCosine));
43
+ newIm.push(xSubtract(imSine, imCosine));
44
+ }
45
+
46
+ return { re: newRe, im: newIm };
47
+ }
48
+
49
+ function shrQuadrature(data: Data2DFidComplete) {
50
+ const { re, im } = data;
51
+ return { re: re.z, im: im.z };
52
+ }
53
+
54
+ function ttpiQuadrature(data: Data2DFidComplete) {
55
+ const newRe: DoubleArray[] = [];
56
+ const newIm: DoubleArray[] = [];
57
+
58
+ const {
59
+ re: { z: reMatrix },
60
+ im: { z: imMatrix },
61
+ } = data;
62
+ for (let i = 0; i < reMatrix.length; i++) {
63
+ newRe.push(i % 2 ? reMatrix[i].slice() : xMultiply(reMatrix[i], -1));
64
+ newIm.push(i % 2 ? imMatrix[i].slice() : xMultiply(imMatrix[i], -1));
65
+ }
66
+
67
+ return { re: newRe, im: newIm };
68
+ }
@@ -0,0 +1,24 @@
1
+ import { DataReIm } from 'ml-spectra-processing';
2
+
3
+ export function digitalFilter(
4
+ data: DataReIm,
5
+ options: { digitalFilterValue: number },
6
+ ) {
7
+ let { digitalFilterValue = 0 } = options;
8
+ let re = new Float64Array(data.re);
9
+ let im = new Float64Array(data.im);
10
+
11
+ let pointsToShift = Math.floor(digitalFilterValue);
12
+
13
+ const skip = 0;
14
+ pointsToShift += 0;
15
+
16
+ const newRe = new Float64Array(re.length);
17
+ const newIm = new Float64Array(im.length);
18
+ newRe.set(re.slice(pointsToShift));
19
+ newRe.set(re.slice(skip, pointsToShift), re.length - pointsToShift);
20
+ newIm.set(im.slice(pointsToShift));
21
+ newIm.set(im.slice(skip, pointsToShift), im.length - pointsToShift);
22
+
23
+ return { re: newRe, im: newIm };
24
+ }
@@ -0,0 +1,111 @@
1
+ import { DoubleArray } from 'cheminfo-types';
2
+ import Matrix from 'ml-matrix';
3
+ import {
4
+ reimAutoPhaseCorrection,
5
+ reimFFT,
6
+ reimPhaseCorrection,
7
+ } from 'ml-spectra-processing';
8
+
9
+ import {
10
+ apodization,
11
+ ApodizationOptions,
12
+ } from '../../../apodization/apodization';
13
+
14
+ import { digitalFilter } from './digitalFilter';
15
+ import { removeDCOffset } from './removeDCOffset';
16
+ import { zeroFilling, ZeroFillingOptions } from './zeroFilling';
17
+
18
+ interface PhaseCorrection {
19
+ mode?: string;
20
+ ph0?: number;
21
+ ph1?: number;
22
+ }
23
+
24
+ export interface DirectDimensionOptions {
25
+ fnMode?: string;
26
+ digitalFilterValue?: number;
27
+ zeroFilling?: ZeroFillingOptions;
28
+ apodization?: ApodizationOptions;
29
+ phaseCorrection?: PhaseCorrection;
30
+ }
31
+
32
+ export function fftDirectDimension(
33
+ data: { re: DoubleArray[]; im: DoubleArray[] },
34
+ options: DirectDimensionOptions,
35
+ ) {
36
+ const { re: reData, im: imData } = data;
37
+ const nbRows = reData.length;
38
+ const nbColumns = reData[0].length;
39
+
40
+ const { zeroFilling: zeroFillingF2, digitalFilterValue = 0 } = options;
41
+
42
+ const { factor: f2Factor = 2 } = zeroFillingF2 || {};
43
+ const nbPointsF2 =
44
+ zeroFillingF2?.nbPoints || 2 ** Math.round(Math.log2(nbColumns * f2Factor));
45
+
46
+ const reFFT = new Matrix(nbRows, nbPointsF2);
47
+ const imFFT = new Matrix(nbRows, nbPointsF2);
48
+
49
+ const { apodization: apodizationF2 } = options;
50
+ let {
51
+ ph0: ph0F2,
52
+ ph1: ph1F2,
53
+ mode: pcModeF2 = 'no',
54
+ } = options?.phaseCorrection || {};
55
+
56
+ for (let i = 0; i < nbRows; i++) {
57
+ const newData = digitalFilter(
58
+ { re: reData[i], im: imData[i] },
59
+ { digitalFilterValue },
60
+ );
61
+
62
+ Object.assign(newData, removeDCOffset(newData, { digitalFilterValue }));
63
+
64
+ if (apodizationF2) {
65
+ const { re: aRe, im: aIm } = apodization(newData, apodizationF2);
66
+ Object.assign(newData, { re: aRe, im: aIm });
67
+ }
68
+
69
+ Object.assign(
70
+ newData,
71
+ zeroFilling(newData, { digitalFilterValue, nbPoints: nbPointsF2 }),
72
+ );
73
+
74
+ Object.assign(newData, reimFFT(newData, { applyZeroShift: true }));
75
+
76
+ const dfResidual =
77
+ (digitalFilterValue - Math.round(digitalFilterValue)) * Math.PI * 2;
78
+ if (dfResidual > 0) {
79
+ Object.assign(newData, reimPhaseCorrection(newData, 0, -dfResidual));
80
+ }
81
+
82
+ if (
83
+ i === 0 &&
84
+ pcModeF2 === 'pk' &&
85
+ ph0F2 === undefined &&
86
+ ph1F2 === undefined
87
+ ) {
88
+ const phased = reimAutoPhaseCorrection(newData, { magnitudeMode: false });
89
+ ph0F2 = phased.ph0;
90
+ ph1F2 = phased.ph1;
91
+ }
92
+ if (pcModeF2 === 'pk' && ph0F2 !== undefined && ph1F2 !== undefined) {
93
+ Object.assign(
94
+ newData,
95
+ reimPhaseCorrection(
96
+ newData,
97
+ (ph0F2 * Math.PI) / 180,
98
+ (ph1F2 * Math.PI) / 180,
99
+ ),
100
+ );
101
+ }
102
+
103
+ reFFT.setRow(i, newData.re);
104
+ imFFT.setRow(i, newData.im);
105
+ }
106
+
107
+ return {
108
+ re: reFFT,
109
+ im: imFFT,
110
+ };
111
+ }
@@ -0,0 +1,123 @@
1
+ import { DoubleArray } from 'cheminfo-types';
2
+ import Matrix from 'ml-matrix';
3
+ import {
4
+ reimAbsolute,
5
+ reimAutoPhaseCorrection,
6
+ reimFFT,
7
+ reimPhaseCorrection,
8
+ } from 'ml-spectra-processing';
9
+
10
+ import {
11
+ apodization,
12
+ ApodizationOptions,
13
+ } from '../../../apodization/apodization';
14
+
15
+ import { zeroFilling, ZeroFillingOptions } from './zeroFilling';
16
+
17
+ interface PhaseCorrection {
18
+ mode?: string;
19
+ ph0?: number;
20
+ ph1?: number;
21
+ }
22
+
23
+ export interface IndirectDimensionOptions {
24
+ fnMode?: string;
25
+ zeroFilling?: ZeroFillingOptions;
26
+ apodization?: ApodizationOptions;
27
+ phaseCorrection?: PhaseCorrection;
28
+ }
29
+
30
+ export function fftIndirectDimension(
31
+ data: { re: DoubleArray[] | Matrix; im: DoubleArray[] | Matrix },
32
+ options: IndirectDimensionOptions,
33
+ ) {
34
+ const reData = Matrix.checkMatrix(data.re);
35
+ const imData = Matrix.checkMatrix(data.im);
36
+
37
+ const nbRows = reData.rows;
38
+ const nbColumns = reData.columns;
39
+
40
+ const { zeroFilling: zeroFillingF1 } = options;
41
+ const { factor: f1Factor = 2 } = zeroFillingF1 || {};
42
+ const nbPointsF1 =
43
+ zeroFillingF1?.nbPoints || 2 ** Math.round(Math.log2(nbRows * f1Factor));
44
+ const { apodization: apodizationF1 } = options;
45
+ let {
46
+ ph0: ph0F1,
47
+ ph1: ph1F1,
48
+ mode: pcModeF1,
49
+ } = options.phaseCorrection || {};
50
+
51
+ const reResult = new Matrix(nbPointsF1, nbColumns);
52
+ const imResult = new Matrix(nbPointsF1, nbColumns);
53
+ for (let i = 0; i < nbColumns; i++) {
54
+ const { re: aRe, im: aIm } = apodization(
55
+ {
56
+ re: reData.getColumn(i),
57
+ im: imData.getColumn(i),
58
+ },
59
+ apodizationF1,
60
+ );
61
+
62
+ const newRe = [];
63
+ const newIm = [];
64
+ if (options.fnMode === 'echo') {
65
+ for (let j = 0; j < aRe.length; j += 2) {
66
+ newRe.push(aRe[j]);
67
+ newIm.push(aRe[j + 1]);
68
+ }
69
+ } else {
70
+ for (let j = 0; j < aRe.length; j++) {
71
+ newRe.push(aRe[j]);
72
+ newIm.push(-aIm[j]);
73
+ }
74
+ }
75
+
76
+ let transformed = reimFFT(
77
+ zeroFilling(
78
+ {
79
+ re: newRe,
80
+ im: newIm,
81
+ },
82
+ { digitalFilterValue: 0, nbPoints: nbPointsF1 },
83
+ ),
84
+ { applyZeroShift: true },
85
+ );
86
+ let { re, im } = transformed;
87
+
88
+ if (options.phaseCorrection?.mode === 'mc') {
89
+ re = reimAbsolute({ re, im });
90
+ im = new Float64Array(im.length);
91
+ }
92
+
93
+ if (pcModeF1 === 'pk') {
94
+ if (i === 0 && ph0F1 === undefined && ph1F1 === undefined) {
95
+ //here we can improve it by checking if the experiment is phase sensitive.
96
+ const phased = reimAutoPhaseCorrection(
97
+ { re, im },
98
+ { magnitudeMode: false },
99
+ );
100
+ ph0F1 = phased.ph0;
101
+ ph1F1 = phased.ph1;
102
+ }
103
+ if (ph0F1 !== undefined && ph1F1 !== undefined) {
104
+ Object.assign(
105
+ transformed,
106
+ reimPhaseCorrection(
107
+ transformed,
108
+ (ph0F1 * Math.PI) / 180,
109
+ (ph1F1 * Math.PI) / 180,
110
+ ),
111
+ );
112
+ }
113
+ }
114
+
115
+ reResult.setColumn(i, re);
116
+ imResult.setColumn(i, im);
117
+ }
118
+
119
+ return {
120
+ re: reResult,
121
+ im: imResult,
122
+ };
123
+ }
@@ -0,0 +1,19 @@
1
+ import { DataReIm, xMean } from 'ml-spectra-processing';
2
+
3
+ export function removeDCOffset(data: DataReIm, options: any) {
4
+ let { digitalFilterValue = 0 } = options;
5
+ const nbPoints = data.re.length;
6
+ const newRe = new Float64Array(data.re);
7
+ const newIm = new Float64Array(data.im);
8
+ const averageRe = xMean(
9
+ data.re.slice((nbPoints * 0.75) >> 0, nbPoints - digitalFilterValue),
10
+ );
11
+ const averageIm = xMean(
12
+ data.im.slice((nbPoints * 0.75) >> 0, nbPoints - digitalFilterValue),
13
+ );
14
+ for (let i = digitalFilterValue; i < nbPoints - digitalFilterValue; i++) {
15
+ newRe[i] -= averageRe;
16
+ newIm[i] -= averageIm;
17
+ }
18
+ return { re: newRe, im: newIm };
19
+ }
@@ -0,0 +1,39 @@
1
+ import { DataReIm } from 'ml-spectra-processing';
2
+
3
+ export interface ZeroFillingOptions {
4
+ nbPoints?: number;
5
+ factor?: number;
6
+ digitalFilterValue?: number;
7
+ }
8
+
9
+ export function zeroFilling(data: DataReIm, options: ZeroFillingOptions) {
10
+ let { nbPoints, factor = 2, digitalFilterValue: grpdly = 0 } = options;
11
+
12
+ if (!nbPoints) {
13
+ nbPoints = 2 ** Math.round(Math.log2(data.re.length * factor));
14
+ }
15
+
16
+ let pointsToShift;
17
+ if (grpdly > 0) {
18
+ pointsToShift = Math.floor(grpdly);
19
+ } else {
20
+ pointsToShift = 0;
21
+ }
22
+
23
+ const { re, im } = data;
24
+
25
+ let newRE = new Float64Array(nbPoints);
26
+ let newIM = new Float64Array(nbPoints);
27
+
28
+ const length = Math.min(nbPoints, re.length);
29
+
30
+ newRE.set(re.slice(0, length - pointsToShift));
31
+ newIM.set(im.slice(0, length - pointsToShift));
32
+
33
+ if (pointsToShift > 0 && pointsToShift < nbPoints) {
34
+ newRE.set(re.slice(re.length - pointsToShift), nbPoints - pointsToShift);
35
+ newIM.set(im.slice(re.length - pointsToShift), nbPoints - pointsToShift);
36
+ }
37
+
38
+ return { re: newRE, im: newIM };
39
+ }