Skip to content

Commit 8b09d31

Browse files
committed
Heavy update of the ToPython package
1 parent 7e4d6ce commit 8b09d31

File tree

3 files changed

+108
-356
lines changed

3 files changed

+108
-356
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ string `''`
1616
## Output
1717

1818
* The Numpy python-ready expression (to be copied as a string)
19-
* The formatted expression will be copied to your clipboard, ready to paste to Python
19+
* Optionally, the formatted expression can be copied to your clipboard automatically
2020

2121
## Installation
2222

ToPython.wl

Lines changed: 107 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
(* ::Package:: *)
22

3-
BeginPackage["ToPython`"]
4-
ToPython::usage = "ToPython[expression,numpystring] converts Mathematica expression to a Numpy compatible expression.
5-
because Numpy can be imported in several ways, numpystring is a string that will be added to appended to function names, e.g., Cos->numpy.cos"
6-
Begin["Private`"]
7-
ToPython[x_,numpyprefix_:"numpy"]:=Module[{expression=x,greekrule,PythonForm,numpypre=numpyprefix,lp,rp,a,b},
8-
(*FUNCTION TO CONVERT MATHEMATICA EXPRESSION TO NUMPY;
3+
(*This package provides a function to convert a Mathematica expression to numpy
94
----------------------------------------------------;
105
INPUT ARGUMENTS;
11-
x: your mathematica expression, it can be numbers, literals, complexes or lists;
6+
expression: your mathematica expression, it can be numbers, literals, complexes or lists;
127
numpy\[LetterSpace]prefix: string defining your Numpy import prefix, e.g.:
138
if your used "import numpy as np", your prefix should be the string "np"
149
if your used "from numpy import *", your prefix should be the empty string ""
@@ -17,38 +12,110 @@ OUTPUT;
1712
the Numpy python-ready expression (to be copied as a string);
1813
!The formatted expression will be copied ot your clipboard, ready to paste on Python!;
1914
------------------------------------------------------;
20-
Not tested for every possible combination; use at your risk, by Gustavo Wiederhecker*)
21-
If[numpyprefix=="",sep="",sep="."];(*if no prefix is included, the "." separator is not used*)
22-
lp="( ";
23-
rp=" )";
24-
PythonForm[Rational[a_,b_]]:=PythonForm[a]<>"/"<>PythonForm[b];
25-
PythonForm[Complex[a_,b_]]:="complex"<>lp<>PythonForm[a]<>","<>PythonForm[b]<>rp;
26-
PythonForm[Times[a_,b_]]:=PythonForm[a]<>" * "<>PythonForm[b];
27-
PythonForm[Plus[a_,b_]]:=lp<>PythonForm[a]<>" + "<>PythonForm[b]<>rp;
28-
PythonForm[h_[args__]]:=numpypre<>sep<>ToLowerCase[PythonForm[h]]<>lp<>PythonForm[args]<>rp;
29-
PythonForm[Power[a_,b_]]:=lp<>PythonForm[a]<>rp<>"**"<>lp<>PythonForm[b]<>rp;
30-
PythonForm[a_ListQ]:=numpypre<>sep<>"array"<>StringReplace[ToString[a],{"{"-> "[","}"-> "]"}];
31-
PythonForm[Arg]=numpypre<>sep<>"angle";
32-
(*Some functions that are note defined in numpy*)
33-
PythonForm[Csc]:="1/"<>numpypre<>sep<>"sin";
34-
PythonForm[Sec]:="1/"<>numpypre<>sep<>"cos";
35-
PythonForm[Cot]:="1/"<>numpypre<>sep<>"tan";
36-
PythonForm[Csch]:="1/"<>numpypre<>sep<>"sinh";
37-
PythonForm[Sech]:="1/"<>numpypre<>sep<>"cosh";
38-
PythonForm[Coth]:="1/"<>numpypre<>sep<>"tanh";
39-
(*Handling arrays*)
40-
PythonForm[List[args__]]:=numpypre<>sep<>"array"<>lp<>"["<>Table[PythonForm[{args}[[ii]]]<>",",{ii,1,Length@{args}}]<>"]"<>rp;
41-
(*Pi and E*)
42-
PythonForm[\[Pi]]=numpypre<>sep<>"pi";
43-
PythonForm[E]=numpypre<>sep<>"e";
44-
(*real numbers, engineering notation*)
45-
PythonForm[r_Real]:=Block[{a=MantissaExponent[r]},If[r>=0,ToString[N[a[[1]],6]]<>"e"<>ToString[a[[2]]],"("<>ToString[N[a[[1]],6]]<>"e"<>ToString[a[[2]]]<>")"]];
46-
(*Greek characters*)
47-
greekrule={"\[Alpha]"->"alpha","\[Beta]"->"beta","\[Gamma]"->"gamma","\[Delta]"->"delta","\[CurlyEpsilon]"->"curlyepsilon","\[Zeta]"->"zeta","\[Eta]"->"eta","\[Theta]"->"theta","\[Iota]"->"iota","\[Kappa]"->"kappa","\[Lambda]"->"lambda","\[Mu]"->"mu","\[Nu]"->"nu","\[Xi]"->"xi","\[Omicron]"->"omicron","\[Pi]"->"pi","\[Rho]"->"rho","\[FinalSigma]"->"finalsigma","\[Sigma]"->"sigma","\[Tau]"->"tau","\[Upsilon]"->"upsilon","\[CurlyPhi]"->"curlyphi","\[Chi]"->"chi","\[Psi]"->"psi","\[Omega]"->"omega","\[CapitalAlpha]"->"Alpha","\[CapitalBeta]"->"Beta","\[CapitalGamma]"->"Gamma","\[CapitalDelta]"->"Delta","\[CapitalEpsilon]"->"CurlyEpsilon","\[CapitalZeta]"->"Zeta","\[CapitalEta]"->"Eta","\[CapitalTheta]"->"Theta","\[CapitalIota]"->"Iota","\[CapitalKappa]"->"Kappa","\[CapitalLambda]"->"Lambda","\[CapitalMu]"->"Mu","\[CapitalNu]"->"Nu","\[CapitalXi]"->"Xi","\[CapitalOmicron]"->"Omicron","\[CapitalPi]"->"Pi","\[CapitalRho]"->"Rho","\[CapitalSigma]"->"Sigma","\[CapitalTau]"->"Tau","\[CapitalUpsilon]"->"Upsilon","\[CapitalPhi]"->"CurlyPhi","\[CapitalChi]"->"Chi","\[CapitalPsi]"->"Psi","\[CapitalOmega]"->"Omega"};
48-
(*Everything else*)
49-
PythonForm[allOther_]:=StringReplace[ToString[allOther,FortranForm],greekrule];
50-
(*Copy results to clipboard*)
51-
CopyToClipboard[PythonForm[expression]];
52-
PythonForm[expression]]
15+
Not tested for every possible combination; use at your risk, by Gustavo Wiederhecker with
16+
modifications by David Zwicker
17+
*)
18+
19+
20+
BeginPackage["ToPython`"]
21+
22+
ToPython::usage = "ToPython[expression, numpyprefix, copy]
23+
converts Mathematica expression to a Numpy compatible expression. Because Numpy can
24+
be imported in several ways, numpyprefix is a string that will be added to appended
25+
to function names, e.g., Cos->np.cos. If copy==True, the result is copied to the clipboard"
26+
27+
ToPythonEquation::usage = "ToPythonEquation[equation, numpyprefix, copy] converts a
28+
Mathematica equation to a Numpy compatible express"
29+
30+
31+
32+
Begin["Private`"]
33+
34+
35+
ToPython[expression_, numpyprefix_:"np", copy_:False] := Module[
36+
{result, greekrule, format, PythonForm, np, a, b, l, m, args},
37+
38+
(* determine the correct numpy prefix *)
39+
If[numpyprefix=="", np=numpyprefix, np=numpyprefix<>"."];
40+
41+
(* general function for formating output *)
42+
format[pattern_String, args__] := ToString @ StringForm[
43+
StringReplace[pattern, "numpy."->np],
44+
Sequence @@ PythonForm /@ List[args]];
45+
46+
(* special forms that are recognized *)
47+
PythonForm[Times[-1, a_]] := format["-(``)", a];
48+
PythonForm[Power[a_, Rational[1, 2]]] := format["numpy.sqrt(``)", a];
49+
PythonForm[Times[a_, Power[b_, -1]]] := format["(``) / (``)", a, b];
50+
51+
(* Simple math *)
52+
PythonForm[Rational[a_, b_]] := format["(``) / (``)", a, b];
53+
PythonForm[Complex[a_, b_]] := format["complex(``, ``)", a, b];
54+
PythonForm[Times[a_, b_]] := format["(``) * (``)", a, b];
55+
PythonForm[Plus[a_, b_]] := format["`` + ``", a, b];
56+
PythonForm[Power[a_, b_]] := format["(``) ** (``)", a, b];
57+
PythonForm[Exp[a_]] := format["numpy.exp(``)", a];
58+
59+
(* Some special functions *)
60+
PythonForm[Arg[a_]] := format["numpy.angle(``)", a];
61+
PythonForm[SphericalHarmonicY[l_, m_, a_, b_]] := format[
62+
"special.sph_harm(``, ``, (``) % (2 * numpy.pi), (``) % numpy.pi)",
63+
m, l, b, a];
64+
PythonForm[BesselI[a_, b_]] := format["special.iv(``, ``)", a, b];
65+
PythonForm[BesselJ[a_, b_]] := format["special.jv(``, ``)", a, b];
66+
PythonForm[BesselK[a_, b_]] := format["special.kn(``, ``)", a, b];
67+
PythonForm[BesselY[a_, b_]] := format["special.yn(``, ``)", a, b];
68+
69+
(* Some functions that are not defined in numpy *)
70+
PythonForm[Csc[a_]] := format["1 / numpy.sin(``)", a];
71+
PythonForm[Sec[a_]] := format["1 / numpy.cos(``)", a];
72+
PythonForm[Cot[a_]] := format["1 / numpy.tan(``)", a];
73+
PythonForm[Csch[a_]] := format["1 / numpy.sinh(``)", a];
74+
PythonForm[Sech[a_]] := format["1 / numpy.cosh(``)", a];
75+
PythonForm[Coth[a_]] := format["1 / numpy.tanh(``)", a];
76+
77+
(* Handling arrays *)
78+
PythonForm[a_NumericArray] :=
79+
np<>"array("<>StringReplace[ToString@Normal@a, {"{"-> "[", "}"-> "]"}]<>")";
80+
PythonForm[List[args__]] :=
81+
np<>"array(["<>StringRiffle[PythonForm/@List[args], ", "]<>"])";
82+
83+
(* Constants *)
84+
PythonForm[\[Pi]] = np<>"pi";
85+
PythonForm[E] = np<>"e";
86+
87+
(* Greek characters *)
88+
greekrule={
89+
"\[Alpha]"->"alpha","\[Beta]"->"beta","\[Gamma]"->"gamma","\[Delta]"->"delta",
90+
"\[CurlyEpsilon]"->"curlyepsilon","\[Zeta]"->"zeta","\[Eta]"->"eta",
91+
"\[Theta]"->"theta","\[Iota]"->"iota","\[Kappa]"->"kappa","\[Lambda]"->"lambda",
92+
"\[Mu]"->"mu","\[Nu]"->"nu","\[Xi]"->"xi","\[Omicron]"->"omicron","\[Pi]"->"pi",
93+
"\[Rho]"->"rho","\[FinalSigma]"->"finalsigma","\[Sigma]"->"sigma","\[Tau]"->"tau",
94+
"\[Upsilon]"->"upsilon","\[CurlyPhi]"->"curlyphi","\[Chi]"->"chi","\[Phi]" -> "phi",
95+
"\[Psi]"->"psi",
96+
"\[Omega]"->"omega","\[CapitalAlpha]"->"Alpha","\[CapitalBeta]"->"Beta",
97+
"\[CapitalGamma]"->"Gamma","\[CapitalDelta]"->"Delta",
98+
"\[CapitalEpsilon]"->"CurlyEpsilon","\[CapitalZeta]"->"Zeta",
99+
"\[CapitalEta]"->"Eta","\[CapitalTheta]"->"Theta","\[CapitalIota]"->"Iota",
100+
"\[CapitalKappa]"->"Kappa","\[CapitalLambda]"->"Lambda","\[CapitalMu]"->"Mu",
101+
"\[CapitalNu]"->"Nu","\[CapitalXi]"->"Xi","\[CapitalOmicron]"->"Omicron",
102+
"\[CapitalPi]"->"Pi","\[CapitalRho]"->"Rho","\[CapitalSigma]"->"Sigma",
103+
"\[CapitalTau]"->"Tau","\[CapitalUpsilon]"->"Upsilon","\[CapitalPhi]"->"CurlyPhi",
104+
"\[CapitalChi]"->"Chi","\[CapitalPsi]"->"Psi","\[CapitalOmega]"->"Omega"};
105+
106+
(* Everything else *)
107+
PythonForm[h_[args__]] := np<>ToLowerCase[PythonForm[h]]<>"("<>PythonForm[args]<>")";
108+
PythonForm[allOther_] := StringReplace[ToString[allOther, FortranForm], greekrule];
109+
110+
result = StringReplace[PythonForm[expression], greekrule];
111+
(* Copy results to clipboard *)
112+
If[copy, CopyToClipboard[result]];
113+
result
114+
]
115+
116+
117+
ToPythonEquation[Equal[a_, b_], numpyprefix_:"np", copy_:True] := ToPython[a - b, numpyprefix, copy]
118+
119+
53120
End[]
54121
EndPackage[]

0 commit comments

Comments
 (0)