LLNL-PyDV 3.4.3__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.
- llnl_pydv-3.4.3.dist-info/LICENSE +60 -0
- llnl_pydv-3.4.3.dist-info/METADATA +68 -0
- llnl_pydv-3.4.3.dist-info/RECORD +21 -0
- llnl_pydv-3.4.3.dist-info/WHEEL +4 -0
- llnl_pydv-3.4.3.dist-info/entry_points.txt +3 -0
- pydv/NOTES +57 -0
- pydv/README.md +27 -0
- pydv/__init__.py +1 -0
- pydv/curve.py +356 -0
- pydv/img/app_icon3.png +0 -0
- pydv/img/window-code-7.png +0 -0
- pydv/img/window-code-7@2x.png +0 -0
- pydv/pdv +17 -0
- pydv/pdv.py +8784 -0
- pydv/pdvnavbar.py +76 -0
- pydv/pdvplot.py +660 -0
- pydv/pdvutil.py +315 -0
- pydv/pydvpy.py +4491 -0
- pydv/scripts/date.txt +1 -0
- pydv/scripts/update_version_and_date.py +64 -0
- pydv/scripts/version.txt +1 -0
pydv/pydvpy.py
ADDED
|
@@ -0,0 +1,4491 @@
|
|
|
1
|
+
# Copyright (c) 2011-2024, Lawrence Livermore National Security, LLC.
|
|
2
|
+
# Produced at the Lawrence Livermore National Laboratory
|
|
3
|
+
# Written by Mason Kwiat, Douglas S. Miller, and Kevin Griffin, Ephraim Rusu
|
|
4
|
+
# e-mail: rusu1@llnl.gov
|
|
5
|
+
# LLNL-CODE-507071
|
|
6
|
+
# All rights reserved.
|
|
7
|
+
|
|
8
|
+
# This file is part of PDV. For details, see <URL describing code and
|
|
9
|
+
# how to download source>. Please also read "Additional BSD Notice".
|
|
10
|
+
|
|
11
|
+
# Redistribution and use in source and binary forms, with or without
|
|
12
|
+
# modification, are permitted provided that the following conditions
|
|
13
|
+
# are met:
|
|
14
|
+
|
|
15
|
+
# Redistributions of source code must retain the above copyright
|
|
16
|
+
# notice, this list of conditions and the disclaimer below.
|
|
17
|
+
# Redistributions in binary form must reproduce the above copyright
|
|
18
|
+
# notice, this list of conditions and the disclaimer (as noted below)
|
|
19
|
+
# in the documentation and/or other materials provided with the
|
|
20
|
+
# distribution. Neither the name of the LLNS/LLNL nor the names of
|
|
21
|
+
# its contributors may be used to endorse or promote products derived
|
|
22
|
+
# from this software without specific prior written permission.
|
|
23
|
+
|
|
24
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
25
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
26
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
27
|
+
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LAWRENCE
|
|
28
|
+
# LIVERMORE NATIONAL SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR
|
|
29
|
+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
30
|
+
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
31
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
32
|
+
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
33
|
+
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
34
|
+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
35
|
+
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
36
|
+
# SUCH DAMAGE.
|
|
37
|
+
|
|
38
|
+
# Additional BSD Notice
|
|
39
|
+
|
|
40
|
+
# 1. This notice is required to be provided under our contract with
|
|
41
|
+
# the U.S. Department of Energy (DOE). This work was produced at
|
|
42
|
+
# Lawrence Livermore National Laboratory under Contract
|
|
43
|
+
# No. DE-AC52-07NA27344 with the DOE.
|
|
44
|
+
|
|
45
|
+
# 2. Neither the United States Government nor Lawrence Livermore
|
|
46
|
+
# National Security, LLC nor any of their employees, makes any
|
|
47
|
+
# warranty, express or implied, or assumes any liability or
|
|
48
|
+
# responsibility for the accuracy, completeness, or usefulness of any
|
|
49
|
+
# information, apparatus, product, or process disclosed, or represents
|
|
50
|
+
# that its use would not infringe privately-owned rights.
|
|
51
|
+
|
|
52
|
+
# 3. Also, reference herein to any specific commercial products,
|
|
53
|
+
# process, or services by trade name, trademark, manufacturer or
|
|
54
|
+
# otherwise does not necessarily constitute or imply its endorsement,
|
|
55
|
+
# recommendation, or favoring by the United States Government or
|
|
56
|
+
# Lawrence Livermore National Security, LLC. The views and opinions
|
|
57
|
+
# of authors expressed herein do not necessarily state or reflect
|
|
58
|
+
# those of the United States Government or Lawrence Livermore National
|
|
59
|
+
# Security, LLC, and shall not be used for advertising or product
|
|
60
|
+
# endorsement purposes.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
"""
|
|
64
|
+
A python interface for PyDV functionality.
|
|
65
|
+
|
|
66
|
+
.. module: pydvpy
|
|
67
|
+
.. moduleauthor:: Ephraim Rusu <rusu1@llnl.gov>
|
|
68
|
+
|
|
69
|
+
>>> import pydv.pydvpy as pydvif
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
import json
|
|
73
|
+
import os
|
|
74
|
+
import traceback
|
|
75
|
+
import sys
|
|
76
|
+
import re
|
|
77
|
+
import copy
|
|
78
|
+
import random as sysrand
|
|
79
|
+
|
|
80
|
+
from distutils.version import LooseVersion
|
|
81
|
+
|
|
82
|
+
import numpy as np
|
|
83
|
+
import scipy
|
|
84
|
+
import scipy.integrate
|
|
85
|
+
import scipy.special
|
|
86
|
+
import scipy.signal
|
|
87
|
+
import scipy.misc
|
|
88
|
+
|
|
89
|
+
import matplotlib.pyplot as plt
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
from matplotlib import style
|
|
93
|
+
stylesLoaded = True
|
|
94
|
+
except:
|
|
95
|
+
stylesLoaded = False
|
|
96
|
+
|
|
97
|
+
# HPC Import
|
|
98
|
+
try:
|
|
99
|
+
import curve
|
|
100
|
+
|
|
101
|
+
# Package Import
|
|
102
|
+
except ImportError:
|
|
103
|
+
from pydv import curve
|
|
104
|
+
|
|
105
|
+
try:
|
|
106
|
+
import pact.pdb as pdb
|
|
107
|
+
pdbLoaded = True
|
|
108
|
+
except:
|
|
109
|
+
pdbLoaded = False
|
|
110
|
+
|
|
111
|
+
try:
|
|
112
|
+
import gnuplotlib as gp # noqaf401
|
|
113
|
+
import time # noqaf401
|
|
114
|
+
except:
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def span(xmin, xmax, numpts=100):
|
|
119
|
+
"""
|
|
120
|
+
Generates a straight line of slope 1 and y intercept 0 in the specified domain with an optional number
|
|
121
|
+
of points.
|
|
122
|
+
|
|
123
|
+
>>> c = pydvif.span(1, 10)
|
|
124
|
+
|
|
125
|
+
:param xmin: The minimum x value
|
|
126
|
+
:type xmin: float
|
|
127
|
+
:param xmax: The maximum x value
|
|
128
|
+
:type xmax: float
|
|
129
|
+
:param numpts: The number of points used to plot the line
|
|
130
|
+
:type numpts: int
|
|
131
|
+
:returns: curve -- the curve object representing the straight line.
|
|
132
|
+
"""
|
|
133
|
+
spacing = (float(xmax) - float(xmin)) / (float(numpts) - 1.0)
|
|
134
|
+
fxmin = float(xmin)
|
|
135
|
+
x = []
|
|
136
|
+
for i in range(numpts):
|
|
137
|
+
x.append(fxmin)
|
|
138
|
+
fxmin += spacing
|
|
139
|
+
x = np.array(x)
|
|
140
|
+
y = np.array(x)
|
|
141
|
+
c = makecurve(x, y, f'Straight Line (m: 1.0 b: 0.0 xmin: {xmin} xmax: {xmax})')
|
|
142
|
+
|
|
143
|
+
return c
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def makecurve(x, y, name='Curve', fname='', xlabel='', ylabel='', title='', record_id='',
|
|
147
|
+
step=False, xticks_labels=None):
|
|
148
|
+
"""
|
|
149
|
+
Generate a curve from two lists of numbers.
|
|
150
|
+
|
|
151
|
+
>>> c1 = pydvif.makecurve([1, 2, 3, 4], [5, 10, 15, 20])
|
|
152
|
+
|
|
153
|
+
>>> c2 = pydvif.makecurve([1, 2, 3, 4], [7, 8, 9, 10], 'Line')
|
|
154
|
+
|
|
155
|
+
:param x: list of x values
|
|
156
|
+
:type x: list
|
|
157
|
+
:param y: list of y values
|
|
158
|
+
:type y: list
|
|
159
|
+
:param name: the name of the new curve
|
|
160
|
+
:type name: str
|
|
161
|
+
:param fname: the name of the file containing this curves data.
|
|
162
|
+
:type fname: str
|
|
163
|
+
:returns: curve -- the curve generated from the x and y list of values.
|
|
164
|
+
"""
|
|
165
|
+
if len(x) != len(y):
|
|
166
|
+
print(f"Curve {name} doesn't have the same length: len(x)={len(x)} and len(y)={len(y)} ")
|
|
167
|
+
name += " !!!ERROR:len(x)!=len(y)!!!"
|
|
168
|
+
c = curve.Curve(fname, name, record_id, xlabel, ylabel, title, step, xticks_labels)
|
|
169
|
+
c.x = np.array(x, dtype=float)
|
|
170
|
+
c.y = np.array(y, dtype=float)
|
|
171
|
+
|
|
172
|
+
return c
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def get_styles():
|
|
176
|
+
"""
|
|
177
|
+
Get the list of available plot styles.
|
|
178
|
+
|
|
179
|
+
:return: list -- the list of available style names or an empty list if no styles exist.
|
|
180
|
+
"""
|
|
181
|
+
if stylesLoaded:
|
|
182
|
+
return plt.style.available
|
|
183
|
+
|
|
184
|
+
return list()
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def create_plot(curvelist, **kwargs):
|
|
188
|
+
"""
|
|
189
|
+
Create a plot from of the curves in curvelist. The available keyword arguments are:
|
|
190
|
+
* Filename: fname='myFile'
|
|
191
|
+
* Save Format: ftype='pdf'
|
|
192
|
+
* Plot Title: title='My Title'
|
|
193
|
+
* X-Axis Label: xlabel='X'
|
|
194
|
+
* Y-Axis Label: ylabel='Y'
|
|
195
|
+
* Show/Hide Plot Legend: legend=True
|
|
196
|
+
* Plot Style: stylename='ggplot'
|
|
197
|
+
* Show X-Axis in log scale: xls=True
|
|
198
|
+
* Show Y-Axis in log scale: yls=True
|
|
199
|
+
* Set the width of the figure in inches: fwidth=1.2
|
|
200
|
+
* Set the height of the figure in inches: fheight=2.1
|
|
201
|
+
|
|
202
|
+
>>> curves = pydvif.read('testData.txt')
|
|
203
|
+
|
|
204
|
+
>>> plot1, fig1, ax1 = pydvif.create_plot(curves, fname='myPlot1')
|
|
205
|
+
|
|
206
|
+
>>> plot2, fig2, ax2 = pydvif.create_plot(curves, fname='myPlot2', ftype='pdf',
|
|
207
|
+
fwidth=10.1, fheight=11.3, title='My Plot',
|
|
208
|
+
xlabel='X', ylabel='Y', legend=True,
|
|
209
|
+
stylename='ggplot')
|
|
210
|
+
|
|
211
|
+
:param curvelist: The curve or list of curves to plot
|
|
212
|
+
:type curvelist: list
|
|
213
|
+
:param kwargs: The keyword arguments to modify the plot.
|
|
214
|
+
:type kwargs: dict
|
|
215
|
+
:return: matplotlib.pyplot, matplotlib.pyplot.figure, and matplotlib.pyplot.axes
|
|
216
|
+
"""
|
|
217
|
+
fname = None
|
|
218
|
+
ftype = 'png'
|
|
219
|
+
title = ''
|
|
220
|
+
xlabel = ''
|
|
221
|
+
ylabel = ''
|
|
222
|
+
legend = False
|
|
223
|
+
stylename = 'ggplot'
|
|
224
|
+
xls = False
|
|
225
|
+
yls = False
|
|
226
|
+
fwidth = None
|
|
227
|
+
fheight = None
|
|
228
|
+
|
|
229
|
+
# Process kwargs
|
|
230
|
+
for key, val in list(kwargs.items()):
|
|
231
|
+
if key == 'fname':
|
|
232
|
+
fname = val
|
|
233
|
+
elif key == 'ftype':
|
|
234
|
+
ftype = val
|
|
235
|
+
elif key == 'title':
|
|
236
|
+
title = val
|
|
237
|
+
elif key == 'xlabel':
|
|
238
|
+
xlabel = val
|
|
239
|
+
elif key == 'ylabel':
|
|
240
|
+
ylabel = val
|
|
241
|
+
elif key == 'legend':
|
|
242
|
+
legend = val
|
|
243
|
+
elif key == 'stylename':
|
|
244
|
+
stylename = val
|
|
245
|
+
elif key == 'xls':
|
|
246
|
+
xls = val
|
|
247
|
+
elif key == 'yls':
|
|
248
|
+
yls = val
|
|
249
|
+
elif key == 'fwidth':
|
|
250
|
+
fwidth = val
|
|
251
|
+
elif key == 'fheight':
|
|
252
|
+
fheight = val
|
|
253
|
+
|
|
254
|
+
if stylesLoaded:
|
|
255
|
+
styles = get_styles()
|
|
256
|
+
|
|
257
|
+
try:
|
|
258
|
+
idx = styles.index(stylename)
|
|
259
|
+
style.use(styles[idx])
|
|
260
|
+
except:
|
|
261
|
+
if len(styles) > 0:
|
|
262
|
+
style.use(styles[0])
|
|
263
|
+
|
|
264
|
+
plt.clf()
|
|
265
|
+
plt.cla()
|
|
266
|
+
axis = plt.gca()
|
|
267
|
+
|
|
268
|
+
if (xls):
|
|
269
|
+
axis.set_xscale('log', nonposx='clip')
|
|
270
|
+
if (yls):
|
|
271
|
+
axis.set_yscale('log', nonposy='clip')
|
|
272
|
+
|
|
273
|
+
curves = list()
|
|
274
|
+
|
|
275
|
+
if isinstance(curvelist, list):
|
|
276
|
+
curves.extend(curvelist)
|
|
277
|
+
else:
|
|
278
|
+
curves.append(curvelist)
|
|
279
|
+
|
|
280
|
+
for cur in curves:
|
|
281
|
+
if not cur.hidden:
|
|
282
|
+
xdat = np.array(cur.x)
|
|
283
|
+
ydat = np.array(cur.y)
|
|
284
|
+
|
|
285
|
+
if (yls):
|
|
286
|
+
for i in range(len(ydat)):
|
|
287
|
+
if (ydat[i] < 0):
|
|
288
|
+
ydat[i] = 1e-301 # custom ydata clipping
|
|
289
|
+
if (xls):
|
|
290
|
+
for i in range(len(xdat)):
|
|
291
|
+
if (xdat[i] < 0):
|
|
292
|
+
xdat[i] = 1e-301 # custom xdata clipping
|
|
293
|
+
|
|
294
|
+
if cur.ebar is not None:
|
|
295
|
+
c = plt.errorbar(xdat, ydat, yerr=[cur.ebar[0], cur.ebar[1]],
|
|
296
|
+
xerr=[cur.ebar[2], cur.ebar[3]], fmt='-')
|
|
297
|
+
elif cur.erange is not None:
|
|
298
|
+
c = plt.plot(xdat, ydat)
|
|
299
|
+
plt.fill_between(xdat, ydat - cur.erange[0], ydat + cur.erange[1],
|
|
300
|
+
alpha=0.4, color=c[0].get_color())
|
|
301
|
+
else:
|
|
302
|
+
c = plt.plot(xdat, ydat)
|
|
303
|
+
|
|
304
|
+
if cur.linespoints:
|
|
305
|
+
plt.setp(c[0], marker=cur.marker, markersize=cur.markersize, linestyle=cur.linestyle)
|
|
306
|
+
elif cur.scatter:
|
|
307
|
+
plt.setp(c[0], marker=cur.marker, markersize=cur.markersize, linestyle=' ')
|
|
308
|
+
else:
|
|
309
|
+
plt.setp(c[0], linestyle=cur.linestyle)
|
|
310
|
+
|
|
311
|
+
if cur.linewidth:
|
|
312
|
+
plt.setp(c[0], lw=cur.linewidth)
|
|
313
|
+
plt.setp(c[0], mew=cur.linewidth)
|
|
314
|
+
|
|
315
|
+
plt.setp(c[0], label=cur.name)
|
|
316
|
+
|
|
317
|
+
if cur.color != '':
|
|
318
|
+
plt.setp(c, color=cur.color)
|
|
319
|
+
else:
|
|
320
|
+
cur.color = c[0].get_color()
|
|
321
|
+
|
|
322
|
+
if cur.dashes is not None:
|
|
323
|
+
c[0].set_dashes(cur.dashes)
|
|
324
|
+
|
|
325
|
+
if legend:
|
|
326
|
+
plt.legend(fancybox=True, numpoints=1, loc=1, ncol=1).get_frame().set_alpha(0.5)
|
|
327
|
+
|
|
328
|
+
plt.xlabel(xlabel)
|
|
329
|
+
plt.ylabel(ylabel)
|
|
330
|
+
plt.title(title)
|
|
331
|
+
|
|
332
|
+
# Change figure size
|
|
333
|
+
figure = plt.gcf()
|
|
334
|
+
if fwidth is not None:
|
|
335
|
+
figure.set_figwidth(float(fwidth), True)
|
|
336
|
+
if fheight is not None:
|
|
337
|
+
figure.set_figheight(float(fheight), True)
|
|
338
|
+
|
|
339
|
+
if fname is not None:
|
|
340
|
+
try:
|
|
341
|
+
plt.savefig(fname + '.' + ftype, format=ftype)
|
|
342
|
+
except:
|
|
343
|
+
print('Error: Could not save image to ' + fname + ' of type ' + ftype)
|
|
344
|
+
|
|
345
|
+
return plt, figure, axis
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def save(fname, curvelist, verbose=False, save_labels=False):
|
|
349
|
+
"""
|
|
350
|
+
Saves the given Curve or list of Curves to a file named fname.
|
|
351
|
+
|
|
352
|
+
>>> curves = list()
|
|
353
|
+
|
|
354
|
+
>>> curves.append(pydvif.makecurve([1, 2, 3, 4], [5, 10, 15, 20]))
|
|
355
|
+
|
|
356
|
+
>>> pydvif.save('myfile.txt', curves) OR
|
|
357
|
+
|
|
358
|
+
>>> pydvif.save('myfile.txt', curves[0])
|
|
359
|
+
|
|
360
|
+
:param fname: ULTRA filename
|
|
361
|
+
:type fname: str
|
|
362
|
+
:param curvelist: The curve or list of curves to save
|
|
363
|
+
:type curvelist: Curve or list
|
|
364
|
+
:param verbose: prints the error stacktrace when True
|
|
365
|
+
:type verbose: bool
|
|
366
|
+
"""
|
|
367
|
+
curves = list()
|
|
368
|
+
|
|
369
|
+
if isinstance(curvelist, list):
|
|
370
|
+
curves.extend(curvelist)
|
|
371
|
+
else:
|
|
372
|
+
curves.append(curvelist)
|
|
373
|
+
|
|
374
|
+
try:
|
|
375
|
+
f = open(fname, 'w')
|
|
376
|
+
for cur in curves:
|
|
377
|
+
if save_labels:
|
|
378
|
+
print('# ' + cur.name + ' # xlabel ' + cur.xlabel + ' # ylabel ' + cur.ylabel + '\n')
|
|
379
|
+
f.write('# ' + cur.name + ' # xlabel ' + cur.xlabel + ' # ylabel ' + cur.ylabel + '\n')
|
|
380
|
+
else:
|
|
381
|
+
f.write('# ' + cur.name + '\n')
|
|
382
|
+
for dex in range(len(cur.x)):
|
|
383
|
+
f.write(' ' + str(cur.x[dex]) + ' ' + str(cur.y[dex]) + '\n')
|
|
384
|
+
except:
|
|
385
|
+
print('Error: Can not write to: ' + fname)
|
|
386
|
+
if verbose:
|
|
387
|
+
traceback.print_exc(file=sys.stdout)
|
|
388
|
+
finally:
|
|
389
|
+
if f:
|
|
390
|
+
f.close()
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def savecsv(fname, curvelist, verbose=False):
|
|
394
|
+
"""
|
|
395
|
+
Saves the Curve or list of Curves to file in comma separated values (csv) format. Assumes
|
|
396
|
+
all curves have the same x basis.
|
|
397
|
+
|
|
398
|
+
>>> curves = list()
|
|
399
|
+
|
|
400
|
+
>>> curves.append(pydvif.makecurve([1, 2, 3, 4], [5, 10, 15, 20]))
|
|
401
|
+
|
|
402
|
+
>>> pydvif.savecsv('myfile.csv', curves)
|
|
403
|
+
|
|
404
|
+
:param fname: ULTRA filename
|
|
405
|
+
:type fname: str
|
|
406
|
+
:param curvelist: The Curve or list of Curves to save
|
|
407
|
+
:type curvelist: list
|
|
408
|
+
:param verbose: prints the error stacktrace when True
|
|
409
|
+
:type verbose: bool
|
|
410
|
+
"""
|
|
411
|
+
curves = list()
|
|
412
|
+
|
|
413
|
+
if isinstance(curvelist, list):
|
|
414
|
+
curves.extend(curvelist)
|
|
415
|
+
else:
|
|
416
|
+
curves.append(curvelist)
|
|
417
|
+
|
|
418
|
+
try:
|
|
419
|
+
f = open(fname, 'w')
|
|
420
|
+
s = '# time'
|
|
421
|
+
for cur in curves:
|
|
422
|
+
s += ', ' + cur.name
|
|
423
|
+
s += '\n'
|
|
424
|
+
f.write(s)
|
|
425
|
+
for i in range(len(curvelist[0].x)):
|
|
426
|
+
s = str(curvelist[0].x[i])
|
|
427
|
+
for j in range(len(curvelist)):
|
|
428
|
+
s += ', ' + str(curvelist[j].y[i])
|
|
429
|
+
s += '\n'
|
|
430
|
+
f.write(s)
|
|
431
|
+
except:
|
|
432
|
+
print('Error: Can not write to: ' + fname)
|
|
433
|
+
if verbose:
|
|
434
|
+
traceback.print_exc(file=sys.stdout)
|
|
435
|
+
finally:
|
|
436
|
+
if f:
|
|
437
|
+
f.close()
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def read(fname, gnu=False, xcol=0, verbose=False, pattern=None, matches=None):
|
|
441
|
+
"""
|
|
442
|
+
Read the file and add parsed curves to a curvelist
|
|
443
|
+
|
|
444
|
+
>>> curves = pydvif.read('testData.txt')
|
|
445
|
+
|
|
446
|
+
>>> curves = pydvif.read('testData.txt', False, 0, False, '*_name', 20)
|
|
447
|
+
|
|
448
|
+
:param fname: ULTRA filename
|
|
449
|
+
:type fname: str
|
|
450
|
+
:param gnu: optional, flag to determine if the file is a column oriented (.gnu) file.
|
|
451
|
+
:type gnu: bool
|
|
452
|
+
:param xcol: optional, x-column number for column oriented (.gnu) files
|
|
453
|
+
:type xcol: int
|
|
454
|
+
:param verbose: optional, prints the error stacktrace when True
|
|
455
|
+
:type verbose: bool
|
|
456
|
+
:param pattern: optional, the regular expression pattern
|
|
457
|
+
:type pattern: str
|
|
458
|
+
:param matches: optional, maximum number of times to match pattern, if specified
|
|
459
|
+
:type matches: int
|
|
460
|
+
:returns: list -- the list of curves from the file matching pattern, if specified
|
|
461
|
+
|
|
462
|
+
"""
|
|
463
|
+
def bundle_curve(_curve, build_x, build_y):
|
|
464
|
+
|
|
465
|
+
_curve.xticks_labels = {}
|
|
466
|
+
|
|
467
|
+
# Numerical data
|
|
468
|
+
try:
|
|
469
|
+
float(build_x[0])
|
|
470
|
+
|
|
471
|
+
# X tick label data
|
|
472
|
+
except:
|
|
473
|
+
|
|
474
|
+
xticks = list(set(build_x))
|
|
475
|
+
xticks.sort()
|
|
476
|
+
xticks_dict = {}
|
|
477
|
+
|
|
478
|
+
for i, xtick in enumerate(xticks):
|
|
479
|
+
xticks_dict[xtick] = i
|
|
480
|
+
|
|
481
|
+
build_x = [xticks_dict[xtick] for xtick in build_x]
|
|
482
|
+
|
|
483
|
+
_curve.xticks_labels = xticks_dict
|
|
484
|
+
|
|
485
|
+
# Step Data
|
|
486
|
+
if len(build_x) != len(build_y):
|
|
487
|
+
build_y.append(build_y[-1])
|
|
488
|
+
|
|
489
|
+
_curve.x = np.array(build_x, dtype=float).repeat(2)[1:]
|
|
490
|
+
_curve.y = np.array(build_y, dtype=float).repeat(2)[:-1]
|
|
491
|
+
_curve.step = True
|
|
492
|
+
_curve.step_original_x = np.array(build_x, dtype=float)
|
|
493
|
+
_curve.step_original_y = np.array(build_y[:-1], dtype=float)
|
|
494
|
+
# Numerical Data
|
|
495
|
+
else:
|
|
496
|
+
_curve.x = np.array(build_x, dtype=float)
|
|
497
|
+
_curve.y = np.array(build_y, dtype=float)
|
|
498
|
+
_curve.step = False
|
|
499
|
+
|
|
500
|
+
return _curve
|
|
501
|
+
|
|
502
|
+
curve_list = list()
|
|
503
|
+
regex = None
|
|
504
|
+
|
|
505
|
+
if pattern:
|
|
506
|
+
regex = re.compile(r"%s" % pattern)
|
|
507
|
+
fname = os.path.expanduser(fname)
|
|
508
|
+
_, ext = os.path.splitext(fname)
|
|
509
|
+
try:
|
|
510
|
+
if gnu or ext == '.gnu':
|
|
511
|
+
return __loadcolumns(fname, xcol)
|
|
512
|
+
|
|
513
|
+
if pdbLoaded:
|
|
514
|
+
try:
|
|
515
|
+
fpdb = pdb.open(fname, 'r')
|
|
516
|
+
return __loadpdb(fname, fpdb)
|
|
517
|
+
except:
|
|
518
|
+
pass
|
|
519
|
+
|
|
520
|
+
match_count = 0
|
|
521
|
+
build_list_x = list()
|
|
522
|
+
build_list_y = list()
|
|
523
|
+
current = None
|
|
524
|
+
new_curve = True
|
|
525
|
+
potential_curve_name = ""
|
|
526
|
+
xlabels = {}
|
|
527
|
+
ylabels = {}
|
|
528
|
+
xlabel = ''
|
|
529
|
+
ylabel = ''
|
|
530
|
+
with open(fname, 'r') as f:
|
|
531
|
+
for line in f:
|
|
532
|
+
labels = False
|
|
533
|
+
split_line = re.split(r'[ \t]+', str.strip(line))
|
|
534
|
+
|
|
535
|
+
# No space between curvename and hashtag #mycurve
|
|
536
|
+
try: # Exponential numbers and single text will cause issues
|
|
537
|
+
if re.search('[a-zA-Z]', split_line[0]):
|
|
538
|
+
split_line_2 = re.split(r'#', str.strip(line))
|
|
539
|
+
split_line = [None] * 2
|
|
540
|
+
split_line[0] = '#'
|
|
541
|
+
split_line[1] = split_line_2[1]
|
|
542
|
+
except:
|
|
543
|
+
split_line = re.split(r'[ \t]+', str.strip(line))
|
|
544
|
+
|
|
545
|
+
# Check for labels
|
|
546
|
+
split_line_3 = re.split(r'#', str.strip(line))
|
|
547
|
+
for split in split_line_3:
|
|
548
|
+
|
|
549
|
+
if re.search('[a-zA-Z]', split):
|
|
550
|
+
if 'xlabel' in split:
|
|
551
|
+
xlabel = split.replace('xlabel', '').strip()
|
|
552
|
+
labels = True
|
|
553
|
+
if 'ylabel' in split:
|
|
554
|
+
ylabel = split.replace('ylabel', '').strip()
|
|
555
|
+
labels = True
|
|
556
|
+
|
|
557
|
+
# Contains x and/or y labels
|
|
558
|
+
if labels:
|
|
559
|
+
split_line = [None] * 2
|
|
560
|
+
split_line[0] = '#'
|
|
561
|
+
split_line[1] = split_line_3[1].strip()
|
|
562
|
+
xlabels[split_line[1]] = xlabel
|
|
563
|
+
ylabels[split_line[1]] = ylabel
|
|
564
|
+
xlabel = ''
|
|
565
|
+
ylabel = ''
|
|
566
|
+
|
|
567
|
+
if not split_line or not split_line[0]:
|
|
568
|
+
continue
|
|
569
|
+
elif split_line[0] in {'##', 'end', 'End', 'END'}:
|
|
570
|
+
continue
|
|
571
|
+
elif split_line[0] == '#':
|
|
572
|
+
# We may have just finished buiding a curve, so we need to
|
|
573
|
+
# add it to the list of curves.
|
|
574
|
+
# If this is the first curve, then current will be None, so
|
|
575
|
+
# we won't add anything.
|
|
576
|
+
# If there is a sequence of lines that start with # before
|
|
577
|
+
# getting to the actual data, then the new_curve flag will
|
|
578
|
+
# keep us from adding all those comments as curves.
|
|
579
|
+
if current and not new_curve:
|
|
580
|
+
# Need this since it will add last match below and outside loop
|
|
581
|
+
if matches and match_count >= matches:
|
|
582
|
+
break
|
|
583
|
+
|
|
584
|
+
curve_list.append(bundle_curve(current, build_list_x, build_list_y))
|
|
585
|
+
build_list_x = list()
|
|
586
|
+
build_list_y = list()
|
|
587
|
+
|
|
588
|
+
# Begin setup of new curve
|
|
589
|
+
new_curve = True
|
|
590
|
+
potential_curve_name = ' '.join(split_line[1:])
|
|
591
|
+
else:
|
|
592
|
+
if new_curve:
|
|
593
|
+
curve_name = potential_curve_name
|
|
594
|
+
new_curve = False
|
|
595
|
+
if regex:
|
|
596
|
+
if regex.search(curve_name):
|
|
597
|
+
match_count += 1
|
|
598
|
+
current = curve.Curve(fname, curve_name,
|
|
599
|
+
xlabel=xlabels.get(curve_name, ''),
|
|
600
|
+
ylabel=ylabels.get(curve_name, ''))
|
|
601
|
+
|
|
602
|
+
# Step Data
|
|
603
|
+
if len(split_line) == 1:
|
|
604
|
+
build_list_x.append(split_line[0])
|
|
605
|
+
# Numerical Data
|
|
606
|
+
elif len(split_line) == 2:
|
|
607
|
+
build_list_x.append(split_line[0])
|
|
608
|
+
build_list_y.append(split_line[-1])
|
|
609
|
+
# Label Data and Paired Data
|
|
610
|
+
else:
|
|
611
|
+
try: # Paired Data
|
|
612
|
+
float(split_line[0])
|
|
613
|
+
build_list_x += split_line[::2]
|
|
614
|
+
build_list_y += split_line[1::2]
|
|
615
|
+
except: # Label Data
|
|
616
|
+
build_list_x.append(" ".join(split_line[:-1]))
|
|
617
|
+
build_list_y.append(split_line[-1])
|
|
618
|
+
else:
|
|
619
|
+
current = None
|
|
620
|
+
else:
|
|
621
|
+
current = curve.Curve(fname, curve_name,
|
|
622
|
+
xlabel=xlabels.get(curve_name, ''),
|
|
623
|
+
ylabel=ylabels.get(curve_name, ''))
|
|
624
|
+
|
|
625
|
+
# Step Data
|
|
626
|
+
if len(split_line) == 1:
|
|
627
|
+
build_list_x.append(split_line[0])
|
|
628
|
+
# Numerical Data
|
|
629
|
+
elif len(split_line) == 2:
|
|
630
|
+
build_list_x.append(split_line[0])
|
|
631
|
+
build_list_y.append(split_line[-1])
|
|
632
|
+
# Label Data and Paired Data
|
|
633
|
+
else:
|
|
634
|
+
try: # Paired Data
|
|
635
|
+
float(split_line[0])
|
|
636
|
+
build_list_x += split_line[::2]
|
|
637
|
+
build_list_y += split_line[1::2]
|
|
638
|
+
except: # Label Data
|
|
639
|
+
build_list_x.append(" ".join(split_line[:-1]))
|
|
640
|
+
build_list_y.append(split_line[-1])
|
|
641
|
+
|
|
642
|
+
elif current and not new_curve: # add data to current curve
|
|
643
|
+
|
|
644
|
+
# Step Data
|
|
645
|
+
if len(split_line) == 1:
|
|
646
|
+
build_list_x.append(split_line[0])
|
|
647
|
+
# Numerical Data
|
|
648
|
+
elif len(split_line) == 2:
|
|
649
|
+
build_list_x.append(split_line[0])
|
|
650
|
+
build_list_y.append(split_line[-1])
|
|
651
|
+
# Label Data and Paired Data
|
|
652
|
+
else:
|
|
653
|
+
try: # Paired Data
|
|
654
|
+
float(split_line[0])
|
|
655
|
+
build_list_x += split_line[::2]
|
|
656
|
+
build_list_y += split_line[1::2]
|
|
657
|
+
except: # Label Data
|
|
658
|
+
build_list_x.append(" ".join(split_line[:-1]))
|
|
659
|
+
build_list_y.append(split_line[-1])
|
|
660
|
+
|
|
661
|
+
if current and build_list_x and build_list_y:
|
|
662
|
+
curve_list.append(bundle_curve(current, build_list_x, build_list_y))
|
|
663
|
+
|
|
664
|
+
except IOError:
|
|
665
|
+
print('could not load file: {}'.format(fname))
|
|
666
|
+
if verbose:
|
|
667
|
+
traceback.print_exc(file=sys.stdout)
|
|
668
|
+
except ValueError:
|
|
669
|
+
print('invalid pydv file: {}'.format(fname))
|
|
670
|
+
if verbose:
|
|
671
|
+
traceback.print_exc(file=sys.stdout)
|
|
672
|
+
|
|
673
|
+
return curve_list
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def filtercurves(curvelist, pattern):
|
|
677
|
+
"""
|
|
678
|
+
Filters the list of curves based on the regular expression pattern.
|
|
679
|
+
|
|
680
|
+
>>> curves = pydvif.filtercurves(curves, "*_name")
|
|
681
|
+
|
|
682
|
+
:param curvelist: the list of curves
|
|
683
|
+
:type curvelist: Curve
|
|
684
|
+
:param pattern: the regular expression pattern
|
|
685
|
+
:type pattern: str
|
|
686
|
+
:return: list -- The list of filtered curves from curvelist based on the regular expression pattern
|
|
687
|
+
"""
|
|
688
|
+
results = list()
|
|
689
|
+
regex = re.compile(r"%s" % pattern)
|
|
690
|
+
|
|
691
|
+
for c in curvelist:
|
|
692
|
+
if regex.search(c.name) is not None:
|
|
693
|
+
results.append(c)
|
|
694
|
+
|
|
695
|
+
return results
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
def readcsv(fname, xcol=0, verbose=False):
|
|
699
|
+
"""
|
|
700
|
+
Load a csv (comma separated values) data file, add parsed curves to
|
|
701
|
+
a curvelist. '#' is the comment character. First uncommented line must
|
|
702
|
+
be the column labels. We assume the first column is the x-data, every
|
|
703
|
+
other column is y-data. We also assume all columns are the same length.
|
|
704
|
+
|
|
705
|
+
>>> curves = readcsv('testData.csv')
|
|
706
|
+
|
|
707
|
+
:param fname: csv filename
|
|
708
|
+
:type fname: str
|
|
709
|
+
:param xcol: x-column number for column oriented (.gnu) files
|
|
710
|
+
:type xcol: int
|
|
711
|
+
:param verbose: prints the error stacktrace when True
|
|
712
|
+
:type verbose: bool
|
|
713
|
+
:returns: list -- the list of curves from the csv file
|
|
714
|
+
"""
|
|
715
|
+
|
|
716
|
+
curvelist = list()
|
|
717
|
+
|
|
718
|
+
try:
|
|
719
|
+
f = open(fname, 'r')
|
|
720
|
+
except IOError:
|
|
721
|
+
print('readcsv: could not load file: ' + fname)
|
|
722
|
+
if verbose:
|
|
723
|
+
traceback.print_exc(file=sys.stdout)
|
|
724
|
+
return curvelist
|
|
725
|
+
|
|
726
|
+
try:
|
|
727
|
+
lines = f.readlines()
|
|
728
|
+
iLine = 0
|
|
729
|
+
for line in lines:
|
|
730
|
+
if line[0] != '#':
|
|
731
|
+
break
|
|
732
|
+
iLine += 1
|
|
733
|
+
if iLine == 0 and False: # FIXME make condition to catch no labels
|
|
734
|
+
print('WARNING: columns have no labels, labels will be assigned...someday')
|
|
735
|
+
alllabels = lines[iLine] # this line has the labels on it.
|
|
736
|
+
colLabels = alllabels.split(',')
|
|
737
|
+
colLabels = [w.strip() for w in colLabels]
|
|
738
|
+
for w in colLabels: # if someone made labels with quotes, kill the quotes
|
|
739
|
+
if '"' in w:
|
|
740
|
+
w.replace('"', '')
|
|
741
|
+
# check that we have a label for every column
|
|
742
|
+
if len(colLabels) != len(lines[iLine].split(',')) and iLine > 0:
|
|
743
|
+
raise RuntimeError('Sorry, right now PDV requires you to have a label for every column.')
|
|
744
|
+
# We assume some column is the x-data, every other column
|
|
745
|
+
# is y-data
|
|
746
|
+
iLine += 1 # go to next line after header labels
|
|
747
|
+
# CSV Data is in x and y pairs
|
|
748
|
+
if xcol == 'paired':
|
|
749
|
+
xcol = 0
|
|
750
|
+
paired = True
|
|
751
|
+
# CSV Data has a single shared x column
|
|
752
|
+
else:
|
|
753
|
+
xcol = int(xcol)
|
|
754
|
+
paired = False
|
|
755
|
+
numcurves = len(lines[iLine].split(',')) - 1
|
|
756
|
+
|
|
757
|
+
# Make the curves, append them to self.curvelist.
|
|
758
|
+
# First, get data into lists of numbers
|
|
759
|
+
# numDataLines = len(lines) - iLine
|
|
760
|
+
localCurves = []
|
|
761
|
+
for i in range(numcurves + 1):
|
|
762
|
+
localCurves.append([]) # FIGURE OUT COOL WAY TO DO THIS LATER: localCurves = (numcurves+1)*[[]]
|
|
763
|
+
# turn the strings into numbers
|
|
764
|
+
for line in lines[iLine:]:
|
|
765
|
+
nums = [np.nan if not n or n == '\n' else float(n) for n in line.split(',')]
|
|
766
|
+
# print 'nums = ', nums, 'numcurves = ', numcurves
|
|
767
|
+
assert len(nums) == numcurves + 1
|
|
768
|
+
if xcol >= numcurves:
|
|
769
|
+
print('xcolumn is %d, larger than the number of curves' % xcol,
|
|
770
|
+
'in the file, use "setxcolumn" to fix that')
|
|
771
|
+
for colID in range(numcurves + 1):
|
|
772
|
+
localCurves[colID].append(nums[colID])
|
|
773
|
+
# convert lists to numpy arrays
|
|
774
|
+
for colID in range(numcurves):
|
|
775
|
+
localCurves[colID] = np.array(localCurves[colID])
|
|
776
|
+
# Make Curve objects, add to self.curvelist
|
|
777
|
+
if paired:
|
|
778
|
+
for colID in range(0, numcurves + 1, 2):
|
|
779
|
+
colLabels[colID] = colLabels[colID][:-4] # ' [x]'
|
|
780
|
+
x = np.array(localCurves[colID])
|
|
781
|
+
x = x[~np.isnan(x)]
|
|
782
|
+
y = np.array(localCurves[colID + 1])
|
|
783
|
+
y = y[~np.isnan(y)]
|
|
784
|
+
c = makecurve(x, y, colLabels[colID], fname)
|
|
785
|
+
print("Appended curve: ", colLabels[colID], len(c.x), len(c.y))
|
|
786
|
+
curvelist.append(c)
|
|
787
|
+
else:
|
|
788
|
+
for colID in range(numcurves + 1):
|
|
789
|
+
if colID != xcol:
|
|
790
|
+
c = makecurve(localCurves[xcol], localCurves[colID], colLabels[colID], fname)
|
|
791
|
+
print("Appended curve: ", colLabels[colID], len(c.x), len(c.y))
|
|
792
|
+
curvelist.append(c)
|
|
793
|
+
# tidy up
|
|
794
|
+
f.close()
|
|
795
|
+
# anticipate failure!
|
|
796
|
+
except ValueError as e:
|
|
797
|
+
print(e)
|
|
798
|
+
print('readcsv: invalid pydv file: ' + fname)
|
|
799
|
+
if verbose:
|
|
800
|
+
traceback.print_exc(file=sys.stdout)
|
|
801
|
+
|
|
802
|
+
return curvelist
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
def readsina(fname, verbose=False):
|
|
806
|
+
"""
|
|
807
|
+
Load a Sina JSON data file, add parsed curves to a curvelist.
|
|
808
|
+
|
|
809
|
+
We assume JSON conforming to the Sina schema, with each curve defined in a curve_set. We assume
|
|
810
|
+
there is only one record, and if there are more then we only read the first one. We also assume
|
|
811
|
+
only one independent variable per curve_set; if there are more than one, then PyDV may exhibit
|
|
812
|
+
undefined behavior. Can also read curve_sets within libraries in library_data.
|
|
813
|
+
|
|
814
|
+
>>> curves = readsina('testData.json')
|
|
815
|
+
|
|
816
|
+
:param fname: Sina JSON filename
|
|
817
|
+
:type fname: str
|
|
818
|
+
:param verbose: prints the error stacktrace when True
|
|
819
|
+
:type verbose: bool
|
|
820
|
+
:returns: list: the list of curves from the sina file
|
|
821
|
+
"""
|
|
822
|
+
curves = {}
|
|
823
|
+
listed_order = []
|
|
824
|
+
try:
|
|
825
|
+
# Load the curve data from the curve_sets
|
|
826
|
+
with open(fname, 'r') as fp:
|
|
827
|
+
try:
|
|
828
|
+
sina_file = json.load(fp)
|
|
829
|
+
record_id = sina_file['records'][0]['id']
|
|
830
|
+
curve_sets = sina_file['records'][0]['curve_sets']
|
|
831
|
+
library_data = sina_file['records'][0].get('library_data', {})
|
|
832
|
+
|
|
833
|
+
def add_curve_set(curve_sets, curves, listed_order, library=''):
|
|
834
|
+
for curve_set_name, curve_set in curve_sets.items():
|
|
835
|
+
independent_dict = next(iter(curve_set['independent'].items()))
|
|
836
|
+
independent_name = independent_dict[0]
|
|
837
|
+
independent_value = independent_dict[1]['value']
|
|
838
|
+
for name, v in curve_set['dependent'].items():
|
|
839
|
+
# TODO: Save the name x and y names with the curves
|
|
840
|
+
dependent_variable_name = name
|
|
841
|
+
full_name = curve_set_name + '__SINA_DEP__' + dependent_variable_name
|
|
842
|
+
dependent_variable_value = v['value']
|
|
843
|
+
curve_name = dependent_variable_name + ' vs ' + independent_name + " (" + \
|
|
844
|
+
curve_set_name + ")"
|
|
845
|
+
if library != '':
|
|
846
|
+
curve_name += ' ' + library
|
|
847
|
+
full_name += '__LIBRARY__' + library
|
|
848
|
+
c = makecurve(x=independent_value, y=dependent_variable_value,
|
|
849
|
+
name=curve_name, fname=fname, xlabel=independent_name,
|
|
850
|
+
ylabel=dependent_variable_name, title=curve_name, record_id=record_id)
|
|
851
|
+
c.step = False
|
|
852
|
+
c.xticks_labels = {}
|
|
853
|
+
print("Appended curve: {}, len x,y: {},{}"
|
|
854
|
+
.format(dependent_variable_name, len(c.x), len(c.y)))
|
|
855
|
+
curves[full_name] = c
|
|
856
|
+
listed_order.append(full_name)
|
|
857
|
+
return curves, listed_order
|
|
858
|
+
|
|
859
|
+
curves, listed_order = add_curve_set(curve_sets, curves, listed_order)
|
|
860
|
+
|
|
861
|
+
for library in library_data:
|
|
862
|
+
if 'curve_sets' in library_data[library]:
|
|
863
|
+
curve_sets = library_data[library]['curve_sets']
|
|
864
|
+
curves, listed_order = add_curve_set(curve_sets, curves, listed_order, library=library)
|
|
865
|
+
except KeyError:
|
|
866
|
+
print('readsina: Sina file {} is malformed'.format(fname))
|
|
867
|
+
if verbose:
|
|
868
|
+
traceback.print_exc(file=sys.stdout)
|
|
869
|
+
return []
|
|
870
|
+
|
|
871
|
+
# Try to load the order in which the user wants to load the curves into PyDV
|
|
872
|
+
with open(fname, 'r') as fp:
|
|
873
|
+
try:
|
|
874
|
+
order_options = json.load(fp)['records'][0]['data']['SINA_timeplot_order']['value']
|
|
875
|
+
except:
|
|
876
|
+
order_options = listed_order
|
|
877
|
+
|
|
878
|
+
except IOError:
|
|
879
|
+
print('readsina: could not load file: {}'.format(fname))
|
|
880
|
+
if verbose:
|
|
881
|
+
traceback.print_exc(file=sys.stdout)
|
|
882
|
+
return []
|
|
883
|
+
|
|
884
|
+
try:
|
|
885
|
+
curves_lst = [curves[name] for name in order_options]
|
|
886
|
+
except KeyError:
|
|
887
|
+
print('readsina: mismatch between dependent variable names in the curve_sets and the '
|
|
888
|
+
'ordering specified in SINA_timeplot_order. Using default ordering instead.')
|
|
889
|
+
if verbose:
|
|
890
|
+
traceback.print_exc(File=sys.stdout)
|
|
891
|
+
curves_lst = [curves[name] for name in listed_order]
|
|
892
|
+
return curves_lst
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
########################################################
|
|
896
|
+
################## Math Functions ##################### # noqa e266
|
|
897
|
+
########################################################
|
|
898
|
+
|
|
899
|
+
def cos(curvelist):
|
|
900
|
+
"""
|
|
901
|
+
Take the cosine of y values of a Curve or list of Curves.
|
|
902
|
+
|
|
903
|
+
>>> curves = pydvif.read('testData.txt')
|
|
904
|
+
|
|
905
|
+
>>> pydvif.cos(curves) OR
|
|
906
|
+
|
|
907
|
+
>>> pydvif.cos(curves[0])
|
|
908
|
+
|
|
909
|
+
:param curvelist: The Curve or list of Curves
|
|
910
|
+
:type curvelist: Curve or list
|
|
911
|
+
"""
|
|
912
|
+
curves = list()
|
|
913
|
+
|
|
914
|
+
if isinstance(curvelist, list):
|
|
915
|
+
curves.extend(curvelist)
|
|
916
|
+
else:
|
|
917
|
+
curves.append(curvelist)
|
|
918
|
+
|
|
919
|
+
for cur in curves:
|
|
920
|
+
cur.y = np.cos(cur.y)
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
def cosx(curvelist):
|
|
924
|
+
"""
|
|
925
|
+
Take the cosine of x values of a Curve or list of Curves.
|
|
926
|
+
|
|
927
|
+
>>> curves = pydvif.read('testData.txt')
|
|
928
|
+
|
|
929
|
+
>>> pydvif.cosx(curves) OR
|
|
930
|
+
|
|
931
|
+
>>> pydvif.cosx(curves[0])
|
|
932
|
+
|
|
933
|
+
:param curvelist: The Curve or list of Curves
|
|
934
|
+
:type curvelist: Curve or list
|
|
935
|
+
"""
|
|
936
|
+
curves = list()
|
|
937
|
+
|
|
938
|
+
if isinstance(curvelist, list):
|
|
939
|
+
curves.extend(curvelist)
|
|
940
|
+
else:
|
|
941
|
+
curves.append(curvelist)
|
|
942
|
+
|
|
943
|
+
for cur in curves:
|
|
944
|
+
cur.x = np.cos(cur.x)
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
def cosh(curvelist):
|
|
948
|
+
"""
|
|
949
|
+
Take the hyperbolic cosine of y values of a Curve or list of Curves.
|
|
950
|
+
|
|
951
|
+
>>> curves = pydvif.read('testData.txt')
|
|
952
|
+
|
|
953
|
+
>>> pydvif.cosh(curves) OR
|
|
954
|
+
|
|
955
|
+
>>> pydvif.cosh(curves[0])
|
|
956
|
+
|
|
957
|
+
:param curvelist: The Curve or list of curves
|
|
958
|
+
:type curvelist: Curve or list
|
|
959
|
+
"""
|
|
960
|
+
curves = list()
|
|
961
|
+
|
|
962
|
+
if isinstance(curvelist, list):
|
|
963
|
+
curves.extend(curvelist)
|
|
964
|
+
else:
|
|
965
|
+
curves.append(curvelist)
|
|
966
|
+
|
|
967
|
+
for cur in curves:
|
|
968
|
+
cur.y = np.cosh(cur.y)
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
def coshx(curvelist):
|
|
972
|
+
"""
|
|
973
|
+
Take the hyperbolic cosine of x values of a Curve or list of Curves.
|
|
974
|
+
|
|
975
|
+
>>> curves = pydvif.read('testData.txt')
|
|
976
|
+
|
|
977
|
+
>>> pydvif.coshx(curves) OR
|
|
978
|
+
|
|
979
|
+
>>> pydvif.coshx(curves[0])
|
|
980
|
+
|
|
981
|
+
:param curvelist: The Curve or list of curves
|
|
982
|
+
:type curvelist: Curve or list
|
|
983
|
+
"""
|
|
984
|
+
curves = list()
|
|
985
|
+
|
|
986
|
+
if isinstance(curvelist, list):
|
|
987
|
+
curves.extend(curvelist)
|
|
988
|
+
else:
|
|
989
|
+
curves.append(curvelist)
|
|
990
|
+
|
|
991
|
+
for cur in curves:
|
|
992
|
+
cur.x = np.cosh(cur.x)
|
|
993
|
+
|
|
994
|
+
|
|
995
|
+
def acosh(curvelist):
|
|
996
|
+
"""
|
|
997
|
+
Take the hyperbolic arccosine of y values of a Curve or list of Curves.
|
|
998
|
+
|
|
999
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1000
|
+
|
|
1001
|
+
>>> pydvif.acosh(curves) OR
|
|
1002
|
+
|
|
1003
|
+
>>> pydvif.acosh(curves[0])
|
|
1004
|
+
|
|
1005
|
+
:param curvelist: The Curve or list of curves
|
|
1006
|
+
:type curvelist: Curve or list
|
|
1007
|
+
"""
|
|
1008
|
+
curves = list()
|
|
1009
|
+
|
|
1010
|
+
if isinstance(curvelist, list):
|
|
1011
|
+
curves.extend(curvelist)
|
|
1012
|
+
else:
|
|
1013
|
+
curves.append(curvelist)
|
|
1014
|
+
|
|
1015
|
+
for cur in curves:
|
|
1016
|
+
cur.y = np.arccosh(cur.y)
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
def acoshx(curvelist):
|
|
1020
|
+
"""
|
|
1021
|
+
Take the hyperbolic arccosine of x values of a Curve or list of Curves.
|
|
1022
|
+
|
|
1023
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1024
|
+
|
|
1025
|
+
>>> pydvif.acoshx(curves) OR
|
|
1026
|
+
|
|
1027
|
+
>>> pydvif.acoshx(curves[0])
|
|
1028
|
+
|
|
1029
|
+
:param curvelist: The Curve or list of curves
|
|
1030
|
+
:type curvelist: Curve or list
|
|
1031
|
+
"""
|
|
1032
|
+
curves = list()
|
|
1033
|
+
|
|
1034
|
+
if isinstance(curvelist, list):
|
|
1035
|
+
curves.extend(curvelist)
|
|
1036
|
+
else:
|
|
1037
|
+
curves.append(curvelist)
|
|
1038
|
+
|
|
1039
|
+
for cur in curves:
|
|
1040
|
+
cur.x = np.arccosh(cur.x)
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
def acos(curvelist):
|
|
1044
|
+
"""
|
|
1045
|
+
Take the arccosine of y values of a Curve or list of Curves
|
|
1046
|
+
|
|
1047
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1048
|
+
|
|
1049
|
+
>>> pydvif.acos(curves) OR
|
|
1050
|
+
|
|
1051
|
+
>>> pydvif.acos(curves[0])
|
|
1052
|
+
|
|
1053
|
+
:param curvelist: The Curve or list of curves
|
|
1054
|
+
:type curvelist: Curve or list
|
|
1055
|
+
"""
|
|
1056
|
+
curves = list()
|
|
1057
|
+
|
|
1058
|
+
if isinstance(curvelist, list):
|
|
1059
|
+
curves.extend(curvelist)
|
|
1060
|
+
else:
|
|
1061
|
+
curves.append(curvelist)
|
|
1062
|
+
|
|
1063
|
+
for cur in curves:
|
|
1064
|
+
cur.y = np.arccos(cur.y)
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
def acosx(curvelist):
|
|
1068
|
+
"""
|
|
1069
|
+
Take the arccosine of x values of a Curve or list of Curves.
|
|
1070
|
+
|
|
1071
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1072
|
+
|
|
1073
|
+
>>> pydvif.acosx(curves) OR
|
|
1074
|
+
|
|
1075
|
+
>>> pydvif.acosx(curves[0])
|
|
1076
|
+
|
|
1077
|
+
:param curvelist: The Curve or list of curves
|
|
1078
|
+
:type curvelist: Curve or list
|
|
1079
|
+
"""
|
|
1080
|
+
curves = list()
|
|
1081
|
+
|
|
1082
|
+
if isinstance(curvelist, list):
|
|
1083
|
+
curves.extend(curvelist)
|
|
1084
|
+
else:
|
|
1085
|
+
curves.append(curvelist)
|
|
1086
|
+
|
|
1087
|
+
for cur in curves:
|
|
1088
|
+
cur.x = np.arccos(cur.x)
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
def sin(curvelist):
|
|
1092
|
+
"""
|
|
1093
|
+
Take the sine of y values of a single curve or multiple curves in list.
|
|
1094
|
+
|
|
1095
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1096
|
+
|
|
1097
|
+
>>> pydvif.sin(curves)
|
|
1098
|
+
|
|
1099
|
+
:param curvelist: A single curve or a list of curves
|
|
1100
|
+
:type curvelist: curve or list
|
|
1101
|
+
"""
|
|
1102
|
+
if isinstance(curvelist, list):
|
|
1103
|
+
for c in curvelist:
|
|
1104
|
+
c.y = np.sin(c.y)
|
|
1105
|
+
else:
|
|
1106
|
+
curvelist.y = np.sin(curvelist.y)
|
|
1107
|
+
|
|
1108
|
+
|
|
1109
|
+
def sinx(curvelist):
|
|
1110
|
+
"""
|
|
1111
|
+
Take the sine of x values of a single curve or multiple curves in list.
|
|
1112
|
+
|
|
1113
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1114
|
+
|
|
1115
|
+
>>> pydvif.sinx(curves)
|
|
1116
|
+
|
|
1117
|
+
:param curvelist: A single curve or a list of curves
|
|
1118
|
+
:type curvelist: curve or list
|
|
1119
|
+
"""
|
|
1120
|
+
|
|
1121
|
+
if isinstance(curvelist, list):
|
|
1122
|
+
for c in curvelist:
|
|
1123
|
+
c.x = np.sin(c.x)
|
|
1124
|
+
else:
|
|
1125
|
+
curvelist.x = np.sin(curvelist.x)
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
def sinh(curvelist):
|
|
1129
|
+
"""
|
|
1130
|
+
Take the hyperbolic sine of y values of a single curve or multiple curves in list.
|
|
1131
|
+
|
|
1132
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1133
|
+
|
|
1134
|
+
>>> pydvif.sinh(curves)
|
|
1135
|
+
|
|
1136
|
+
:param curvelist: A single curve or a list of curves
|
|
1137
|
+
:type curvelist: curve or list
|
|
1138
|
+
"""
|
|
1139
|
+
|
|
1140
|
+
if isinstance(curvelist, list):
|
|
1141
|
+
for c in curvelist:
|
|
1142
|
+
c.y = np.sinh(c.y)
|
|
1143
|
+
else:
|
|
1144
|
+
curvelist.y = np.sinh(curvelist.y)
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
def sinhx(curvelist):
|
|
1148
|
+
"""
|
|
1149
|
+
Take the hyperbolic sine of x values of a single curve or multiple curves in list.
|
|
1150
|
+
|
|
1151
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1152
|
+
|
|
1153
|
+
>>> pydvif.sinhx(curves)
|
|
1154
|
+
|
|
1155
|
+
:param curvelist: A single curve or a list of curves
|
|
1156
|
+
:type curvelist: curve or list
|
|
1157
|
+
"""
|
|
1158
|
+
|
|
1159
|
+
if isinstance(curvelist, list):
|
|
1160
|
+
for c in curvelist:
|
|
1161
|
+
c.x = np.sinh(c.x)
|
|
1162
|
+
else:
|
|
1163
|
+
curvelist.x = np.sinh(curvelist.x)
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
def asinh(curvelist):
|
|
1167
|
+
"""
|
|
1168
|
+
Take the hyperbolic arcsine of y values of a single curve or curves in a list.
|
|
1169
|
+
|
|
1170
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1171
|
+
|
|
1172
|
+
>>> pydvif.asinh(curves)
|
|
1173
|
+
|
|
1174
|
+
:param curvelist: A single curve or a list of curves
|
|
1175
|
+
:type curvelist: curve or list
|
|
1176
|
+
"""
|
|
1177
|
+
|
|
1178
|
+
if isinstance(curvelist, list):
|
|
1179
|
+
for c in curvelist:
|
|
1180
|
+
c.y = np.asinh(c.y)
|
|
1181
|
+
else:
|
|
1182
|
+
curvelist.y = np.asinh(curvelist.y)
|
|
1183
|
+
|
|
1184
|
+
|
|
1185
|
+
def asinhx(curvelist):
|
|
1186
|
+
"""
|
|
1187
|
+
Take the hyperbolic arcsine of x values of a single curve or curves in a list.
|
|
1188
|
+
|
|
1189
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1190
|
+
|
|
1191
|
+
>>> pydvif.asinhx(curves)
|
|
1192
|
+
|
|
1193
|
+
:param curvelist: A single curve or a list of curves
|
|
1194
|
+
:type curvelist: curve or list
|
|
1195
|
+
"""
|
|
1196
|
+
|
|
1197
|
+
if isinstance(curvelist, list):
|
|
1198
|
+
for c in curvelist:
|
|
1199
|
+
c.x = np.asinh(c.x)
|
|
1200
|
+
else:
|
|
1201
|
+
curvelist.x = np.asinh(curvelist.x)
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
def asin(curvelist):
|
|
1205
|
+
"""
|
|
1206
|
+
Take the arcsine of y values of a single curve or curves in a list.
|
|
1207
|
+
|
|
1208
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1209
|
+
|
|
1210
|
+
>>> pydvif.asin(curves)
|
|
1211
|
+
|
|
1212
|
+
:param curvelist: A single curve or a list of curves
|
|
1213
|
+
:type curvelist: curve or list
|
|
1214
|
+
"""
|
|
1215
|
+
if isinstance(curvelist, list):
|
|
1216
|
+
for c in curvelist:
|
|
1217
|
+
c.y = np.asin(c.y)
|
|
1218
|
+
else:
|
|
1219
|
+
curvelist.y = np.asin(curvelist.y)
|
|
1220
|
+
|
|
1221
|
+
|
|
1222
|
+
def asinx(curvelist):
|
|
1223
|
+
"""
|
|
1224
|
+
Take the arcsine of x values of a single curve or curves in a list.
|
|
1225
|
+
|
|
1226
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1227
|
+
|
|
1228
|
+
>>> pydvif.asinx(curves)
|
|
1229
|
+
|
|
1230
|
+
:param curvelist: A single curve or a list of curves
|
|
1231
|
+
:type curvelist: curve or list
|
|
1232
|
+
"""
|
|
1233
|
+
|
|
1234
|
+
if isinstance(curvelist, list):
|
|
1235
|
+
for c in curvelist:
|
|
1236
|
+
c.x = np.asin(c.x)
|
|
1237
|
+
else:
|
|
1238
|
+
curvelist.x = np.asin(curvelist.x)
|
|
1239
|
+
|
|
1240
|
+
|
|
1241
|
+
def tan(curvelist):
|
|
1242
|
+
"""
|
|
1243
|
+
Take the tangent of y values of a single curve or multiple curves in list.
|
|
1244
|
+
|
|
1245
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1246
|
+
|
|
1247
|
+
>>> pydvif.tan(curves)
|
|
1248
|
+
|
|
1249
|
+
:param curvelist: A single curve or a list of curves
|
|
1250
|
+
:type curvelist: curve or list
|
|
1251
|
+
"""
|
|
1252
|
+
|
|
1253
|
+
if isinstance(curvelist, list):
|
|
1254
|
+
for c in curvelist:
|
|
1255
|
+
c.y = np.tan(c.y)
|
|
1256
|
+
else:
|
|
1257
|
+
curvelist.y = np.tan(curvelist.y)
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
def tanx(curvelist):
|
|
1261
|
+
"""
|
|
1262
|
+
Take the tangent of x values of a single curve or multiple curves in list.
|
|
1263
|
+
|
|
1264
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1265
|
+
|
|
1266
|
+
>>> pydvif.tanx(curves)
|
|
1267
|
+
|
|
1268
|
+
:param curvelist: A single curve or a list of curves
|
|
1269
|
+
:type curvelist: curve or list
|
|
1270
|
+
"""
|
|
1271
|
+
|
|
1272
|
+
if isinstance(curvelist, list):
|
|
1273
|
+
for c in curvelist:
|
|
1274
|
+
c.x = np.tan(c.x)
|
|
1275
|
+
else:
|
|
1276
|
+
curvelist.x = np.tan(curvelist.x)
|
|
1277
|
+
|
|
1278
|
+
|
|
1279
|
+
def tanh(curvelist):
|
|
1280
|
+
"""
|
|
1281
|
+
Take the hyperbolic tangent of y values of a single curve or multiple curves in list.
|
|
1282
|
+
|
|
1283
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1284
|
+
|
|
1285
|
+
>>> pydvif.tanh(curves)
|
|
1286
|
+
|
|
1287
|
+
:param curvelist: A single curve or a list of curves
|
|
1288
|
+
:type curvelist: curve or list
|
|
1289
|
+
"""
|
|
1290
|
+
|
|
1291
|
+
if isinstance(curvelist, list):
|
|
1292
|
+
for c in curvelist:
|
|
1293
|
+
c.y = np.tanh(c.y)
|
|
1294
|
+
else:
|
|
1295
|
+
curvelist.y = np.tanh(curvelist.y)
|
|
1296
|
+
|
|
1297
|
+
|
|
1298
|
+
def tanhx(curvelist):
|
|
1299
|
+
"""
|
|
1300
|
+
Take the hyperbolic tangent of x values of a single curve or multiple curves in list.
|
|
1301
|
+
|
|
1302
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1303
|
+
|
|
1304
|
+
>>> pydvif.tanhx(curves)
|
|
1305
|
+
|
|
1306
|
+
:param curvelist: A single curve or a list of curves
|
|
1307
|
+
:type curvelist: curve or list
|
|
1308
|
+
"""
|
|
1309
|
+
|
|
1310
|
+
if isinstance(curvelist, list):
|
|
1311
|
+
for c in curvelist:
|
|
1312
|
+
c.x = np.tanh(c.x)
|
|
1313
|
+
else:
|
|
1314
|
+
curvelist.x = np.tanh(curvelist.x)
|
|
1315
|
+
|
|
1316
|
+
|
|
1317
|
+
def atan(curvelist):
|
|
1318
|
+
"""
|
|
1319
|
+
Take the arctangent of y values of a single curve or curves in a list.
|
|
1320
|
+
|
|
1321
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1322
|
+
|
|
1323
|
+
>>> pydvif.atan(curves)
|
|
1324
|
+
|
|
1325
|
+
:param curvelist: A single curve or a list of curves
|
|
1326
|
+
:type curvelist: curve or list
|
|
1327
|
+
"""
|
|
1328
|
+
|
|
1329
|
+
if isinstance(curvelist, list):
|
|
1330
|
+
for c in curvelist:
|
|
1331
|
+
c.y = np.atan(c.y)
|
|
1332
|
+
else:
|
|
1333
|
+
curvelist.y = np.atan(curvelist.y)
|
|
1334
|
+
|
|
1335
|
+
|
|
1336
|
+
def atanx(curvelist):
|
|
1337
|
+
"""
|
|
1338
|
+
Take the arctangent of x values of a single curve or curves in a list.
|
|
1339
|
+
|
|
1340
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1341
|
+
|
|
1342
|
+
>>> pydvif.atanx(curves)
|
|
1343
|
+
|
|
1344
|
+
:param curvelist: A single curve or a list of curves
|
|
1345
|
+
:type curvelist: curve or list
|
|
1346
|
+
"""
|
|
1347
|
+
|
|
1348
|
+
if isinstance(curvelist, list):
|
|
1349
|
+
for c in curvelist:
|
|
1350
|
+
c.x = np.atan(c.x)
|
|
1351
|
+
else:
|
|
1352
|
+
curvelist.x = np.atan(curvelist.x)
|
|
1353
|
+
|
|
1354
|
+
|
|
1355
|
+
def atanh(curvelist):
|
|
1356
|
+
"""
|
|
1357
|
+
Take the hyperbolic arctangent of y values of a single curve or curves in a list.
|
|
1358
|
+
|
|
1359
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1360
|
+
|
|
1361
|
+
>>> pydvif.atanh(curves)
|
|
1362
|
+
|
|
1363
|
+
:param curvelist: A single curve or a list of curves
|
|
1364
|
+
:type curvelist: curve or list
|
|
1365
|
+
"""
|
|
1366
|
+
|
|
1367
|
+
if isinstance(curvelist, list):
|
|
1368
|
+
for c in curvelist:
|
|
1369
|
+
c.y = np.atanh(c.y)
|
|
1370
|
+
else:
|
|
1371
|
+
curvelist.y = np.atanh(curvelist.y)
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
def atanhx(curvelist):
|
|
1375
|
+
"""
|
|
1376
|
+
Take the hyperbolic arctangent of x values of a single curve or curves in a list.
|
|
1377
|
+
|
|
1378
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1379
|
+
|
|
1380
|
+
>>> pydvif.atanhx(curves)
|
|
1381
|
+
|
|
1382
|
+
:param curvelist: A single curve or a list of curves
|
|
1383
|
+
:type curvelist: curve or list
|
|
1384
|
+
"""
|
|
1385
|
+
|
|
1386
|
+
if isinstance(curvelist, list):
|
|
1387
|
+
for c in curvelist:
|
|
1388
|
+
c.x = np.atanh(c.x)
|
|
1389
|
+
else:
|
|
1390
|
+
curvelist.x = np.atanh(curvelist.x)
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
def atan2(c1, c2, t=None):
|
|
1394
|
+
"""
|
|
1395
|
+
Perform the atan2 method for a pair of curves.
|
|
1396
|
+
|
|
1397
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1398
|
+
|
|
1399
|
+
>>> pydvif.atan2(curves[0], curves[1]) OR
|
|
1400
|
+
|
|
1401
|
+
>>> pydvif.atan2(curves[0], curves[1], tuple(['A', 'B']))
|
|
1402
|
+
|
|
1403
|
+
:param c1: the first curve
|
|
1404
|
+
:type c1: curve
|
|
1405
|
+
:param c2: the second curve
|
|
1406
|
+
:type c2: curve
|
|
1407
|
+
:param t: A tuple containing exactly two values to insert into the name string for the new curve
|
|
1408
|
+
:type t: tuple
|
|
1409
|
+
:return: curve -- a new curve with the results from this operation
|
|
1410
|
+
"""
|
|
1411
|
+
if t is None:
|
|
1412
|
+
t = tuple([c1.name, c2.name])
|
|
1413
|
+
|
|
1414
|
+
c = curve.Curve('', 'atan2(%s,%s)' % t)
|
|
1415
|
+
c.x = np.array(c1.x)
|
|
1416
|
+
c.y = np.arctan2(c1.y, c2.y)
|
|
1417
|
+
|
|
1418
|
+
return c
|
|
1419
|
+
|
|
1420
|
+
|
|
1421
|
+
def add(curvelist):
|
|
1422
|
+
"""
|
|
1423
|
+
Add one or more curves.
|
|
1424
|
+
|
|
1425
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1426
|
+
|
|
1427
|
+
>>> c = pydvif.add(curves)
|
|
1428
|
+
|
|
1429
|
+
:param curvelist: The list of curves
|
|
1430
|
+
:type curvelist: list
|
|
1431
|
+
:returns: curve -- the curve containing the sum of the curves in curvelist
|
|
1432
|
+
"""
|
|
1433
|
+
|
|
1434
|
+
numcurves = len(curvelist)
|
|
1435
|
+
if numcurves > 1:
|
|
1436
|
+
name = curvelist[0].name
|
|
1437
|
+
sendline = 'curvelist[' + str(0) + ']'
|
|
1438
|
+
for i in range(1, numcurves):
|
|
1439
|
+
name += ' + ' + curvelist[i].name
|
|
1440
|
+
sendline += '+ curvelist[' + str(i) + ']'
|
|
1441
|
+
|
|
1442
|
+
c = eval(sendline)
|
|
1443
|
+
c.name = name
|
|
1444
|
+
|
|
1445
|
+
if c.x is None or len(c.x) < 2:
|
|
1446
|
+
print('Error: curve overlap is insufficient')
|
|
1447
|
+
return 0
|
|
1448
|
+
|
|
1449
|
+
return c
|
|
1450
|
+
elif numcurves == 1:
|
|
1451
|
+
return curvelist[0]
|
|
1452
|
+
else:
|
|
1453
|
+
return curvelist
|
|
1454
|
+
|
|
1455
|
+
|
|
1456
|
+
def subtract(curvelist):
|
|
1457
|
+
"""
|
|
1458
|
+
Take difference of curves.
|
|
1459
|
+
|
|
1460
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1461
|
+
|
|
1462
|
+
>>> c = pydvif.subtract(curves)
|
|
1463
|
+
|
|
1464
|
+
:param curvelist: The list of curves
|
|
1465
|
+
:type curvelist: list
|
|
1466
|
+
:returns: curve -- the curve containing the difference of the curves
|
|
1467
|
+
"""
|
|
1468
|
+
|
|
1469
|
+
numcurves = len(curvelist)
|
|
1470
|
+
if numcurves > 1:
|
|
1471
|
+
name = curvelist[0].name
|
|
1472
|
+
sendline = 'curvelist[' + str(0) + ']'
|
|
1473
|
+
for i in range(1, numcurves):
|
|
1474
|
+
name += ' - ' + curvelist[i].name
|
|
1475
|
+
sendline += '- curvelist[' + str(i) + ']'
|
|
1476
|
+
|
|
1477
|
+
c = eval(sendline)
|
|
1478
|
+
c.name = name
|
|
1479
|
+
|
|
1480
|
+
if c.x is None or len(c.x) < 2:
|
|
1481
|
+
print('Error: curve overlap is insufficient')
|
|
1482
|
+
return 0
|
|
1483
|
+
|
|
1484
|
+
return c
|
|
1485
|
+
elif numcurves == 1:
|
|
1486
|
+
return curvelist[0]
|
|
1487
|
+
else:
|
|
1488
|
+
return curvelist
|
|
1489
|
+
|
|
1490
|
+
|
|
1491
|
+
def multiply(curvelist):
|
|
1492
|
+
"""
|
|
1493
|
+
Take product of curves.
|
|
1494
|
+
|
|
1495
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1496
|
+
|
|
1497
|
+
>>> c = pydvif.multiply(curves)
|
|
1498
|
+
|
|
1499
|
+
:param curvelist: The list of curves
|
|
1500
|
+
:type curvelist: list
|
|
1501
|
+
:returns: Curve -- the curve containing the product of the curves
|
|
1502
|
+
"""
|
|
1503
|
+
numcurves = len(curvelist)
|
|
1504
|
+
if numcurves > 1:
|
|
1505
|
+
name = __toCurveString(curvelist[0])
|
|
1506
|
+
sendline = 'curvelist[' + str(0) + ']'
|
|
1507
|
+
for i in range(1, numcurves):
|
|
1508
|
+
name += ' * ' + __toCurveString(curvelist[i])
|
|
1509
|
+
sendline += '* curvelist[' + str(i) + ']'
|
|
1510
|
+
|
|
1511
|
+
c = eval(sendline)
|
|
1512
|
+
c.name = name
|
|
1513
|
+
|
|
1514
|
+
if c.x is None or len(c.x) < 2:
|
|
1515
|
+
print('Error: curve overlap is insufficient')
|
|
1516
|
+
return 0
|
|
1517
|
+
|
|
1518
|
+
return c
|
|
1519
|
+
elif numcurves == 1:
|
|
1520
|
+
return curvelist[0]
|
|
1521
|
+
else:
|
|
1522
|
+
return curvelist
|
|
1523
|
+
|
|
1524
|
+
|
|
1525
|
+
def divide(curvelist):
|
|
1526
|
+
"""
|
|
1527
|
+
Take quotient of curves.
|
|
1528
|
+
|
|
1529
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1530
|
+
|
|
1531
|
+
>>> c = pydvif.divide(curves)
|
|
1532
|
+
|
|
1533
|
+
:param curvelist: The list of curves
|
|
1534
|
+
:type curvelist: list
|
|
1535
|
+
:returns: curve -- the curve containing the quotient of the curves
|
|
1536
|
+
"""
|
|
1537
|
+
numcurves = len(curvelist)
|
|
1538
|
+
if numcurves > 1:
|
|
1539
|
+
name = __toCurveString(curvelist[0])
|
|
1540
|
+
sendline = 'curvelist[' + str(0) + ']'
|
|
1541
|
+
for i in range(1, numcurves):
|
|
1542
|
+
name += ' / ' + __toCurveString(curvelist[i])
|
|
1543
|
+
sendline += '/ curvelist[' + str(i) + ']'
|
|
1544
|
+
|
|
1545
|
+
c = eval(sendline)
|
|
1546
|
+
c.name = name
|
|
1547
|
+
|
|
1548
|
+
if c.x is None or len(c.x) < 2:
|
|
1549
|
+
print('Error: curve overlap is insufficient')
|
|
1550
|
+
return 0
|
|
1551
|
+
|
|
1552
|
+
return c
|
|
1553
|
+
elif numcurves == 1:
|
|
1554
|
+
return curvelist[0]
|
|
1555
|
+
else:
|
|
1556
|
+
return curvelist
|
|
1557
|
+
|
|
1558
|
+
|
|
1559
|
+
def divx(curvelist, value):
|
|
1560
|
+
"""
|
|
1561
|
+
Divide x values of the curve(s) by a constant value.
|
|
1562
|
+
|
|
1563
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1564
|
+
|
|
1565
|
+
>>> pydvif.divx(curves, 4)
|
|
1566
|
+
|
|
1567
|
+
:param curvelist: The curve or curvelist
|
|
1568
|
+
:type curvelist: Curve or list
|
|
1569
|
+
:param value: The divisor
|
|
1570
|
+
:type value: float
|
|
1571
|
+
"""
|
|
1572
|
+
curves = list()
|
|
1573
|
+
|
|
1574
|
+
if isinstance(curvelist, list):
|
|
1575
|
+
curves.extend(curvelist)
|
|
1576
|
+
else:
|
|
1577
|
+
curves.append(curvelist)
|
|
1578
|
+
|
|
1579
|
+
for c in curves:
|
|
1580
|
+
if float(value) == 0:
|
|
1581
|
+
value = 1.e-10
|
|
1582
|
+
c.x /= float(value)
|
|
1583
|
+
|
|
1584
|
+
|
|
1585
|
+
def divy(curvelist, value):
|
|
1586
|
+
"""
|
|
1587
|
+
Divide y values of the curve(s) by a constant value.
|
|
1588
|
+
|
|
1589
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1590
|
+
|
|
1591
|
+
>>> pydvif.divy(curves, 4)
|
|
1592
|
+
|
|
1593
|
+
:param curvelist: The curve or curvelist
|
|
1594
|
+
:type curvelist: Curve or list
|
|
1595
|
+
:param value: The divisor
|
|
1596
|
+
:type value: float
|
|
1597
|
+
"""
|
|
1598
|
+
curves = list()
|
|
1599
|
+
|
|
1600
|
+
if isinstance(curvelist, list):
|
|
1601
|
+
curves.extend(curvelist)
|
|
1602
|
+
else:
|
|
1603
|
+
curves.append(curvelist)
|
|
1604
|
+
|
|
1605
|
+
for c in curves:
|
|
1606
|
+
if float(value) == 0:
|
|
1607
|
+
value = 1.e-10
|
|
1608
|
+
c.y /= float(value)
|
|
1609
|
+
|
|
1610
|
+
|
|
1611
|
+
def dx(curvelist, value):
|
|
1612
|
+
"""
|
|
1613
|
+
Shift x values of a curve or list of curves by a constant value.
|
|
1614
|
+
|
|
1615
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1616
|
+
|
|
1617
|
+
>>> pydvif.dx(curves, 4) OR
|
|
1618
|
+
|
|
1619
|
+
>>> pydvif.dx(curves[0], 4)
|
|
1620
|
+
|
|
1621
|
+
|
|
1622
|
+
:param curvelist: A curve or curvelist
|
|
1623
|
+
:type curvelist: Curve or list
|
|
1624
|
+
:param value: The amount to shift the x values by
|
|
1625
|
+
:type value: float
|
|
1626
|
+
"""
|
|
1627
|
+
curves = list()
|
|
1628
|
+
|
|
1629
|
+
if isinstance(curvelist, list):
|
|
1630
|
+
curves.extend(curvelist)
|
|
1631
|
+
else:
|
|
1632
|
+
curves.append(curvelist)
|
|
1633
|
+
|
|
1634
|
+
for c in curves:
|
|
1635
|
+
c.x += float(value)
|
|
1636
|
+
|
|
1637
|
+
|
|
1638
|
+
def dy(curvelist, value):
|
|
1639
|
+
"""
|
|
1640
|
+
Shift y values of a curve or list of curves by a constant value.
|
|
1641
|
+
|
|
1642
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1643
|
+
|
|
1644
|
+
>>> pydvif.dy(curves, 4) OR
|
|
1645
|
+
|
|
1646
|
+
>>> pydvif.dy(curves[0], 4)
|
|
1647
|
+
|
|
1648
|
+
|
|
1649
|
+
:param curvelist: A curve or curvelist
|
|
1650
|
+
:type curvelist: Curve or list
|
|
1651
|
+
:param value: The amount to shift the y values by
|
|
1652
|
+
:type value: float
|
|
1653
|
+
"""
|
|
1654
|
+
curves = list()
|
|
1655
|
+
|
|
1656
|
+
if isinstance(curvelist, list):
|
|
1657
|
+
curves.extend(curvelist)
|
|
1658
|
+
else:
|
|
1659
|
+
curves.append(curvelist)
|
|
1660
|
+
|
|
1661
|
+
for c in curves:
|
|
1662
|
+
c.y += float(value)
|
|
1663
|
+
|
|
1664
|
+
|
|
1665
|
+
def mx(curvelist, value):
|
|
1666
|
+
"""
|
|
1667
|
+
Scale x values of a curve or list of curves by a constant value.
|
|
1668
|
+
|
|
1669
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1670
|
+
|
|
1671
|
+
>>> pydvif.mx(curves, 4) OR
|
|
1672
|
+
|
|
1673
|
+
>>> pydvif.mx(curves[0], 4)
|
|
1674
|
+
|
|
1675
|
+
|
|
1676
|
+
:param curvelist: A curve or curvelist
|
|
1677
|
+
:type curvelist: Curve or list
|
|
1678
|
+
:param value: The amount to scale the x values by
|
|
1679
|
+
:type value: float
|
|
1680
|
+
"""
|
|
1681
|
+
curves = list()
|
|
1682
|
+
|
|
1683
|
+
if isinstance(curvelist, list):
|
|
1684
|
+
curves.extend(curvelist)
|
|
1685
|
+
else:
|
|
1686
|
+
curves.append(curvelist)
|
|
1687
|
+
|
|
1688
|
+
for c in curves:
|
|
1689
|
+
c.x *= float(value)
|
|
1690
|
+
|
|
1691
|
+
|
|
1692
|
+
def my(curvelist, value):
|
|
1693
|
+
"""
|
|
1694
|
+
Scale y values of a curve or list of curves by a constant value.
|
|
1695
|
+
|
|
1696
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1697
|
+
|
|
1698
|
+
>>> pydvif.my(curves, 4) OR
|
|
1699
|
+
|
|
1700
|
+
>>> pydvif.my(curves[0], 4)
|
|
1701
|
+
|
|
1702
|
+
|
|
1703
|
+
:param curvelist: A curve or curvelist
|
|
1704
|
+
:type curvelist: Curve or list
|
|
1705
|
+
:param value: The amount to scale the y values by
|
|
1706
|
+
:type value: float
|
|
1707
|
+
"""
|
|
1708
|
+
curves = list()
|
|
1709
|
+
|
|
1710
|
+
if isinstance(curvelist, list):
|
|
1711
|
+
curves.extend(curvelist)
|
|
1712
|
+
else:
|
|
1713
|
+
curves.append(curvelist)
|
|
1714
|
+
|
|
1715
|
+
for c in curves:
|
|
1716
|
+
c.y *= float(value)
|
|
1717
|
+
|
|
1718
|
+
|
|
1719
|
+
def l1(c1, c2, xmin=None, xmax=None):
|
|
1720
|
+
"""
|
|
1721
|
+
Make a new curve that is the L1 norm of curve c1 and curve c2.
|
|
1722
|
+
The L1-norm is the integral(\|c1 - c2\|) over the interval [xmin, xmax]. # noqa w605
|
|
1723
|
+
|
|
1724
|
+
>>> c = pydvif.l1(curve1, curve2)
|
|
1725
|
+
|
|
1726
|
+
>>> c2 = pydvif.l1(curve1, curve2, 1.1, 10.9)
|
|
1727
|
+
|
|
1728
|
+
:param c1: The first curve
|
|
1729
|
+
:type c1: Curve
|
|
1730
|
+
:param c2: The second curve
|
|
1731
|
+
:type c2: Curve
|
|
1732
|
+
:param xmin: the minimum x value to perform the L1 norm
|
|
1733
|
+
:type xmin: float
|
|
1734
|
+
:param xmax: the maximum x value to perform the L1 norm
|
|
1735
|
+
:type xmax: float
|
|
1736
|
+
:returns Curve: A new curve that is the L1 norm of c1 and c2
|
|
1737
|
+
"""
|
|
1738
|
+
c = c1 - c2
|
|
1739
|
+
c.y = np.abs(c.y)
|
|
1740
|
+
|
|
1741
|
+
if xmin is not None and xmax is not None:
|
|
1742
|
+
if xmax <= xmin:
|
|
1743
|
+
raise RuntimeError("xmin > xmax or xmin == xmax in l1")
|
|
1744
|
+
else:
|
|
1745
|
+
xmin = np.min(c.x)
|
|
1746
|
+
xmax = np.max(c.x)
|
|
1747
|
+
|
|
1748
|
+
d = integrate(c, xmin, xmax)
|
|
1749
|
+
d[0].name = "L1 of " + __toCurveString(c1) + " and " + __toCurveString(c2)
|
|
1750
|
+
|
|
1751
|
+
return d[0]
|
|
1752
|
+
|
|
1753
|
+
|
|
1754
|
+
def l2(c1, c2, xmin=None, xmax=None):
|
|
1755
|
+
"""
|
|
1756
|
+
Make a new curve that is the L2 norm of curve c1 and curve c2.
|
|
1757
|
+
The L2-norm is (integral((c1 - c2)**2)**(1/2) over the interval [xmin, xmax].
|
|
1758
|
+
|
|
1759
|
+
>>> c = pydvif.l2(curve1, curve2)
|
|
1760
|
+
|
|
1761
|
+
>>> c2 = pydvif.l2(curve1, curve2, 3.1, 30.9)
|
|
1762
|
+
|
|
1763
|
+
:param c1: The first curve
|
|
1764
|
+
:type c1: Curve
|
|
1765
|
+
:param c2: The second curve
|
|
1766
|
+
:type c2: Curve
|
|
1767
|
+
:param xmin: the minimum x value to perform the L2 norm
|
|
1768
|
+
:type xmin: float
|
|
1769
|
+
:param xmax: the maximum x value to perform the L2 norm
|
|
1770
|
+
:type xmax: float
|
|
1771
|
+
:returns Curve: A new curve that is the L2 norm of c1 and c2
|
|
1772
|
+
"""
|
|
1773
|
+
c = c1 - c2
|
|
1774
|
+
c.y = np.abs(c.y)
|
|
1775
|
+
c = c**2.0
|
|
1776
|
+
|
|
1777
|
+
if xmin is not None and xmax is not None:
|
|
1778
|
+
if xmax <= xmin:
|
|
1779
|
+
raise RuntimeError("xmin > xmax or xmin == xmax in l2")
|
|
1780
|
+
else:
|
|
1781
|
+
xmin = np.min(c.x)
|
|
1782
|
+
xmax = np.max(c.x)
|
|
1783
|
+
|
|
1784
|
+
d = integrate(c, xmin, xmax)
|
|
1785
|
+
d[0] = d[0]**(0.5)
|
|
1786
|
+
d[0].name = "L2 of " + __toCurveString(c1) + " and " + __toCurveString(c2)
|
|
1787
|
+
|
|
1788
|
+
return d[0]
|
|
1789
|
+
|
|
1790
|
+
|
|
1791
|
+
def norm(c1, c2, p, xmin=None, xmax=None):
|
|
1792
|
+
"""
|
|
1793
|
+
Make a new curve that is the p-norm of curve c1 and curve c2.
|
|
1794
|
+
|
|
1795
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1796
|
+
|
|
1797
|
+
>>> c = pydvif.norm(curves[0], curves[1], 'inf')
|
|
1798
|
+
|
|
1799
|
+
>>> curves.append(c)
|
|
1800
|
+
|
|
1801
|
+
:param c1: The first curve
|
|
1802
|
+
:type c1: Curve
|
|
1803
|
+
:param c2: The second curve
|
|
1804
|
+
:type c2: Curve
|
|
1805
|
+
:param p: the order (e.g., 'inf', '3', '5')
|
|
1806
|
+
:type p: str
|
|
1807
|
+
:param xmin: the minimum x value to perform the p-norm
|
|
1808
|
+
:type xmin: float
|
|
1809
|
+
:param xmax: the maximum x value to perform the p-norm
|
|
1810
|
+
:type xmax: float
|
|
1811
|
+
:returns Curve: A new curve that is the p-norm of c1 and c2
|
|
1812
|
+
"""
|
|
1813
|
+
c = c1 - c2
|
|
1814
|
+
c.y = np.abs(c.y)
|
|
1815
|
+
|
|
1816
|
+
if p.lower() != "inf":
|
|
1817
|
+
N = int(p)
|
|
1818
|
+
c = c**N
|
|
1819
|
+
|
|
1820
|
+
if xmin is not None and xmax is not None:
|
|
1821
|
+
if xmax <= xmin:
|
|
1822
|
+
raise RuntimeError("xmin > xmax or xmin == xmax in norm")
|
|
1823
|
+
else:
|
|
1824
|
+
xmin = np.min(c.x)
|
|
1825
|
+
xmax = np.max(c.x)
|
|
1826
|
+
|
|
1827
|
+
if p.lower() == "inf":
|
|
1828
|
+
Linf = 0.0
|
|
1829
|
+
for xi, yi in zip(c.x, c.y):
|
|
1830
|
+
if xmin <= xi <= xmax:
|
|
1831
|
+
Linf = max(Linf, yi)
|
|
1832
|
+
d = c
|
|
1833
|
+
d.y = np.array([Linf] * c.y.shape[0])
|
|
1834
|
+
d.name = "Linf of " + __toCurveString(c1) + " and " + __toCurveString(c2)
|
|
1835
|
+
|
|
1836
|
+
return d
|
|
1837
|
+
else:
|
|
1838
|
+
d = integrate(c, xmin, xmax)
|
|
1839
|
+
d[0] = d[0]**(1.0 / N)
|
|
1840
|
+
d[0].name = "L%d of " % N + __toCurveString(c1) + " and " + __toCurveString(c2)
|
|
1841
|
+
|
|
1842
|
+
return d[0]
|
|
1843
|
+
|
|
1844
|
+
|
|
1845
|
+
def abs(curvelist):
|
|
1846
|
+
"""
|
|
1847
|
+
Take the absolute value of the y values of the Curve or list of curves.
|
|
1848
|
+
|
|
1849
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1850
|
+
|
|
1851
|
+
>>> pydvif.abs(curves) OR
|
|
1852
|
+
|
|
1853
|
+
>>> pydvif.abs(curves[0])
|
|
1854
|
+
|
|
1855
|
+
:param curvelist: the Curve or list of curves
|
|
1856
|
+
:type curvelist: Curve or list
|
|
1857
|
+
"""
|
|
1858
|
+
curves = list()
|
|
1859
|
+
|
|
1860
|
+
if isinstance(curvelist, list):
|
|
1861
|
+
curves.extend(curvelist)
|
|
1862
|
+
else:
|
|
1863
|
+
curves.append(curvelist)
|
|
1864
|
+
|
|
1865
|
+
for cur in curves:
|
|
1866
|
+
cur.y = np.abs(cur.y)
|
|
1867
|
+
|
|
1868
|
+
|
|
1869
|
+
def absx(curvelist):
|
|
1870
|
+
"""
|
|
1871
|
+
Take the absolute value of the x values of the Curve or list of curves.
|
|
1872
|
+
|
|
1873
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1874
|
+
|
|
1875
|
+
>>> pydvif.absx(curves) OR
|
|
1876
|
+
|
|
1877
|
+
>>> pydvif.absx(curves[0])
|
|
1878
|
+
|
|
1879
|
+
:param curvelist: the Curve or list of curves
|
|
1880
|
+
:type curvelist: Curve or list
|
|
1881
|
+
"""
|
|
1882
|
+
curves = list()
|
|
1883
|
+
|
|
1884
|
+
if isinstance(curvelist, list):
|
|
1885
|
+
curves.extend(curvelist)
|
|
1886
|
+
else:
|
|
1887
|
+
curves.append(curvelist)
|
|
1888
|
+
|
|
1889
|
+
for cur in curves:
|
|
1890
|
+
cur.x = np.abs(cur.x)
|
|
1891
|
+
|
|
1892
|
+
|
|
1893
|
+
def log(curvelist, keep=True):
|
|
1894
|
+
"""
|
|
1895
|
+
Take the natural logarithm of y values of the Curve or list of curves.
|
|
1896
|
+
|
|
1897
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1898
|
+
|
|
1899
|
+
>>> pydvif.log(curves) OR
|
|
1900
|
+
|
|
1901
|
+
>>> pydvif.log(curves[0])
|
|
1902
|
+
|
|
1903
|
+
:param curvelist: the Curve or list of curves
|
|
1904
|
+
:type curvelist: Curve or list
|
|
1905
|
+
:param keep: flag to determine whether or not to discard zero or negative y-values before taking the log.
|
|
1906
|
+
keep is True by default.
|
|
1907
|
+
:type keep: optional, boolean
|
|
1908
|
+
"""
|
|
1909
|
+
curves = list()
|
|
1910
|
+
|
|
1911
|
+
if isinstance(curvelist, list):
|
|
1912
|
+
curves.extend(curvelist)
|
|
1913
|
+
else:
|
|
1914
|
+
curves.append(curvelist)
|
|
1915
|
+
|
|
1916
|
+
for c in curves:
|
|
1917
|
+
if not keep:
|
|
1918
|
+
skiplist = np.where(c.y <= 0)[0]
|
|
1919
|
+
if len(skiplist) > 0:
|
|
1920
|
+
c.y = np.delete(c.y, skiplist)
|
|
1921
|
+
c.x = np.delete(c.x, skiplist)
|
|
1922
|
+
|
|
1923
|
+
c.y = np.log(c.y)
|
|
1924
|
+
if c.name[:3] == 'exp':
|
|
1925
|
+
c.name = c.name[4:-1] # Pop off the exp( from the front and the ) from the back
|
|
1926
|
+
else:
|
|
1927
|
+
c.name = 'log(' + c.name + ')'
|
|
1928
|
+
|
|
1929
|
+
|
|
1930
|
+
def logx(curvelist, keep=True):
|
|
1931
|
+
"""
|
|
1932
|
+
Take the natural logarithm of x values of the Curve or list of curves.
|
|
1933
|
+
|
|
1934
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1935
|
+
|
|
1936
|
+
>>> pydvif.logx(curves) OR
|
|
1937
|
+
|
|
1938
|
+
>>> pydvif.logx(curves[0])
|
|
1939
|
+
|
|
1940
|
+
:param curvelist: the Curve or list of curves
|
|
1941
|
+
:type curvelist: Curve or list
|
|
1942
|
+
:param keep: flag to determine whether or not to discard zero or negative x-values before taking the log.
|
|
1943
|
+
keep is True by default.
|
|
1944
|
+
:type keep: optional, boolean
|
|
1945
|
+
"""
|
|
1946
|
+
curves = list()
|
|
1947
|
+
|
|
1948
|
+
if isinstance(curvelist, list):
|
|
1949
|
+
curves.extend(curvelist)
|
|
1950
|
+
else:
|
|
1951
|
+
curves.append(curvelist)
|
|
1952
|
+
|
|
1953
|
+
for c in curves:
|
|
1954
|
+
if not keep:
|
|
1955
|
+
skiplist = np.where(c.x <= 0)[0]
|
|
1956
|
+
if len(skiplist) > 0:
|
|
1957
|
+
c.y = np.delete(c.y, skiplist)
|
|
1958
|
+
c.x = np.delete(c.x, skiplist)
|
|
1959
|
+
|
|
1960
|
+
c.x = np.log(c.x)
|
|
1961
|
+
if c.name[:4] == 'expx':
|
|
1962
|
+
c.name = c.name[5:-1] # Pop off the expx( from the front and the ) from the back
|
|
1963
|
+
else:
|
|
1964
|
+
c.name = 'logx(' + c.name + ')'
|
|
1965
|
+
|
|
1966
|
+
|
|
1967
|
+
def log10(curvelist, keep=True):
|
|
1968
|
+
"""
|
|
1969
|
+
Take the base 10 logarithm of y values of a Curve or list of curves.
|
|
1970
|
+
|
|
1971
|
+
>>> curves = pydvif.read('testData.txt')
|
|
1972
|
+
|
|
1973
|
+
>>> pydvif.log10(curves) OR
|
|
1974
|
+
|
|
1975
|
+
>>> pydvif.log10(curves[0])
|
|
1976
|
+
|
|
1977
|
+
:param curvelist: the Curve or list of curves
|
|
1978
|
+
:type curvelist: Curve or list
|
|
1979
|
+
:param keep: flag to determine whether or not to discard zero
|
|
1980
|
+
or negative y-values before taking the base 10 logarithm.
|
|
1981
|
+
keep is True by default.
|
|
1982
|
+
:type keep: optional, boolean
|
|
1983
|
+
"""
|
|
1984
|
+
curves = list()
|
|
1985
|
+
|
|
1986
|
+
if isinstance(curvelist, list):
|
|
1987
|
+
curves.extend(curvelist)
|
|
1988
|
+
else:
|
|
1989
|
+
curves.append(curvelist)
|
|
1990
|
+
|
|
1991
|
+
for c in curves:
|
|
1992
|
+
if not keep:
|
|
1993
|
+
skiplist = np.where(c.y <= 0)[0]
|
|
1994
|
+
if len(skiplist) > 0:
|
|
1995
|
+
c.y = np.delete(c.y, skiplist)
|
|
1996
|
+
c.x = np.delete(c.x, skiplist)
|
|
1997
|
+
|
|
1998
|
+
c.y = np.log10(c.y)
|
|
1999
|
+
c.name = 'log10(' + c.name + ')'
|
|
2000
|
+
|
|
2001
|
+
|
|
2002
|
+
def log10x(curvelist, keep=True):
|
|
2003
|
+
"""
|
|
2004
|
+
Take the base 10 logarithm of x values of a Curve or list of curves.
|
|
2005
|
+
|
|
2006
|
+
>>> curves = pydvif.read('testData.txt')
|
|
2007
|
+
|
|
2008
|
+
>>> pydvif.log10x(curves) OR
|
|
2009
|
+
|
|
2010
|
+
>>> pydvif.log10x(curves[0])
|
|
2011
|
+
|
|
2012
|
+
:param curvelist: the Curve or list of curves
|
|
2013
|
+
:type curvelist: Curve or list
|
|
2014
|
+
:param keep: flag to determine whether or not to discard zero
|
|
2015
|
+
or negative y-values before taking the base 10 logarithm.
|
|
2016
|
+
keep is True by default.
|
|
2017
|
+
:type keep: optional, boolean
|
|
2018
|
+
"""
|
|
2019
|
+
curves = list()
|
|
2020
|
+
|
|
2021
|
+
if isinstance(curvelist, list):
|
|
2022
|
+
curves.extend(curvelist)
|
|
2023
|
+
else:
|
|
2024
|
+
curves.append(curvelist)
|
|
2025
|
+
|
|
2026
|
+
for c in curves:
|
|
2027
|
+
if not keep:
|
|
2028
|
+
skiplist = np.where(c.x <= 0)[0]
|
|
2029
|
+
if len(skiplist) > 0:
|
|
2030
|
+
c.y = np.delete(c.y, skiplist)
|
|
2031
|
+
c.x = np.delete(c.x, skiplist)
|
|
2032
|
+
|
|
2033
|
+
c.x = np.log10(c.x)
|
|
2034
|
+
c.name = 'log10x(' + c.name + ')'
|
|
2035
|
+
|
|
2036
|
+
|
|
2037
|
+
def exp(curvelist):
|
|
2038
|
+
"""
|
|
2039
|
+
Exponentiate y values of the Curve or list of curves (e**y).
|
|
2040
|
+
|
|
2041
|
+
>>> curves = pydvif.read('testData.txt')
|
|
2042
|
+
|
|
2043
|
+
>>> pydvif.exp(curves) OR
|
|
2044
|
+
|
|
2045
|
+
>>> pydvif.exp(curves[0])
|
|
2046
|
+
|
|
2047
|
+
:param curvelist: the Curve or list of curves
|
|
2048
|
+
:type curvelist: Curve or list
|
|
2049
|
+
"""
|
|
2050
|
+
curves = list()
|
|
2051
|
+
|
|
2052
|
+
if isinstance(curvelist, list):
|
|
2053
|
+
curves.extend(curvelist)
|
|
2054
|
+
else:
|
|
2055
|
+
curves.append(curvelist)
|
|
2056
|
+
|
|
2057
|
+
for cur in curves:
|
|
2058
|
+
cur.y = np.exp(cur.y)
|
|
2059
|
+
|
|
2060
|
+
|
|
2061
|
+
def expx(curvelist):
|
|
2062
|
+
"""
|
|
2063
|
+
Exponentiate x values of the Curve or list of curves (e**x).
|
|
2064
|
+
|
|
2065
|
+
>>> curves = pydvif.read('testData.txt')
|
|
2066
|
+
|
|
2067
|
+
>>> pydvif.expx(curves) OR
|
|
2068
|
+
|
|
2069
|
+
>>> pydvif.expx(curves[0])
|
|
2070
|
+
|
|
2071
|
+
:param curvelist: the Curve or list of curves
|
|
2072
|
+
:type curvelist: Curve or list
|
|
2073
|
+
"""
|
|
2074
|
+
curves = list()
|
|
2075
|
+
|
|
2076
|
+
if isinstance(curvelist, list):
|
|
2077
|
+
curves.extend(curvelist)
|
|
2078
|
+
else:
|
|
2079
|
+
curves.append(curvelist)
|
|
2080
|
+
|
|
2081
|
+
for cur in curves:
|
|
2082
|
+
cur.x = np.exp(cur.x)
|
|
2083
|
+
|
|
2084
|
+
|
|
2085
|
+
def powa(curvelist, a):
|
|
2086
|
+
"""
|
|
2087
|
+
Raise a fixed value, a, to the power of the y values of the Curve or list of curves. y = a^y
|
|
2088
|
+
|
|
2089
|
+
>>> curves = pydvif.read('testData.txt')
|
|
2090
|
+
|
|
2091
|
+
>>> pydvif.powa(curves, 2) OR
|
|
2092
|
+
|
|
2093
|
+
>>> pydvif.powa(curves[0], 2)
|
|
2094
|
+
|
|
2095
|
+
:param curvelist: the Curve or list of curves
|
|
2096
|
+
:type curvelist: Curve or list
|
|
2097
|
+
:param a: the fixed value
|
|
2098
|
+
:type a: float
|
|
2099
|
+
"""
|
|
2100
|
+
curves = list()
|
|
2101
|
+
|
|
2102
|
+
if isinstance(curvelist, list):
|
|
2103
|
+
curves.extend(curvelist)
|
|
2104
|
+
else:
|
|
2105
|
+
curves.append(curvelist)
|
|
2106
|
+
|
|
2107
|
+
for cur in curves:
|
|
2108
|
+
cur.y = np.power(float(a), cur.y)
|
|
2109
|
+
|
|
2110
|
+
|
|
2111
|
+
def powax(curvelist, a):
|
|
2112
|
+
"""
|
|
2113
|
+
Raise a fixed value, a, to the power of the x values of the Curve or curves. x = a^x
|
|
2114
|
+
|
|
2115
|
+
>>> curves = pydvif.read('testData.txt')
|
|
2116
|
+
|
|
2117
|
+
>>> pydvif.powax(curves, 4.2) OR
|
|
2118
|
+
|
|
2119
|
+
>>> pydvif.powax(curves[0], 4.2)
|
|
2120
|
+
|
|
2121
|
+
:param curvelist: the Curve or list of curves
|
|
2122
|
+
:type curvelist: Curve or list
|
|
2123
|
+
:param a: the fixed value
|
|
2124
|
+
:type a: float
|
|
2125
|
+
"""
|
|
2126
|
+
curves = list()
|
|
2127
|
+
|
|
2128
|
+
if isinstance(curvelist, list):
|
|
2129
|
+
curves.extend(curvelist)
|
|
2130
|
+
else:
|
|
2131
|
+
curves.append(curvelist)
|
|
2132
|
+
|
|
2133
|
+
for cur in curves:
|
|
2134
|
+
cur.x = np.power(float(a), cur.x)
|
|
2135
|
+
|
|
2136
|
+
|
|
2137
|
+
def powr(curvelist, a):
|
|
2138
|
+
"""
|
|
2139
|
+
Raise a the y values of a curve or list of curves to a fixed power, y = y^a.
|
|
2140
|
+
|
|
2141
|
+
>>> curves = pydvif.read('testData.txt')
|
|
2142
|
+
|
|
2143
|
+
>>> pydvif.powr(curves, 4.2) OR
|
|
2144
|
+
|
|
2145
|
+
>>> pydvif.powr(curves[0], 4.2)
|
|
2146
|
+
|
|
2147
|
+
:param curvelist: the curve or list of curves
|
|
2148
|
+
:type curvelist: curve or list
|
|
2149
|
+
:param a: the fixed value
|
|
2150
|
+
:type a: float
|
|
2151
|
+
"""
|
|
2152
|
+
if isinstance(curvelist, list):
|
|
2153
|
+
for c in curvelist:
|
|
2154
|
+
c.y = np.power(c.y, float(a))
|
|
2155
|
+
else:
|
|
2156
|
+
curvelist.y = np.power(curvelist.y, float(a))
|
|
2157
|
+
|
|
2158
|
+
|
|
2159
|
+
def powrx(curvelist, a):
|
|
2160
|
+
"""
|
|
2161
|
+
Raise a the x values of a curve or list of curves to a fixed power, x = x^a.
|
|
2162
|
+
|
|
2163
|
+
>>> curves = pydvif.read('testData.txt')
|
|
2164
|
+
|
|
2165
|
+
>>> pydvif.powrx(curves, 4.2) OR
|
|
2166
|
+
|
|
2167
|
+
>>> pydvif.powrx(curves[0], 4.2)
|
|
2168
|
+
|
|
2169
|
+
:param curvelist: the curve or list of curves
|
|
2170
|
+
:type curvelist: curve or list
|
|
2171
|
+
:param a: the fixed value
|
|
2172
|
+
:type a: float
|
|
2173
|
+
"""
|
|
2174
|
+
|
|
2175
|
+
if isinstance(curvelist, list):
|
|
2176
|
+
for c in curvelist:
|
|
2177
|
+
c.x = np.power(c.x, float(a))
|
|
2178
|
+
else:
|
|
2179
|
+
curvelist.x = np.power(curvelist.x, float(a))
|
|
2180
|
+
|
|
2181
|
+
|
|
2182
|
+
def sqr(curvelist):
|
|
2183
|
+
"""
|
|
2184
|
+
Take the square of the y values in a curve or list of curves.
|
|
2185
|
+
|
|
2186
|
+
:param curvelist: the curve or list of curves
|
|
2187
|
+
:type curvelist: curve or list
|
|
2188
|
+
"""
|
|
2189
|
+
|
|
2190
|
+
if isinstance(curvelist, list):
|
|
2191
|
+
for c in curvelist:
|
|
2192
|
+
c.y = np.square(c.y)
|
|
2193
|
+
else:
|
|
2194
|
+
curvelist.y = np.square(curvelist.y)
|
|
2195
|
+
|
|
2196
|
+
|
|
2197
|
+
def sqrx(curvelist):
|
|
2198
|
+
"""
|
|
2199
|
+
Take the square of the x values in a curve or list of curves.
|
|
2200
|
+
|
|
2201
|
+
:param curvelist: the curve or list of curves
|
|
2202
|
+
:type curvelist: curve or list
|
|
2203
|
+
"""
|
|
2204
|
+
|
|
2205
|
+
if isinstance(curvelist, list):
|
|
2206
|
+
for c in curvelist:
|
|
2207
|
+
c.x = np.square(c.x)
|
|
2208
|
+
else:
|
|
2209
|
+
curvelist.x = np.square(curvelist.x)
|
|
2210
|
+
|
|
2211
|
+
|
|
2212
|
+
def sqrt(curvelist):
|
|
2213
|
+
"""
|
|
2214
|
+
Take the square root of the y values in a curve or list of curves.
|
|
2215
|
+
|
|
2216
|
+
:param curvelist: the curve or list of curves
|
|
2217
|
+
:type curvelist: curve or list
|
|
2218
|
+
"""
|
|
2219
|
+
|
|
2220
|
+
if isinstance(curvelist, list):
|
|
2221
|
+
for c in curvelist:
|
|
2222
|
+
c.y = np.sqrt(c.y)
|
|
2223
|
+
else:
|
|
2224
|
+
curvelist.y = np.sqrt(curvelist.y)
|
|
2225
|
+
|
|
2226
|
+
|
|
2227
|
+
def sqrtx(curvelist):
|
|
2228
|
+
"""
|
|
2229
|
+
Take the square root of the x values in a curve or list of curves.
|
|
2230
|
+
|
|
2231
|
+
:param curvelist: the curve or list of curves
|
|
2232
|
+
:type curvelist: curve or list
|
|
2233
|
+
"""
|
|
2234
|
+
|
|
2235
|
+
if isinstance(curvelist, list):
|
|
2236
|
+
for c in curvelist:
|
|
2237
|
+
c.x = np.sqrt(c.x)
|
|
2238
|
+
else:
|
|
2239
|
+
curvelist.x = np.sqrt(curvelist.x)
|
|
2240
|
+
|
|
2241
|
+
|
|
2242
|
+
def xmax(curvelist, limit):
|
|
2243
|
+
"""
|
|
2244
|
+
Filter out points in the curve or list of curves whose x values are greater than limit.
|
|
2245
|
+
|
|
2246
|
+
:param curvelist: The curve or list of curves
|
|
2247
|
+
:type curvelist: curve or list
|
|
2248
|
+
:param limit: The maximum value
|
|
2249
|
+
:type limit: float
|
|
2250
|
+
"""
|
|
2251
|
+
|
|
2252
|
+
curves = list()
|
|
2253
|
+
|
|
2254
|
+
if isinstance(curvelist, list):
|
|
2255
|
+
curves = curvelist
|
|
2256
|
+
else:
|
|
2257
|
+
curves.append(curvelist)
|
|
2258
|
+
|
|
2259
|
+
for c in curves:
|
|
2260
|
+
nx = []
|
|
2261
|
+
ny = []
|
|
2262
|
+
|
|
2263
|
+
for i in range(len(c.x)):
|
|
2264
|
+
if c.x[i] <= float(limit):
|
|
2265
|
+
nx.append(c.x[i])
|
|
2266
|
+
ny.append(c.y[i])
|
|
2267
|
+
|
|
2268
|
+
c.x = np.array(nx)
|
|
2269
|
+
c.y = np.array(ny)
|
|
2270
|
+
|
|
2271
|
+
|
|
2272
|
+
def xmin(curvelist, min):
|
|
2273
|
+
"""
|
|
2274
|
+
Filter out points in the curve or list of curves whose x values are less than min.
|
|
2275
|
+
|
|
2276
|
+
:param curvelist: The curve or list of curves
|
|
2277
|
+
:type curvelist: curve or list
|
|
2278
|
+
:param min: The minimum value
|
|
2279
|
+
:type min: float
|
|
2280
|
+
"""
|
|
2281
|
+
|
|
2282
|
+
curves = list()
|
|
2283
|
+
|
|
2284
|
+
if isinstance(curvelist, list):
|
|
2285
|
+
curves = curvelist
|
|
2286
|
+
else:
|
|
2287
|
+
curves.append(curvelist)
|
|
2288
|
+
|
|
2289
|
+
for c in curves:
|
|
2290
|
+
nx = []
|
|
2291
|
+
ny = []
|
|
2292
|
+
|
|
2293
|
+
for i in range(len(c.x)):
|
|
2294
|
+
if c.x[i] >= float(min):
|
|
2295
|
+
nx.append(c.x[i])
|
|
2296
|
+
ny.append(c.y[i])
|
|
2297
|
+
|
|
2298
|
+
c.x = np.array(nx)
|
|
2299
|
+
c.y = np.array(ny)
|
|
2300
|
+
|
|
2301
|
+
|
|
2302
|
+
def xminmax(curvelist, min, max):
|
|
2303
|
+
"""
|
|
2304
|
+
Filter out points in the curve or list of curves whose x values are
|
|
2305
|
+
less than min or greater than max.
|
|
2306
|
+
|
|
2307
|
+
:param curvelist: The curve or list of curves
|
|
2308
|
+
:type curvelist: curve or list
|
|
2309
|
+
:param min: The minimum value
|
|
2310
|
+
:type min: float
|
|
2311
|
+
:param max: The maximum value
|
|
2312
|
+
:type max: float
|
|
2313
|
+
"""
|
|
2314
|
+
curves = list()
|
|
2315
|
+
|
|
2316
|
+
if isinstance(curvelist, list):
|
|
2317
|
+
curves = curvelist
|
|
2318
|
+
else:
|
|
2319
|
+
curves.append(curvelist)
|
|
2320
|
+
|
|
2321
|
+
for c in curves:
|
|
2322
|
+
nx = []
|
|
2323
|
+
ny = []
|
|
2324
|
+
|
|
2325
|
+
for i in range(len(c.x)):
|
|
2326
|
+
if float(min) <= c.x[i] <= float(max):
|
|
2327
|
+
nx.append(c.x[i])
|
|
2328
|
+
ny.append(c.y[i])
|
|
2329
|
+
|
|
2330
|
+
c.x = np.array(nx)
|
|
2331
|
+
c.y = np.array(ny)
|
|
2332
|
+
|
|
2333
|
+
|
|
2334
|
+
def ymax(curvelist, max):
|
|
2335
|
+
"""
|
|
2336
|
+
Filter out points in the curve or list of curves whose y values are greater than limit.
|
|
2337
|
+
|
|
2338
|
+
:param curvelist: The curve or list of curves
|
|
2339
|
+
:type curvelist: curve or list
|
|
2340
|
+
:param max: The maximum value
|
|
2341
|
+
:type max: float
|
|
2342
|
+
"""
|
|
2343
|
+
|
|
2344
|
+
curves = list()
|
|
2345
|
+
|
|
2346
|
+
if isinstance(curvelist, list):
|
|
2347
|
+
curves = curvelist
|
|
2348
|
+
else:
|
|
2349
|
+
curves.append(curvelist)
|
|
2350
|
+
|
|
2351
|
+
for c in curves:
|
|
2352
|
+
nx = []
|
|
2353
|
+
ny = []
|
|
2354
|
+
|
|
2355
|
+
for i in range(len(c.y)):
|
|
2356
|
+
if c.y[i] <= float(max):
|
|
2357
|
+
nx.append(c.x[i])
|
|
2358
|
+
ny.append(c.y[i])
|
|
2359
|
+
|
|
2360
|
+
c.x = np.array(nx)
|
|
2361
|
+
c.y = np.array(ny)
|
|
2362
|
+
|
|
2363
|
+
|
|
2364
|
+
def ymin(curvelist, min):
|
|
2365
|
+
"""
|
|
2366
|
+
Filter out points in the curve or list of curves whose y values are less than min.
|
|
2367
|
+
|
|
2368
|
+
:param curvelist: The curve or list of curves
|
|
2369
|
+
:type curvelist: curve or list
|
|
2370
|
+
:param min: The minimum value
|
|
2371
|
+
:type min: float
|
|
2372
|
+
"""
|
|
2373
|
+
|
|
2374
|
+
curves = list()
|
|
2375
|
+
|
|
2376
|
+
if isinstance(curvelist, list):
|
|
2377
|
+
curves = curvelist
|
|
2378
|
+
else:
|
|
2379
|
+
curves.append(curvelist)
|
|
2380
|
+
|
|
2381
|
+
for c in curves:
|
|
2382
|
+
nx = []
|
|
2383
|
+
ny = []
|
|
2384
|
+
|
|
2385
|
+
for i in range(len(c.y)):
|
|
2386
|
+
if c.y[i] >= float(min):
|
|
2387
|
+
nx.append(c.x[i])
|
|
2388
|
+
ny.append(c.y[i])
|
|
2389
|
+
|
|
2390
|
+
c.x = np.array(nx)
|
|
2391
|
+
c.y = np.array(ny)
|
|
2392
|
+
|
|
2393
|
+
|
|
2394
|
+
def yminmax(curvelist, min, max):
|
|
2395
|
+
"""
|
|
2396
|
+
Filter out points in the curve or list of curves whose y values are
|
|
2397
|
+
less than min or greater than max.
|
|
2398
|
+
|
|
2399
|
+
:param curvelist: The curve or list of curves
|
|
2400
|
+
:type curvelist: curve or list
|
|
2401
|
+
:param min: The minimum value
|
|
2402
|
+
:type min: float
|
|
2403
|
+
:param max: The maximum value
|
|
2404
|
+
:type max: float
|
|
2405
|
+
"""
|
|
2406
|
+
curves = list()
|
|
2407
|
+
|
|
2408
|
+
if isinstance(curvelist, list):
|
|
2409
|
+
curves.extend(curvelist)
|
|
2410
|
+
else:
|
|
2411
|
+
curves.append(curvelist)
|
|
2412
|
+
|
|
2413
|
+
for c in curves:
|
|
2414
|
+
nx = []
|
|
2415
|
+
ny = []
|
|
2416
|
+
|
|
2417
|
+
for i in range(len(c.y)):
|
|
2418
|
+
if float(min) <= c.y[i] <= float(max):
|
|
2419
|
+
nx.append(c.x[i])
|
|
2420
|
+
ny.append(c.y[i])
|
|
2421
|
+
|
|
2422
|
+
c.x = np.array(nx)
|
|
2423
|
+
c.y = np.array(ny)
|
|
2424
|
+
|
|
2425
|
+
|
|
2426
|
+
def yn(curvelist, n):
|
|
2427
|
+
"""
|
|
2428
|
+
Take the Bessel function of the second kind of order n for the y values of
|
|
2429
|
+
curves in curvelist.
|
|
2430
|
+
|
|
2431
|
+
:param curvelist: The curve or list of curves
|
|
2432
|
+
:type curvelist: curve or list
|
|
2433
|
+
:param n: The order
|
|
2434
|
+
:type n: int
|
|
2435
|
+
"""
|
|
2436
|
+
# scipy.special.errprint(1)
|
|
2437
|
+
curves = list()
|
|
2438
|
+
|
|
2439
|
+
if isinstance(curvelist, list):
|
|
2440
|
+
curves.extend(curvelist)
|
|
2441
|
+
else:
|
|
2442
|
+
curves.append(curvelist)
|
|
2443
|
+
|
|
2444
|
+
for c in curves:
|
|
2445
|
+
c.y = scipy.special.yn(int(n), c.y)
|
|
2446
|
+
|
|
2447
|
+
|
|
2448
|
+
def ynx(curvelist, n):
|
|
2449
|
+
"""
|
|
2450
|
+
Take the Bessel function of the second kind of order n for the x values of
|
|
2451
|
+
curves in curvelist.
|
|
2452
|
+
|
|
2453
|
+
:param curvelist: The curve or list of curves
|
|
2454
|
+
:type curvelist: curve or list
|
|
2455
|
+
:param n: The order
|
|
2456
|
+
:type n: int
|
|
2457
|
+
"""
|
|
2458
|
+
# scipy.special.errprint(1)
|
|
2459
|
+
curves = list()
|
|
2460
|
+
|
|
2461
|
+
if isinstance(curvelist, list):
|
|
2462
|
+
curves.extend(curvelist)
|
|
2463
|
+
else:
|
|
2464
|
+
curves.append(curvelist)
|
|
2465
|
+
|
|
2466
|
+
for c in curves:
|
|
2467
|
+
c.x = scipy.special.yn(int(n), c.x)
|
|
2468
|
+
|
|
2469
|
+
|
|
2470
|
+
def y0(curvelist):
|
|
2471
|
+
"""
|
|
2472
|
+
Take the Bessel function of the second kind of the zeroth order for the y values of
|
|
2473
|
+
curves in curvelist.
|
|
2474
|
+
|
|
2475
|
+
:param curvelist: The curve or list of curves
|
|
2476
|
+
:type curvelist: curve or list
|
|
2477
|
+
"""
|
|
2478
|
+
# scipy.special.errprint(1)
|
|
2479
|
+
curves = list()
|
|
2480
|
+
|
|
2481
|
+
if isinstance(curvelist, list):
|
|
2482
|
+
curves.extend(curvelist)
|
|
2483
|
+
else:
|
|
2484
|
+
curves.append(curvelist)
|
|
2485
|
+
|
|
2486
|
+
for c in curves:
|
|
2487
|
+
c.y = scipy.special.y0(c.y)
|
|
2488
|
+
|
|
2489
|
+
|
|
2490
|
+
def y0x(curvelist):
|
|
2491
|
+
"""
|
|
2492
|
+
Take the Bessel function of the second kind of the zeroth order for the x values of
|
|
2493
|
+
curves in curvelist.
|
|
2494
|
+
|
|
2495
|
+
:param curvelist: The curve or list of curves
|
|
2496
|
+
:type curvelist: curve or list
|
|
2497
|
+
"""
|
|
2498
|
+
# scipy.special.errprint(1)
|
|
2499
|
+
curves = list()
|
|
2500
|
+
|
|
2501
|
+
if isinstance(curvelist, list):
|
|
2502
|
+
curves.extend(curvelist)
|
|
2503
|
+
else:
|
|
2504
|
+
curves.append(curvelist)
|
|
2505
|
+
|
|
2506
|
+
for c in curves:
|
|
2507
|
+
c.x = scipy.special.y0(c.x)
|
|
2508
|
+
|
|
2509
|
+
|
|
2510
|
+
def y1(curvelist):
|
|
2511
|
+
"""
|
|
2512
|
+
Take the Bessel function of the second kind of the first order for the y values of
|
|
2513
|
+
curves in curvelist.
|
|
2514
|
+
|
|
2515
|
+
:param curvelist: The curve or list of curves
|
|
2516
|
+
:type curvelist: curve or list
|
|
2517
|
+
"""
|
|
2518
|
+
# scipy.special.errprint(1)
|
|
2519
|
+
curves = list()
|
|
2520
|
+
|
|
2521
|
+
if isinstance(curvelist, list):
|
|
2522
|
+
curves.extend(curvelist)
|
|
2523
|
+
else:
|
|
2524
|
+
curves.append(curvelist)
|
|
2525
|
+
|
|
2526
|
+
for c in curves:
|
|
2527
|
+
c.y = scipy.special.y1(c.y)
|
|
2528
|
+
|
|
2529
|
+
|
|
2530
|
+
def y1x(curvelist):
|
|
2531
|
+
"""
|
|
2532
|
+
Take the Bessel function of the second kind of the first order for the x values of
|
|
2533
|
+
curves in curvelist.
|
|
2534
|
+
|
|
2535
|
+
:param curvelist: The curve or list of curves
|
|
2536
|
+
:type curvelist: curve or list
|
|
2537
|
+
"""
|
|
2538
|
+
# scipy.special.errprint(1)
|
|
2539
|
+
curves = list()
|
|
2540
|
+
|
|
2541
|
+
if isinstance(curvelist, list):
|
|
2542
|
+
curves.extend(curvelist)
|
|
2543
|
+
else:
|
|
2544
|
+
curves.append(curvelist)
|
|
2545
|
+
|
|
2546
|
+
for c in curves:
|
|
2547
|
+
c.x = scipy.special.y1(c.x)
|
|
2548
|
+
|
|
2549
|
+
|
|
2550
|
+
def jn(curvelist, n):
|
|
2551
|
+
"""
|
|
2552
|
+
Take the Bessel function of the first kind of the nth order for the y values of
|
|
2553
|
+
curves in curvelist.
|
|
2554
|
+
|
|
2555
|
+
:param curvelist: The curve or list of curves
|
|
2556
|
+
:type curvelist: curve or list
|
|
2557
|
+
:param n: The order
|
|
2558
|
+
:type n: float
|
|
2559
|
+
"""
|
|
2560
|
+
# scipy.special.errprint(1)
|
|
2561
|
+
curves = list()
|
|
2562
|
+
|
|
2563
|
+
if isinstance(curvelist, list):
|
|
2564
|
+
curves.extend(curvelist)
|
|
2565
|
+
else:
|
|
2566
|
+
curves.append(curvelist)
|
|
2567
|
+
|
|
2568
|
+
for c in curves:
|
|
2569
|
+
c.y = scipy.special.jn(float(n), c.y)
|
|
2570
|
+
|
|
2571
|
+
|
|
2572
|
+
def jnx(curvelist, n):
|
|
2573
|
+
"""
|
|
2574
|
+
Take the Bessel function of the first kind of the nth order for the x values of
|
|
2575
|
+
curves in curvelist.
|
|
2576
|
+
|
|
2577
|
+
:param curvelist: The curve or list of curves
|
|
2578
|
+
:type curvelist: curve or list
|
|
2579
|
+
:param n: The order
|
|
2580
|
+
:type n: float
|
|
2581
|
+
"""
|
|
2582
|
+
# scipy.special.errprint(1)
|
|
2583
|
+
curves = list()
|
|
2584
|
+
|
|
2585
|
+
if isinstance(curvelist, list):
|
|
2586
|
+
curves.extend(curvelist)
|
|
2587
|
+
else:
|
|
2588
|
+
curves.append(curvelist)
|
|
2589
|
+
|
|
2590
|
+
for c in curves:
|
|
2591
|
+
c.x = scipy.special.jn(int(n), c.x)
|
|
2592
|
+
|
|
2593
|
+
|
|
2594
|
+
def j0(curvelist):
|
|
2595
|
+
"""
|
|
2596
|
+
Take the Bessel function of the first kind of the zeroth order for the y values of
|
|
2597
|
+
curves in curvelist.
|
|
2598
|
+
|
|
2599
|
+
:param curvelist: The curve or list of curves
|
|
2600
|
+
:type curvelist: curve or list
|
|
2601
|
+
"""
|
|
2602
|
+
# scipy.special.errprint(1)
|
|
2603
|
+
curves = list()
|
|
2604
|
+
|
|
2605
|
+
if isinstance(curvelist, list):
|
|
2606
|
+
curves.extend(curvelist)
|
|
2607
|
+
else:
|
|
2608
|
+
curves.append(curvelist)
|
|
2609
|
+
|
|
2610
|
+
for c in curves:
|
|
2611
|
+
c.y = scipy.special.j0(c.y)
|
|
2612
|
+
|
|
2613
|
+
|
|
2614
|
+
def j0x(curvelist):
|
|
2615
|
+
"""
|
|
2616
|
+
Take the Bessel function of the first kind of the zeroth order for the x values of
|
|
2617
|
+
curves in curvelist.
|
|
2618
|
+
|
|
2619
|
+
:param curvelist: The curve or list of curves
|
|
2620
|
+
:type curvelist: curve or list
|
|
2621
|
+
"""
|
|
2622
|
+
# scipy.special.errprint(1)
|
|
2623
|
+
curves = list()
|
|
2624
|
+
|
|
2625
|
+
if isinstance(curvelist, list):
|
|
2626
|
+
curves.extend(curvelist)
|
|
2627
|
+
else:
|
|
2628
|
+
curves.append(curvelist)
|
|
2629
|
+
|
|
2630
|
+
for c in curves:
|
|
2631
|
+
c.x = scipy.special.j0(c.x)
|
|
2632
|
+
|
|
2633
|
+
|
|
2634
|
+
def j1(curvelist):
|
|
2635
|
+
"""
|
|
2636
|
+
Take the Bessel function of the first kind of the first order for the y values of
|
|
2637
|
+
curves in curvelist.
|
|
2638
|
+
|
|
2639
|
+
:param curvelist: The curve or list of curves
|
|
2640
|
+
:type curvelist: curve or list
|
|
2641
|
+
"""
|
|
2642
|
+
# scipy.special.errprint(1)
|
|
2643
|
+
curves = list()
|
|
2644
|
+
|
|
2645
|
+
if isinstance(curvelist, list):
|
|
2646
|
+
curves.extend(curvelist)
|
|
2647
|
+
else:
|
|
2648
|
+
curves.append(curvelist)
|
|
2649
|
+
|
|
2650
|
+
for c in curves:
|
|
2651
|
+
c.y = scipy.special.j1(c.y)
|
|
2652
|
+
|
|
2653
|
+
|
|
2654
|
+
def j1x(curvelist):
|
|
2655
|
+
"""
|
|
2656
|
+
Take the Bessel function of the first kind of the first order for the x values of
|
|
2657
|
+
curves in curvelist.
|
|
2658
|
+
|
|
2659
|
+
:param curvelist: The curve or list of curves
|
|
2660
|
+
:type curvelist: curve or list
|
|
2661
|
+
"""
|
|
2662
|
+
# scipy.special.errprint(1)
|
|
2663
|
+
curves = list()
|
|
2664
|
+
|
|
2665
|
+
if isinstance(curvelist, list):
|
|
2666
|
+
curves.extend(curvelist)
|
|
2667
|
+
else:
|
|
2668
|
+
curves.append(curvelist)
|
|
2669
|
+
|
|
2670
|
+
for c in curves:
|
|
2671
|
+
c.x = scipy.special.j1(c.x)
|
|
2672
|
+
|
|
2673
|
+
|
|
2674
|
+
def recip(curvelist):
|
|
2675
|
+
"""
|
|
2676
|
+
Take the reciprocal of the y values of the curve or list of curves.
|
|
2677
|
+
|
|
2678
|
+
>>> curves = pydvif.read('testData.txt')
|
|
2679
|
+
|
|
2680
|
+
>>> pydvif.recip(curves[1])
|
|
2681
|
+
|
|
2682
|
+
>>> pydvif.create_plot(curves, legend=True, stylename='ggplot')
|
|
2683
|
+
|
|
2684
|
+
:param curvelist: The curve or list of curves
|
|
2685
|
+
:type curvelist: Curve or list
|
|
2686
|
+
"""
|
|
2687
|
+
curves = list()
|
|
2688
|
+
|
|
2689
|
+
if isinstance(curvelist, list):
|
|
2690
|
+
curves.extend(curvelist)
|
|
2691
|
+
else:
|
|
2692
|
+
curves.append(curvelist)
|
|
2693
|
+
|
|
2694
|
+
for c in curves:
|
|
2695
|
+
c.y = np.reciprocal(c.y)
|
|
2696
|
+
|
|
2697
|
+
|
|
2698
|
+
def recipx(curvelist):
|
|
2699
|
+
"""
|
|
2700
|
+
Take the reciprocal of the x values of the curve or list of curves.
|
|
2701
|
+
|
|
2702
|
+
>>> curves = pydvif.read('testData.txt')
|
|
2703
|
+
|
|
2704
|
+
>>> pydvif.dx(curves, 2)
|
|
2705
|
+
|
|
2706
|
+
>>> pydvif.recipx(curves)
|
|
2707
|
+
|
|
2708
|
+
>>> pydvif.create_plot(curves, legend=True, stylename='ggplot')
|
|
2709
|
+
|
|
2710
|
+
:param curvelist: The curve or list of curves
|
|
2711
|
+
:type curvelist: Curve or list
|
|
2712
|
+
:return:
|
|
2713
|
+
"""
|
|
2714
|
+
curves = list()
|
|
2715
|
+
|
|
2716
|
+
if isinstance(curvelist, list):
|
|
2717
|
+
curves.extend(curvelist)
|
|
2718
|
+
else:
|
|
2719
|
+
curves.append(curvelist)
|
|
2720
|
+
|
|
2721
|
+
for c in curves:
|
|
2722
|
+
c.x = np.reciprocal(c.x)
|
|
2723
|
+
|
|
2724
|
+
|
|
2725
|
+
def integrate(curvelist, low=None, high=None):
|
|
2726
|
+
"""
|
|
2727
|
+
Take the integral of the curve or curves in curvelist.
|
|
2728
|
+
|
|
2729
|
+
:param curvelist: A curve or list of curves
|
|
2730
|
+
:type curvelist: curve or list
|
|
2731
|
+
:param low: The lower limit
|
|
2732
|
+
:type low: float
|
|
2733
|
+
:param high: The maximum limit
|
|
2734
|
+
:type high: float
|
|
2735
|
+
:return: list -- the list of integrated curves
|
|
2736
|
+
"""
|
|
2737
|
+
curves = list()
|
|
2738
|
+
ncurves = list()
|
|
2739
|
+
|
|
2740
|
+
if isinstance(curvelist, list):
|
|
2741
|
+
curves.extend(curvelist)
|
|
2742
|
+
else:
|
|
2743
|
+
curves.append(curvelist)
|
|
2744
|
+
|
|
2745
|
+
for c in curves:
|
|
2746
|
+
nc = c.copy()
|
|
2747
|
+
nc.plotname = ''
|
|
2748
|
+
nc.color = ''
|
|
2749
|
+
|
|
2750
|
+
if low is None:
|
|
2751
|
+
nc.name = 'Integrate ' + c.plotname
|
|
2752
|
+
else:
|
|
2753
|
+
nc.name = 'Integrate %s [%.1f,%.1f]' % (c.plotname, low, high)
|
|
2754
|
+
|
|
2755
|
+
if low is None:
|
|
2756
|
+
low = min(nc.x)
|
|
2757
|
+
|
|
2758
|
+
if high is None:
|
|
2759
|
+
high = max(nc.x)
|
|
2760
|
+
|
|
2761
|
+
r = __get_sub_range(nc.x, low, high)
|
|
2762
|
+
nc.x = nc.x[r[0]:r[1] + 1]
|
|
2763
|
+
nc.y = nc.y[r[0]:r[1] + 1]
|
|
2764
|
+
nc.y = np.array(scipy.integrate.cumtrapz(nc.y, nc.x, initial=0.0))
|
|
2765
|
+
|
|
2766
|
+
ncurves.append(nc)
|
|
2767
|
+
|
|
2768
|
+
return ncurves
|
|
2769
|
+
|
|
2770
|
+
|
|
2771
|
+
def alpha(ac, ig, res, npts=-1):
|
|
2772
|
+
if npts == -1:
|
|
2773
|
+
npts = len(ac.y)
|
|
2774
|
+
|
|
2775
|
+
ai = curve.Curve.__mul__(ac, ig)
|
|
2776
|
+
num = convolveb(ai, res, npts)
|
|
2777
|
+
denom = convolveb(ig, res, npts)
|
|
2778
|
+
alpha_measured = curve.Curve.__div__(num, denom)
|
|
2779
|
+
|
|
2780
|
+
alpha_measured.name = "Measured alpha"
|
|
2781
|
+
alpha_measured.plotname = ''
|
|
2782
|
+
return alpha_measured
|
|
2783
|
+
|
|
2784
|
+
|
|
2785
|
+
def gaussian(amp, wid, center, num=100, nsd=3):
|
|
2786
|
+
"""
|
|
2787
|
+
Generate a gaussian function.
|
|
2788
|
+
|
|
2789
|
+
>>> curve = pydvif.gaussian(5, 10, 0)
|
|
2790
|
+
|
|
2791
|
+
>>> pydvif.create_plot(curve, legend=True, stylename='ggplot')
|
|
2792
|
+
|
|
2793
|
+
:param amp: amplitude
|
|
2794
|
+
:type amp: float
|
|
2795
|
+
:param wid: width
|
|
2796
|
+
:type wid: float
|
|
2797
|
+
:param center: center
|
|
2798
|
+
:type center: float
|
|
2799
|
+
:param num: optional, number of points
|
|
2800
|
+
:type num: int
|
|
2801
|
+
:param nsd: optional, number of half-widths
|
|
2802
|
+
:type nsd: float
|
|
2803
|
+
:return: Curve -- representing the gaussian function
|
|
2804
|
+
"""
|
|
2805
|
+
crv_min = center - (nsd * wid)
|
|
2806
|
+
crv_max = center + (nsd * wid)
|
|
2807
|
+
cc = span(crv_min, crv_max, num)
|
|
2808
|
+
|
|
2809
|
+
dd = cc.y - center
|
|
2810
|
+
cc.y = dd * dd * -1
|
|
2811
|
+
cc.y = np.exp(cc.y / (wid * wid))
|
|
2812
|
+
cc.y = cc.y * amp
|
|
2813
|
+
|
|
2814
|
+
cc.name = f"Gaussian (a: {amp} w: {wid} c: {center})"
|
|
2815
|
+
return cc
|
|
2816
|
+
|
|
2817
|
+
|
|
2818
|
+
def getymax(c, xmin=None, xmax=None):
|
|
2819
|
+
"""
|
|
2820
|
+
Get the maximum y-value for the curve within the specified domain.
|
|
2821
|
+
|
|
2822
|
+
:param c: the curve
|
|
2823
|
+
:type Curve:
|
|
2824
|
+
:param xmin: the minimum x-value for the sub-domain
|
|
2825
|
+
:type xmin: float, optional
|
|
2826
|
+
:param xmax: the maximum x-value for the sub-domain
|
|
2827
|
+
:type xmax: float, optional
|
|
2828
|
+
:return: str -- curve name
|
|
2829
|
+
list -- a list of tuples where each tuple contains the x-value and
|
|
2830
|
+
the max y-value.
|
|
2831
|
+
"""
|
|
2832
|
+
try:
|
|
2833
|
+
if xmin is not None:
|
|
2834
|
+
r = __get_sub_range(c.x, xmin, xmax)
|
|
2835
|
+
ymax = max(c.y[r[0]:r[1] + 1])
|
|
2836
|
+
else:
|
|
2837
|
+
ymax = max(c.y)
|
|
2838
|
+
r = [0, len(c.x) - 1]
|
|
2839
|
+
except:
|
|
2840
|
+
pass
|
|
2841
|
+
|
|
2842
|
+
if r[0] >= r[1]:
|
|
2843
|
+
# User range is in between actual curve points
|
|
2844
|
+
# c.x val1 val2 c.x
|
|
2845
|
+
xl = c.x[0] if xmin is None else xmin
|
|
2846
|
+
xr = c.x[-1] if xmax is None else xmax
|
|
2847
|
+
range_x = np.linspace(xl, xr, num=1000)
|
|
2848
|
+
y_interp = np.interp(range_x, c.x, c.y)
|
|
2849
|
+
ymax = max(y_interp)
|
|
2850
|
+
|
|
2851
|
+
# User range has only one curve point in between
|
|
2852
|
+
# val1 c.x val2
|
|
2853
|
+
if r[0] == r[1] and c.y[r[0]] > ymax: # Local max
|
|
2854
|
+
ymax = c.y[r[0]]
|
|
2855
|
+
xy_pairs_at_max = getx(c, ymax, xmin, xmax)
|
|
2856
|
+
|
|
2857
|
+
return __toCurveString(c), xy_pairs_at_max
|
|
2858
|
+
|
|
2859
|
+
|
|
2860
|
+
def getymin(c, xmin=None, xmax=None):
|
|
2861
|
+
"""
|
|
2862
|
+
Get the minimum y-value for the curve within the specified domain.
|
|
2863
|
+
|
|
2864
|
+
:param c: the curve
|
|
2865
|
+
:type Curve:
|
|
2866
|
+
:param xmin: the minimum x-value for the sub-domain
|
|
2867
|
+
:type xmin: float, optional
|
|
2868
|
+
:param xmax: the maximum x-value for the sub-domain
|
|
2869
|
+
:type xmax: float, optional
|
|
2870
|
+
:return: str -- curve name
|
|
2871
|
+
list -- a list of tuples where each tuple contains the x-value and
|
|
2872
|
+
the min y-value.
|
|
2873
|
+
"""
|
|
2874
|
+
try:
|
|
2875
|
+
if xmin is not None:
|
|
2876
|
+
r = __get_sub_range(c.x, xmin, xmax)
|
|
2877
|
+
ymin = min(c.y[r[0]:r[1] + 1])
|
|
2878
|
+
else:
|
|
2879
|
+
ymin = min(c.y)
|
|
2880
|
+
r = [0, len(c.x) - 1]
|
|
2881
|
+
except:
|
|
2882
|
+
pass
|
|
2883
|
+
|
|
2884
|
+
if r[0] >= r[1]:
|
|
2885
|
+
# User range is in between actual curve points
|
|
2886
|
+
# c.x val1 val2 c.x
|
|
2887
|
+
xl = c.x[0] if xmin is None else xmin
|
|
2888
|
+
xr = c.x[-1] if xmax is None else xmax
|
|
2889
|
+
range_x = np.linspace(xl, xr, num=1000)
|
|
2890
|
+
y_interp = np.interp(range_x, c.x, c.y)
|
|
2891
|
+
ymin = min(y_interp)
|
|
2892
|
+
|
|
2893
|
+
# User range has only one curve point in between
|
|
2894
|
+
# val1 c.x val2
|
|
2895
|
+
if r[0] == r[1] and c.y[r[0]] < ymin: # Local min
|
|
2896
|
+
ymin = c.y[r[0]]
|
|
2897
|
+
|
|
2898
|
+
xy_pairs_at_min = getx(c, ymin, xmin, xmax)
|
|
2899
|
+
|
|
2900
|
+
return __toCurveString(c), xy_pairs_at_min
|
|
2901
|
+
|
|
2902
|
+
|
|
2903
|
+
def cumsum(c1):
|
|
2904
|
+
"""
|
|
2905
|
+
Creates a new curve which is the cumulative sum of the original curve
|
|
2906
|
+
|
|
2907
|
+
:param c1: The original curve
|
|
2908
|
+
:type c1: Curve
|
|
2909
|
+
|
|
2910
|
+
:return: Curve -- the cumulative sum of the original curve
|
|
2911
|
+
"""
|
|
2912
|
+
nc = curve.Curve('', 'cumsum(' + __toCurveString(c1) + ')')
|
|
2913
|
+
|
|
2914
|
+
nc.x = c1.x
|
|
2915
|
+
nc.y = np.cumsum(c1.y)
|
|
2916
|
+
|
|
2917
|
+
return nc
|
|
2918
|
+
|
|
2919
|
+
|
|
2920
|
+
def correlate(c1, c2, mode='valid'):
|
|
2921
|
+
"""
|
|
2922
|
+
Computes the cross-correlation of two 1D sequences (c1.y and c2.y) as defined by numpy.correlate.
|
|
2923
|
+
|
|
2924
|
+
:param c1: The first curve with 1D input sequence c1.y
|
|
2925
|
+
:type c1: Curve
|
|
2926
|
+
:param c2: The second curve with 1D input sequence c2.y
|
|
2927
|
+
:type c2: Curve
|
|
2928
|
+
:param mode:
|
|
2929
|
+
full:
|
|
2930
|
+
By default, mode is 'full'. This returns the convolution
|
|
2931
|
+
at each point of overlap, with an output shape of (N+M-1,). At
|
|
2932
|
+
the end-points of the convolution, the signals do not overlap
|
|
2933
|
+
completely, and boundary effects may be seen.
|
|
2934
|
+
|
|
2935
|
+
same:
|
|
2936
|
+
Mode 'same' returns output of length ``max(M, N)``. Boundary
|
|
2937
|
+
effects are still visible.
|
|
2938
|
+
|
|
2939
|
+
valid:
|
|
2940
|
+
Mode 'valid' returns output of length
|
|
2941
|
+
``max(M, N) - min(M, N) + 1``. The convolution product is only given
|
|
2942
|
+
for points where the signals overlap completely. Values outside
|
|
2943
|
+
the signal boundary have no effect.
|
|
2944
|
+
:type mode: 'full'(default), 'same' or 'valid'
|
|
2945
|
+
:return: Curve -- the cross-correlation of c1.y and c2.y
|
|
2946
|
+
"""
|
|
2947
|
+
nc = curve.Curve('', 'correlate(' + __toCurveString(c1) + ', ' + __toCurveString(c2) + ')')
|
|
2948
|
+
|
|
2949
|
+
ic1, step = curve.interp1d(c1, len(c1.x), True)
|
|
2950
|
+
c2npts = (max(c2.x) - min(c2.x)) / step
|
|
2951
|
+
ic2 = curve.interp1d(c2, c2npts)
|
|
2952
|
+
|
|
2953
|
+
y = np.correlate(ic1.y, ic2.y, mode)
|
|
2954
|
+
start = min([min(ic1.x), min(ic2.x)])
|
|
2955
|
+
stop = max([max(ic1.x), max(ic2.x)])
|
|
2956
|
+
nc.x = np.linspace(start, stop, num=len(y))
|
|
2957
|
+
nc.y = np.array(y)
|
|
2958
|
+
|
|
2959
|
+
return nc
|
|
2960
|
+
|
|
2961
|
+
|
|
2962
|
+
def theta(xmin, x0, xmax, numpts=100):
|
|
2963
|
+
"""
|
|
2964
|
+
Generate a unit step distribution.
|
|
2965
|
+
|
|
2966
|
+
:param xmin: The left most point
|
|
2967
|
+
:type xmin: Union[int,float]
|
|
2968
|
+
:param x0: The step point
|
|
2969
|
+
:type x0: Union[int,float]
|
|
2970
|
+
:param xmax: The right most point
|
|
2971
|
+
:type xmax: Union[int,float]
|
|
2972
|
+
:param numpts: Number of points, defaults to 100
|
|
2973
|
+
:type numpts: Union[int,float], optional
|
|
2974
|
+
:return: The curve
|
|
2975
|
+
:rtype: curve.Curve
|
|
2976
|
+
"""
|
|
2977
|
+
|
|
2978
|
+
numpts = round(numpts / 2)
|
|
2979
|
+
|
|
2980
|
+
firstx = np.linspace(xmin, x0, num=numpts)
|
|
2981
|
+
firsty = [0] * len(firstx)
|
|
2982
|
+
|
|
2983
|
+
secondx = np.linspace(x0, xmax, num=numpts)
|
|
2984
|
+
secondy = [1] * len(secondx)
|
|
2985
|
+
|
|
2986
|
+
x = np.concatenate((firstx, secondx), axis=None)
|
|
2987
|
+
y = firsty + secondy
|
|
2988
|
+
|
|
2989
|
+
c = makecurve(x, y, f'Theta {xmin} {x0} {xmax}')
|
|
2990
|
+
|
|
2991
|
+
return c
|
|
2992
|
+
|
|
2993
|
+
|
|
2994
|
+
def normalize(c):
|
|
2995
|
+
"""
|
|
2996
|
+
Normalize a curve.
|
|
2997
|
+
|
|
2998
|
+
:param c: The curve to normalize
|
|
2999
|
+
:type c: curve.Curve
|
|
3000
|
+
:return: The normalized curve
|
|
3001
|
+
:rtype: curve.Curve
|
|
3002
|
+
"""
|
|
3003
|
+
norm_c = c.normalize()
|
|
3004
|
+
c = makecurve(norm_c.x, norm_c.y, f'Normalized {norm_c.plotname}')
|
|
3005
|
+
return c
|
|
3006
|
+
|
|
3007
|
+
|
|
3008
|
+
def hypot(c1, c2):
|
|
3009
|
+
"""
|
|
3010
|
+
Calculate harmonic average of two curves, sqrt(a^2+b^2).
|
|
3011
|
+
|
|
3012
|
+
:param c1: The first curve
|
|
3013
|
+
:type c1: curve.Curve
|
|
3014
|
+
:param c2: The second curve
|
|
3015
|
+
:type c2: curve.Curve
|
|
3016
|
+
:return: The harmonic average of two curves, sqrt(a^2+b^2)
|
|
3017
|
+
:rtype: curve.Curve
|
|
3018
|
+
"""
|
|
3019
|
+
|
|
3020
|
+
if not np.array_equal(c1.x, c2.x):
|
|
3021
|
+
raise ValueError('Curves must have the same x values')
|
|
3022
|
+
|
|
3023
|
+
y = np.sqrt(c1.y**2 + c2.y**2)
|
|
3024
|
+
c = makecurve(c1.x, y, f'hypot {__toCurveString(c1)} {__toCurveString(c2)}')
|
|
3025
|
+
|
|
3026
|
+
return c
|
|
3027
|
+
|
|
3028
|
+
|
|
3029
|
+
def convolve(c1, c2, npts=100, norm=True, debug=False):
|
|
3030
|
+
print("Use convolvec for (g*h)(x) = Int(-inf, inf, dt*g(t)*h(x-t))")
|
|
3031
|
+
print("Use convolveb for (g*h)(x) = Int(-inf, inf, dt*g(t)*h(x-t)) / Int(-inf, inf, dt*h(t))")
|
|
3032
|
+
return
|
|
3033
|
+
|
|
3034
|
+
|
|
3035
|
+
def convolvec(c1, c2, npts=100, npts_interp=100, debug=False):
|
|
3036
|
+
"""
|
|
3037
|
+
Computes the convolution of the two given curves:
|
|
3038
|
+
-
|
|
3039
|
+
- ``(g*h)(x) = Int(-inf, inf, dt*g(t)*h(x-t))``
|
|
3040
|
+
-
|
|
3041
|
+
This computes the integrals directly which avoid padding and aliasing
|
|
3042
|
+
problems associated with FFT methods (it is however slower).
|
|
3043
|
+
|
|
3044
|
+
:param c1: (N,) The first curve g(t)
|
|
3045
|
+
:type c1: Curve
|
|
3046
|
+
:param c2: (M,) The second curve h(t)
|
|
3047
|
+
:type c2: Curve
|
|
3048
|
+
:param npts: the number of points to divide the combined domain of the curves to give delx
|
|
3049
|
+
:type npts: int
|
|
3050
|
+
:param npts_interp: the number of points to interpolate at each delx step
|
|
3051
|
+
:type npts_interp: int
|
|
3052
|
+
:param debug: Used only in CLI, plots curves and c2 h(x-t) as it moves
|
|
3053
|
+
:type debug: bool
|
|
3054
|
+
:return: Curve -- the convolution of the two curves c1 and c2 using integration and no normalization
|
|
3055
|
+
"""
|
|
3056
|
+
|
|
3057
|
+
return convolve_int(c1, c2, False, npts, npts_interp, debug)
|
|
3058
|
+
|
|
3059
|
+
|
|
3060
|
+
def convolveb(c1, c2, npts=100, npts_interp=100, debug=False):
|
|
3061
|
+
"""
|
|
3062
|
+
Computes the convolution of the two given curves:
|
|
3063
|
+
-
|
|
3064
|
+
- ``(g*h)(x) = Int(-inf, inf, dt*g(t)*h(x-t)) / Int(-inf, inf, dt*h(t))``
|
|
3065
|
+
-
|
|
3066
|
+
This computes the integrals directly which avoid padding and aliasing
|
|
3067
|
+
problems associated with FFT methods (it is however slower).
|
|
3068
|
+
|
|
3069
|
+
:param c1: (N,) The first curve g(t)
|
|
3070
|
+
:type c1: Curve
|
|
3071
|
+
:param c2: (M,) The second curve h(t)
|
|
3072
|
+
:type c2: Curve
|
|
3073
|
+
:param npts: the number of points to divide the combined domain of the curves to give delx
|
|
3074
|
+
:type npts: int
|
|
3075
|
+
:param npts_interp: the number of points to interpolate at each delx step
|
|
3076
|
+
:type npts_interp: int
|
|
3077
|
+
:param debug: Used only in CLI, plots curves and c2 h(x-t) as it moves
|
|
3078
|
+
:type debug: bool
|
|
3079
|
+
:return: Curve -- the convolution of the two curves c1 and c2 using integration and normalizing by c2
|
|
3080
|
+
"""
|
|
3081
|
+
|
|
3082
|
+
return convolve_int(c1, c2, True, npts, npts_interp, debug)
|
|
3083
|
+
|
|
3084
|
+
|
|
3085
|
+
def convolve_int(c1, c2, norm=True, npts=100, npts_interp=100, debug=False):
|
|
3086
|
+
"""
|
|
3087
|
+
Computes the convolution of the two given curves:
|
|
3088
|
+
-
|
|
3089
|
+
- norm=False: ``(g*h)(x) = Int(-inf, inf, dt*g(t)*h(x-t))``
|
|
3090
|
+
- norm=True : ``(g*h)(x) = Int(-inf, inf, dt*g(t)*h(x-t)) / Int(-inf, inf, dt*h(t))``
|
|
3091
|
+
-
|
|
3092
|
+
This computes the integrals directly which avoid padding and aliasing
|
|
3093
|
+
problems associated with FFT methods (it is however slower).
|
|
3094
|
+
|
|
3095
|
+
:param c1: (N,) The first curve g(t)
|
|
3096
|
+
:type c1: Curve
|
|
3097
|
+
:param c2: (M,) The second curve h(t)
|
|
3098
|
+
:type c2: Curve
|
|
3099
|
+
:param norm: if true then normalize c2 h(t) before integration. Used in convolc
|
|
3100
|
+
:type norm: bool
|
|
3101
|
+
:param npts: the number of points to divide the combined domain of the curves to give delx
|
|
3102
|
+
:type npts: int
|
|
3103
|
+
:param npts_interp: the number of points to interpolate at each delx step
|
|
3104
|
+
:type npts_interp: int
|
|
3105
|
+
:param debug: Used only in CLI, plots curves and c2 h(x-t) as it moves
|
|
3106
|
+
:type debug: bool
|
|
3107
|
+
:return: nc: Curve -- the convolution of the two curves c1 and c2
|
|
3108
|
+
"""
|
|
3109
|
+
|
|
3110
|
+
c1_copy = copy.deepcopy(c1) # g(t)
|
|
3111
|
+
c2_copy = copy.deepcopy(c2) # h(t)
|
|
3112
|
+
|
|
3113
|
+
c2_original = copy.deepcopy(c2)
|
|
3114
|
+
|
|
3115
|
+
c2_copy.x = np.flip(c2_copy.x) * float(-1)
|
|
3116
|
+
c2_copy.y = np.flip(c2_copy.y)
|
|
3117
|
+
|
|
3118
|
+
dom_c1 = getdomain(c1_copy)
|
|
3119
|
+
dom_c2 = getdomain(c2_copy)
|
|
3120
|
+
|
|
3121
|
+
# Start of g(t)
|
|
3122
|
+
xmn = dom_c1[0][1]
|
|
3123
|
+
# End of g(t) + domain of h(t)
|
|
3124
|
+
xmx = dom_c1[0][2] + (dom_c2[0][2] - dom_c2[0][1])
|
|
3125
|
+
|
|
3126
|
+
# Moving end of h(t) to start of g(t)
|
|
3127
|
+
c2_copy.x += float(xmn) - dom_c2[0][2]
|
|
3128
|
+
|
|
3129
|
+
# Delta x is domain of combined domains
|
|
3130
|
+
delx = (xmx - xmn) / (npts)
|
|
3131
|
+
|
|
3132
|
+
def _integ(cr1, cr2, xcur, xval, yval, iter):
|
|
3133
|
+
|
|
3134
|
+
while iter < npts:
|
|
3135
|
+
|
|
3136
|
+
# Current overlap of g(t) and h(t)
|
|
3137
|
+
overlap = list(cr1.x[np.where(np.logical_and(cr1.x >= cr2.x[0], cr1.x <= cr2.x[-1]))])
|
|
3138
|
+
overlap.extend(list(cr2.x[np.where(np.logical_and(cr2.x >= xmn, cr2.x <= cr1.x[-1]))]))
|
|
3139
|
+
overlap = list(set(overlap))
|
|
3140
|
+
overlap.sort()
|
|
3141
|
+
|
|
3142
|
+
# np.linespace() between first and last overlap
|
|
3143
|
+
overlap_interp = np.linspace(overlap[0], overlap[-1], npts_interp) if overlap else overlap
|
|
3144
|
+
|
|
3145
|
+
# Adding np.linespace() points to original overlap points
|
|
3146
|
+
overlap.extend(overlap_interp)
|
|
3147
|
+
overlap = list(set(overlap))
|
|
3148
|
+
overlap.sort()
|
|
3149
|
+
|
|
3150
|
+
new_y1 = np.interp(overlap, cr1.x, cr1.y)
|
|
3151
|
+
new_y2 = np.interp(overlap, cr2.x, cr2.y)
|
|
3152
|
+
new_y = new_y1 * new_y2
|
|
3153
|
+
|
|
3154
|
+
# if debug:
|
|
3155
|
+
# time.sleep(.5)
|
|
3156
|
+
# gp.plot((cr1.x, cr1.y, dict(legend='g(t)')),
|
|
3157
|
+
# (c2_original.x, c2_original.y, dict(legend='h(x)')),
|
|
3158
|
+
# (cr2.x, cr2.y, dict(legend='h(x-t)')),
|
|
3159
|
+
# (overlap, new_y, dict(legend='g(t)*h(x-t)')),
|
|
3160
|
+
# xmin=xmn - (dom_c2[0][2] - dom_c2[0][1]) * 1.5,
|
|
3161
|
+
# xmax=xmx * 1.5)
|
|
3162
|
+
|
|
3163
|
+
area = scipy.integrate.trapezoid(new_y, overlap)
|
|
3164
|
+
|
|
3165
|
+
cr2.x += delx
|
|
3166
|
+
xval.append(xcur)
|
|
3167
|
+
yval.append(area)
|
|
3168
|
+
iter += 1
|
|
3169
|
+
xcur += delx
|
|
3170
|
+
# return _integ(cr1, cr2, xcur + delx, xval, yval, iter)
|
|
3171
|
+
|
|
3172
|
+
return xval, yval
|
|
3173
|
+
|
|
3174
|
+
x, y = _integ(c1_copy, c2_copy, float(xmn) - dom_c2[0][2], [], [], 0)
|
|
3175
|
+
|
|
3176
|
+
namestr = f'Conv {c1.plotname} * {c2.plotname}'
|
|
3177
|
+
if norm:
|
|
3178
|
+
namestr = f'(Conv {c1.plotname} * {c2.plotname})/Area({c2.plotname})'
|
|
3179
|
+
area0 = scipy.integrate.trapezoid(c2_original.y, c2_original.x)
|
|
3180
|
+
y /= area0
|
|
3181
|
+
|
|
3182
|
+
nc = makecurve(x, y, namestr)
|
|
3183
|
+
|
|
3184
|
+
return nc
|
|
3185
|
+
|
|
3186
|
+
|
|
3187
|
+
def fft(c, n=None, axis=-1, norm=None):
|
|
3188
|
+
"""
|
|
3189
|
+
Compute the one-dimensional discrete Fourier Transform for the x- or y-values of c.
|
|
3190
|
+
|
|
3191
|
+
This function computes the one-dimensional *n*-point discrete Fourier
|
|
3192
|
+
Transform (DFT) with the efficient Fast Fourier Transform (FFT)
|
|
3193
|
+
algorithm [CT].
|
|
3194
|
+
|
|
3195
|
+
Raises IndexError: if `axes` is larger than the last axis of `a`.
|
|
3196
|
+
|
|
3197
|
+
Notes: FFT (Fast Fourier Transform) refers to a way the discrete Fourier
|
|
3198
|
+
Transform (DFT) can be calculated efficiently, by using symmetries in the
|
|
3199
|
+
calculated terms. The symmetry is highest when `n` is a power of 2, and
|
|
3200
|
+
the transform is therefore most efficient for these sizes.
|
|
3201
|
+
|
|
3202
|
+
The DFT is defined, with the conventions used in this implementation, in
|
|
3203
|
+
the documentation for the `numpy.fft` module.
|
|
3204
|
+
|
|
3205
|
+
Citation: Cooley, James W., and John W. Tukey, 1965, "An algorithm for the
|
|
3206
|
+
machine calculation of complex Fourier series," *Math. Comput.*
|
|
3207
|
+
19: 297-301.
|
|
3208
|
+
|
|
3209
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3210
|
+
|
|
3211
|
+
>>> realcurve, imagcurve = pydvif.fft(curves[0])
|
|
3212
|
+
|
|
3213
|
+
:param c: Curve with x- or y-values as input array, can be complex.
|
|
3214
|
+
:type c: Curve
|
|
3215
|
+
:param n: Length of the transformed axis of the output. If `n` is smaller than
|
|
3216
|
+
the length of the input, the input is cropped. If it is larger, the input is padded with zeros.
|
|
3217
|
+
If `n` is not given, the length of the input along the axis specified by `axis` is used.
|
|
3218
|
+
:type n: int, optional
|
|
3219
|
+
:param axis: Axis over which to compute the FFT. If not given, the last axis is used.
|
|
3220
|
+
:type axis: int, optional
|
|
3221
|
+
:param norm: Normalization mode (see `numpy.fft`). Default is None.
|
|
3222
|
+
:type norm: None, "ortho", optional
|
|
3223
|
+
:return: Curve tuple -- Two curves with the real and imaginary parts.
|
|
3224
|
+
"""
|
|
3225
|
+
|
|
3226
|
+
nc1 = curve.Curve('', 'Real part FFT ' + __toCurveString(c))
|
|
3227
|
+
nc2 = curve.Curve('', 'Imaginary part FFT ' + __toCurveString(c))
|
|
3228
|
+
|
|
3229
|
+
numpy1_10 = LooseVersion(np.__version__) >= LooseVersion("1.10.0")
|
|
3230
|
+
cnorm = c.normalize()
|
|
3231
|
+
clen = len(c.x)
|
|
3232
|
+
|
|
3233
|
+
if numpy1_10:
|
|
3234
|
+
complex_array = np.fft.fft(cnorm.y, n, axis, norm)
|
|
3235
|
+
complex_array = np.fft.fftshift(complex_array)
|
|
3236
|
+
else:
|
|
3237
|
+
complex_array = np.fft.fft(cnorm.y, n, axis)
|
|
3238
|
+
complex_array = np.fft.fftshift(complex_array)
|
|
3239
|
+
|
|
3240
|
+
val = 1.0 / (float(max(cnorm.x) - min(cnorm.x)) / 2.0)
|
|
3241
|
+
nc1.x = np.fft.fftfreq(clen, d=val)
|
|
3242
|
+
nc1.x = np.fft.fftshift(nc1.x)
|
|
3243
|
+
nc1.y = complex_array.real
|
|
3244
|
+
|
|
3245
|
+
nc2.x = np.array(nc1.x)
|
|
3246
|
+
nc2.y = complex_array.imag
|
|
3247
|
+
|
|
3248
|
+
my(nc2, -1)
|
|
3249
|
+
|
|
3250
|
+
return nc1, nc2
|
|
3251
|
+
|
|
3252
|
+
|
|
3253
|
+
def derivative(c, eo=1):
|
|
3254
|
+
"""
|
|
3255
|
+
Take the derivative of the curve.
|
|
3256
|
+
|
|
3257
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3258
|
+
|
|
3259
|
+
>>> newCurve = pydvif.derivative(curves[0])
|
|
3260
|
+
|
|
3261
|
+
:param c: The curve
|
|
3262
|
+
:type c: Curve
|
|
3263
|
+
:param eo: edge_order, gradient is calculated using N-th order accurate differences at the boundaries.
|
|
3264
|
+
Default: 1.
|
|
3265
|
+
:type eo: int, optional
|
|
3266
|
+
:return: A new curve representing the derivate of c
|
|
3267
|
+
"""
|
|
3268
|
+
nc = curve.Curve('', 'Derivative ' + __toCurveString(c))
|
|
3269
|
+
|
|
3270
|
+
nc.x = c.x
|
|
3271
|
+
nc.y = np.gradient(c.y, c.x, edge_order=eo)
|
|
3272
|
+
|
|
3273
|
+
return nc
|
|
3274
|
+
|
|
3275
|
+
|
|
3276
|
+
def diffMeasure(c1, c2, tol=1e-8):
|
|
3277
|
+
"""
|
|
3278
|
+
Compare two curves. For the given curves a fractional difference measure and its average are computed.
|
|
3279
|
+
|
|
3280
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3281
|
+
|
|
3282
|
+
>>> c1, c2 = pydvif.diffMeasure(curves[0], curves[1])
|
|
3283
|
+
|
|
3284
|
+
>>> curves.append(c1)
|
|
3285
|
+
|
|
3286
|
+
>>> curves.append(c2)
|
|
3287
|
+
|
|
3288
|
+
>>> pydvif.create_plot(curves, legend=True)
|
|
3289
|
+
|
|
3290
|
+
:param c1: The first curve
|
|
3291
|
+
:type c1: Curve
|
|
3292
|
+
:param c2: The second curve
|
|
3293
|
+
:type c2: Curve
|
|
3294
|
+
:param tol: The tolerance
|
|
3295
|
+
:type tol: float
|
|
3296
|
+
:return: tuple -- Two curves representing the fractional difference measure and its average
|
|
3297
|
+
"""
|
|
3298
|
+
cdiff = curve.Curve('', 'FD = $|$' + __toCurveString(c1) + ' - ' + __toCurveString(c2) + # noqaw504
|
|
3299
|
+
'$|$/($|$' + __toCurveString(c1) + '$|$ + $|$' + __toCurveString(c2) + '$|$)')
|
|
3300
|
+
ic1, ic2 = curve.getinterp(c1, c2)
|
|
3301
|
+
f1 = tol * (np.max(ic1.y) - np.min(ic1.y))
|
|
3302
|
+
f2 = tol * (np.max(ic2.y) - np.min(ic2.y))
|
|
3303
|
+
ydiff = np.abs(ic1.y - ic2.y)
|
|
3304
|
+
yden = (np.abs(ic1.y) + f1) + (np.abs(ic2.y) + f2)
|
|
3305
|
+
dx = np.max(ic1.x) - np.min(ic1.x)
|
|
3306
|
+
cdiff.x = np.array(ic1.x)
|
|
3307
|
+
cdiff.y = np.array(ydiff / yden)
|
|
3308
|
+
cdiff.y[np.isnan(cdiff.y)] = 0 # corner case where both curves are all zeros since f1 and f2 will also be 0
|
|
3309
|
+
|
|
3310
|
+
cint = curve.Curve('', 'Integral(FD)/dX')
|
|
3311
|
+
yint = scipy.integrate.cumtrapz(cdiff.y, cdiff.x, initial=0.0)
|
|
3312
|
+
cint.x = np.array(ic1.x)
|
|
3313
|
+
cint.y = np.array(yint / dx)
|
|
3314
|
+
|
|
3315
|
+
return cdiff, cint
|
|
3316
|
+
|
|
3317
|
+
|
|
3318
|
+
########################################################
|
|
3319
|
+
################## Curve Related ##################### # noqa e266
|
|
3320
|
+
########################################################
|
|
3321
|
+
|
|
3322
|
+
def vs(c1, c2):
|
|
3323
|
+
"""
|
|
3324
|
+
Create a new curve that will plot as the range of the first curve against
|
|
3325
|
+
the range of the second curve.
|
|
3326
|
+
|
|
3327
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3328
|
+
|
|
3329
|
+
>>> c1 = pydvif.vs(curves[0], curves[1])
|
|
3330
|
+
|
|
3331
|
+
>>> curves.append(c1)
|
|
3332
|
+
|
|
3333
|
+
>>> pydvif.create_plot(curves, legend=True)
|
|
3334
|
+
|
|
3335
|
+
:param c1: The first curve
|
|
3336
|
+
:type c1: Curve
|
|
3337
|
+
:param c2: The second curve
|
|
3338
|
+
:type c2: Curve
|
|
3339
|
+
:return: Curve -- the new curve
|
|
3340
|
+
"""
|
|
3341
|
+
newfilename = ''
|
|
3342
|
+
newrecord_id = ''
|
|
3343
|
+
if c1.filename == c2.filename:
|
|
3344
|
+
newfilename = c1.filename
|
|
3345
|
+
if c1.record_id == c2.record_id:
|
|
3346
|
+
newrecord_id = c1.record_id
|
|
3347
|
+
nc = curve.Curve(newfilename, __toCurveString(c1) + ' vs ' + __toCurveString(c2),
|
|
3348
|
+
newrecord_id, c2.ylabel, c1.ylabel)
|
|
3349
|
+
ic1, ic2 = curve.getinterp(c1, c2)
|
|
3350
|
+
nc.x = np.array(ic2.y)
|
|
3351
|
+
nc.y = np.array(ic1.y)
|
|
3352
|
+
return nc
|
|
3353
|
+
|
|
3354
|
+
|
|
3355
|
+
def subsample(curvelist, stride=2, verbose=False):
|
|
3356
|
+
"""
|
|
3357
|
+
Subsample the curve or list of curves, i.e., reduce to every nth value.
|
|
3358
|
+
|
|
3359
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3360
|
+
|
|
3361
|
+
>>> pydvif.subsample(curves, 4)
|
|
3362
|
+
|
|
3363
|
+
>>> pydvif.create_plot(curves, legend=True)
|
|
3364
|
+
|
|
3365
|
+
:param curvelist: The curve or list of curves
|
|
3366
|
+
:type curvelist: Curve or list
|
|
3367
|
+
:param stride: The step size through the array
|
|
3368
|
+
:type stride: int
|
|
3369
|
+
:param verbose: If True additional information will be printed to stdout
|
|
3370
|
+
:type verbose: bool
|
|
3371
|
+
"""
|
|
3372
|
+
curves = list()
|
|
3373
|
+
|
|
3374
|
+
if isinstance(curvelist, list):
|
|
3375
|
+
curves.extend(curvelist)
|
|
3376
|
+
else:
|
|
3377
|
+
curves.append(curvelist)
|
|
3378
|
+
|
|
3379
|
+
for c in curves:
|
|
3380
|
+
n = len(c.x)
|
|
3381
|
+
xss = c.x[0:n:int(stride)]
|
|
3382
|
+
yss = c.y[0:n:int(stride)]
|
|
3383
|
+
c.x = xss
|
|
3384
|
+
c.y = yss
|
|
3385
|
+
|
|
3386
|
+
if verbose:
|
|
3387
|
+
print("Reduced %s from %i -> %i values." % (c.name, n, len(c.x)))
|
|
3388
|
+
|
|
3389
|
+
|
|
3390
|
+
def smooth(curvelist, factor=1):
|
|
3391
|
+
"""
|
|
3392
|
+
Smooth the curve to the given degree.
|
|
3393
|
+
|
|
3394
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3395
|
+
|
|
3396
|
+
>>> pydvif.smooth(curves, 4)
|
|
3397
|
+
|
|
3398
|
+
>>> pydvif.create_plot(curves, legend=True)
|
|
3399
|
+
|
|
3400
|
+
:param curvelist: The curve or list of curves
|
|
3401
|
+
:type curvelist: Curve or list
|
|
3402
|
+
:param factor: The smooth factor
|
|
3403
|
+
:type factor: int
|
|
3404
|
+
"""
|
|
3405
|
+
curves = list()
|
|
3406
|
+
|
|
3407
|
+
if isinstance(curvelist, list):
|
|
3408
|
+
curves.extend(curvelist)
|
|
3409
|
+
else:
|
|
3410
|
+
curves.append(curvelist)
|
|
3411
|
+
|
|
3412
|
+
for c in curves:
|
|
3413
|
+
if len(c.x) < 2:
|
|
3414
|
+
return 0
|
|
3415
|
+
|
|
3416
|
+
x = list()
|
|
3417
|
+
y = list()
|
|
3418
|
+
|
|
3419
|
+
for i in range(len(c.x)):
|
|
3420
|
+
tfactor = factor
|
|
3421
|
+
|
|
3422
|
+
if i - factor < 0 and i < (len(c.x) - 1) / 2:
|
|
3423
|
+
tfactor = i
|
|
3424
|
+
elif i + factor >= len(c.x):
|
|
3425
|
+
tfactor = len(c.x) - 1 - i
|
|
3426
|
+
|
|
3427
|
+
xsum = 0
|
|
3428
|
+
ysum = 0
|
|
3429
|
+
|
|
3430
|
+
for j in range(-tfactor, tfactor + 1):
|
|
3431
|
+
xsum += c.x[i + j]
|
|
3432
|
+
for j in range(-factor, factor + 1):
|
|
3433
|
+
if 0 <= i + j < len(c.x):
|
|
3434
|
+
ysum += c.y[i + j]
|
|
3435
|
+
elif i + j < 0:
|
|
3436
|
+
ysum += c.y[0]
|
|
3437
|
+
else:
|
|
3438
|
+
ysum += c.y[-1]
|
|
3439
|
+
|
|
3440
|
+
x.append(xsum / (2 * tfactor + 1))
|
|
3441
|
+
y.append(ysum / (2 * factor + 1))
|
|
3442
|
+
|
|
3443
|
+
c.x = np.array(x)
|
|
3444
|
+
c.y = np.array(y)
|
|
3445
|
+
|
|
3446
|
+
|
|
3447
|
+
def errorbar(scur, cury1, cury2, curx1=None, curx2=None, mod=1):
|
|
3448
|
+
"""
|
|
3449
|
+
Plot error bars on the given curve.
|
|
3450
|
+
|
|
3451
|
+
>>> curves = list()
|
|
3452
|
+
|
|
3453
|
+
>>> curves.append(pydvif.span(1,10))
|
|
3454
|
+
|
|
3455
|
+
>>> curves.append(pydvif.span(1,10))
|
|
3456
|
+
|
|
3457
|
+
>>> curves.append(pydvif.span(1,10))
|
|
3458
|
+
|
|
3459
|
+
>>> pydvif.dy(curves[0], 0.25)
|
|
3460
|
+
|
|
3461
|
+
>>> pydvif.dy(curves[2], -0.25)
|
|
3462
|
+
|
|
3463
|
+
>>> pydvif.errorbar(curves[1], curves[0], curves[2])
|
|
3464
|
+
|
|
3465
|
+
>>> pydvif.create_plot(curves, legend=True)
|
|
3466
|
+
|
|
3467
|
+
:param scur: The given curve
|
|
3468
|
+
:type scur: Curve
|
|
3469
|
+
:param cury1: y-error-curve
|
|
3470
|
+
:type cury1: Curve
|
|
3471
|
+
:param cury2: y+error-curve
|
|
3472
|
+
:type cury2: Curve
|
|
3473
|
+
:param curx1: x-error-curve
|
|
3474
|
+
:type curx1: Curve
|
|
3475
|
+
:param curx2: x+error-curve
|
|
3476
|
+
:type curx2: Curve
|
|
3477
|
+
:param mod: point-skip
|
|
3478
|
+
:type mod: int
|
|
3479
|
+
"""
|
|
3480
|
+
ebar = [np.zeros(len(scur.x)), np.zeros(len(scur.x)), np.zeros(len(scur.x)), np.zeros(len(scur.x))]
|
|
3481
|
+
lowy = list()
|
|
3482
|
+
for i in range(len(scur.x)):
|
|
3483
|
+
y = np.interp(scur.x[i], cury1.x, cury1.y)
|
|
3484
|
+
if scur.y[i] - y <= 0:
|
|
3485
|
+
lowy.append(y)
|
|
3486
|
+
else:
|
|
3487
|
+
lowy.append(scur.y[i])
|
|
3488
|
+
|
|
3489
|
+
ebar[0] = np.array(lowy)
|
|
3490
|
+
ebar[1] = np.interp(scur.x, cury2.x, cury2.y)
|
|
3491
|
+
|
|
3492
|
+
if curx1 is not None and curx2 is not None:
|
|
3493
|
+
ebar[2] = np.interp(scur.x, curx1.x, curx1.y)
|
|
3494
|
+
ebar[3] = np.interp(scur.x, curx2.x, curx2.y)
|
|
3495
|
+
|
|
3496
|
+
for i in range(len(ebar[0])):
|
|
3497
|
+
if (i % int(mod) != 0) and (i != len(ebar[0]) - 1):
|
|
3498
|
+
ebar[0][i] = None
|
|
3499
|
+
ebar[1][i] = None
|
|
3500
|
+
ebar[2][i] = None
|
|
3501
|
+
ebar[3][i] = None
|
|
3502
|
+
|
|
3503
|
+
scur.ebar = ebar
|
|
3504
|
+
scur.erange = None
|
|
3505
|
+
|
|
3506
|
+
|
|
3507
|
+
def errorrange(scur, cury1, cury2):
|
|
3508
|
+
"""
|
|
3509
|
+
Plot shaded error region on given curve.
|
|
3510
|
+
|
|
3511
|
+
>>> curves = list()
|
|
3512
|
+
|
|
3513
|
+
>>> curves.append(pydvif.span(1,10))
|
|
3514
|
+
|
|
3515
|
+
>>> curves.append(pydvif.span(1,10))
|
|
3516
|
+
|
|
3517
|
+
>>> curves.append(pydvif.span(1,10))
|
|
3518
|
+
|
|
3519
|
+
>>> pydvif.dy(curves[0], 0.25)
|
|
3520
|
+
|
|
3521
|
+
>>> pydvif.dy(curves[2], -0.25)
|
|
3522
|
+
|
|
3523
|
+
>>> pydvif.errorrange(curves[1], curves[0], curves[2])
|
|
3524
|
+
|
|
3525
|
+
>>> pydvif.create_plot(curves, legend=True)
|
|
3526
|
+
|
|
3527
|
+
:param scur: The given curve
|
|
3528
|
+
:type scur: Curve
|
|
3529
|
+
:param cury1: y-error-curve
|
|
3530
|
+
:type cury1: Curve
|
|
3531
|
+
:param cury2: y+error-curve
|
|
3532
|
+
:type cury2: Curve
|
|
3533
|
+
"""
|
|
3534
|
+
|
|
3535
|
+
errorbar(scur, cury1, cury2)
|
|
3536
|
+
scur.erange = [scur.ebar[0], scur.ebar[1]]
|
|
3537
|
+
scur.ebar = None
|
|
3538
|
+
|
|
3539
|
+
|
|
3540
|
+
def fit(c, n=1, logx=False, logy=False):
|
|
3541
|
+
"""
|
|
3542
|
+
Make a new curve that is a polynomial fit to curve c.
|
|
3543
|
+
|
|
3544
|
+
>>> curves = list()
|
|
3545
|
+
|
|
3546
|
+
>>> curves.append(pydvif.span(1,10))
|
|
3547
|
+
|
|
3548
|
+
>>> pydvif.sin(curves)
|
|
3549
|
+
|
|
3550
|
+
>>> curves.append(pydvif.fit(curves[0], 2))
|
|
3551
|
+
|
|
3552
|
+
>>> pydvif.create_plot(curves, legend=True)
|
|
3553
|
+
|
|
3554
|
+
:param c: The curve to fit
|
|
3555
|
+
:type c: Curve
|
|
3556
|
+
:param n: Degree of the fitting polynomial
|
|
3557
|
+
:type n: int
|
|
3558
|
+
:param logx: Take the log(x-values) before fitting if True
|
|
3559
|
+
:type logx: bool
|
|
3560
|
+
:param logy: Take the log(y-values) before fitting if True
|
|
3561
|
+
:type logy: bool
|
|
3562
|
+
:return: Curve -- The fitting polynomial
|
|
3563
|
+
"""
|
|
3564
|
+
x = c.x
|
|
3565
|
+
y = c.y
|
|
3566
|
+
|
|
3567
|
+
if logx:
|
|
3568
|
+
x = np.log10(x)
|
|
3569
|
+
|
|
3570
|
+
if logy:
|
|
3571
|
+
y = np.log10(y)
|
|
3572
|
+
|
|
3573
|
+
coeffs = scipy.polyfit(x, y, n)
|
|
3574
|
+
if len(coeffs) == 2:
|
|
3575
|
+
print("slope = ", coeffs[0], " intercept = ", coeffs[1])
|
|
3576
|
+
else:
|
|
3577
|
+
print("coefficients are: ", coeffs)
|
|
3578
|
+
|
|
3579
|
+
if n == 1:
|
|
3580
|
+
oString = "1st "
|
|
3581
|
+
elif n == 2:
|
|
3582
|
+
oString = "2nd "
|
|
3583
|
+
elif n == 3:
|
|
3584
|
+
oString = "3rd "
|
|
3585
|
+
else:
|
|
3586
|
+
oString = "%dth " % n
|
|
3587
|
+
|
|
3588
|
+
nc = curve.Curve('', oString + 'order fit to ' + __toCurveString(c))
|
|
3589
|
+
nc.x = np.array(x)
|
|
3590
|
+
nc.y = scipy.polyval(coeffs, x)
|
|
3591
|
+
|
|
3592
|
+
if logx:
|
|
3593
|
+
nc.x = 10.0**nc.x
|
|
3594
|
+
|
|
3595
|
+
if logy:
|
|
3596
|
+
nc.y = 10.0**nc.y
|
|
3597
|
+
|
|
3598
|
+
return nc
|
|
3599
|
+
|
|
3600
|
+
|
|
3601
|
+
def getdomain(curvelist):
|
|
3602
|
+
"""
|
|
3603
|
+
Get domain of the curve or list of curves.
|
|
3604
|
+
|
|
3605
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3606
|
+
|
|
3607
|
+
>>> domains = pydvif.getdomain(curves)
|
|
3608
|
+
|
|
3609
|
+
>>> plotname, minx, maxx = domains[0]
|
|
3610
|
+
|
|
3611
|
+
:param curvelist: The given curve or list of curves
|
|
3612
|
+
:type curvelist: Curve or list
|
|
3613
|
+
:return: list -- A list of tuples where each tuple contains the curve name, minimum x, and maximum x
|
|
3614
|
+
"""
|
|
3615
|
+
domains = list()
|
|
3616
|
+
curves = list()
|
|
3617
|
+
|
|
3618
|
+
if isinstance(curvelist, list):
|
|
3619
|
+
curves.extend(curvelist)
|
|
3620
|
+
else:
|
|
3621
|
+
curves.append(curvelist)
|
|
3622
|
+
|
|
3623
|
+
for c in curves:
|
|
3624
|
+
domains.append((__toCurveString(c), min(c.x), max(c.x)))
|
|
3625
|
+
|
|
3626
|
+
return domains
|
|
3627
|
+
|
|
3628
|
+
|
|
3629
|
+
def sum(curvelist):
|
|
3630
|
+
"""
|
|
3631
|
+
Return sum of the x and y values of each curve.
|
|
3632
|
+
|
|
3633
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3634
|
+
|
|
3635
|
+
>>> sums = pydvif.sum(curves)
|
|
3636
|
+
|
|
3637
|
+
>>> plotname, sumx, sumy = sums[0]
|
|
3638
|
+
|
|
3639
|
+
:param curvelist: The given curve or list of curves
|
|
3640
|
+
:type curvelist: Curve or list
|
|
3641
|
+
:return: list -- A list of tuples where each tuple contains the curve name, sum of x-values, and sum of y-values
|
|
3642
|
+
"""
|
|
3643
|
+
sums = list()
|
|
3644
|
+
curves = list()
|
|
3645
|
+
|
|
3646
|
+
if isinstance(curvelist, list):
|
|
3647
|
+
curves.extend(curvelist)
|
|
3648
|
+
else:
|
|
3649
|
+
curves.append(curvelist)
|
|
3650
|
+
|
|
3651
|
+
for c in curves:
|
|
3652
|
+
sums.append((__toCurveString(c), np.sum(c.x), np.sum(c.y)))
|
|
3653
|
+
|
|
3654
|
+
return sums
|
|
3655
|
+
|
|
3656
|
+
|
|
3657
|
+
def area(curvelist):
|
|
3658
|
+
"""
|
|
3659
|
+
Return area of each curve.
|
|
3660
|
+
|
|
3661
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3662
|
+
|
|
3663
|
+
>>> areas = pydvif.area(curves)
|
|
3664
|
+
|
|
3665
|
+
>>> plotname, area = areas[0]
|
|
3666
|
+
|
|
3667
|
+
:param curvelist: The given curve or list of curves
|
|
3668
|
+
:type curvelist: Curve or list
|
|
3669
|
+
:return: list -- A list of tuples where each tuple contains the curve name and area
|
|
3670
|
+
"""
|
|
3671
|
+
areas = list()
|
|
3672
|
+
curves = list()
|
|
3673
|
+
|
|
3674
|
+
if isinstance(curvelist, list):
|
|
3675
|
+
curves.extend(curvelist)
|
|
3676
|
+
else:
|
|
3677
|
+
curves.append(curvelist)
|
|
3678
|
+
|
|
3679
|
+
for c in curves:
|
|
3680
|
+
areas.append((__toCurveString(c), scipy.integrate.simpson(c.y, c.x)))
|
|
3681
|
+
|
|
3682
|
+
return areas
|
|
3683
|
+
|
|
3684
|
+
|
|
3685
|
+
def disp(c, domain=True):
|
|
3686
|
+
"""
|
|
3687
|
+
Create a string formatted list of the curve's x-values if domain is True, otherwise y-values.
|
|
3688
|
+
|
|
3689
|
+
>>> c = pydvif.span(1, 10)
|
|
3690
|
+
|
|
3691
|
+
>>> yvalues = pydvif.disp(c, False)
|
|
3692
|
+
|
|
3693
|
+
:param c: The given curve
|
|
3694
|
+
:type curvelist: Curve
|
|
3695
|
+
:param domain: if True, display the x-values of the curve. Otherwise, display the y-values of the curve
|
|
3696
|
+
:type domain: bool, optional
|
|
3697
|
+
:return: list -- The list of x- or y-values as strings
|
|
3698
|
+
"""
|
|
3699
|
+
ss = list()
|
|
3700
|
+
|
|
3701
|
+
for i in range(len(c.x)):
|
|
3702
|
+
if domain:
|
|
3703
|
+
ss.append('x[%d]: %.4f' % (i, c.x[i]))
|
|
3704
|
+
else:
|
|
3705
|
+
ss.append('y[%d]: %.4f' % (i, c.y[i]))
|
|
3706
|
+
|
|
3707
|
+
return ss
|
|
3708
|
+
|
|
3709
|
+
|
|
3710
|
+
def getnumpoints(curve):
|
|
3711
|
+
"""
|
|
3712
|
+
Return the given curve's number of points.
|
|
3713
|
+
|
|
3714
|
+
:param curve: The given curve
|
|
3715
|
+
:return: int -- the number of points in curve
|
|
3716
|
+
"""
|
|
3717
|
+
return len(curve.x)
|
|
3718
|
+
|
|
3719
|
+
|
|
3720
|
+
def getrange(curvelist):
|
|
3721
|
+
"""
|
|
3722
|
+
Get the range of the curve or list of curves.
|
|
3723
|
+
|
|
3724
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3725
|
+
|
|
3726
|
+
>>> ranges = pydvif.getrange(curves)
|
|
3727
|
+
|
|
3728
|
+
>>> plotname, miny, maxy = ranges[0]
|
|
3729
|
+
|
|
3730
|
+
:param curvelist: The given curve or list of curves
|
|
3731
|
+
:type curvelist: Curve or list
|
|
3732
|
+
:return: list -- A list of tuples where each tuple contains the curve name, minimum y, and maximum y
|
|
3733
|
+
"""
|
|
3734
|
+
ranges = list()
|
|
3735
|
+
curves = list()
|
|
3736
|
+
|
|
3737
|
+
if isinstance(curvelist, list):
|
|
3738
|
+
curves.extend(curvelist)
|
|
3739
|
+
else:
|
|
3740
|
+
curves.append(curvelist)
|
|
3741
|
+
|
|
3742
|
+
for c in curves:
|
|
3743
|
+
ranges.append((__toCurveString(c), min(c.y), max(c.y)))
|
|
3744
|
+
|
|
3745
|
+
return ranges
|
|
3746
|
+
|
|
3747
|
+
|
|
3748
|
+
def getx(c, value, xmin=None, xmax=None):
|
|
3749
|
+
"""
|
|
3750
|
+
Get the x values of the curve for a given y.
|
|
3751
|
+
|
|
3752
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3753
|
+
|
|
3754
|
+
>>> vals = pydvif.getx(curves[0], 4)
|
|
3755
|
+
|
|
3756
|
+
>>> x, y = vals[0]
|
|
3757
|
+
|
|
3758
|
+
:param c: The curve
|
|
3759
|
+
:type c: Curve
|
|
3760
|
+
:param value: y value
|
|
3761
|
+
:type value: float
|
|
3762
|
+
:return: list -- A list of tuples where each tuple contains the x value, and the given y
|
|
3763
|
+
"""
|
|
3764
|
+
xypairs = list()
|
|
3765
|
+
r = __get_sub_range(c.x, xmin, xmax)
|
|
3766
|
+
|
|
3767
|
+
if float(value) < np.amin(c.y) or float(value) > np.amax(c.y):
|
|
3768
|
+
raise ValueError('y-value out of range')
|
|
3769
|
+
|
|
3770
|
+
if r[0] < r[1]:
|
|
3771
|
+
for i in range(r[0], r[1] + 1):
|
|
3772
|
+
if c.y[i] == float(value): # value exists in curve
|
|
3773
|
+
xypairs.append((c.x[i], float(value)))
|
|
3774
|
+
else: # value does not exist in curve
|
|
3775
|
+
ymax = c.y[i]
|
|
3776
|
+
if i + 1 < len(c.y):
|
|
3777
|
+
ymax = c.y[i + 1]
|
|
3778
|
+
|
|
3779
|
+
if c.y[i] < float(value) < ymax:
|
|
3780
|
+
x = np.interp(float(value), [c.y[i], ymax], [c.x[i], c.x[i + 1]])
|
|
3781
|
+
xypairs.append((x, float(value)))
|
|
3782
|
+
elif ymax < float(value) < c.y[i]:
|
|
3783
|
+
x = np.interp(float(value), [ymax, c.y[i]], [c.x[i + 1], c.x[i]])
|
|
3784
|
+
xypairs.append((x, float(value)))
|
|
3785
|
+
else:
|
|
3786
|
+
|
|
3787
|
+
# User range is in between actual curve points
|
|
3788
|
+
# c.x val1 val2 c.x
|
|
3789
|
+
xl = c.x[0] if xmin is None else xmin
|
|
3790
|
+
xr = c.x[-1] if xmax is None else xmax
|
|
3791
|
+
range_x = np.linspace(xl, xr, num=1000)
|
|
3792
|
+
y_interp = np.interp(range_x, c.x, c.y)
|
|
3793
|
+
for x, y in zip(range_x, y_interp):
|
|
3794
|
+
if y == value:
|
|
3795
|
+
xypairs.append((x, y))
|
|
3796
|
+
|
|
3797
|
+
# User range has only one curve point in between
|
|
3798
|
+
# val1 c.x val2
|
|
3799
|
+
if r[0] == r[1]:
|
|
3800
|
+
if c.y[r[0]] == float(value): # value exists in curve
|
|
3801
|
+
xypairs.append((c.x[r[0]], float(value)))
|
|
3802
|
+
|
|
3803
|
+
return xypairs
|
|
3804
|
+
|
|
3805
|
+
|
|
3806
|
+
def gety(c, value):
|
|
3807
|
+
"""
|
|
3808
|
+
Get the y values of the curve for a given x.
|
|
3809
|
+
|
|
3810
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3811
|
+
|
|
3812
|
+
>>> vals = pydvif.gety(curves[0], 2)
|
|
3813
|
+
|
|
3814
|
+
>>> x, y = vals[0]
|
|
3815
|
+
|
|
3816
|
+
:param c: The curve
|
|
3817
|
+
:type c: Curve
|
|
3818
|
+
:param value: x value
|
|
3819
|
+
:type value: float
|
|
3820
|
+
:return: list -- A list of tuples where each tuple contains the y value, and the given x
|
|
3821
|
+
"""
|
|
3822
|
+
xypairs = list()
|
|
3823
|
+
|
|
3824
|
+
# if float(value) < np.amin(c.x) or float(value) > np.amax(c.x):
|
|
3825
|
+
# raise ValueError, 'x-value out of range'
|
|
3826
|
+
|
|
3827
|
+
for i in range(len(c.x)):
|
|
3828
|
+
if float(value) < np.amin(c.x):
|
|
3829
|
+
xypairs.append((float(value), 0)) # c.y[0]))
|
|
3830
|
+
elif float(value) > np.amax(c.x):
|
|
3831
|
+
xypairs.append((float(value), 0)) # c.y[-1]))
|
|
3832
|
+
elif c.x[i] == float(value):
|
|
3833
|
+
xypairs.append((float(value), c.y[i]))
|
|
3834
|
+
else:
|
|
3835
|
+
xmax = c.x[i]
|
|
3836
|
+
if i + 1 < len(c.x):
|
|
3837
|
+
xmax = c.x[i + 1]
|
|
3838
|
+
|
|
3839
|
+
if c.x[i] < float(value) < xmax:
|
|
3840
|
+
y = np.interp(float(value), [c.x[i], xmax], [c.y[i], c.y[i + 1]])
|
|
3841
|
+
xypairs.append((float(value), y))
|
|
3842
|
+
elif xmax < float(value) < c.x[i]:
|
|
3843
|
+
y = np.interp(float(value), [xmax, c.x[i]], [c.y[i + 1], c.y[i]])
|
|
3844
|
+
xypairs.append((float(value), y))
|
|
3845
|
+
|
|
3846
|
+
return xypairs
|
|
3847
|
+
|
|
3848
|
+
|
|
3849
|
+
def line(m, b, xmin, xmax, numpts=100):
|
|
3850
|
+
"""
|
|
3851
|
+
Generate a line with y = mx + b and an optional number of points.
|
|
3852
|
+
|
|
3853
|
+
>>> curves = list()
|
|
3854
|
+
|
|
3855
|
+
>>> curves.append(pydvif.line(2, 5, 0, 10))
|
|
3856
|
+
|
|
3857
|
+
>>> pydvif.create_plot(curves, legend=True, stylename='ggplot')
|
|
3858
|
+
|
|
3859
|
+
:param m: The slope
|
|
3860
|
+
:type m: float
|
|
3861
|
+
:param b: The y-intercept
|
|
3862
|
+
:type b: float
|
|
3863
|
+
:param xmin: The minimum x value
|
|
3864
|
+
:type xmin: float
|
|
3865
|
+
:param xmax: The maximum x value
|
|
3866
|
+
:type xmax: float
|
|
3867
|
+
:param numpts: The number of points to use for the new line
|
|
3868
|
+
:type numpts: int
|
|
3869
|
+
:return: Curve -- The curve representing the newly created line
|
|
3870
|
+
"""
|
|
3871
|
+
m = float(m)
|
|
3872
|
+
b = float(b)
|
|
3873
|
+
xmin = float(xmin)
|
|
3874
|
+
xmax = float(xmax)
|
|
3875
|
+
numpts = int(numpts)
|
|
3876
|
+
|
|
3877
|
+
spacing = (xmax - xmin) / (numpts - 1)
|
|
3878
|
+
x = list()
|
|
3879
|
+
y = list()
|
|
3880
|
+
|
|
3881
|
+
for i in range(numpts):
|
|
3882
|
+
x.append(xmin)
|
|
3883
|
+
y.append(xmin * m + b)
|
|
3884
|
+
xmin += spacing
|
|
3885
|
+
|
|
3886
|
+
x = np.array(x)
|
|
3887
|
+
y = np.array(y)
|
|
3888
|
+
c = curve.Curve('', f'Straight Line (m: {m} b: {b} xmin: {xmin} xmax: {xmax})')
|
|
3889
|
+
c.x = x
|
|
3890
|
+
c.y = y
|
|
3891
|
+
|
|
3892
|
+
return c
|
|
3893
|
+
|
|
3894
|
+
|
|
3895
|
+
def delta(xmn, x0, xmx, npts=100):
|
|
3896
|
+
"""
|
|
3897
|
+
Procedure: Generate a Dirac delta distribution such that
|
|
3898
|
+
Int(xmin, xmax, dt*delta(t - x0)) = 1
|
|
3899
|
+
|
|
3900
|
+
:param xmn: The minimum x location
|
|
3901
|
+
:type xmn: float
|
|
3902
|
+
:param x0: The location of the unit impulse
|
|
3903
|
+
:type x0: float
|
|
3904
|
+
:param xmx: The maximum x location
|
|
3905
|
+
:type xmx: float
|
|
3906
|
+
:param npts: The number of points for the curve
|
|
3907
|
+
:type npts: int
|
|
3908
|
+
:return: The Dirac delta distribution
|
|
3909
|
+
:rtype: curve.Curve
|
|
3910
|
+
"""
|
|
3911
|
+
# From Ultra
|
|
3912
|
+
dxt = xmx - xmn
|
|
3913
|
+
dxi = dxt / npts
|
|
3914
|
+
dxl = x0 - xmn
|
|
3915
|
+
dnl = dxl / dxi
|
|
3916
|
+
xv1 = (dxi * dnl) + xmn
|
|
3917
|
+
xv2 = xv1 + dxi
|
|
3918
|
+
ds = dxi**2
|
|
3919
|
+
yv1 = (xv2 - x0) / ds
|
|
3920
|
+
yv2 = (x0 - xv1) / ds
|
|
3921
|
+
# dxr = xmx - x0
|
|
3922
|
+
numl = dnl - 1
|
|
3923
|
+
numr = (npts - 2) - numl
|
|
3924
|
+
|
|
3925
|
+
crvl = line(0, 0, xmn, xv1 - dxi, numl)
|
|
3926
|
+
crvr = line(0, 0, xv2 + dxi, xmx, numr)
|
|
3927
|
+
crvm = makecurve([xv1, xv2], [yv1, yv2])
|
|
3928
|
+
|
|
3929
|
+
x = np.concatenate([crvl.x, crvm.x, crvr.x])
|
|
3930
|
+
y = np.concatenate([crvl.y, crvm.y, crvr.y])
|
|
3931
|
+
|
|
3932
|
+
c = makecurve(x, y, f'Dirac Delta {xmn} {x0} {xmx}')
|
|
3933
|
+
|
|
3934
|
+
return c
|
|
3935
|
+
|
|
3936
|
+
|
|
3937
|
+
def makeextensive(curvelist):
|
|
3938
|
+
"""
|
|
3939
|
+
Set the y-values such that ``y[i] *= (x[i+1] - x[i])``
|
|
3940
|
+
|
|
3941
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3942
|
+
|
|
3943
|
+
>>> pydvif.makeextensive(curves)
|
|
3944
|
+
|
|
3945
|
+
>>> pydvif.create_plot(curves, legend=True)
|
|
3946
|
+
|
|
3947
|
+
:param curvelist: The curve or list of curves
|
|
3948
|
+
:type curvelist: Curve or list
|
|
3949
|
+
"""
|
|
3950
|
+
curves = list()
|
|
3951
|
+
|
|
3952
|
+
if isinstance(curvelist, list):
|
|
3953
|
+
curves.extend(curvelist)
|
|
3954
|
+
else:
|
|
3955
|
+
curves.append(curvelist)
|
|
3956
|
+
|
|
3957
|
+
for c in curves:
|
|
3958
|
+
for i in range(1, len(c.y)):
|
|
3959
|
+
c.y[i] *= (c.x[i] - c.x[i - 1])
|
|
3960
|
+
|
|
3961
|
+
c.y[0] = c.y[1]
|
|
3962
|
+
c.name = 'mkext(' + c.name + ')'
|
|
3963
|
+
|
|
3964
|
+
|
|
3965
|
+
def makeintensive(curvelist):
|
|
3966
|
+
"""
|
|
3967
|
+
Set the y-values such that y[i] /= (x[i+1] - x[i]).
|
|
3968
|
+
|
|
3969
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3970
|
+
|
|
3971
|
+
>>> pydvif.makeintensive(curves)
|
|
3972
|
+
|
|
3973
|
+
>>> pydvif.create_plot(curves, legend=True)
|
|
3974
|
+
|
|
3975
|
+
:param curvelist: The curve or list of curves
|
|
3976
|
+
:type curvelist: Curve or list
|
|
3977
|
+
"""
|
|
3978
|
+
curves = list()
|
|
3979
|
+
|
|
3980
|
+
if isinstance(curvelist, list):
|
|
3981
|
+
curves.extend(curvelist)
|
|
3982
|
+
else:
|
|
3983
|
+
curves.append(curvelist)
|
|
3984
|
+
|
|
3985
|
+
for c in curves:
|
|
3986
|
+
for i in range(1, len(c.y)):
|
|
3987
|
+
d = c.x[i] - c.x[i - 1] if (c.x[i] - c.x[i - 1]) != 0 else 0.000000001
|
|
3988
|
+
c.y[i] /= d
|
|
3989
|
+
|
|
3990
|
+
c.y[0] = c.y[1]
|
|
3991
|
+
c.name = 'mkint(' + c.name + ')'
|
|
3992
|
+
|
|
3993
|
+
|
|
3994
|
+
def dupx(curvelist):
|
|
3995
|
+
"""
|
|
3996
|
+
Duplicate the x-values such that y = x for each of the given curves.
|
|
3997
|
+
|
|
3998
|
+
>>> curves = pydvif.read('testData.txt')
|
|
3999
|
+
|
|
4000
|
+
>>> pydvif.dupx(curves)
|
|
4001
|
+
|
|
4002
|
+
>>> pydvif.create_plot(curves, legend=True)
|
|
4003
|
+
|
|
4004
|
+
:param curvelist: The curve or list of curves
|
|
4005
|
+
:type curvelist: Curve or list
|
|
4006
|
+
"""
|
|
4007
|
+
curves = list()
|
|
4008
|
+
|
|
4009
|
+
if isinstance(curvelist, list):
|
|
4010
|
+
curves.extend(curvelist)
|
|
4011
|
+
else:
|
|
4012
|
+
curves.append(curvelist)
|
|
4013
|
+
|
|
4014
|
+
for c in curves:
|
|
4015
|
+
c.y = np.copy(c.x)
|
|
4016
|
+
|
|
4017
|
+
|
|
4018
|
+
def sort(curve):
|
|
4019
|
+
"""
|
|
4020
|
+
Sort the specified curve so that their points are plotted in order of ascending x values.
|
|
4021
|
+
|
|
4022
|
+
>>> c = pydvif.span(1, 10)
|
|
4023
|
+
|
|
4024
|
+
>>> pydvif.sort(c)
|
|
4025
|
+
|
|
4026
|
+
:param curve: The curve to sort
|
|
4027
|
+
:type curve: Curve
|
|
4028
|
+
"""
|
|
4029
|
+
index_array = np.argsort(curve.x)
|
|
4030
|
+
x = list()
|
|
4031
|
+
y = list()
|
|
4032
|
+
|
|
4033
|
+
for index in index_array:
|
|
4034
|
+
x.append(curve.x[index])
|
|
4035
|
+
y.append(curve.y[index])
|
|
4036
|
+
|
|
4037
|
+
curve.x = np.array(x)
|
|
4038
|
+
curve.y = np.array(y)
|
|
4039
|
+
|
|
4040
|
+
|
|
4041
|
+
def rev(curve):
|
|
4042
|
+
"""
|
|
4043
|
+
Swap x and y values for the specified curves. You may want to sort after this one.
|
|
4044
|
+
|
|
4045
|
+
>>> c = pydvif.span(1, 10)
|
|
4046
|
+
|
|
4047
|
+
>>> pydvif.rev(c)
|
|
4048
|
+
|
|
4049
|
+
:param curve: The curve to sort
|
|
4050
|
+
:type curve: Curve
|
|
4051
|
+
"""
|
|
4052
|
+
x = np.copy(curve.y)
|
|
4053
|
+
y = np.copy(curve.x)
|
|
4054
|
+
|
|
4055
|
+
curve.x = x
|
|
4056
|
+
curve.y = y
|
|
4057
|
+
|
|
4058
|
+
|
|
4059
|
+
def random(curve):
|
|
4060
|
+
"""
|
|
4061
|
+
Generate random y values between -1 and 1 for the specified curves.
|
|
4062
|
+
|
|
4063
|
+
>>> c = pydvif.span(1, 10)
|
|
4064
|
+
|
|
4065
|
+
>>> pydvif.random(c)
|
|
4066
|
+
|
|
4067
|
+
:param curve: The curve to sort
|
|
4068
|
+
:type curve: Curve
|
|
4069
|
+
"""
|
|
4070
|
+
for i in range(len(curve.y)):
|
|
4071
|
+
curve.y[i] = sysrand.uniform(-1, 1)
|
|
4072
|
+
|
|
4073
|
+
|
|
4074
|
+
def xindex(curvelist):
|
|
4075
|
+
"""
|
|
4076
|
+
Create curves with y-values vs. integer index values.
|
|
4077
|
+
|
|
4078
|
+
>>> curves = pydvif.read('testData.txt')
|
|
4079
|
+
|
|
4080
|
+
>>> pydvif.xindex(curves)
|
|
4081
|
+
|
|
4082
|
+
>>> pydvif.create_plot(curves, legend=True)
|
|
4083
|
+
|
|
4084
|
+
:param curvelist: The curve or list of curves
|
|
4085
|
+
:type curvelist: Curve or list
|
|
4086
|
+
"""
|
|
4087
|
+
curves = list()
|
|
4088
|
+
|
|
4089
|
+
if isinstance(curvelist, list):
|
|
4090
|
+
curves.extend(curvelist)
|
|
4091
|
+
else:
|
|
4092
|
+
curves.append(curvelist)
|
|
4093
|
+
|
|
4094
|
+
for c in curves:
|
|
4095
|
+
stop = len(c.y)
|
|
4096
|
+
c.x = np.linspace(1, stop, num=stop)
|
|
4097
|
+
|
|
4098
|
+
|
|
4099
|
+
def appendcurves(curvelist):
|
|
4100
|
+
"""
|
|
4101
|
+
Merge two or more curves over the union of their domains. Where domains overlap, take the
|
|
4102
|
+
average of the curve's y-values.
|
|
4103
|
+
|
|
4104
|
+
>>> curves = pydvif.read('testData.txt')
|
|
4105
|
+
|
|
4106
|
+
>>> newcurve = pydvif.appendcurve(curves)
|
|
4107
|
+
|
|
4108
|
+
:param curvelist: the specified curves
|
|
4109
|
+
:type curvelist: list
|
|
4110
|
+
:return: Curve -- the merging of the two curves c1 and c2
|
|
4111
|
+
"""
|
|
4112
|
+
if len(curvelist) < 2:
|
|
4113
|
+
if len(curvelist) == 1:
|
|
4114
|
+
return curvelist[0]
|
|
4115
|
+
else:
|
|
4116
|
+
return
|
|
4117
|
+
else:
|
|
4118
|
+
nc = curve.append(curvelist[0], curvelist[1])
|
|
4119
|
+
|
|
4120
|
+
for i in range(2, len(curvelist)):
|
|
4121
|
+
nc = curve.append(nc, curvelist[i])
|
|
4122
|
+
|
|
4123
|
+
suffix = ''
|
|
4124
|
+
for c in curvelist:
|
|
4125
|
+
suffix += "%s" % c.plotname
|
|
4126
|
+
|
|
4127
|
+
nc.name = 'Append(' + suffix + ')'
|
|
4128
|
+
|
|
4129
|
+
return nc
|
|
4130
|
+
|
|
4131
|
+
|
|
4132
|
+
def max_curve(curvelist):
|
|
4133
|
+
"""
|
|
4134
|
+
Construct a curve from the maximum y values of the intersection of the curves domain.
|
|
4135
|
+
|
|
4136
|
+
:param curvelist: the specified curves
|
|
4137
|
+
:return: Curve -- a new curve with the maximum y-values over the intersection of the
|
|
4138
|
+
domains of the specified curves.
|
|
4139
|
+
"""
|
|
4140
|
+
# Get union of domains
|
|
4141
|
+
if len(curvelist) <= 1:
|
|
4142
|
+
return None
|
|
4143
|
+
else:
|
|
4144
|
+
ux = set(curvelist[0].x).union(set(curvelist[1].x))
|
|
4145
|
+
for i in range(2, len(curvelist)):
|
|
4146
|
+
ux = set(curvelist[i].x).union(ux)
|
|
4147
|
+
|
|
4148
|
+
ux = list(ux)
|
|
4149
|
+
ux.sort()
|
|
4150
|
+
|
|
4151
|
+
# Create curve label suffix
|
|
4152
|
+
name_suffix = ''
|
|
4153
|
+
for i in range(len(curvelist)):
|
|
4154
|
+
name_suffix += "%s" % curvelist[i].plotname
|
|
4155
|
+
|
|
4156
|
+
# Calculate max
|
|
4157
|
+
x = np.array(ux)
|
|
4158
|
+
y = np.zeros(len(x))
|
|
4159
|
+
|
|
4160
|
+
for i in range(len(x)):
|
|
4161
|
+
y[i] = float(-sys.maxsize - 1)
|
|
4162
|
+
for j in range(len(curvelist)):
|
|
4163
|
+
try:
|
|
4164
|
+
vals = gety(curvelist[j], x[i])
|
|
4165
|
+
for val in vals:
|
|
4166
|
+
if y[i] < val[1]:
|
|
4167
|
+
y[i] = val[1]
|
|
4168
|
+
except:
|
|
4169
|
+
pass
|
|
4170
|
+
|
|
4171
|
+
nc = curve.Curve('', 'Max(' + name_suffix + ')')
|
|
4172
|
+
nc.x = np.array(x)
|
|
4173
|
+
nc.y = y
|
|
4174
|
+
|
|
4175
|
+
return nc
|
|
4176
|
+
|
|
4177
|
+
|
|
4178
|
+
def min_curve(curvelist):
|
|
4179
|
+
"""
|
|
4180
|
+
Construct a curve from the minimum y values of the intersection of the curves domain.
|
|
4181
|
+
|
|
4182
|
+
:param curvelist: the specified curves
|
|
4183
|
+
:return: Curve -- a new curve with the minimum y-values over the intersection of the
|
|
4184
|
+
domains of the specified curves.
|
|
4185
|
+
"""
|
|
4186
|
+
# Get union of domains
|
|
4187
|
+
if len(curvelist) <= 1:
|
|
4188
|
+
return None
|
|
4189
|
+
else:
|
|
4190
|
+
ux = set(curvelist[0].x).union(set(curvelist[1].x))
|
|
4191
|
+
for i in range(2, len(curvelist)):
|
|
4192
|
+
ux = set(curvelist[i].x).union(ux)
|
|
4193
|
+
|
|
4194
|
+
ux = list(ux)
|
|
4195
|
+
ux.sort()
|
|
4196
|
+
|
|
4197
|
+
# Create curve label suffix
|
|
4198
|
+
name_suffix = ''
|
|
4199
|
+
for i in range(len(curvelist)):
|
|
4200
|
+
name_suffix += "%s" % curvelist[i].plotname
|
|
4201
|
+
|
|
4202
|
+
# Calculate min
|
|
4203
|
+
x = np.array(ux)
|
|
4204
|
+
y = np.zeros(len(x))
|
|
4205
|
+
|
|
4206
|
+
for i in range(len(x)):
|
|
4207
|
+
y[i] = float(sys.maxsize)
|
|
4208
|
+
for j in range(len(curvelist)):
|
|
4209
|
+
try:
|
|
4210
|
+
vals = gety(curvelist[j], x[i])
|
|
4211
|
+
for val in vals:
|
|
4212
|
+
if y[i] > val[1]:
|
|
4213
|
+
y[i] = val[1]
|
|
4214
|
+
except:
|
|
4215
|
+
pass
|
|
4216
|
+
|
|
4217
|
+
nc = curve.Curve('', 'Min(' + name_suffix + ')')
|
|
4218
|
+
nc.x = np.array(x)
|
|
4219
|
+
nc.y = y
|
|
4220
|
+
|
|
4221
|
+
return nc
|
|
4222
|
+
|
|
4223
|
+
|
|
4224
|
+
def average_curve(curvelist):
|
|
4225
|
+
"""
|
|
4226
|
+
Average the specified curves over the intersection of their domains.
|
|
4227
|
+
|
|
4228
|
+
:param curvelist: the specified curves
|
|
4229
|
+
:return: Curve -- a new curve with the average values over the intersection of the domains of the specified curves.
|
|
4230
|
+
"""
|
|
4231
|
+
# Get union of domains
|
|
4232
|
+
if len(curvelist) <= 1:
|
|
4233
|
+
return None
|
|
4234
|
+
else:
|
|
4235
|
+
ux = set(curvelist[0].x).union(set(curvelist[1].x))
|
|
4236
|
+
for i in range(2, len(curvelist)):
|
|
4237
|
+
ux = set(curvelist[i].x).union(ux)
|
|
4238
|
+
|
|
4239
|
+
ux = list(ux)
|
|
4240
|
+
ux.sort()
|
|
4241
|
+
|
|
4242
|
+
# Create curve label suffix
|
|
4243
|
+
name_suffix = ''
|
|
4244
|
+
for i in range(len(curvelist)):
|
|
4245
|
+
name_suffix += "%s" % curvelist[i].plotname
|
|
4246
|
+
|
|
4247
|
+
# Calculate average
|
|
4248
|
+
x = np.array(ux)
|
|
4249
|
+
y = np.zeros(len(x))
|
|
4250
|
+
|
|
4251
|
+
for i in range(len(x)):
|
|
4252
|
+
cnt = 0
|
|
4253
|
+
for j in range(len(curvelist)):
|
|
4254
|
+
try:
|
|
4255
|
+
vals = gety(curvelist[j], x[i])
|
|
4256
|
+
for val in vals:
|
|
4257
|
+
y[i] += val[1]
|
|
4258
|
+
cnt += 1
|
|
4259
|
+
except:
|
|
4260
|
+
pass
|
|
4261
|
+
|
|
4262
|
+
y[i] /= cnt
|
|
4263
|
+
|
|
4264
|
+
nc = curve.Curve('', 'Average(' + name_suffix + ')')
|
|
4265
|
+
nc.x = np.array(x)
|
|
4266
|
+
nc.y = y
|
|
4267
|
+
|
|
4268
|
+
return nc
|
|
4269
|
+
|
|
4270
|
+
|
|
4271
|
+
########################################################
|
|
4272
|
+
################## Private Methods ##################### # noqa e266
|
|
4273
|
+
########################################################
|
|
4274
|
+
|
|
4275
|
+
def __fft(c):
|
|
4276
|
+
"""
|
|
4277
|
+
Compute the Fast Fourier Transform of a real curve.
|
|
4278
|
+
|
|
4279
|
+
:param c: The curve
|
|
4280
|
+
:type c: Curve
|
|
4281
|
+
:return: tuple - two curves, one with the real part and the other with the imaginary part for their y-values.
|
|
4282
|
+
"""
|
|
4283
|
+
nc1 = curve.Curve('', 'Real part FFT ' + __toCurveString(c))
|
|
4284
|
+
nc2 = curve.Curve('', 'Imaginary part FFT ' + __toCurveString(c))
|
|
4285
|
+
|
|
4286
|
+
cnorm = c.normalize()
|
|
4287
|
+
clen = len(c.x)
|
|
4288
|
+
|
|
4289
|
+
complex_array = np.fft.fft(cnorm.y)
|
|
4290
|
+
|
|
4291
|
+
nc1.y = complex_array.real
|
|
4292
|
+
nc1.x = np.linspace(min(cnorm.x), max(cnorm.x), len(nc1.y))
|
|
4293
|
+
|
|
4294
|
+
nc2.y = complex_array.imag
|
|
4295
|
+
nc2.x = np.linspace(min(cnorm.x), max(cnorm.x), clen)
|
|
4296
|
+
|
|
4297
|
+
my(nc2, -1)
|
|
4298
|
+
|
|
4299
|
+
return nc1, nc2
|
|
4300
|
+
|
|
4301
|
+
|
|
4302
|
+
def __ifft(cr, ci):
|
|
4303
|
+
"""
|
|
4304
|
+
Compute the 1D inverse discrete Fourier Transform.
|
|
4305
|
+
|
|
4306
|
+
:param cr: Curve containing the real part of a complex number as it's y-values.
|
|
4307
|
+
:type c: Curve
|
|
4308
|
+
:param ci: Curve containing the imaginary part of a complex number as it's y-values
|
|
4309
|
+
:type c: Curve
|
|
4310
|
+
:return: tuple - two curves, one with the real part and the other with the imaginary part for their y-values.
|
|
4311
|
+
"""
|
|
4312
|
+
nc1 = curve.Curve('', 'Real part iFFT ' + __toCurveString(cr))
|
|
4313
|
+
nc2 = curve.Curve('', 'Imaginary part iFFT ' + __toCurveString(ci))
|
|
4314
|
+
|
|
4315
|
+
carray = np.zeros(len(cr.y), dtype=complex)
|
|
4316
|
+
|
|
4317
|
+
for i in range(len(cr.y)):
|
|
4318
|
+
carray[i] = complex(cr.y[i], ci.y[i])
|
|
4319
|
+
|
|
4320
|
+
numpy1_10 = LooseVersion(np.__version__) >= LooseVersion("1.10.0")
|
|
4321
|
+
|
|
4322
|
+
if numpy1_10:
|
|
4323
|
+
complex_array = np.fft.ifft(carray)
|
|
4324
|
+
else:
|
|
4325
|
+
complex_array = np.fft.ifft(carray)
|
|
4326
|
+
|
|
4327
|
+
# nc1.x = np.array(cr.x)
|
|
4328
|
+
nc1.y = complex_array.real
|
|
4329
|
+
nc1.x = np.linspace(min(cr.x), max(cr.x), len(nc1.y))
|
|
4330
|
+
|
|
4331
|
+
# nc2.x = np.array(ci.x)
|
|
4332
|
+
nc2.y = complex_array.imag
|
|
4333
|
+
nc2.x = np.linspace(min(ci.x), max(ci.x), len(nc2.y))
|
|
4334
|
+
|
|
4335
|
+
return nc1, nc2
|
|
4336
|
+
|
|
4337
|
+
|
|
4338
|
+
def __complex_times(ra, ia, rb, ib):
|
|
4339
|
+
"""
|
|
4340
|
+
Perform the complex product of the given pairs of curves representing the real and imaginary components.
|
|
4341
|
+
|
|
4342
|
+
:param ra: Curve containing the real part
|
|
4343
|
+
:type ra: Curve
|
|
4344
|
+
:param ia: Curve containing the imaginary part
|
|
4345
|
+
:type ia: Curve
|
|
4346
|
+
:param rb: Curve containing the real part
|
|
4347
|
+
:type rb: Curve
|
|
4348
|
+
:param ib: Curve containing the imaginary part
|
|
4349
|
+
:type ib: Curve
|
|
4350
|
+
:return: tuple - pair of curves representing the complex conjugate
|
|
4351
|
+
"""
|
|
4352
|
+
rs1 = ra * rb
|
|
4353
|
+
rs2 = ia * ib
|
|
4354
|
+
is1 = ra * ib
|
|
4355
|
+
is2 = ia * rb
|
|
4356
|
+
sa = rs1 - rs2
|
|
4357
|
+
sb = is1 + is2
|
|
4358
|
+
|
|
4359
|
+
return sa, sb
|
|
4360
|
+
|
|
4361
|
+
|
|
4362
|
+
def __get_sub_range(x, low, high):
|
|
4363
|
+
"""
|
|
4364
|
+
Returns a tuple with the index of the first value in x greater than low and
|
|
4365
|
+
the index of the first value in x less than high.
|
|
4366
|
+
|
|
4367
|
+
:param x: The array of x-values
|
|
4368
|
+
:type x: array
|
|
4369
|
+
:param low: The lower definite integral interval value
|
|
4370
|
+
:type low: float
|
|
4371
|
+
:param high: The upper definite integral interval value
|
|
4372
|
+
:type high: float
|
|
4373
|
+
:return: tuple -- a tuple with the indices of the first value in x that is
|
|
4374
|
+
greater than low and the first value in x less than high.
|
|
4375
|
+
If low or high is not specified, the corresponding return
|
|
4376
|
+
will be None.
|
|
4377
|
+
"""
|
|
4378
|
+
min_idx = np.where(x >= low)[0][0] if low is not None else 0
|
|
4379
|
+
max_idx = np.where(x <= high)[0][-1] if high is not None else len(x) - 1
|
|
4380
|
+
return min_idx, max_idx
|
|
4381
|
+
|
|
4382
|
+
|
|
4383
|
+
def __toCurveString(c):
|
|
4384
|
+
"""
|
|
4385
|
+
Returns the string description of the curve.
|
|
4386
|
+
|
|
4387
|
+
:param c: The curve
|
|
4388
|
+
:type c: Curve
|
|
4389
|
+
:return: str -- The curve's name if not empty, otherwise, the curve's plotname
|
|
4390
|
+
"""
|
|
4391
|
+
if c.name:
|
|
4392
|
+
return c.name
|
|
4393
|
+
|
|
4394
|
+
return c.plotname
|
|
4395
|
+
|
|
4396
|
+
|
|
4397
|
+
def __loadcolumns(fname, xcol):
|
|
4398
|
+
"""
|
|
4399
|
+
Load a column oriented text data file, add parsed curves to the curvelist.
|
|
4400
|
+
'#' is the comment character. The last comment line must be the column
|
|
4401
|
+
labels. We assume the first column is the x-data, every other column is y-data.
|
|
4402
|
+
We also assume all columns are the same length.
|
|
4403
|
+
|
|
4404
|
+
:param fname: The column oriented (.gnu) file
|
|
4405
|
+
:type fname: str
|
|
4406
|
+
:param xcol: x-column number for column oriented (.gnu) files
|
|
4407
|
+
:type xcol: int
|
|
4408
|
+
:returns: list -- the list of curves from the file
|
|
4409
|
+
"""
|
|
4410
|
+
curvelist = []
|
|
4411
|
+
|
|
4412
|
+
try:
|
|
4413
|
+
f = open(fname, 'r')
|
|
4414
|
+
lines = f.readlines()
|
|
4415
|
+
iLine = 0
|
|
4416
|
+
for line in lines:
|
|
4417
|
+
if line.strip()[0] != '#':
|
|
4418
|
+
break
|
|
4419
|
+
iLine += 1
|
|
4420
|
+
if iLine == 0:
|
|
4421
|
+
print('WARNING: columns have no labels, labels will be assigned...someday')
|
|
4422
|
+
alllabels = lines[iLine - 1][1:] # drop leading '#' character
|
|
4423
|
+
if '"' in alllabels:
|
|
4424
|
+
colLabels = [x for x in alllabels.split('"')[1:-1] if len(x.replace(" ", "")) > 0]
|
|
4425
|
+
else:
|
|
4426
|
+
colLabels = alllabels.split()
|
|
4427
|
+
# check that we have a label for every column
|
|
4428
|
+
if len(colLabels) != len(lines[iLine].split()) and iLine > 0:
|
|
4429
|
+
raise RuntimeError('Sorry, right now PyDV requires you to have a label for every column.')
|
|
4430
|
+
# We assume some column is the x-data, every other column
|
|
4431
|
+
# is y-data
|
|
4432
|
+
numcurves = len(lines[iLine].split()) - 1
|
|
4433
|
+
|
|
4434
|
+
# Make the curves, append them to self.curvelist.
|
|
4435
|
+
# First, get data into lists of numbers
|
|
4436
|
+
# numDataLines = len(lines) - iLine
|
|
4437
|
+
localCurves = []
|
|
4438
|
+
for i in range(numcurves + 1):
|
|
4439
|
+
localCurves.append([])
|
|
4440
|
+
# FIGURE OUT COOL WAY TO DO THIS LATER: localCurves = (numcurves+1)*[[]]
|
|
4441
|
+
for line in lines[iLine:]:
|
|
4442
|
+
nums = [float(n) for n in line.split()]
|
|
4443
|
+
assert len(nums) == numcurves + 1
|
|
4444
|
+
for colID in range(numcurves + 1):
|
|
4445
|
+
localCurves[colID].append(nums[colID])
|
|
4446
|
+
# convert lists to numpy arrays
|
|
4447
|
+
for colID in range(numcurves):
|
|
4448
|
+
localCurves[colID] = np.array(localCurves[colID])
|
|
4449
|
+
# Make Curve objects, add to curvelist
|
|
4450
|
+
for colID in range(numcurves + 1):
|
|
4451
|
+
if colID != xcol:
|
|
4452
|
+
c = curve.Curve(fname, colLabels[colID])
|
|
4453
|
+
c.x = localCurves[xcol]
|
|
4454
|
+
c.y = localCurves[colID]
|
|
4455
|
+
print("Appended curve: ", colLabels[colID], len(c.x), len(c.y))
|
|
4456
|
+
curvelist.append(c)
|
|
4457
|
+
# tidy up
|
|
4458
|
+
f.close()
|
|
4459
|
+
# anticipate failure!
|
|
4460
|
+
except IOError:
|
|
4461
|
+
traceback.print_exc(file=sys.stdout)
|
|
4462
|
+
print('could not load file: ' + fname)
|
|
4463
|
+
except ValueError:
|
|
4464
|
+
print('invalid pydv file: ' + fname)
|
|
4465
|
+
|
|
4466
|
+
return curvelist
|
|
4467
|
+
|
|
4468
|
+
|
|
4469
|
+
def __loadpdb(fname, fpdb):
|
|
4470
|
+
curvelist = []
|
|
4471
|
+
|
|
4472
|
+
try:
|
|
4473
|
+
curveList = fpdb.ls('curve*')
|
|
4474
|
+
if (len(curveList) == 0):
|
|
4475
|
+
raise ValueError
|
|
4476
|
+
for cname in curveList:
|
|
4477
|
+
curveid = fpdb.read(cname).strip('\x00').split('|')
|
|
4478
|
+
if (len(curveid) != 8):
|
|
4479
|
+
raise IOError
|
|
4480
|
+
current = curve.Curve(fname, fpdb.read(curveid[1]).strip('\x00'))
|
|
4481
|
+
current.x = np.array(fpdb.read(curveid[3]))
|
|
4482
|
+
current.y = np.array(fpdb.read(curveid[4]))
|
|
4483
|
+
curvelist.append(current)
|
|
4484
|
+
|
|
4485
|
+
fpdb.close()
|
|
4486
|
+
except IOError:
|
|
4487
|
+
print('could not load file: ' + fname)
|
|
4488
|
+
except ValueError:
|
|
4489
|
+
print('invalid pydv file: ' + fname)
|
|
4490
|
+
|
|
4491
|
+
return curvelist
|