How can I convert the following Mathematica code into sympy? - wolfram-mathematica

I am trying to convert some Mathematica code into python and I didn't know how to handle the following function. Is there a way to go about is using sympy or other python module? TPUV, AM1UV and GUV are vectors computed by other accompanying functions.
perpUnitVector[]:=Module[
{sol,a3,b3,c3,a4,b4,c4},
sol=Quiet[Solve[
{a3,b3,c3}.TPUV==0&&
{a3,b3,c3}.AM1UV==0&&
{a3,b3,c3}.{a3,b3,c3}==1&&
Sign[Cross[-GUV,{a3,b3,c3}].Cross[{1,0,0},-GUV]]>0,
{a3,b3,c3},Reals]];
{a4,b4,c4}=Flatten[{a3,b3,c3}/.sol[[1]],1]
]
Test case:
With TPU = {1,3,4}, AM1UV = {4, 5, 6}, GUV = {1,1,1}, Mathematica gives
a4 = -0.408248, b4 = 0.816497, and c4 = -0.408248.
my sympy attempt is here but doesn't seem to work
import numpy as np
import sympy as sym
GUV = [1.0, 1.0, 1.0];
AM1UV = [4.0, 5.0, 6.0];
TPUV = [1.0, 2.0, 3.0];
a3,b3,c3,a4,b4,c4 = sym.symbols('a3 b3 c3 a4 b4 c4')
sol = sym.solveset(np.dot([a3,b3,c3],TPUV),
np.dot([a3,b3,c3],AM1UV),
np.dot([a3,b3,c3],[a3,b3,c3])-1,
np.sign(np.dot(np.cross(-GUV,[a3,b3,c3]),
np.cross([1,0,0],-GUV)))>0,
[a3,b3,c3],S.Reals)

Related

How to convert a Julia plot (via Plots.jl) into a Matrix{RGB{N0f8}}

Matplotlib can convert a plot/figure into a RGB array as follows:
import matplotlib.pyplot as plt
import numpy as np
import io
fig, ax = plt.subplots()
n=256
I, J = np.indices((n, n))
im = ax.imshow((I | J) % 19, interpolation='none')
fig.colorbar(im, ax=ax)
#Convert fig to a RGB array
io_buf = io.BytesIO()
fig.savefig(io_buf, format='raw')
io_buf.seek(0)
fig_arr = np.reshape(np.frombuffer(io_buf.getvalue(), dtype=np.uint8),
newshape=(int(fig.bbox.bounds[3]), int(fig.bbox.bounds[2]), -1))
print(f"The shape of the rgb array: {fig_arr.shape}")
plt.show()
It displays:
The shape of the rgb array: (480, 640, 4)
Is it possible to convert similarly a Plots plot into a Matrix{RGB{N0f8}}?
The first part:
using Plots
n = 255
I = [i for i in 0:n, j in 0:n]
h = heatmap(mod.((I .| I'), 19), c= :deep, yflip=true, size=(400, 400), aspect_ratio=:equal)
I searched for Julia equivalent of numpy.frombuffer, but no result has been returned
With h holding the plot, as the code in the OP has described. The following:
using FileIO
io = IOBuffer()
show(io, MIME("image/png"), h);
strm = Stream(format"PNG", io)
img = load(strm)
leaves img with the Matrix{RGB{...}}.

Bayesian calibration for ode system

I tried to use the 'pymc3' package in Python to calibrate a first-order ODE system in a Bayesian way.
I started with a toy ODE system first. It is dy1/dt = y2; dy2/dt = -b* y2 - c*sin(y1). b and c are the parameters I want to calibrate.
Firstly, I generated some outputs for y1 and y2 from t[0,10] by setting parameters b = 0.25 and c = 0.5 with normally distributed noise~N(0,0.7^2). Then, I calibrated the ODE system by setting prior distributions for b~N(0,1) and c~N(0,9) and sigma~HalfNormal
But it gave the errors: (1) TypeError: float() argument must be a string or a number, not 'TensorVariable'(2)ValueError: setting an array element with a sequence.
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
from scipy.integrate import ode
import pymc3 as pm
def pend(y, t, b, c):
theta, omega = y
dydt = [omega, -b*omega - c*np.sin(theta)]
return dydt
true_b = 0.25
true_c = 5.0
y0 = [np.pi - 0.1, 0.0]
t = np.linspace(0, 10, 101)
sol = odeint(pend, y0, t, args=(true_b, true_c))
true_sigma = 0.7
noise = np.random.randn(101,2)*true_sigma
Y_obs = sol+noise
pend_model = pm.Model()
with pend_model:
# Priors for unknown model parameters
b = pm.Normal('b', mu=0, sd=1)
c = pm.Normal('c', mu=7, sd=3)
sigma = pm.HalfNormal('sigma', sd=1)
# Expected value of outcome
mu = odeint(pend, y0, t, args=(b, c))
# Likelihood (sampling distribution) of observations
Y = pm.Normal('Y_obs', mu=mu, sd=sigma, observed=Y_obs)
trace = pm.sample(draws=5000, tune=500, chains=1)

convert hued displot of X to plot of hue vs mode(X given hue)?

I have a Seaborn displot with a hued variable:
For each hued variable, I want to extract the mode of the density estimate and then plot each hue variable versus its mode, like so:
How do I do this?
You can use scipy.stats.gaussian_kde to create the density estimation function. And then call that function on an array of x-values to calculate its maximum.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
df = pd.DataFrame({'x': np.random.normal(0.001, 1, 1300).cumsum() + 30,
'hue': np.repeat(np.arange(0.08, 0.20001, 0.01), 100).round(2)})
g = sns.displot(df, x='x', hue='hue', palette='turbo', kind='kde', fill=True, height=6, aspect=1.5)
plt.show()
from scipy.stats import gaussian_kde
from matplotlib.cm import ScalarMappable
fig, ax = plt.subplots(figsize=(10, 6))
hues = df['hue'].unique()
num_hues = len(hues)
colors = sns.color_palette('turbo', num_hues)
xmin, xmax = df['x'].min(), df['x'].max()
xs = np.linspace(xmin, xmax, 500)
for hue, color in zip(hues, colors):
data = df[df['hue'] == hue]['x'].values
kde = gaussian_kde(data)
mode_index = np.argmax(kde(xs))
mode_x = xs[mode_index]
sns.scatterplot(x=[hue], y=[mode_x], color=color, s=50, ax=ax)
cmap = sns.color_palette('turbo', as_cmap=True)
norm = plt.Normalize(hues.min(), hues.max())
plt.colorbar(ScalarMappable(cmap=cmap, norm=norm), ax=ax, ticks=hues)
plt.show()
Here is another approach, extracting the kde curves. It uses the legend of the kde plot to get the correspondence between the curves and the hue values. sns.kdeplot is the axes-level function used by sns.displot(kind='kde'). fill=False creates lines instead of filled polygons for the curves, for which the values are easier to extract. (ax1.fill_between can fill the curves during a second pass). The x and y axes of the second plot are switched to align the x-axes of both plots.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
df = pd.DataFrame({'x': np.random.normal(0.007, 0.1, 1300).cumsum() + 30,
'hue': np.repeat(np.arange(0.08, 0.20001, 0.01), 100).round(2)})
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(12, 10), sharex=True)
sns.kdeplot(data=df, x='x', hue='hue', palette='turbo', fill=False, ax=ax1)
hues = [float(txt.get_text()) for txt in ax1.legend_.get_texts()]
ax2.set_yticks(hues)
ax2.set_ylabel('hue')
for hue, line in zip(hues, ax1.lines[::-1]):
color = line.get_color()
x = line.get_xdata()
y = line.get_ydata()
ax1.fill_between(x, y, color=color, alpha=0.3)
mode_ind = np.argmax(y)
mode_x = x[mode_ind]
sns.scatterplot(x=[mode_x], y=hue, color=color, s=50, ax=ax2)
sns.despine()
plt.tight_layout()
plt.show()

pymc3 multinomial mixture gets stuck

I am trying use PYMC3 to implement an example where the data comes from a mixture of multinomials. The goal is to infer the underlying state_prob vector (see below). The code runs, but the Metropolis sampler gets stuck at the initial state_prior vector. Also, for some reason I have not been able to get NUTS to work.
import numpy as np
import pandas as pd
from pymc3 import Model, Multinomial, Dirichlet
import pymc3
import theano.tensor as tt
from theano import function, printing
N = 10
state_prior = np.array([.3, .3, .3])
state_prob = np.array([0.3, 0.1, 0.6]) #need to infer this
state_emission_tran = np.array([[0.3, 0.2, 0.5],
[0.1, 0.5, 0.4],
[0.0, 0.05, 0.95]])
state_data = np.random.multinomial(1, state_prob, size=N)
emission_prob_given_state = np.matmul(state_data, state_emission_tran)
def rand_mult(row_p):
return np.random.multinomial(1, row_p)
emission_data = np.apply_along_axis(rand_mult, 1, emission_prob_given_state)
# done with creating data
with Model() as simple_dag:
state = Dirichlet('state', state_prior*100, shape=3)
emission_dist = [pymc3.Multinomial.dist(p=state_emission_tran[i], n=1, shape=3) for i in range(3)]
emission_mix = pymc3.Mixture('emission_mix', w = state, comp_dists = emission_dist, observed=emission_data)
with simple_dag:
step = pymc3.Metropolis(vars=[state])
trace = pymc3.sample(10000, cores=2, chains=2, tune=500, step=step, progressbar=True)
Try this one:
import numpy as np
import pandas as pd
from pymc3 import Model, Multinomial, Dirichlet
import pymc3
import theano.tensor as tt
from theano import function, printing
N = 10
state_prior = np.array([.3, .3, .3])
state_prob = np.array([0.3, 0.1, 0.6]) #need to infer this
state_emission_tran = np.array([[0.3, 0.2, 0.5],
[0.1, 0.5, 0.4],
[0.0, 0.05, 0.95]])
state_data = np.random.multinomial(1, state_prob, size=N)
emission_prob_given_state = np.matmul(state_data, state_emission_tran)
def rand_mult(row_p):
return np.random.multinomial(1, row_p)
emission_data = np.apply_along_axis(rand_mult, 1, emission_prob_given_state)
# done with creating data
with Model() as simple_dag:
state = Dirichlet('state', state_prior*100, shape=3)
emission_dist = [pymc3.Multinomial.dist(p=state_emission_tran[i], n=1, shape=3) for i in range(3)]
emission_mix = pymc3.Mixture('emission_mix', w = state, comp_dists = emission_dist, observed=emission_data)
with simple_dag:
trace = pymc3.sample(3000, tune=1000)
I am using pymc3 version 3.5 in Linux and it works fine.

matplotlib: jpg image special effect/transformation as if its on a page of an open book

I wish to appear a figure (and certain text) as if they are printed on a page of an open book. Is it possible to transform an jpg image programmatically or in matplotlib to have such an effect?
You can use a background axis along with an open source book image to do something like this,
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax2 = fig.add_axes([0.2, 0.3, 0.25, 0.3])
#Plot page from a book
im = plt.imread("./book_page.jpg")
implot = ax1.imshow(im, origin='lower')
# Plot a graph and set background to transparent
x = np.linspace(0,4.*np.pi,40)
y = np.sin(x)
ax2.plot(x,y,'-ro',alpha=0.5)
ax2.set_ylim([-1.1,1.1])
ax2.patch.set_alpha(0.0)
from matplotlib import rc
rc('text', usetex=True)
margin = im.shape[0]*0.075
ytext = im.shape[1]/2.+10
ax1.text(margin, ytext, "The following text is an example")
ax1.text(margin, 90, "Figure 1. Showing a sine function")
plt.show()
Which looks like this,
where I used the following book image.
UPDATE: Added non-affine transformation based on scikit-image warp example, but with Maxwell distribution. The solution saves the matplotlib line as an image in order to apply a pointwise transform. Mapping for vector graphics may be possible but I think this will be more complicated...
import numpy as np
import matplotlib.pyplot as plt
def maxwellian_transform_image(image):
from skimage.transform import PiecewiseAffineTransform, warp
rows, cols = image.shape[0], image.shape[1]
src_cols = np.linspace(0, cols, 20)
src_rows = np.linspace(0, rows, 10)
src_rows, src_cols = np.meshgrid(src_rows, src_cols)
src = np.dstack([src_cols.flat, src_rows.flat])[0]
# add maxwellian to row coordinates
x = np.linspace(0, 3., src.shape[0])
dst_rows = src[:, 1] + (np.sqrt(2/np.pi)*x**2 * np.exp(-x**2/2)) * 50
dst_cols = src[:, 0]
dst_rows *= 1.5
dst_rows -= 1.0 * 50
dst = np.vstack([dst_cols, dst_rows]).T
tform = PiecewiseAffineTransform()
tform.estimate(src, dst)
out_rows = image.shape[0] - 1.5 * 50
out_cols = cols
out = warp(image, tform, output_shape=(out_rows, out_cols))
return out
#Create the new figure
fig = plt.figure()
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
#Plot page from a book
im = plt.imread("./book_page.jpg")
implot = ax.imshow(im, origin='lower')
# Plot and save graph as image, will need some manipulation of location
temp, at = plt.subplots()
margin = im.shape[0]*0.1
x = np.linspace(margin,im.shape[0]/2.,40)
y = im.shape[1]/3. + 0.1*im.shape[1]*np.sin(12.*np.pi*x/im.shape[0])
at.plot(x,y,'-ro',alpha=0.5)
temp.savefig("lineplot.png",transparent=True)
#Read in plot as an image and apply transform
plot = plt.imread("./lineplot.png")
out = maxwellian_transform_image(plot)
ax.imshow(out, extent=[0,im.shape[1],0,im.shape[0]])
plt.show()
The figure now looks like,

Resources