Writing in a specific format to a txt file in Python - python

I am trying to write theta in a specific format to a .txt file. I present the current and expected output.
import numpy as np
theta = np.pi/3
with open('Contact angle.txt', 'w+') as f:
f.write(f"theta = {str(theta)}\n")
The current output is
theta = 1.0471975511965976
The expected output is
theta = pi/3

NumPy doesn't understand symbolic math, so that's not going to work. What you should probably use instead is SymPy.
>>> import sympy
>>> theta = sympy.pi / 3
>>> theta
pi/3
And if you need to convert it to float, you can do that:
>>> float(theta)
1.0471975511965979

Why not code it like this:
theta = "pi/3"
with open('Contact angle.txt', 'w+') as f:
f.write(f"theta = {theta}\n")

This might be a job that is best suited for SymPy.
If theta will always be pi/<integer>, then you could do something like
import numpy as np
theta = np.pi/3
divisor = int(np.pi/theta)
with open('Contact angle.txt', 'w+') as f:
f.write(f'theta = pi/{divisor}\n")
The code will have to get a lot more fancy if theta is always some fraction of pi: theta = <integer1>pi/<integer2>

you can write theta as a string and use the function eval to get the value of theta like this:
from numpy import pi
theta = "pi/3"
with open('Contact angle.txt', 'w+') as f:
f.write(f"theta = {theta}\n")
the output of eval(theta) will be 1.0471975511965976

Related

Universal function with multiple array arguments

I am trying to make a universal function with multiple numpy array arguments using python.
import numpy as np
import matplotlib.pyplot as plt
import scipy.constants
pi = np.pi
i = 0.+1.j
c = scipy.constants.c
lam = 0.860e-6
f_c = c/lam
def refl_general(array_r, array_L, f):
array_phi = 2*pi*array_L*f/c
phi_sum = np.sum(array_phi)
exp_sum = np.exp(i*phi_sum)
r_all = np.prod(array_r)
r_in = array_r[0]
r_except_in = np.prod(array_r[1:])
return (-r_in + r_except_in*exp_sum)/(1-r_all*exp_sum)
This function works like refl_general(np.array([np.sqrt(0.5), np.sqrt(0.5), np.sqrt(0.5)]), np.array([1, 1, 1]), f_c).
I'd like to plot refl_general(np.array([np.sqrt(0.5), np.sqrt(0.5), np.sqrt(0.5)]), np.array([L/3, L/3, L/3]), f_c) against L = np.linspace(lam, 3*lam, 1000) without remaking the function.
I'd like to apply this function to each elements of L and get an array of each output. In other words, I want to write the following without using for.
array_L = np.linspace(lam, 3*lam, 1000)
array_signal = np.array([])
for L in array_L:
signal = np.abs(refl_general(np.array([np.sqrt(0.5), np.sqrt(0.5), np.sqrt(0.5)]), np.array([L/3, L/3, L/3]), f_c))
array_signal = np.append(array_signal, signal)
plt.plot(array_L, array_signal)
Simply writing refl_general(np.array([np.sqrt(0.5), np.sqrt(0.5), np.sqrt(0.5)]), np.array([L/3, L/3, L/3]), f_c) doesn doesn't achieve the desired output since np.array([L/3, L/3, L/3]) becomes a two-dimensional array
For example, I already know how to create a universal function using np.frompyfunc.
But, this also doesn't work as expected because the argument np.array([L/3, L/3, L/3]) is a two-dimensional array.

operation on Matrices with the elements in function form

I have a set of functions which are tended to be the elements of a matrix, and I have to do some + and * and / operation on them and also between each matrix element.
I am using Numpy, Sympy to do this and here is the code written on Python 2.7.
import numpy as np
import math
import cmath
import matplotlib.pyplot as pl
from cmath import*
from sympy import*
# delta, deltz and some other numbers are simple float number I changed varibles in for loop to the first value to test this section of my whole cod
f1 = Matrix([[1, 0],[ 0, 1]]) #an empty matrix from sympy
delta = 2.0*np.pi*1.6*((1.0/1530)-(1.0/(2.0*1550))) #this is a simple float number
deltz = (5*(10.0**6))/50
def apdFunc(x):
return np.exp(-2*np.log(2)*((x-(5/2))/5)**2)
def modFunc(x):
return (1+np.cos((2*np.pi/1)*x))
d1 = np.linspace(-20.0, 20.0, 5000)
apdFunc = apdFunc(d1)
modFunc = modFunc(d2)
Profile = modFunc*apdFunc
sig = (np.pi/1530)*fbgProfile + delta
kaa = (np.pi/1530)*fbgProfile
j = sqrt(-1)
gammab = np.sqrt(kaa**2.0-sig**2.0)
#Matrix elements definition
f11 = np.cosh(gammab*deltz)-1j*(sig/gammab)*np.sinh(gammab*deltz)
f22 = np.cosh(gammab*deltz)+1j*(sig/gammab)*np.sinh(gammab*deltz)
f12 = -1j*(kaa/gammab)*np.sinh(gammab*deltz)
f21 = 1j*(kaa/gammab)*np.sinh(gammab*deltz)
f1 = f1*Matrix([[f11, f12],[ f21, f22]])
PO=f1[0,0]
NO=f1[1,0]
REF=abs((NO/PO)**2)
pl.plot(d3,REF)
pl.show()
print f1[0,0]
print PO
print REF
The first problem is : gammab=np.sqrt(kaa**2.0-sig**2.0) that numpy can't accept complex number I mean negative value under sqrt and if I don't use Numpy I can't do Operation on them because kaa and sig are functions.
Second : I cant print the matrix elements (after reversing kaa**2.0-sig**2.0 and solving first problem), thus I can't plot the REF=abs((NO/PO)**2) and an error apears telling
AttributeError: 'ImmutableDenseNDimArray' object has no attribute 'as_coeff_Mul'
Any help appreciated and if you can introduce a reference to learn how to solve the problem.

Jacobi Method & Basic Matrix Math using NUMPY

I'm getting an import error for "norm". What am I not doing correct??
I'm open to constructive feedback on improving the code, however I have to keep the parameters as they are!
Thanks!!!
Code is below:
import numpy as np
from numpy import norm, inalg, array, zeros, diag, diagflat, dot, linalg
"""Test Case Data"""
A = np.matrix([[4,-1,-1],[-2,6,1],[-1,1,7]])
b = np.matrix([[3],[9],[-6]])
x = np.matrix([[0],[0],[0]])
"""Main Function"""
def jacobi(A, b, x, Tolerance, Iterations):
V = np.diag(A)
D = np.diag(V)
R = D-A
D_I = D.I
D = np.asmatrix(D)
Counter_1 = 1
tol_gauge = 100
while Counter_1 <= Iterations:
# I considered using the "dot" function in NUMPY but I was wary of mixed results
iterative_approach_form = D_I * ((R*x)+b)
tol_gauge = np.linalg.norm(iterative_approach_form-x)
x = iterative_approach_form
if initial_tol <= Tolerance:
return("The Solution x = {},y={}, z={} ".format(x[0], x[1], x[2]))
return("The Solution was found in %s interation(s)" %(Counter_1))
else:
pass
Counter_1 +=1
return("The Solution was not found in {} iteration(s)".format(Iterations))
You need to specify which numpy module you are importing from. The following works if you want to use a function only by its name:
from numpy import linalg
from numpy.linalg import norm
from numpy import zeros, array, diag, diagflat, dot
Looking at you code however, you don't need the second import line, because in the rest of the code the numpy functions are specified according to the accepted norm. For example, norm is already present in your code as np.linalg.norm.
There are three more issues with your code: 1) initial_tol is not assigned a value; 2) tol_gauge is assigned but not used in the code; 3) the last return statement is not indented properly (perhaps only here) and the same is very likely for the block in your while loop.

Time dependent equation fitting: Input is vector whereas output is scalar

I am new to python an d hope someone could help me here. I have this code i want to use for fitting of an experimental data:
import numpy as np
import scipy
import pandas as pd
import sys
from scipy.optimize import minimize
fileID = open("testdata.txt", "r+")
(t,Ids_measured) = np.loadtxt(fileID,unpack =True)
try:
all_the_file = fileID.readlines()
finally:
fileID.close()
Ids_final = Ids_measured[-1]
Ids_m = ()
def model_Ids(x0):
Amp = x0[0]
ß = x0[1]
tau = x0[2]
for i in range(len(t)):
Ids_m=(Ids_final - sum(Amp* (np.exp((-(t/ tau))))**ß))
return Ids_m
def objective(x0):
Ids_model = ()
Ids_m = ()
Ids_model =model_Ids(x0)
obj = 0.0
for i in range(len(Ids_measured)):
obj = obj + ((Ids_m[i]-Ids_measured[i])/Ids_measured[i])**2
return obj
x0 = np.zeros(3)
x0[0] = 0.0 # Amp
x0[1] = 0.0 # ß
x0[2] = 0.0 # tau
First, i want to load a text file and using a mathematical equation solve for Ids_m (modeling part). Since equation for Ids_m has some model variables, i want to change this later to match the objective defined in the objective function. The problem is when i run the code, i usually get a scalar for Ids_m instead of a vector for all values of t. Thus i have the error:
obj = obj + ((Ids_m[i]-Ids_measured[i])/Ids_measured[i])**2
IndexError: tuple index out of range
Can someone help me point to the error in this line of code. I would like to have the function model_Ids(x0) return a vector with lenght equal to the lenght of t
Thanks.

Python 3: Sympy: Include list information to optimize lambdify

I use lambdify to compile an expression which is a function of certain parameters. Each parameter has N points. So I need to evaluate the expression N times. The following shows a simplified example on how this is done.
import numpy as np
from sympy.parsing.sympy_parser import parse_expr
from sympy.utilities.lambdify import lambdify, implemented_function
from sympy import S, Symbol
from sympy.utilities.autowrap import ufuncify
def CreateMagneticFieldsList(dataToSave,equationString,DSList):
expression = S(equationString)
numOfElements = len(dataToSave["MagneticFields"])
#initialize the magnetic field output array
magFieldsArray = np.empty(numOfElements)
magFieldsArray[:] = np.NaN
lam_f = lambdify(tuple(DSList),expression,modules='numpy')
try:
for i in range(numOfElements):
replacementList = np.zeros(len(DSList))
for j in range(len(DSList)):
replacementList[j] = dataToSave[DSList[j]][i]
try:
val = np.double(lam_f(*replacementList))
except:
val = np.nan
magFieldsArray[i] = val
except:
print("Error while evaluating the magnetic field expression")
return magFieldsArray
list={"MagneticFields":list(range(10000)), "Chx":list(range(10000))}
out=CreateMagneticFieldsList(list,"MagneticFields*5+Chx",["MagneticFields","Chx"])
print(out)
Is there a way to optimize this call further? Specifically, I mean is there a way to make lambdify include that I'm calculating for a list of points, so that the loop evalulation can be optimized?
Thanks to #asmeurer, he gave the idea on how to do it.
Since lambdify is compiled using numpy, then one could simply pass the lists as arguments! The following is a working example
#!/usr/bin/python3
import numpy as np
from sympy.parsing.sympy_parser import parse_expr
from sympy.utilities.lambdify import lambdify, implemented_function
from sympy import S, Symbol
from sympy.utilities.autowrap import ufuncify
def CreateMagneticFieldsListOpt(dataToSave,equationString,DSList):
expression = S(equationString)
numOfElements = len(dataToSave["MagneticFields"])
#initialize the magnetic field output array
magFieldsArray = np.empty(numOfElements)
magFieldsArray[:] = np.NaN
lam_f = lambdify(tuple(DSList),expression,modules='numpy')
replacementList = [None]*len(DSList)
for j in range(len(DSList)):
replacementList[j] = np.array(dataToSave[DSList[j]])
print(replacementList)
magFieldsArray = np.double(lam_f(*replacementList))
return magFieldsArray
list={"MagneticFields":[1,2,3,4,5],"ChX":[2,4,6,8,10]}
out=CreateMagneticFieldsListOpt(list,"MagneticFields*5+ChX",["MagneticFields","ChX"])
print(out)

Categories

Resources