I am writing a Python module using SageMath9.4. Basically, I want to import this module into Jupyterlab Notebooks (running a SageMath 9.4 kernel) to do calculations etc.
Here is the start of it:
class Coxeter_System:
'''This class defines the standard root system associated to an abstract Coxeter group.'''
def __init__(self, coxeter_matrix):
'''Sets up a Coxeter system and root system. At this stage, limited to up to rank 7.
'''
def set_up_coefficient_space(coxeter_matrix):
'''Sets up a polynomial ring a Free module over a polynomial ring quotiented by the minimal polynomials of the
non-rational cos(pi/m_ij) values.
This is so roots can be compared using an abstract free module rather than over reals'''
A = coxeter_matrix
k = len(A.rows())
# Get the cos(pi/m_ij) which are irrational
non_rational_angles = [x for x in [cos(pi/x) for x in set(A[i,j] for i in range(0,k) for j in range(0,k))] if x not in QQ]
However, when I open another Jupyterlab session, import the Python module and try to create an instance of the object "Coxeter_System", I get the following error (I have tried to do from math import cos both from the notebook where I want to import the module to, and in the module itself, but I still get the same error.
Any help would be greatly appreciated!):
NameError Traceback (most recent call last)
<ipython-input-6-6b542b6cb042> in <module>
----> 1 W = c.Coxeter_System(Matrix([[Integer(1),Integer(3),Integer(4)],[Integer(3),Integer(1),Integer(3)],[Integer(4),Integer(3),Integer(1)]]))
~/coxeter_groups.py in __init__(self, coxeter_matrix)
60 return matrix(R,k,B)
61
---> 62 R = set_up_coefficient_space(coxeter_matrix)
63 A = coxeter_matrix
64 k = len(A.rows())
~/coxeter_groups.py in set_up_coefficient_space(coxeter_matrix)
17
18 # Get the cos(pi/m_ij) which are irrational
---> 19 non_rational_angles = [x for x in [cos(pi/x) for x in set(A[i,j] for i in range(0,k) for j in range(0,k))] if x not in QQ]
20
21 # sort the irrational values of cos(pi/m_ij) in ascending order
~/coxeter_groups.py in <listcomp>(.0)
17
18 # Get the cos(pi/m_ij) which are irrational
---> 19 non_rational_angles = [x for x in [cos(pi/x) for x in set(A[i,j] for i in range(0,k) for j in range(0,k))] if x not in QQ]
20
21 # sort the irrational values of cos(pi/m_ij) in ascending order
NameError: name 'cos' is not defined
Just use math.cos instead of using cos after from math import cos
e.g. math.cos(pi/x)
import math
math.cos(pi/x)
For most IDEs you will have to import some of the most popular math packages,
# Example:
import numpy as np
import math as m
import sagemath as sm
numpy and math you will have no problem using it with a simple import numpy in Google Colab or most popular IDEs.
What is SageMath?
SageMath, previously known as Sage, is a computational algebraic system (CAS) that stands out for being built on mathematical and contrasted packages such as NumPy, Sympy, PARI/GP o Máxima.
Install the SageMath package in Jupyter Notebook:
In the case of sagemath, inside jupyter you will have to do some extra steps.
To install the sagemath package we must do a pip:
!pip install sagemath
The image shows the confirmation within Jupyter
Using sagemath
# import and add the alias s
import sagemath as s
Yo use it we place the alias "s" in front of the function
s.cos(s.pi/x)
If sagemath does not always work correctly.
We know the following: "The philosophy of SageMath is to use existing open-source libraries wherever they exist. Therefore, it uses many libraries from other projects."
For these mathematical functions you can use numpy:
import numpy as np
np.cos(np.pi/x)
It will not fail and also in Jupyter you do not need additional installation.
I hope I've been useful.
Related
I noticed that the performance of mpmath, as oddly as it sounds, depends on whether sagemath is installed or not, regardless of whether the sage module is loaded in the current session. In particular, I experienced this for operations with multiple precision floats.
Example:
from mpmath import mp
import time
mp.prec = 650
t = time.time()
for i in range(1000000):
x_mpmath + y_mpmath
w = time.time()
print('plus:\t', (w-t), 'μs')
t = time.time()
for i in range(1000000):
x_mpmath * y_mpmath
w = time.time()
print('times:\t', (w-t), 'μs')
# If sagemath is installed:
# plus: 0.12919950485229492 μs
# times: 0.17601895332336426 μs
#
# If sagemath is *not* installed:
# plus: 0.6239776611328125 μs
# times: 0.6283771991729736 μs
While in both cases the module mpmath is the exact same
import mpmath
print(mpmath.__file__)
# /usr/lib/python3.9/site-packages/mpmath/__init__.py
I thought that mpmath's backend would depend on some sagemath dependency, and if that is missing it falls back to a less optimized one, but I cannot figure out what it is precisely. My goal is to be able to install only the required packages to speed up mpmath instead of installing all of sagemath.
Since this may very well be dependent on how things are packaged, you might need to have details on my system: I am using Arch Linux and all packages are updated to the most recent versions (sagemath 9.3, mpmath 1.2.1, python 3.9.5).
I found the explanation. In /usr/lib/python3.9/site-packages/mpmath/libmp/backend.py at line 82 there is
if 'MPMATH_NOSAGE' not in os.environ:
try:
import sage.all
import sage.libs.mpmath.utils as _sage_utils
sage = sage.all
sage_utils = _sage_utils
BACKEND = 'sage'
MPZ = sage.Integer
except:
pass
This loads all of sage if sagemath is installed and also sets it as a backend. This means that the following library is loaded next:
import sage.libs.mpmath.ext_libmp as ext_lib
From /usr/lib/python3.9/site-packages/mpmath/libmp/libmpf.py at line 1407. By looking at the __file__ of that module, one sees that it's a .so object, hence compiled, thus faster.
This also means that by exporting MPMATH_NOSAGE to any nonempty value will force the backend to be the default one (python or gmpy) and indeed I can confirm that the code I wrote in the question does run slower in this case, even with sagemath installed.
I am trying to run a project from github , every object counter applications using sort algorithm. I can't run any of them because of a specific error, attaching errors screenshot. Can anyone help me about fixing this issue?
The linear_assignment function is deprecated in 0.21 and will be removed from 0.23, but sklearn.utils.linear_assignment_ can be replaced by scipy.optimize.linear_sum_assignment.
You can use:
from scipy.optimize import linear_sum_assignment as linear_assignment
then you can run the file and don't need to change the code.
pip install scikit-learn==0.22.2
As yiakwy points out in a github comment the scipy.optimize.linear_sum_assignment is not the perfect replacement:
I am concerned that linear_sum_assignment is not equivalent to linear_assignment which later implements "maximum values" matching strategy not "complete matching" strategy, i.e. in tracking problem maybe an old landmark lost and a new detection coming in. We don't have to make a complete assignment, just match as more as possible.
I have found this out while trying to use it inside SORT-based yolo tracking code which that replacement broke (I was lucky that it did otherwise, I would get wrong results from the experiments without realising it...)
Instead, I suggest copying the module itself to the last version of sklearn and include as module in your code.
https://github.com/scikit-learn/scikit-learn/blob/0.22.X/sklearn/utils/linear_assignment_.py
For instance if you copy this file into an utils directory import with from utils.linear_assignment_ import linear_assignment
Solution
Use pip to install lap and optionally scipy
Uncomment the import and use the following function
def linear_assignment(cost_matrix):
try:
import lap
_, x, y = lap.lapjv(cost_matrix, extend_cost=True)
return np.array([[y[i], i] for i in x if i >= 0])
except ImportError:
from scipy.optimize import linear_sum_assignment
x, y = linear_sum_assignment(cost_matrix)
return np.array(list(zip(x, y)))
You are getting this error because you haven't install scikit module yet.
Install scikit-learn module from https://pypi.org/project/scikit-learn/
The basic question is this: Let's say I was writing R functions which called python via rPython, and I want to integrate this into a package. That's simple---it's irrelevant that the R function wraps around Python, and you proceed as usual. e.g.
# trivial example
# library(rPython)
add <- function(x, y) {
python.assign("x", x)
python.assign("y", y)
python.exec("result = x+y")
result <- python.get("result")
return(result)
}
But what if the python code with R functions require users to import Python libraries first? e.g.
# python code, not R
import numpy as np
print(np.sin(np.deg2rad(90)))
# R function that call Python via rPython
# *this function will not run without first executing `import numpy as np`
print_sin <- function(degree){
python.assign("degree", degree)
python.exec('result = np.sin(np.deg2rad(degree))')
result <- python.get('result')
return(result)
}
If you run this without importing the library numpy, you will get an error.
How do you import a Python library in an R package? How do you comment it with roxygen2?
It appears the R standard is this:
# R function that call Python via rPython
# *this function will not run without first executing `import numpy as np`
print_sin <- function(degree){
python.assign("degree", degree)
python.exec('import numpy as np')
python.exec('result = np.sin(np.deg2rad(degree))')
result <- python.get('result')
return(result)
}
Each time you run an R function, you will import an entire Python library.
As #Spacedman and #DirkEddelbuettel suggest you could add a .onLoad/.onAttach function to your package that calls python.exec to import the modules that will typically always be required by users of your package.
You could also test whether the module has already been imported before importing it, but (a) that gets you into a bit of a regression problem because you need to import sys in order to perform the test, (b) the answers to that question suggest that at least in terms of performance, it shouldn't matter, e.g.
If you want to optimize by not importing things twice, save yourself the hassle because Python already takes care of this.
(although admittedly there is some quibblingdiscussion elsewhere on that page about possible scenarios where there could be a performance cost).
But maybe your concern is stylistic rather than performance-oriented ...
I have the next code in python
import np_plots as npp
import matplotlib.pyplot as plt
import numpy as np
import math as m
import scipy
from scipy.integrate import odeint
def plotLimitCycle(bval):
rhs = lambda X, t: [-X[0]+X[1]*X[0]**2, bval - X[1]*X[0]**2]
xeq, yeq = bval, 1.0/bval
cyclerad = m.sqrt(1-bval)
nbh = min(cyclerad, 0.05)
IC = [xeq-nbh/5.0, yeq-nbh/5.0]
time_span = np.linspace(0,400,40000)
fig = plt.figure()
solution = odeint(rhs, IC, time_span)
X, Y = zip(*solution)
plt.plot(X, Y)
axes = plt.gca()
axXmin, axXmax = axes.get_xlim()
axYmin, axYmax = axes.get_ylim()
xmin = max(-15, axXmin)
xmax = min(15, axXmax)
ymin = max(-15, axYmin)
ymax = min(15, axYmax)
X,Y,U,V = npp.ezDomainQuiver2D([[xmin, xmax],[ymin, ymax]],[25,25],lambda X: rhs(X, 0),Normalize=True)
plt.quiver(X,Y,U,V)
plt.scatter([xeq],[yeq], color='red')
plt.xlim([xmin, xmax])
plt.ylim([ymin, ymax])
plt.axes().set_aspect('equal', 'datalim')
plt.show()
It work pretty well on my friend computer because he showed me the plots but I can't make it run in mine, I'm using Python 3.5.0cr1 Shell to run it out but it always came with te next error:
**Traceback (most recent call last):
File "C:\Users\PankePünke\Desktop\limites.py", line 1, in <module>
import np_plots as npp
ImportError: No module named 'np_plots'**
I'm totally new in Python programming and my friend made this program for me in order to make some advances in my thesis but I want to continue working with this program and get the plots from this. I do not know how to install or what kind of procceddure I should follow in order to get what I want (the plots and graphics that this program make) So... I'll be very thankful if somebody can help me in not a advance way, because how a wrote I'm totally new in Python, I just installed it and that is all.
You friend had a lib called np_plots on their computer, it is not part of the standard lib so you need to also install/get it on your comp or the code will not run. Most likely your friend actually wrote the code as I cannot see any mention of that lib anywhere so you will have to get it from them.
Apart from your friends lib, scipy and numpy are also not in the standard library, they do come with some distributions like Canopy but if you just installed a regular version of python you will need to install those also.
Might be worth checking out pip as it is the de-facto standard package manager for python.
I'm doing simulations for scientific computing, and I'm almost always going to want to be in the interactive interpreter to poke around at the output of my simulations. I'm trying to write classes to define simulated objects (neural populations) and I'd like to formalize my testing of these classes by calling a script %run test_class_WC.py in ipython. Since the module/file containing the class is changing as I try to debug it/add features, I'm reloading it each time.
./test_class_WC.py:
import WC_class # make sure WC_class exists
reload(WC_class) # make sure it's the most current version
import numpy as np
from WC_class import WC_unit # put the class into my global namespace?
E1 = WC_unit(Iapp=100)
E1.update() # see if it works
print E1.r
So right off the bat I'm using reload to make sure I've got the most current version of the module loaded so I've got the freshest class definition-- I'm sure this is clunky as heck (and maybe more sinister?), but it saves me some trouble from doing %run WC_class.py and having to do a separate call to %run test_WC.py
and ./WC_class:
class WC_unit:
nUnits = 0
def __init__(self,**kwargs):
self.__dict__.update(dict( # a bunch of params
gee = .6, # i need to be able to change
ke=.1,the=.2, # in test_class_WC.py
tau=100.,dt=.1,r=0.,Iapp=1.), **kwargs)
WC_unit.nUnits +=1
def update(self):
def f(x,k=self.ke,th=self.the): # a function i define inside a method
return 1/(1+np.exp(-(x-th)/k)) # using some of those params
x = self.Iapp + self.gee * self.r
self.r += self.dt/self.tau * (-self.r + f(x))
WC_unit basically defines a bunch of default parameters and defines an ODE that updates using basic Euler integration. I expect that test_class_WC sets up a global namespace containing np (and WC_unit, and WC_class)
When I run it, I get the following error:
In [14]: %run test_class_WC.py
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/Users/steeles/Desktop/science/WC_sequence/test_class_WC.py in <module>()
8
9 E1 = WC_unit(Iapp=100)
---> 10 E1.update()
11
12 # if bPlot:
/Users/steeles/Desktop/science/WC_sequence/WC_class.py in update(self)
19 return 1/(1+np.exp(-(x-th)/k))
20 x = self.Iapp + self.gee * self.r
---> 21 self.r += self.dt/self.tau * (-self.r + f(x))
22
23 # #class_method
/Users/steeles/Desktop/science/WC_sequence/WC_class.py in f(x, k, th)
17 def update(self):
18 def f(x,k=self.ke,th=self.the):
---> 19 return 1/(1+np.exp(-(x-th)/k))
20 x = self.Iapp + self.gee * self.r
21 self.r += self.dt/self.tau * (-self.r + f(x))
NameError: global name 'np' is not defined
Now I can get around this by just importing numpy as np in top of the WC_class module, or even by doing from numpy import exp in test_class_WC and change the update() method to contain exp() instead of np.exp()... but I'm not trying to do this because it's easy, I want to learn how all this namespace/module stuff works so I stop being a python idiot. Why is np getting lost in the WC_unit namespace? Is it because I'm dealing with two different files/modules? Does the call to np.exp inside a function have to do with it?
I'm also open to suggestions regarding improving my workflow and file structure, as it seems to be not particularly pythonic. My background is in MATLAB if that helps anyone understand. I'm editing my .py files in SublimeText2. Sorry the code is not very minimal, I've been having a hard time reproducing the problem.
The correct approach is to do an import numpy as np at the top of your sub-module as well. Here's why:
The key thing to note is that in Python, global actually means "shared at a module-level", and the namespaces for each module exist distinct from each other except when a module explicitly imports from another module. An imported module definitely cannot reach out to its 'parent' module's namespace, which is probably a good thing all things considered, otherwise you'll have modules whose behavior depends entirely on the variables defined in the module that imports it.
So when the stack trace says global name 'np' is not defined, it's talking about it at a module level. Python does not let the WC_Class module access objects in its parent module by default.
(As an aside, effbot has a quick note on how to do inter-module globals)
Another key thing to note is that even if you have multiple import numpy as np in various modules of your code, the module actually only gets loaded (i.e. executed) once. Once loaded, modules (being Python objects themselves) can be found in the dictionary sys.modules, and if a module already exists in this dictionary, any import module_to_import statement simply lets the importing module access names in the namespace of module_to_import. So having import numpy as np scattered across multiple modules in your codebase isn't wasteful.
Edit: On deeper digging, effbot has an even deeper (but still pretty quick and simple) exploration of what actually happens in module imports. For deeper exploration of the topic, you may want to check the import system discussion newly added in the Python 3 documentation.
It is normal in Python to import each module that is needed with in each. Don't count on any 'global' imports. In fact there isn't such a thing. With one exception. I discovered in
Do I have to specify import when Python script is being run in Ipython?
that %run -i myscript runs the script in the Ipython interactive namespace. So for quick test scripts this can save a bunch of imports.
I don't see the need for this triple import
import WC_class # make sure WC_class exists
reload(WC_class) # make sure it's the most current version
...
from WC_class import WC_unit
If all you are using from WC_class just use the last line.