concatenation in IPython.display in a notebook using Latex+symbols - python

Say I have an expression which I would like to display in LateX form and one which is a result of an analytical calculation where variables like theta appear and are pretty printed in the end. I would like to print both in one line. Here an example:
from IPython.display import display, Math, Latex
import numpy as np
from sympy import *
init_printing()
# In[1]:
name='\Gamma^'+str(1)+'_{'+str(2)+str(3)+'}'+'='
# In[2]:
theta = symbols('theta')
# In[3]:
display(Math(name),theta)
The last command prints name in a pretty form (LateX) as well as theta. However, a line-break is added which I would like to omit. How can this be achieved?

You need to form latex string first. Use sympy.latex() to make string from any printable sympy variable:
display(Math(name + latex(theta)))
I also wrote simple function with variable number of arguments for such output. No need to wrap variables with latex() here:
def prlat(*args):
str = ''
for arg in args:
str += latex(arg)
display(Math(str))
prlat(name, theta, '= 0')

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

My code doesn't output the full parametric equation only the first value in python

I am trying to find the parametric equations for a certain set of plots, however when I implement the code I only get the first value back. The code is from a website, as I am not very proficient in python. I am using 3.6.5. Here is the code:
import numpy as np
import scipy as sp
from fractions import Fraction
def trigSeries(x):
f=sp.fft(x)
n=len(x)
A0=abs(f[0])/n
A0=Fraction(A0).limit_denominator(1000)
hn=np.ceil(n/2)
f=f[1:int(hn)]
A=2*abs(f)/n
P=sp.pi/2-sp.angle(f)
A=map(Fraction,A)
A=map(lambda a:a.limit_denominator(1000),A)
P=map(Fraction,P)
P=map(lambda a:a.limit_denominator(1000),P)
s=map(str,A)
s=map(lambda a: a+"*np.sin(", s)
s=map(lambda a,b,c :
a+str(b)+"-2*sp.pi*t*"+str(c)+")",
s,P,range(1,len(list(P))+1))
s="+".join(s)
s=str(A0)+"+"+s
return s
x=[5041,4333,3625,3018,2816,2967,3625,4535,5800,6811,7823,8834,8429,7418,6305,5193,4181,3018,3018,3777,4687,5496,6912,7974,9087]
y=[4494,5577,6930,8825,10990,13426,14509,15456,15456,15186,15321,17486,19246,21005,21276,21952,22223,23712,25877,27501,28178,28448,27636,26960,25742]
xf=trigSeries(x)
print(xf)
Any help would be appreciated.
I tried to make the code to work but i could not manage to do it.
The problem id that when you call map(...) You create an iterator, so in order to print it's content you have to do:
for data in iterator:
print(data)
The problem her is that when you apply the lambda function if you cycle over the variable it returns nothing.
You colud convert all the lambda in for cycles, but you have to think over the triple-argument lambda.
The problem is at the step
s=map(lambda a,b,c :
a+str(b)+"-2*sp.pi*t*"+str(c)+")",
s,P,range(1,len(list(P))+1))
it returns empty list. To resolve it, convert s and P to lists just before feeding to this map function. Add two lines above.
s = list(s)
P = list(P)
Output for your example
134723/25+308794/391*np.sin(-1016/709-2*sp.pi*t*1)+2537094/989*np.sin(641/835-2*sp.pi*t*2)+264721/598*np.sin(-68/241-2*sp.pi*t*3)+285344/787*np.sin(-84/997-2*sp.pi*t*4)+118145/543*np.sin(-190/737-2*sp.pi*t*5)+281400/761*np.sin(-469/956-2*sp.pi*t*6)+1451/8*np.sin(-563/489-2*sp.pi*t*7)+122323/624*np.sin(-311/343-2*sp.pi*t*8)+115874/719*np.sin(-137/183-2*sp.pi*t*9)+171452/861*np.sin(-67/52-2*sp.pi*t*10)+18152/105*np.sin(-777/716-2*sp.pi*t*11)+24049/125*np.sin(-107/76-2*sp.pi*t*12)

How can I dynamically generate a python symbol statement?

I am trying to write a routine that normalizes (rewrites) a mathematical equation that may have more than one symbol on the LHS so that it only has one.
The following code illustrates what I want to do
Assume I have an equation
ln(x)-ln(x1)= -(a+by)
I want to solve for x or return
x=x1*exp(-a+by)
Using sympy I can do the following
from sympy import *
formula=' log(x)-log(x1) =-(a+b*y)'
lhs,rhs=formula.split('=',1)
x,x_1,y,a,b,y=symbols('x x_1 y a b y')
r=sympy.solve(eval(lhs)-eval(rhs),x)
r
==>
Output: [x1*exp(-a - b*y)]
I am trying to automate this for a range of input lines as follows
from sympy import *
import re
# eventually to be read ina loop from a file
formula="DLOG(SAUMMCREDBISCN/SAUNECONPRVTXN) =-0.142368233181-0.22796245228*(LOG(SAUMMCREDBISCN(-1)/SAUNECONPRVTXN(-1))+0.2*((SAUMMLOANINTRCN(-1)-SAUINTR(-1))/100)-LOG(SAUNYGDPMKTPKN(-1)))+0.576050997065*SAUNYGDPGAP_/100"
#try to convert formula into a string containing just the synbols
sym1=formula.replace("*"," ")
sym1=sym1.replace("DLOG"," ")
sym1=sym1.replace("LOG"," ")
sym1=sym1.replace("EXP"," ")
sym1=sym1.replace("RECODE"," ")
sym1=re.sub('[()/+-\=]',' ',sym1)
sym1=re.sub(' +',' ',sym1)
#This logic works for this particular formula
sym1
#now generate a string that has, instead of spaces between symbols
ss2=sym1.replace(' ',',')
#This is the part that does not work I want to generate a command that effectively says
#symbol,symbol2,..,symboln=symbols('symbol1 symbol2 ... symboln')
#tried this but it fails
eval(ss2)=symbols(sym1)
Generates the result
eval(ss2)=symbols(sym1)
^
SyntaxError: can't assign to function call
Any help for this py noob, would be greatly appreciated.
var('a b c') will inject symbol name 'a', 'b', 'c' into the namespace but perhaps #Blorgbeard is asking about lists or dicts because instead of creating many symbols you could put the symbols in a dictionary and then access them by name:
>>> formula=' log(x)-log(x1) =-(a+b*y)'
>>> eq = Eq(*map(S, formula.split('=', 1)))
>>> v = dict([(i.name, i) for i in eq.free_symbols]); v
{'y': y, 'b': b, 'x': x, 'x1': x1, 'a': a}
>>> solve(eq, v['x'])
[x1*exp(-a - b*y)]
So it is not actually necessary to use eval or to have a variable matching a symbol name: S can convert a string to an expression and free_symbols can identify which symbols are present. Putting them in a dictionary with keys being the Symbol name allows them to be retrieved from the dictionary with a string.
I think what you want to generate a string from these two statements and then you can eval that string
str_eq = f'{ss2} = {symbols(sym1)}'
print(str_eq)
>>' ,SAUMMCREDBISCN,SAUNECONPRVTXN,SAUMMCREDBISCN,SAUNECONPRVTXN,SAUMMLOANINTRCN,SAUINTR,SAUNYGDPMKTPKN,SAUNYGDPGAP_, = (SAUMMCREDBISCN, SAUNECONPRVTXN, SAUMMCREDBISCN, SAUNECONPRVTXN, SAUMMLOANINTRCN, SAUINTR, SAUNYGDPMKTPKN, SAUNYGDPGAP_)'
The first line says - give me a string but run the python code between the {} before returning it. For instance
print(f'Adding two numbers: (2+3) = {2 + 3}')
>> Adding two numbers: (2+3) = 5
First, maybe this could help make your code a bit denser.
If I understand correctly, you're trying to assign a variable using a list of names. You could use vars()[x]=:
import re
from sympy import symbols
symbol_names = re.findall("SAU[A-Z_]+",formula)
symbol_objs = symbols(symbol_names)
for sym_name,sym_obj in zip(symbol_names,symbol_objs):
vars()[sym] = sym_obj
A colleague of mine (Ib Hansen) gave me a very nice and elegant solution to the original problem (how to solve for the complicated expression) that by-passed the string manipulation solution that my original question was struggling with and which most answers addressed.
His solution is to use sympify and solve from sympy
from sympy import sympify, solve
import re
def normalize(var,eq,simplify=False,manual=False):
'''normalize an equation with respect to var using sympy'''
lhs, rhs = eq.split('=')
kat = sympify(f'Eq({lhs},{rhs})')
var_sym = sympify(var)
out = str(solve(kat, var_sym,simplify=simplify,manual=manual))[1:-1]
return f'{var} = {out}'
This works perfectly
from sympy import sympify, solve
import re
def norm(var,eq,simplify=False,manual=False):
'''normalize an equation with respect to var using sympy'''
lhs, rhs = eq.split('=')
kat = sympify(f'Eq({lhs},{rhs})')
var_sym = sympify(var)
out = str(solve(kat, var_sym,simplify=simplify,manual=manual))[1:-1] # simplify takes for ever
return f'{var} = {out}'
``` Re write equation spelling out the dlog (delta log) function that python does no know, and putting log into lowe case '''
test8=norm('saummcredbiscn','log(saummcredbiscn/sauneconprvtxn) -log(saummcredbiscn(-1)/sauneconprvtxn(-1)) =-0.142368233181-0.22796245228*(log(saummcredbiscn(-1)/sauneconprvtxn(-1))+0.2*((saummloanintrcn(-1)-sauintr(-1))/100)-log(saunygdpmktpkn(-1)))+0.576050997065*saunygdpgap_/100')
print (test8)
with result
saummcredbiscn = 0.867301828366361*sauneconprvtxn*(saummcredbiscn(-1.0)/sauneconprvtxn(-1.0))**(19300938693/25000000000)*saunygdpmktpkn(-1.0)**(5699061307/25000000000)*exp(0.00576050997065*saunygdpgap_ + 0.00045592490456*sauintr(-1.0) - 0.00045592490456*saummloanintrcn(-1.0)

Python string formatting exponential output

I'm trying to change the output of an exponential string formatting. I've fitted a curve to some data and would like to write these into the plot. Problem is, the x e-y format doesn't look nice, is there a posibility to change it so x * 10^-y?
Here is an example of the code I'm working with:
plt.plot(x, y, 'x', label = '$f(t) = {a:.0f} \cdot x + {b:.2e}$'.format(a = para[0], b = para[1])
a is some number bigger than 10000, that's why there is no need for decimalnumbers, but b is around 10^-7. Writing it as a float is spacewasting for the leading 0s, but the e^-7 doesn't look nice for publishing, that why I would like to change the output of the e-formatter, so it gives \cdot 10^{-7} (the \cdot {} for LaTeX) back.
Thanks
I would suggest you write an ad-hoc function to format the number in the output you want, something like this:
import numpy as np
def myformat(x):
myexp = np.floor(np.log10(x))
xout = x*10**(-myexp)
strout = "{:.2f} \times 10^{}".format(xout, myexp)
return strout
All, that need to be formated in LaTex style, must be wrapped with $ sign:
label='$f(t)$ = $x$ $\cdot$10$^-$$^7$'
Sign ^ makes aftergoing char as superscript (x$^5$ will give x to the power of 5) and _ is using for subscript (x$_5$ will give you x with index 5)

user inputs in python giving float, array multiplication issue

I have following lines of code working fine when inputs given in console:
import numpy as np
def simple_exponential_smoothing(actuals, n_forecast_periods,alpha):
return np.array([np.array([alpha*((1-alpha)**k)*actuals[len(actuals)-k-1] for k in range (len(actuals))]).sum()]*n_forecast_periods)
simple_exponential_smoothing(actuals, n_forecast_periods,alpha)
However, it doesn't work when try to get same user inputs in code itself:
import numpy as np
actuals = []
actuals = input("Input list:")
n_forecast_periods = int(input("Int:"))
alpha = float(input("float:"))
def simple_exponential_smoothing(actuals, n_forecast_periods,alpha):
return np.array([np.array([alpha*((1-alpha)**k)*actuals[len(actuals)-k-1] for k in range (len(actuals))]).sum()]*n_forecast_periods)
simple_exponential_smoothing(actuals, n_forecast_periods,alpha)
Apologize, if this is not a good question. I am new to Python.
I have already tried using map function for multiplication; too complex for me to use it in following setup.

Categories