Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended qnArrayTwo class to include all ufuncs which make sense #2

Open
wants to merge 106 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
93be5e4
added new html_str property to quantity to provide html formatting
mayya-bondarevskaya Feb 28, 2017
d28840a
resolve encoding issues
mayya-bondarevskaya Jun 27, 2017
016fb33
add basic initialisation of qnArray class
mayya-bondarevskaya Jun 27, 2017
8f097a2
minor qnArray compatibility resolvement
mayya-bondarevskaya Jun 27, 2017
b7f3a36
allow division with qnArray as well
mayya-bondarevskaya Jun 27, 2017
1af4204
add division function to qnArray class
mayya-bondarevskaya Jun 27, 2017
bf424f9
begin testing of qnArray class
mayya-bondarevskaya Jun 27, 2017
9759a6d
add new error-raising features
mayya-bondarevskaya Jun 27, 2017
fa68171
add more qnArray initialisation tests
mayya-bondarevskaya Jun 27, 2017
84d8ceb
add check for arrays of strings as input values
mayya-bondarevskaya Jun 28, 2017
d4a999f
add compatibility with qn_array
mayya-bondarevskaya Jun 28, 2017
02298fc
add tests
mayya-bondarevskaya Jun 28, 2017
1460451
change numpy array from containing Quantity objects to containing an …
mayya-bondarevskaya Jul 3, 2017
d355195
add multiplication test
mayya-bondarevskaya Jul 3, 2017
d2f94c9
add more qnArray multiplication tests
mayya-bondarevskaya Jul 3, 2017
bb32317
add test for other object type to be only Quantity
mayya-bondarevskaya Jul 3, 2017
22f6224
add qnArray division test
mayya-bondarevskaya Jul 3, 2017
14168e4
add more comprehensive error testing
mayya-bondarevskaya Jul 3, 2017
ef49589
separate exception raising situations into separate tests
mayya-bondarevskaya Jul 3, 2017
3f4fd2a
another variation of qn_array
mayya-bondarevskaya Jul 4, 2017
236411d
add tests to qnArrayTwo class
mayya-bondarevskaya Jul 4, 2017
98d39d2
add testing of standard deviation initialisation in qnArrayTwo
mayya-bondarevskaya Jul 4, 2017
2a9b766
add function created
mayya-bondarevskaya Jul 4, 2017
33868f3
add function in qnArrayTwo tested
mayya-bondarevskaya Jul 4, 2017
30f8afc
add functin to subtract qnArrayTwo objects
mayya-bondarevskaya Jul 4, 2017
aecb9da
add tests for subtracting qnArrayTwo objects
mayya-bondarevskaya Jul 4, 2017
1d5a0ec
add multiplication function
mayya-bondarevskaya Jul 4, 2017
1b8e93a
add testing of multiplication of qnArrayTwo objects
mayya-bondarevskaya Jul 4, 2017
f8e27c9
add division function
mayya-bondarevskaya Jul 4, 2017
c0e80cc
test division function
mayya-bondarevskaya Jul 4, 2017
dfb73da
add standard deviation calculations to algebra function
mayya-bondarevskaya Jul 4, 2017
0b6e892
test standard deivation calculations during algebraic calculations
mayya-bondarevskaya Jul 4, 2017
dfbb8ef
add standard deviation calculation to __pow__ function
mayya-bondarevskaya Jul 4, 2017
306b4de
add __pow__ function to qnArrayTwo class
mayya-bondarevskaya Jul 4, 2017
0a53c63
test qnArrayTwo __pow__ function
mayya-bondarevskaya Jul 4, 2017
b6f9c09
added __eq__ function but facing recursion depth exceded error
mayya-bondarevskaya Jul 4, 2017
1c8033f
prepare tests for not currently functioning __eq__ function
mayya-bondarevskaya Jul 4, 2017
fd6db2a
add html_str function to output html style representation of the array
mayya-bondarevskaya Jul 4, 2017
df8068b
add tests for html_str function
mayya-bondarevskaya Jul 4, 2017
73f4e27
add test file for Dimensions class
mayya-bondarevskaya Jul 6, 2017
f28400c
add DimensionsError class to handle exceptions
mayya-bondarevskaya Jul 6, 2017
3986d72
add tests for usage of DimensionsError class and when it arises furin…
mayya-bondarevskaya Jul 6, 2017
f562e10
add tests for Dimensions objects mutiplication and division
mayya-bondarevskaya Jul 6, 2017
73e5629
add tests for Dimensions class for __pow__ and __eq__
mayya-bondarevskaya Jul 6, 2017
95fb38b
add dimensions __neq__ function tests
mayya-bondarevskaya Jul 7, 2017
c3e923a
add testing of kwargs during init
mayya-bondarevskaya Jul 7, 2017
fc24734
add test for var type in dims list upon init
mayya-bondarevskaya Jul 7, 2017
e8ae7d7
add tests for Dimensions initialisation using key word args
mayya-bondarevskaya Jul 7, 2017
fe4a31d
add tests for Dimensions class str representation
mayya-bondarevskaya Jul 7, 2017
4a0b43e
add test for symbol class init
mayya-bondarevskaya Jul 7, 2017
dc505c0
add str output to symbol in case no name is supplied
mayya-bondarevskaya Jul 7, 2017
8eb3768
add test for str representation of symbol class
mayya-bondarevskaya Jul 7, 2017
cc6ef62
add tests of si_prefixes
mayya-bondarevskaya Jul 7, 2017
85cf58e
add test for SIPrefix init
mayya-bondarevskaya Jul 7, 2017
398c83b
add test for BaseUnit class
mayya-bondarevskaya Jul 10, 2017
87d72d3
add test for equality between base units
mayya-bondarevskaya Jul 10, 2017
e9cdcbb
add test for str representation of base units
mayya-bondarevskaya Jul 10, 2017
e140da8
add SIPrefix pbject comparison function
mayya-bondarevskaya Jul 10, 2017
3a79b18
add SIPrefix object comparison tests
mayya-bondarevskaya Jul 10, 2017
06866cd
add Quantity.parse function tests
mayya-bondarevskaya Jul 10, 2017
b43d274
remove sd parameter in favour of speed, adjust all algebraic operatio…
mayya-bondarevskaya Jul 12, 2017
a7a6a9b
adjust tests to not include sd parameter in the qnArrayTwo class init…
mayya-bondarevskaya Jul 12, 2017
79b9ace
add radd, rsub, rmul, and rtruediv functions to qnArrayTwo class
mayya-bondarevskaya Jul 12, 2017
ead8019
add possiblity to add, divide, multiply, and subtract by qnArrayTwo o…
mayya-bondarevskaya Jul 12, 2017
d3eafcf
add tests for all combinations of algebraic operations
mayya-bondarevskaya Jul 12, 2017
ca2a490
add __eq__ function to qnArrayTwo
mayya-bondarevskaya Jul 12, 2017
a4d414f
add tests for __eq__ function
mayya-bondarevskaya Jul 12, 2017
cc6906c
fix html_str functions results to not include standard deviation and …
mayya-bondarevskaya Jul 12, 2017
de2bb0c
add initialisation of Quantity object standard deviation to 0 if None…
mayya-bondarevskaya Jul 13, 2017
ca3eeca
add standard deviation initialisation and calculation when adding/sub…
mayya-bondarevskaya Jul 13, 2017
daac867
add tests for manipulation of standard deviation when adding qn arrays
mayya-bondarevskaya Jul 13, 2017
d5daae4
replace algebraic functions with predefined ufuncs using __array_ufunc__
mayya-bondarevskaya Jul 13, 2017
16ae6a1
add test for AtomUnit init
mayya-bondarevskaya Jul 13, 2017
7789815
add test for pow of AtomUnit
mayya-bondarevskaya Jul 13, 2017
c4a2046
fix quantity class to provide result to __pow__ function using Quanti…
mayya-bondarevskaya Jul 10, 2017
2039ece
implement radd, rsub, rmul, and rtruediv functions
mayya-bondarevskaya Jul 19, 2017
61a2428
add future tests for other ufuncs
mayya-bondarevskaya Jul 19, 2017
a0ef262
implement exp ufunc
mayya-bondarevskaya Jul 19, 2017
90fee7d
fix testing equation
mayya-bondarevskaya Jul 19, 2017
5995aad
implement sin and cos ufuncs
mayya-bondarevskaya Jul 19, 2017
d4ddb9e
add tests for sin and cos ufuncs
mayya-bondarevskaya Jul 19, 2017
e856c31
implement more arcsin, arccos, arctan, sinh, cosh, tanh, arcsinh, arc…
mayya-bondarevskaya Jul 19, 2017
12a5dc9
implement tests for arcsin, arccos, and arctan ufuncs
mayya-bondarevskaya Jul 19, 2017
c03ed2f
add more tests for sd prop
mayya-bondarevskaya Jul 20, 2017
064eefb
add conversion function
mayya-bondarevskaya Jul 20, 2017
04783e6
add tests for qnArrayTwo conversion
mayya-bondarevskaya Jul 20, 2017
a7bd632
add function to append values to qnArrayTwo and to plot two qnArrayTw…
mayya-bondarevskaya Jul 20, 2017
b25fe35
test append function
mayya-bondarevskaya Jul 20, 2017
3fa23b4
add unit checking for ufuncs, make append function only accept Quanti…
mayya-bondarevskaya Jul 24, 2017
cab9536
adjust tests for appending only Quantities to qnArrayTwo types
mayya-bondarevskaya Jul 24, 2017
33ed106
add more robust testing mechanism for ufuncs
mayya-bondarevskaya Jul 25, 2017
a602c03
add true_divide, floor_divide, and negative ufuncs
mayya-bondarevskaya Jul 25, 2017
afb2f0c
complete testing of all ufuncs in ufunc_dict_one_input
mayya-bondarevskaya Jul 26, 2017
05e5c78
add changing of units given a ufunc with two inputs
mayya-bondarevskaya Jul 26, 2017
93d79e1
add testing of ufuncs with two inputs
mayya-bondarevskaya Jul 26, 2017
00f9cf6
add checking of all ufuncs with two inputs
mayya-bondarevskaya Jul 26, 2017
869dffc
add all math operator ufuncs that make sense in the qnArrayTwo context
mayya-bondarevskaya Jul 26, 2017
2bca371
fix minor bug
mayya-bondarevskaya Jul 27, 2017
37e3abe
rearrange testing mechanism to loop over reworked ufuncs
mayya-bondarevskaya Jul 27, 2017
2ac3fdb
add separate file for ufuncs and error calculation function
mayya-bondarevskaya Jul 27, 2017
215c295
fix minor bugs
mayya-bondarevskaya Jul 26, 2017
d440ae6
remove original qnArray and replace with qnArrayTwo as primary array …
mayya-bondarevskaya Aug 1, 2017
17a2cdd
add more meaningful commenting of class methods
mayya-bondarevskaya Aug 1, 2017
44a8bf2
add preamble to file
mayya-bondarevskaya Aug 1, 2017
c8ba250
add units checking for addition and subtraction of QnArray objects
mayya-bondarevskaya Aug 7, 2017
8dc6146
fix conversion to mol
mayya-bondarevskaya Aug 23, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions pyqn/dimensions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# dimensions.py
# A class representing the dimensions of a physical quantity's units, in
# terms of powers of length (L), mass (M), time (T), temperature (Theta),
Expand All @@ -22,9 +25,15 @@
# You should have received a copy of the GNU General Public License
# along with PyQn. If not, see <http://www.gnu.org/licenses/>

class DimensionsError(Exception):
def __init__(self, error_str):
self.error_str = error_str
def __str__(self):
return self.error_str

class Dimensions(object):
# these are the abbreviations for Length, Mass, Time, Temperature,
# Quantity (amount of substance), Current, and Luminous Intensity:
# Quantity (amount of substance), Current, and Luminous Intensity
dim_names = ['L', 'M', 'T', 'Theta', 'Q', 'C', 'I']
dim_desc = ['length', 'mass', 'time', 'temperature', 'amount',
'current', 'luminous intensity']
Expand All @@ -37,10 +46,12 @@ def __init__(self, dims=None, **kwargs):
if dims:
# initialize by dims array
if not kwargs:
self.dims = dims
if (len(dims) == 7) and (type(dims[0]) is not str):
self.dims = dims
else:
raise DimensionsError('Inconsistent number of dimensions in input or non-value elements of input array')
else:
print('bad initialisation of Dimensions object')
sys.exit(1)
raise DimensionsError('Bad initialisation of Dimensions object')
else:
# initialize by keyword arguments
for dim_name in kwargs:
Expand Down Expand Up @@ -104,4 +115,4 @@ def __ne__(self, other):
d_voltage = d_energy / d_charge # 1 V = 1 J/C
d_magfield_strength = d_voltage * d_time / d_area # 1 T = 1 V.s/m^2
d_magnetic_flux = d_voltage * d_time # 1 Wb = 1 V.s
d_temperature = Dimensions(Theta=1)
d_temperature = Dimensions(Theta=1)
277 changes: 266 additions & 11 deletions pyqn/qn_array.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,274 @@
from .symbol import Symbol
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# qn_array.py
# A class representing an array of physical quantities, with units and
# uncertainty.
#
# Copyright (C) 2012-2017 Christian Hill
# Department of Physics and Astronomy, University College London
# [email protected]
#
# This file is part of PyQn
#
# PyQn is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyQn is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PyQn. If not, see <http://www.gnu.org/licenses/>

import numpy as np
from .units import Units
from .quantity import Quantity
from .ufunc_dictionaries import *
import matplotlib.pyplot as plt
import csv

class qnArrayError(Exception):
class QnArrayError(Exception):
"""
An Exception class for errors that might occur whilst manipulating
QnArray objects.

"""

def __init__(self, error_str):
self.error_str = error_str
def __str__(self):
return self.error_str

class qnArray(Symbol):
def __init__(self, name=None, latex=None, html=None, values=None,
units=None, sd=None, definition=None)
Symbol.__init__(self, name, latex, html, definition)
if type(values)==list:
self.values = np.array(values)
elif type(values)==numpy.ndarray:
self.values = values
class QnArray(np.ndarray):
"""
A Python class representing an array of values, their units and
errors. This class extends the numpy ndarray class such that
QnArray objects can be used with numpy ufuncs and the errors are
propagated using the functions defined in the ufunc_dictionaries.py
file.

"""

def __new__(cls, input_array, info=None, units='1', sd=None):
"""
Initialises a qnArray as a child class derived from the numpy
ndarray. The units are set to default to be unitless, but can
be set to be a string (which will be converted to a Units
object) or set straight away to be a Units object, the standard
deviation is set to default to an array of zeros.

"""

obj = np.asarray(input_array).view(cls)
obj.info = info
if sd is None:
obj.sd = np.zeros(len(input_array))
else:
raise qnArrayError
obj.sd = np.array(sd)

if type(units) is str:
obj.units = Units(units) #records units as Unit class
elif type(units) is Units:
obj.units = units
return obj

def __array_finalize__(self, obj):
"""
Function which is called each time that a function is operated
on the QnArray object.

"""

if obj is None: return
self.info = getattr(obj, 'info', None)
self.sd = getattr(obj, 'sd', None)

def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
"""
Function which is called when numpy ufuncs are called on the
QnArray object. It uses predefined equations to calculate the
new errors of the returned QnArray objects.

"""

if ufunc in ufunc_dict_alg:
alg_func = ufunc_dict_alg[ufunc][0]
sd_func = ufunc_dict_alg[ufunc][1]
units_func = ufunc_dict_alg[ufunc][2]
alg_func_reverse = ufunc_dict_alg[ufunc][3]

if all([hasattr(x, 'units') for x in inputs]):
result_units = units_func(inputs[0].units,
inputs[1].units)

# if both are qn arrays
if (type(inputs[1]) is QnArray) and \
(type(inputs[0]) is QnArray):
result_val = getattr(np.asarray(inputs[0]),
alg_func)(np.asarray(inputs[1]))
result_sd = sd_func(result_val, np.asarray(inputs[0]),
np.asarray(inputs[1]),
inputs[0].sd,
inputs[1].sd)

# if one input is a quantity
elif type(inputs[1]) is Quantity:
result_val = getattr(np.asarray(inputs[0]),
alg_func)(inputs[1].value)
result_sd = sd_func(result_val, np.asarray(inputs[0]),
inputs[1].value,
inputs[0].sd,
inputs[1].sd)

elif type(inputs[0]) is Quantity:
result_val = getattr(np.asarray(inputs[1]),
alg_func_reverse)(inputs[0].value)
result_sd = sd_func(result_val, inputs[0].value,
np.asarray(inputs[1]),
inputs[0].sd,
inputs[1].sd)

# for all other object types
elif type(inputs[0]) is QnArray:
result_val = getattr(np.asarray(inputs[0]),
alg_func)(inputs[1])
result_sd = sd_func(result_val, np.asarray(inputs[0]),
inputs[1],
inputs[0].sd, 0)
result_units = units_func(inputs[0].units, Units('1'))

else:
result_val = getattr(np.asarray(inputs[1]),
alg_func_reverse)(inputs[0])
result_sd = sd_func(result_val, inputs[0],
np.asarray(inputs[1]),
0, inputs[1].sd)
result_units = units_func(Units('1'), inputs[1].units)

return QnArray(result_val, units = result_units,
sd = result_sd)

elif ufunc in ufunc_dict_one_input:
#checks if units of input are valid
unit_test_func = ufunc_dict_one_input[ufunc][1]
inputs_checked = unit_test_func(inputs[0])

#extracts functions for finding sd and units
sd_func = ufunc_dict_one_input[ufunc][0]
units_func = ufunc_dict_one_input[ufunc][2]

#calculates results
result_val = ufunc(np.asarray(inputs_checked))
result_sd = sd_func(result_val,
np.asarray(inputs_checked),
np.asarray(inputs_checked.sd))
result_units = units_func(inputs[0].units)
return QnArray(result_val, units = result_units,
sd = result_sd)

elif ufunc in ufunc_dict_two_inputs:
unit_test_func = ufunc_dict_two_inputs[ufunc][1]
input1 = unit_test_func(inputs[0])
input2 = unit_test_func(inputs[1])
sd_func = ufunc_dict_two_inputs[ufunc][0]
units_func = ufunc_dict_two_inputs[ufunc][2]
result_val = ufunc(np.asarray(input1),np.asarray(input2))
result_sd = sd_func(result_val, np.asarray(input1),
np.asarray(input2),
input1.sd, input2.sd)
result_units = units_func(input1.units, input2.units)
return QnArray(result_val, units = result_units,
sd = result_sd)

def __eq__(self, other):
"""
Checks if two QnArray objects are the same, given that their
values and units are the same.

"""

if all(super(QnArray, self).__eq__(super(QnArray, other))) and \
(self.units == other.units):
return True
else:
return False

@property
def html_str(self):
"""
Creates a representation of the array in the HTML format.

"""

html_chunks = []
for i in range(len(self)):
html_chunks.append('{} {}'.format(self[i],self.units))
return ', '.join(html_chunks)

def convert_units_to(self, new_units, force=None):
"""
Converts the units of the array given a new unit. It uses the
conversion factor generator of the Units class.

"""

to_units = Units(new_units)
fac = self.units.conversion(to_units, force)
new_vals = np.asarray(self)*fac
new_sd = self.sd*fac
return QnArray(new_vals, units = new_units, sd = new_sd)

def append(self, input_quantity):
"""
Appends a Quantity object to the QnArray object.

"""

if self.units != input_quantity.units:
raise QnArrayError('Same units expected')
return QnArray(np.append(np.asarray(self),
input_quantity.value),
units = self.units,
sd = np.append(self.sd,input_quantity.sd))

def plot_qn_arrays(qn_arr_1, qn_arr_2):
"""
Plots two QnArray objects using matplotlib with their errors.

"""

plt.errorbar(np.asarray(qn_arr_1),np.asarray(qn_arr_2),
xerr = qn_arr_1.sd, yerr = qn_arr_2.sd)
plt.show()

def load_data(filename, file_type, errors=False):
"""
Function which generates two QnArray objects given a csv file.

"""

vals1 = []
vals2 = []
sd1 = []
sd2 = []
if file_type is 'csv':
with open(filename,'rb') as f:
reader = csv.reader(f)
if errors is False:
for row in reader:
vals1.append(row[0])
vals2.append(row[1])
sd1.append(0)
sd2.append(0)
else:
for row in reader:
vals1.append(row[0])
sd1.append(row[1])
vals2.append(row[2])
sd2.append(row[3])
return QnArray(vals1, units = '1', sd = sd1), \
QnArray(vals2, units = '1', sd = sd2)
Loading