Modify or add functions to an existing package - python

I want to modify functions from a package in Python. To be precise, I'll take the example of the fastkde package. I have two questions.
Looking at the source code of the function pdf_at_points, the object returned is pdf. Instead, I'd like to return the _pdfobj object. How can I do so without modifying the source code ? Ideally, I'd like to do it in a random script, so that my code is "transferable".
The last two lines of the pdf_at_points function call the applyBernacchiaFilter and the __transformphiSC_points__ functions, that cannot be called in a script. How can I make them accessible in a random script ?
Here's an idea of the ideal output:
from fastkde import fastKDE
import numpy as np
N = 2e5
var1 = 50*np.random.normal(size=N) + 0.1
var2 = 0.01*np.random.normal(size=N) - 300
var3 = 50*np.random.normal(size=N) + 0.1
var4 = 0.01*np.random.normal(size=N) - 300
test_points = list(zip(var3, var4))
# Some lines of code here that I'm looking for,
# that would create the pdf_at_points_modified function
# and that would make applyBernacchiaFilter and __transformphiSC_points__
# functions usable
myPDF = fastKDE.pdf_at_points_modified(var1,var2)
myPDF.applyBernacchiaFilterModified()
pred = myPDF.__transformphiSC_points__(test_points)
pdf_at_points_modified corresponds to the modified pdf_at_points function.
Thanks in advance.

Related

Saving an image of an expression displayed with Sympy?

I'm relatively new to Sympy and had a lot of trouble with the information that I was able to scavenge on this site. My main goal is basically to take a string, representing some mathematical expression, and then save an image of that expression but in a cleaner form.
So for example, if this is the expression string:
"2**x+(3-(4*9))"
I want it to display like this
cleaner image.
This is currently the code that I have written in order to achieve this, based off of what I was able to read on StackExchange:
from matplotlib import pylab
from sympy.parsing.sympy_parser import parse_expr
from sympy.plotting import plot
from sympy.printing.preview import preview
class MathString:
def __init__(self, expression_str: str):
self.expression_str = expression_str
#property
def expression(self):
return parse_expr(self.expression_str)
def plot_expression(self):
return plot(self.expression)
def save_plot(self):
self.plot_expression().saveimage("imagePath",
format='png')
And then using a main function:
def main():
test_expression = '2**x+(3-(4*9))'
test = MathString(test_expression)
test.save_plot()
main()
However, when I run main(), it just sends me an actual graphical plot of the equation I provided. I've tried multiple other solutions but the errors ranged from my environment not supporting LaTeX to the fact that I am passing trying to pass the expression as a string.
Please help! I'm super stuck and do not understand what I am doing wrong! Given a certain address path where I can store my images, how can I save an image of the displayed expression using Sympy/MatPlotLib/whatever other libraries I may need?
The program in your question does not convert the expression from
string format to the sympy internal format. See below for examples.
Also, sympy has capabilities to detect what works best in your
environment. Running the following program in Spyder 5.0 with an
iPython 7.22 terminal, I get the output in Unicode format.
from sympy import *
my_names = 'x'
x = symbols(','.join(my_names))
ns1 = {'x': x}
my_symbols = tuple(ns1.values())
es1 = '2**x+(3-(4*9))'
e1 = sympify(es1, locals=ns1)
e2 = sympify(es1, locals=ns1, evaluate=False)
print(f"String {es1} with symbols {my_symbols}",
f"\n\tmakes expression {e1}",
f"\n\tor expression {e2}")
# print(simplify(e1))
init_printing()
pprint(e2)
Output (in Unicode):
# String 2**x+(3-(4*9)) with symbols (x,)
# makes expression 2**x - 33
# or expression 2**x - 4*9 + 3
# x
# 2 - 4⋅9 + 3

Using python to process a LaTeX file and create random questions

I am using python to pre-process a LaTeX file before running it through the LaTeX compiler. I have a python script which reads a .def file. The .def file contains some python code at the top which helps to initialize problems with randomization. Below the python code I have LaTeX code for the problem. For each variable in the LaTeX code, I use the symbol # to signify that it should be randomized and replaced before compiling. For example, I may write #a to be a random integer between 1 and 10.
There may be larger issues with what I'm trying to do, but so far it's working mostly as I need it to. Here is a sample .def file:
a = random.choice(range(-3,2))
b = random.choice(range(-6,1))
x1 = random.choice(range(a-3,a))
x2 = x1+3
m = 2*x1 - 2*a + 3
y1 = (x1-a)**2+b
y2 = (x2-a)**2+b
xmin = a - 5
xmax = a + 5
ymin = b-1
ymax = b+10
varNames = [["#a", str(a)],["#b", str(b)], ["#x1",str(x1)], ["#x2",str(x2)], ["#m", str(m)], ["#y1",str(y1)], ["#y2",str(y2)], ["#xmin", str(xmin)], ["#xmax", str(xmax)], ["#ymin", str(ymin)], ["#ymax", str(ymax)]]
#####
\question The graph of $f(x) = (x-#a)^2+#b$ is shown below along with a secant line between the points $(#x1,#y1)$ and $(#x2,#y2)$.
\begin{center}
\begin{wc_graph}[xmin=#xmin, xmax=#xmax, ymin=#ymin, ymax=#ymax, scale=.75]
\draw[domain=#a-3.16:#a + 3.16, smooth] plot ({\x}, {(\x-#a)^2+#b});
\draw (#x1,#y1) to (#x2,#y2);
\pic at (#x1,#y1) {closed};
\pic at (#x2,#y2) {closed};
\end{wc_graph}
\end{center}
\begin{parts}
\part What does the slope of the secant line represent?
\vfill
\part Compute the slope of the secant line.
\vfill
\end{parts}
\newpage
As you can see, removing the #a and replacing it with the actual value of a is starting to become tedious. In my python script, I just replace all of the #ed things in my latexCode string.
for x in varNames:
latexCode = latexCode.replace(x[0],x[1])
which seems to work okay. However, it seems obnoxious and ugly.
My Question: Is there a better way of working between the variable identifier and the string version of the identifier? It would be great if I could simply make a python list of variable names I'm using in the .def file, and then run a simple command to update the LaTeX code. What I've done is cumbersome and painful. Thanks in advance!
Yes either eval (name) or getattr (obj, name) or globals () [name]. In this case I'd say globals [name].
Also vars would work:
https://docs.python.org/3/library/functions.html#vars
In the following fragment it's e.g used to make objects know their own name:
def _setPublicElementNames (self):
for var in vars (self):
if not var.startswith ('_'):
getattr (self, var) ._name = var
Yet another, unnecessary complicated, solution would be to generate a .py file with the right replace statements from your .def file.

Where to create multiple variables?

I have some python code which reads in a series of user-specified variables from another file, including some if statements for variables that aren't always selected by the user. An example of the code I have is as follows:
import sys
if __name__=="__main__":
#Read-in user input file
filename = sys.argv[-1]
#Import user-defined parameters
m = __import__(filename)
directory = m.directory
experimentNumber = m.experimentNumber
dataInput = m.dataInput
outputFile = m.outputFile
save_flag = m.save_flag
cores = m.cores
npts1 = m.npts1
npts2_recorded = m.npts2_recorded
weightingFuncNameDim2 = m.weightingFuncNameDim2
weightingFuncParamsDim2 = m.weightingFuncParamsDim2
if int(m.ndim) >= 2:
weightingFuncNameDim3 = m.weightingFuncNameDim3
weightingFuncParamsDim3 = m.weightingFuncParamsDim3
else:
weightingFuncNameDim3 = '-'
weightingFuncParamsDim3 = '-'
In total there are around 50 of these variables imported from the user-defined file. The imported variables are all used by other functions later in the code. The way I have coded this seems to set these as global variables so they can easily be used by other variables. However, is there a more pythonic way to do this? However, I'm not sure what the best approach would be to make these variables available without passing 50 variables into each function (cumbersome).

How to write a function in python?

I am doing exploratory data analysis, while doing that i am using the same lines of code many times .So i came to know that why can't i wrote the function for that.But i am new to python i don't know how to define a function exactly.So please help me.....
textdata is my main dataframe and tonumber,smstext are my variables
# subsetting the textdata
mesbytonum = textdata[['tonumber', 'smstext']]
# calculating the no.of messages by tonumber
messbytonum_freq = mesbytonum.groupby('tonumber').agg(len)
# resetting the index
messbytonum_freq.reset_index(inplace=True)
# making them in a descending order
messbytonum_freq_result = messbytonum_freq.sort(['smstext'], ascending=[0])
#calcuating percentages
messbytonum_freq_result['percentage'] = messbytonum_freq_result['smstext']/sum(messbytonum_freq_result['smstext'])
# considering top10
top10tonum = messbytonum_freq_result.head(10)
# top10tonum
i have repeated the similar kind of code around 20 times so i want to write the function for the above code which makes my code smaller. So please help me how can i define.
Thanks in advance
The function is defined like this:
def func(arg1, arg2, argN):
# do something
# you may need to return value(s) too
And called like this:
func(1,2,3) # you can use anything instead of 1,2 and 3
It will be
def MyFunc(textdata):
mesbytonum = textdata[['tonumber', 'smstext']]
messbytonum_freq = mesbytonum.groupby('tonumber').agg(len)
messbytonum_freq.reset_index(inplace=True)
messbytonum_freq_result = messbytonum_freq.sort(['smstext'], ascending=[0])
messbytonum_freq_result['percentage'] = messbytonum_freq_result['smstext']/sum(messbytonum_freq_result['smstext'])
top10tonum = messbytonum_freq_result.head(10)
return # what do you want to return?
# use this function
result=MyFunc(<argument here>)
# then you need to use result somehow
Your function can also return multiple values
return spam, egg
which you have to use like this
mySpam, myEgg=MyFunction(<argument>)

SymPy/SciPy: solving a system of ordinary differential equations with different variables

I am new to SymPy and Python in general, and I am currently working with Python 2.7 and SymPy 0.7.5 with the objective to:
a) read a system of differential equations from a text file
b) solve the system
I already read this question and this other question, and they are almost what I am looking for, but I have an additional issue: I do not know in advance the form of the system of equations, so I cannot create the corresponding function using def inside the script, as in this example. The whole thing has to be managed at run-time.
So, here are some snippets of my code. Suppose I have a text file system.txt containing the following:
dx/dt = 0.0387*x - 0.0005*x*y
dy/dt = 0.0036*x*y - 0.1898*y
What I do is:
# imports
import sympy
import scipy
import re as regex
# define all symbols I am going to use
x = sympy.Symbol('x')
y = sympy.Symbol('y')
t = sympy.Symbol('t')
# read the file
systemOfEquations = []
with open("system.txt", "r") as fp :
for line in fp :
pattern = regex.compile(r'.+?\s+=\s+(.+?)$')
expressionString = regex.search(pattern, line) # first match ends in group(1)
systemOfEquations.append( sympy.sympify( expressionString.group(1) ) )
At this point, I am stuck with the two symbolic expressions inside the systemOfEquation list. Provided that I can read the initial conditions for the ODE system from another file, in order to use scipy.integrate.odeint, I would have to convert the system into a Python-readable function, something like:
def dX_dt(X, t=0):
return array([ 0.0387*X[0] - 0.0005*X[0]*X[1] ,
-0.1898*X[1] + 0.0036*X[0]*X[1] ])
Is there a nice way to create this at run-time? For example, write the function to another file and then import the newly created file as a function? (maybe I am being stupid here, but remember that I am relatively new to Python :-D)
I've seen that with sympy.utilities.lambdify.lambdify it's possible to convert a symbolic expression into a lambda function, but I wonder if this can help me...lambdify seems to work with one expression at the time, not with systems.
Thank you in advance for any advice :-)
EDIT:
With minimal modifications, Warren's answer worked flawlessly. I have a list of all symbols inside listOfSymbols; moreover, they appear in the same order as the columns of data X that will be used by odeint. So, the function I used is
def dX_dt(X, t):
vals = dict()
for index, s in enumerate(listOfSymbols) :
if s != time :
vals[s] = X[index]
vals[time] = t
return [eq.evalf(subs=vals) for eq in systemOfEquations]
I just make an exception for the variable 'time' in my specific problem. Thanks again! :-)
If you are going to solve the system in the same script that reads the file (so systemOfEquations is available as a global variable), and if the only variables used in systemOfEquations are x, y and possibly t, you could define dX_dt in the same file like this:
def dX_dt(X, t):
vals = dict(x=X[0], y=X[1], t=t)
return [eq.evalf(subs=vals) for eq in systemOfEquations]
dX_dt can be used in odeint. In the following ipython session, I have already run the script that creates systemOfEquations and defines dX_dt:
In [31]: odeint(dX_dt, [1,2], np.linspace(0, 1, 5))
Out[31]:
array([[ 1. , 2. ],
[ 1.00947534, 1.90904183],
[ 1.01905178, 1.82223595],
[ 1.02872997, 1.73939226],
[ 1.03851059, 1.66032942]]

Categories