nmrglue-ng 1.0.0__py3-none-any.whl

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 (44) hide show
  1. nmrglue/__init__.py +6 -0
  2. nmrglue/analysis/__init__.py +8 -0
  3. nmrglue/analysis/analysisbase.py +387 -0
  4. nmrglue/analysis/helpers.py +58 -0
  5. nmrglue/analysis/integration.py +207 -0
  6. nmrglue/analysis/leastsqbound.py +342 -0
  7. nmrglue/analysis/linesh.py +809 -0
  8. nmrglue/analysis/lineshapes1d.py +603 -0
  9. nmrglue/analysis/peakpick.py +561 -0
  10. nmrglue/analysis/segmentation.py +563 -0
  11. nmrglue/fileio/__init__.py +16 -0
  12. nmrglue/fileio/bruker.py +2911 -0
  13. nmrglue/fileio/convert.py +618 -0
  14. nmrglue/fileio/fileiobase.py +797 -0
  15. nmrglue/fileio/glue.py +254 -0
  16. nmrglue/fileio/jcampdx.py +1148 -0
  17. nmrglue/fileio/jeol.py +768 -0
  18. nmrglue/fileio/nmrml.py +81 -0
  19. nmrglue/fileio/pipe.py +2613 -0
  20. nmrglue/fileio/rnmrtk.py +819 -0
  21. nmrglue/fileio/rs2d.py +256 -0
  22. nmrglue/fileio/simpson.py +407 -0
  23. nmrglue/fileio/sparky.py +1751 -0
  24. nmrglue/fileio/spinsolve.py +306 -0
  25. nmrglue/fileio/table.py +429 -0
  26. nmrglue/fileio/tecmag.py +535 -0
  27. nmrglue/fileio/varian.py +2112 -0
  28. nmrglue/process/__init__.py +5 -0
  29. nmrglue/process/nmrtxt/__init__.py +1 -0
  30. nmrglue/process/nmrtxt/rance_kay.py +38 -0
  31. nmrglue/process/pipe_proc.py +3328 -0
  32. nmrglue/process/proc_autophase.py +286 -0
  33. nmrglue/process/proc_base.py +2780 -0
  34. nmrglue/process/proc_bl.py +424 -0
  35. nmrglue/process/proc_lp.py +1210 -0
  36. nmrglue/util/__init__.py +1 -0
  37. nmrglue/util/misc.py +212 -0
  38. nmrglue/util/xcpy.py +469 -0
  39. nmrglue/util/xcpy_test.py +31 -0
  40. nmrglue_ng-1.0.0.dist-info/METADATA +224 -0
  41. nmrglue_ng-1.0.0.dist-info/RECORD +44 -0
  42. nmrglue_ng-1.0.0.dist-info/WHEEL +5 -0
  43. nmrglue_ng-1.0.0.dist-info/licenses/LICENSE.txt +38 -0
  44. nmrglue_ng-1.0.0.dist-info/top_level.txt +1 -0
nmrglue/__init__.py ADDED
@@ -0,0 +1,6 @@
1
+ from .fileio import *
2
+ from .process import *
3
+ from .util import *
4
+ from .analysis import *
5
+
6
+ __version__ = '1.0.0'
@@ -0,0 +1,8 @@
1
+ from . import analysisbase
2
+ from . import leastsqbound
3
+ from . import segmentation
4
+ from . import peakpick
5
+ from . import linesh
6
+ from . import lineshapes1d
7
+ from . import helpers
8
+ from . import integration
@@ -0,0 +1,387 @@
1
+ """
2
+ analysisbase provides general purpose analysis functions and classes used by
3
+ several nmrglue.analysis modules
4
+ """
5
+
6
+ import numpy as np
7
+
8
+ pi = np.pi
9
+
10
+
11
+ # helper functions
12
+ def neighbors(pt, shape, structure):
13
+ """
14
+ Generate a list of all neighbors to a point.
15
+
16
+ Parameters
17
+ ----------
18
+ pt : tuple of ints
19
+ Index of the point to find neighbors of.
20
+ shape : tuple of ints
21
+ Shape of the region.
22
+ structure : ndarray of bools
23
+ Structure element that defines connections.
24
+
25
+ Returns
26
+ -------
27
+ pts : list of int tuples
28
+ List of tuples which represent indices for all points neighboring pt.
29
+ Edges are treated as stopping points.
30
+
31
+ """
32
+ # set middle of structure to False
33
+ s = np.copy(structure) # copy structure
34
+ middle = [int(np.floor(i / 2.)) for i in s.shape] # find middle
35
+ s.flat[np.ravel_multi_index(middle, s.shape)] = False
36
+ offsets = np.argwhere(s) - middle
37
+
38
+ # loop over the offset adding all valid points
39
+ pts = []
40
+ for offset in offsets:
41
+ npt = pt - offset
42
+ if valid_pt(npt, shape):
43
+ pts.append(tuple(npt))
44
+ return pts
45
+
46
+
47
+ def valid_pt(pt, shape):
48
+ """
49
+ Determine if a point (indices) is valid for a given shaped
50
+ """
51
+ for i, j in zip(pt, shape):
52
+ if i < 0: # index is not negative
53
+ return False
54
+ if i >= j: # index is less than j
55
+ return False
56
+ return True
57
+
58
+ dimension_names = ['A', 'Z', 'Y', 'X']
59
+
60
+
61
+ # utility functions
62
+ def find_limits(pts):
63
+ """
64
+ Find the limits which outline the provided list of points
65
+
66
+ Parameters
67
+ ----------
68
+ pts : list of int tuples
69
+ List of points [(z0, y0, x0), (z1, y1, x1), ...]
70
+
71
+ Returns
72
+ -------
73
+ min : ndarray
74
+ Array of minimum indices: array([zmin, ymin, xmin]
75
+ max : ndarray
76
+ Array of maximum indices: array([zmin, ymin, xmin]
77
+
78
+ See Also
79
+ --------
80
+ limits2slice : Create a list of slices from min, max limits
81
+
82
+ """
83
+ arr_pts = np.array(pts)
84
+ return np.min(arr_pts, 0), np.max(arr_pts, 0)
85
+
86
+
87
+ def limits2slice(limits):
88
+ """
89
+ Create a set of slice objects given an array of min, max limits.
90
+
91
+ Parameters
92
+ ----------
93
+ limits: tuple, (ndarray, ndarray)
94
+ Two tuple consisting of array of the minimum and maximum indices.
95
+
96
+ Returns
97
+ -------
98
+ slices : list
99
+ List of slice objects which return points between limits
100
+
101
+ See Also
102
+ --------
103
+ find_limits : Find the minimum and maximum limits from a list of points.
104
+ slice2limits : Find a minimum and maximum limits for a list of slices.
105
+
106
+ """
107
+ mins, maxs = limits
108
+ return tuple([slice(i, j + 1) for i, j in zip(mins, maxs)])
109
+
110
+
111
+ def slice2limits(slices):
112
+ """
113
+ Create a tuple of minimum, maximum limits from a set of slices.
114
+
115
+ Parameters
116
+ ----------
117
+ slices : list
118
+ List of slice objects which return points between limits
119
+
120
+ Returns
121
+ -------
122
+ limits: tuple, (ndarray, ndarray)
123
+ Two tuple consisting of array of the minimum and maximum indices.
124
+
125
+ See Also
126
+ --------
127
+ limits2slice : Find a list of slices given minimum and maximum limits.
128
+ """
129
+ mins = [s.start for s in slices]
130
+ maxs = [s.stop - 1 for s in slices]
131
+ return mins, maxs
132
+
133
+
134
+ def squish(r, axis):
135
+ """
136
+ Squish array along an axis.
137
+
138
+ Determine the sum along all but one axis for an array.
139
+
140
+ Parameters
141
+ ----------
142
+ r : ndarray
143
+ Array to squish.
144
+ axis : int
145
+ Axis of r to squish along.
146
+
147
+ Returns
148
+ -------
149
+ s : 1D ndarray
150
+ Array r squished into a single dimension.
151
+
152
+ """
153
+ # put axis to be squished as the last axis
154
+ N = int(r.ndim)
155
+ r = r.swapaxes(axis, N - 1)
156
+
157
+ # sum along leading axis N-1 times
158
+ for i in range(N - 1):
159
+ r = r.sum(0)
160
+ return r
161
+
162
+
163
+ # Windowing classes
164
+ class ndwindow:
165
+ """
166
+ An N-dimensional iterator to slice arrays into windows.
167
+
168
+ Given the shape of an array and a window size, an 'ndwindow' instance
169
+ iterators over tuples of slices which slice an the array into wsize
170
+ sub-arrays. At each iteration, the index of the center of the sub-array
171
+ is incremented by one along the last dimension. Array borders are ignored
172
+ so the resulting sub-array can be smaller than wsize. If wsize contains
173
+ even values the window is off center containing an additional point with
174
+ lower index.
175
+
176
+ Parameters
177
+ ----------
178
+ size : tuple of ints
179
+ Size of array to generate tuples of slices from.
180
+ wsize : tuple of ints
181
+ Window/sub-array size. Size of the area to select from array. This is
182
+ the maximum size of the window.
183
+
184
+ Examples
185
+ --------
186
+
187
+ >>> a = np.arange(12).reshape(3,4)
188
+ >>> for s in ndwindow(a.shape,(3,3)):
189
+ ... print(a[s])
190
+ [[0 1]
191
+ [4 5]]
192
+ [[0 1 2]
193
+ [4 5 6]]
194
+ [[1 2 3]
195
+ [5 6 7]]
196
+ [[2 3]
197
+ [6 7]]
198
+ [[0 1]
199
+ [4 5]
200
+ [8 9]]
201
+ [[ 0 1 2]
202
+ [ 4 5 6]
203
+ [ 8 9 10]]
204
+ [[ 1 2 3]
205
+ [ 5 6 7]
206
+ [ 9 10 11]]
207
+ [[ 2 3]
208
+ [ 6 7]
209
+ [10 11]]
210
+ [[4 5]
211
+ [8 9]]
212
+ [[ 4 5 6]
213
+ [ 8 9 10]]
214
+ [[ 5 6 7]
215
+ [ 9 10 11]]
216
+ [[ 6 7]
217
+ [10 11]]
218
+
219
+ See Also
220
+ --------
221
+ ndwindow_index : Iterator of a ndwindow and index of the window center
222
+ ndwindow_inside : Iterator over equal sized windows in the array.
223
+
224
+ """
225
+ def __init__(self, shape, wsize):
226
+ """ Set up the ndwindow object """
227
+ if len(shape) != len(wsize):
228
+ raise ValueError("shape and wsize do match match")
229
+ self.ndindex = np.ndindex(shape)
230
+ wsize = np.array(wsize)
231
+ self.sub = np.ceil((wsize - 1.) / 2.)
232
+ self.add = wsize - 1. - self.sub
233
+
234
+ def __next__(self):
235
+ """ next iterator. """
236
+ return self.next()
237
+
238
+ def next(self):
239
+ """ x.next() -> the next value, or raise StopIteration """
240
+ center = self.ndindex.next()
241
+ start = [max(0, i - j) for i, j in zip(center, self.sub)]
242
+ stop = [i + j + 1 for i, j in zip(center, self.add)]
243
+ return tuple([slice(x, y) for x, y in zip(start, stop)])
244
+
245
+ def __iter__(self):
246
+ """ x.__iter__() <==> iter(x) """
247
+ return self
248
+
249
+
250
+ class ndwindow_index:
251
+ """
252
+ An N-dimensional iterator object which returns the index of the window
253
+ center and a :py:class:`ndwindow` slice array. See :py:class:`ndwindow`
254
+ for additional documentation.
255
+
256
+ This class is equivalent to:
257
+
258
+ for slices, index in zip(np.ndindex(shape), ndwindow(shape,wshape)):
259
+ return (index, slice)
260
+
261
+ See Also
262
+ --------
263
+ ndwindow: Iterator over only the window slices.
264
+ ndwindow_inside : Iterator over equal sized windows in the array.
265
+
266
+ """
267
+ def __init__(self, shape, wsize):
268
+ """ Set up the object """
269
+ if len(shape) != len(wsize):
270
+ raise ValueError("shape and wsize do match match")
271
+ self.ndindex = np.ndindex(shape)
272
+ wsize = np.array(wsize)
273
+ self.sub = np.ceil((wsize - 1.) / 2.)
274
+ self.add = wsize - 1. - self.sub
275
+
276
+ def __next__(self):
277
+ """ next iterator. """
278
+ return self.next()
279
+
280
+ def next(self):
281
+ """ x.next() -> the next value, or raise StopIteration """
282
+ center = self.ndindex.next()
283
+ start = [max(0, i - j) for i, j in zip(center, self.sub)]
284
+ stop = [i + j + 1 for i, j in zip(center, self.add)]
285
+ return center, tuple([slice(x, y) for x, y in zip(start, stop)])
286
+
287
+ def __iter__(self):
288
+ """ x.__iter__() <==> iter(x) """
289
+ return self
290
+
291
+
292
+ class ndwindow_inside:
293
+ """
294
+ An N-dimensional iterator to slice arrays into uniform size windows.
295
+
296
+ Given the shape of an array and a window size, an 'ndwindow_inside'
297
+ instance iterators over tuples of slices which slice an the array into
298
+ uniform size wsize windows/sub-arrays. At each iteration, the index of
299
+ the top left of the sub-array is incremented by one along the last
300
+ dimension until the resulting windows would extend past the array border.
301
+ All sub-arrays are equal sized (wsize).
302
+
303
+ Parameters
304
+ ----------
305
+ size : tuple of ints
306
+ Size of array to generate tuples of slices from.
307
+ wsize : tuple of ints
308
+ Size of the area to select from array (widow size).
309
+
310
+ Examples
311
+ --------
312
+
313
+ >>> a = np.arange(9).reshape(3,3)
314
+ >>> for s in ndwindow_inside(a.shape,(2,2)):
315
+ ... print(a[s])
316
+ [[0 1]
317
+ [3 4]]
318
+ [[1 2]
319
+ [4 5]]
320
+ [[3 4]
321
+ [6 7]]
322
+ [[4 5]
323
+ [7 8]]
324
+
325
+ See Also
326
+ --------
327
+ ndwindow : Iterator over non-uniform windows.
328
+ ndwindow_inside_index : Iterator of a ndwindow_inside and the index of the
329
+ window's top left point.
330
+
331
+ """
332
+ def __init__(self, shape, wsize):
333
+ """ Set up the object """
334
+ if len(shape) != len(wsize):
335
+ raise ValueError("shape and wsize do match match")
336
+ self.ndindex = np.ndindex(
337
+ tuple(np.array(shape) - np.array(wsize) + 1))
338
+ self.wsize = wsize
339
+
340
+ def __next__(self):
341
+ """ next iterator. """
342
+ return self.next()
343
+
344
+ def next(self):
345
+ """ x.next() -> the next value, or raise StopIteration """
346
+ start = self.ndindex.next()
347
+ stop = np.array(start) + np.array(self.wsize)
348
+ return tuple([slice(x, y) for x, y in zip(start, stop)])
349
+
350
+ def __iter__(self):
351
+ """ x.__iter__() <==> iter(x) """
352
+ return self
353
+
354
+
355
+ class ndwindow_inside_index:
356
+ """
357
+ An N-dimensional iterator object which returns the index of the window
358
+ top-left and a :py:class:`ndwindow_inside` slice array.
359
+
360
+ Similar to :py:class:`ndwindow_index` but reports top left index of
361
+ window.
362
+
363
+ See :py:class:`ndwindow_inside` and :py:class`ndwindow_index` for addition
364
+ documentation.
365
+
366
+ """
367
+ def __init__(self, shape, wsize):
368
+ " Set up the object """
369
+ if len(shape) != len(wsize):
370
+ raise ValueError("shape and wsize do match match")
371
+ self.ndindex = np.ndindex(
372
+ tuple(np.array(shape) - np.array(wsize) + 1))
373
+ self.wsize = wsize
374
+
375
+ def __next__(self):
376
+ """ next iterator. """
377
+ return self.next()
378
+
379
+ def next(self):
380
+ """ x.next() -> the next value, or raiseStopIteration """
381
+ start = self.ndindex.next()
382
+ stop = np.array(start) + np.array(self.wsize)
383
+ return (start, tuple([slice(x, y) for x, y in zip(start, stop)]))
384
+
385
+ def __iter__(self):
386
+ """ x.__iter__() <==> iter(x) """
387
+ return self
@@ -0,0 +1,58 @@
1
+ """
2
+ Helper functions for lineshape fitting.
3
+ """
4
+
5
+
6
+ # bound functions
7
+ def delta(v, d):
8
+ """
9
+ Limits of v +/- d for array v and d.
10
+ """
11
+ return zip(v - d, v + d)
12
+
13
+
14
+ def limit(vmin, vmax, npeaks):
15
+ """
16
+ Fixed limits, vmin to vmax for all peaks.
17
+ """
18
+ return [(vmin, vmax)] * npeaks
19
+
20
+
21
+ def scale_params(rec, prefix, first, last):
22
+ """
23
+ scale lineshape parameters in rec with name prefixX with X from from
24
+ first to last (inclusive)
25
+ """
26
+ return [rec[prefix + str(z)] for z in range(first, last + 1)]
27
+
28
+
29
+ def no_limits(nparams, npeaks):
30
+ """
31
+ No limits on nparameters for npeaks.
32
+ """
33
+ return [[(None, None)] * npeaks] * nparams
34
+
35
+
36
+ def no_limits_amp(npeaks):
37
+ """
38
+ No amplitude limits for npeaks
39
+ """
40
+ return [(None, None)] * npeaks
41
+
42
+
43
+ # misc
44
+ def super_zip(l):
45
+ """
46
+ Zip a list after zipping each element.
47
+
48
+ Useful for lineshape parameter and bounds.
49
+ """
50
+ return zip(*[zip(*i) for i in l])
51
+
52
+
53
+ def scale_columns(prefix, first, last):
54
+ """
55
+ Create a list of scale parameter column names with name prefixX with X
56
+ from first to last (inclusive)
57
+ """
58
+ return [prefix + str(i) for i in range(first, last + 1)]
@@ -0,0 +1,207 @@
1
+ import numpy as np
2
+
3
+
4
+ def integrate(data, unit_conv, limits, unit='ppm', noise_limits=None,
5
+ norm_to_range=None, calibrate=1.0):
6
+ r"""
7
+ Integrate one 1D data array within limits given in units. Data points must
8
+ be equally spaced.
9
+
10
+ Functional form of integration is:
11
+
12
+ .. math::
13
+ value = \sum_a^b s(x_{i}) dx
14
+
15
+ Where:
16
+ s is the signal, a and b are the limits of integration and dx is the width
17
+ of each bin.
18
+
19
+ The integration error due to baseline noise is calculated as:
20
+
21
+ .. math::
22
+ error = \sigma_{vol} = \sigma \sqrt{n}
23
+
24
+ if the noise_limits are set.
25
+
26
+ Where:
27
+
28
+ .. math::
29
+ n = \frac{|b-a|}{dx}+1
30
+
31
+ sigma is the standard deviation of the baseline noise. n is the number
32
+ of bins in the integration range.
33
+
34
+ Parameters
35
+ ----------
36
+ data: array like
37
+ 1d array of intensity
38
+ unit_conv: `fileiobase.unit_conversion` object
39
+ unit_conversion object associated with data
40
+ limits: array like
41
+ With shape (2,) or (P, 2). Array with lower and upper integration
42
+ limit. Or array with P rows of lower and upper integration limits.
43
+ noise_limits: Optional[array like]
44
+ With shape(2, ). Array with lower and upper limits to section of data
45
+ with only noise. A larger range will likely yield a more accurate
46
+ estimate. It is unwise to use the very end of the spectrum for the
47
+ noise range.
48
+ norm_to_range: Optional[int]
49
+ If given, all values are normalized to the value determined within the
50
+ range given by limits[norm_to_range, :]
51
+ calibrate: Optional[float]
52
+ If norm_to_range is given, the values are re-normalized so that the
53
+ integral within limits[norm_to_range, :] equals some number.
54
+
55
+ Returns
56
+ -------
57
+ array
58
+ [value, ...] integration values
59
+
60
+ if noise_limits is given:
61
+
62
+ array
63
+ [[value, error], ...] where error a one sigma estimate of the error
64
+ only from the spectrum noise
65
+
66
+ """
67
+ # convert form limits in units to lower and upper index
68
+ limits = np.array(limits)
69
+ if limits.size == 2:
70
+ limits = np.expand_dims(limits, axis=0)
71
+ inds = [(unit_conv(x0, unit), unit_conv(x1, unit)) for (x0, x1) in limits]
72
+ inds = np.array([sorted(ind) for ind in inds])
73
+
74
+ # sum part of the integral
75
+ sum_slice = np.array([np.sum(data[slice(*ind)]) for ind in inds])
76
+
77
+ # dx part of the integral
78
+ scale = unit_conv.ppm_scale()
79
+ dx = abs(scale[1]-scale[0])
80
+
81
+ # put together the integral
82
+ values = sum_slice * dx
83
+
84
+ if noise_limits is not None:
85
+
86
+ # determine the standard deviation of the noise
87
+ noise_inds = (unit_conv(noise_limits[0], unit),
88
+ unit_conv(noise_limits[1], unit))
89
+ noise_inds = sorted(noise_inds)
90
+
91
+ # the error (from noise) is std * dx * limits range
92
+ std = np.std(data[slice(*noise_inds)])
93
+ errors = std * np.sqrt(inds[:, 1] - inds[:, 0])
94
+
95
+ if norm_to_range is not None:
96
+ # You must normalize the error before you normalize the value!
97
+ errors = (errors / values[norm_to_range]) * calibrate
98
+ values = (values / values[norm_to_range]) * calibrate
99
+ return np.vstack((values, errors)).T
100
+
101
+ else:
102
+
103
+ if norm_to_range is not None:
104
+ values = (values / values[norm_to_range]) * calibrate
105
+ return values
106
+
107
+
108
+ def ndintegrate(data, unit_conv, limits, unit='ppm', noise_limits=None):
109
+ r"""
110
+ Integrate one nD data array within limits given in units. Data points must
111
+ be equally spaced. Can only integrate one region per function call.
112
+
113
+ The integration error due to baseline noise is calculated as:
114
+
115
+ .. math::
116
+ error = \sigma_{vol} = \sigma \sqrt{\prod_i^{d} n_{i}},
117
+
118
+ if the noise_limits are set.
119
+
120
+ Where:
121
+ sigma is the standard deviation of the baseline noise. n is the number
122
+ of bins in the integration range for each d dimensions.
123
+
124
+ See integrate for more information.
125
+
126
+ Parameters
127
+ ----------
128
+ data: array like
129
+ 1d array of intensity
130
+ unit_convs: [`fileiobase.unit_conversion`, ] list
131
+ list of unit_conversion object associated with each dim of data.
132
+ limits: array like
133
+ With shape (2,) or (d, 2). 1D Array with lower and upper integration
134
+ limits for 1D . Or array with d rows of lower and upper integration
135
+ limits for each dimension.
136
+ noise_limits: Optional[array like]
137
+ With shape(2, ). Array with lower and upper limits to section of data
138
+ with only noise. A larger range will likely yield a more accurate
139
+ estimate. It is unwise to use the very end of the spectrum for the
140
+ noise range.
141
+
142
+ Returns
143
+ -------
144
+ array
145
+ [value, ...] integration values
146
+
147
+ if noise_limits is given:
148
+
149
+ array
150
+ [[value, error], ...] where error a one sigma estimate of the error
151
+ only from the spectrum noise
152
+ """
153
+
154
+ # determine the dimensionality of the data.
155
+ d = np.ndim(data)
156
+
157
+ try:
158
+ iter(unit_conv)
159
+ except TypeError:
160
+ unit_conv = [unit_conv, ]
161
+
162
+ if d != len(unit_conv):
163
+ mesg = 'A unit_conversion object is needed for each dimension.'
164
+ raise ValueError(mesg)
165
+
166
+ limits = np.array(limits)
167
+ if limits.ndim == 1:
168
+ limits = np.expand_dims(limits, axis=0)
169
+
170
+ if limits.shape[0] != d and limits.shape[1] != 2:
171
+ mesg = 'A lower and upper limit is needed for each dimension.'
172
+ raise ValueError(mesg)
173
+
174
+ inds = [(uc(x[0], unit), uc(x[1], unit))
175
+ for (uc, x) in zip(unit_conv, limits)]
176
+ inds = [sorted(x) for x in inds]
177
+
178
+ # the integrate_nd needs to be scaled by the bin width in ppm
179
+ ppm_scales = [x.ppm_scale() for x in unit_conv]
180
+ dx = np.prod(np.array([abs(x[1]-x[0]) for x in ppm_scales]))
181
+
182
+ slice_sum = (data[tuple([slice(x[0], x[1]) for x in np.flipud(inds)])]).sum()
183
+
184
+ value = slice_sum * dx
185
+
186
+ if noise_limits is None:
187
+ return value
188
+
189
+ else:
190
+ noise_limits = np.array(noise_limits)
191
+ if noise_limits.size == 2:
192
+ noise_limits = np.expand_dims(noise_limits, axis=0)
193
+
194
+ if noise_limits.shape[0] != d and noise_limits.shape[1] != 2:
195
+ mesg = 'If given, a noise limit is needed for each dimension.'
196
+ raise ValueError(mesg)
197
+
198
+ noise_inds = [(uc(x[0], unit), uc(x[1], unit))
199
+ for (uc, x) in zip(unit_conv, noise_limits)]
200
+ noise_inds = [sorted(x) for x in noise_inds]
201
+
202
+ # see docstring of integrate
203
+ nm = np.prod(np.array([abs(x[1]-x[0]) for x in noise_inds]))
204
+ std = np.std(data[[slice(x[0], x[1])for x in np.flipud(noise_inds)]])
205
+
206
+ error = std * np.sqrt(nm)
207
+ return np.hstack((value, error))