I'm not sure I'll follow with this blog...
I'm now involved in teaching Python to astronomers colleagues... and I set up another one, where I share the course I'm giving. If you are interested, follow it THERE.
lundi 27 février 2012
jeudi 30 juin 2011
calling shell commands from within python
That's quite easy to interact with the shell from within python, it only needs to import the subprocess module.
If the matter is just executing a command, use the call method:
>>>>subprocess.call('ls')
Applications SharedLin Volumes etc mach_kernel sbin var
Developer SharedXP bin home net sw
Library System cores iraf opt tmp
Network Users dev lost+found private usr
If some arguments need to be used, you cannot put them in the same string as the command, need to use:
>>>>subprocess.call(['ls','-l'])
total 40733
drwxrwxr-x+ 134 root admin 4556 28 jui 00:21 Applications
drwxrwxr-x@ 18 root admin 612 18 mar 20:03 Developer
[...]
or you'll need to execute the command in a shell:
>>>>subprocess.call('ls -l', shell=True)
If one want to deal with the output, use the Popen and communicate methods :
>>>>ls = subprocess.Popen(["ls"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
>>>>stdout, stderr = ls.communicate()
You can access the distinct values of the stdout by splitting them:
stdout.split()
Now, one can need to execute the command with a givenfile as input and redirect the output to another file.
That's possible using the Popen method:
input_file = open('model.in','r')
output_file = open('model.out','wb')
p = subprocess.Popen('cloudy.exe', stdout=output_file, stdin = input_file)
input_file.close()
output_file.close()
That's it!
References:
http://docs.python.org/library/subprocess.html
http://jimmyg.org/blog/2009/working-with-python-subprocess.html
If the matter is just executing a command, use the call method:
>>>>subprocess.call('ls')
Applications SharedLin Volumes etc mach_kernel sbin var
Developer SharedXP bin home net sw
Library System cores iraf opt tmp
Network Users dev lost+found private usr
If some arguments need to be used, you cannot put them in the same string as the command, need to use:
>>>>subprocess.call(['ls','-l'])
total 40733
drwxrwxr-x+ 134 root admin 4556 28 jui 00:21 Applications
drwxrwxr-x@ 18 root admin 612 18 mar 20:03 Developer
[...]
or you'll need to execute the command in a shell:
>>>>subprocess.call('ls -l', shell=True)
If one want to deal with the output, use the Popen and communicate methods :
>>>>ls = subprocess.Popen(["ls"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
>>>>stdout, stderr = ls.communicate()
You can access the distinct values of the stdout by splitting them:
stdout.split()
Now, one can need to execute the command with a givenfile as input and redirect the output to another file.
That's possible using the Popen method:
input_file = open('model.in','r')
output_file = open('model.out','wb')
p = subprocess.Popen('cloudy.exe', stdout=output_file, stdin = input_file)
input_file.close()
output_file.close()
That's it!
References:
http://docs.python.org/library/subprocess.html
http://jimmyg.org/blog/2009/working-with-python-subprocess.html
jeudi 23 juin 2011
.r and %run and Debugging
From IDL, it's easy to run a program at main level and stay after the execution with all the variables as they are defined by the program.
In (i)python, if you interactively import myprog it will execute it, but let you without any access to what has been set within the program.
There is a way to do the equivalent of .r in IDL, but you needs to run ipython.
ipython:
%run myprog
..... executing the myprog.py and give you the prompt back so you can explore the variables and objects to see if they are as they are supposed to be...
The %run (the % is needed, it's not a prompt) function is recompiling the code each time it is used, so changes are taken into account (it's not the case with import).
Nice tip for developpers...
BTW, there is also a debugger mode : from ipython, just type %pdb and then import or %run what you want. If something wrong happens, you will be let where it happened, with access to all the variables... like in IDL ;-) You have this activated by default using ipython -pdb.
More and more important informations on ipython here (I think I must read these pages every week for the next 3 months!):
http://ipython.org/documentation.html
In (i)python, if you interactively import myprog it will execute it, but let you without any access to what has been set within the program.
There is a way to do the equivalent of .r in IDL, but you needs to run ipython.
ipython:
%run myprog
..... executing the myprog.py and give you the prompt back so you can explore the variables and objects to see if they are as they are supposed to be...
The %run (the % is needed, it's not a prompt) function is recompiling the code each time it is used, so changes are taken into account (it's not the case with import).
Nice tip for developpers...
BTW, there is also a debugger mode : from ipython, just type %pdb and then import or %run what you want. If something wrong happens, you will be let where it happened, with access to all the variables... like in IDL ;-) You have this activated by default using ipython -pdb.
More and more important informations on ipython here (I think I must read these pages every week for the next 3 months!):
http://ipython.org/documentation.html
lundi 6 juin 2011
Broadcasting: adding arrays of different shapes
Something very different between python-numpy and IDL is the way they are both dealing with linear algebra in case of operations on different size or shape arrays.
In IDL, trying to operate on 2 vectors with different size reduces the oprtation to the lowest size:
IDL> a=[1,2,3]
IDL> b=[10,20,30,40]
IDL> print,a+b
11 22 33
As we can see, the latest element is purely omitted.
IDL> c=[[1,2,3,4]]
IDL> d=[[10],[20],[30],[40]]
IDL> print,c
1 2 3 4
IDL> print,d
10
20
30
40
The shape of the first operand is conserved:
IDL> print,c+d
11 22 33 44
IDL> print,d+c
11
22
33
44
And we can loose part of the vector:
IDL> print,a+c
2 4 6
IDL> print,a+d
11 22 33
On the contrary, Python-numpy is adding some information, this is the broadcasting.
import numpy as np
a=np.array([1,2,3.])
b=np.array([10,20,30.,40])
a*b
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
#ValueError: shape mismatch: objects cannot be broadcast to a single shape
BUT:
a = a.reshape(3,1)
a
#array([[ 1.],
# [ 2.],
# [ 3.]])
b
#array([ 10., 20., 30., 40.])
a*b
#array([[ 10., 20., 30., 40.],
# [ 20., 40., 60., 80.],
# [ 30., 60., 90., 120.]])
Another example where Python is guessing in which dimension the array must be extended:
c= a*b
c.shape
# (3, 4)
c*a
#array([[ 10., 20., 30., 40.],
# [ 40., 80., 120., 160.],
# [ 90., 180., 270., 360.]])
c*b
#array([[ 100., 400., 900., 1600.],
# [ 200., 800., 1800., 3200.],
# [ 300., 1200., 2700., 4800.]])
b2==np.array([10,20,30.])
#array([False, False, False], dtype=bool)
d=a*b2
d.shape
#(3, 3)
d
#array([[ 1., 2., 3.],
# [ 2., 4., 6.],
3 [ 3., 6., 9.]])
d*a
#array([[ 1., 2., 3.],
# [ 4., 8., 12.],
# [ 9., 18., 27.]])
d*b2
#array([[ 1., 4., 9.],
# [ 2., 8., 18.],
# [ 3., 12., 27.]])
More details and nice figures in:
http://www.scipy.org/EricsBroadcastingDoc
In IDL, trying to operate on 2 vectors with different size reduces the oprtation to the lowest size:
IDL> a=[1,2,3]
IDL> b=[10,20,30,40]
IDL> print,a+b
11 22 33
As we can see, the latest element is purely omitted.
IDL> c=[[1,2,3,4]]
IDL> d=[[10],[20],[30],[40]]
IDL> print,c
1 2 3 4
IDL> print,d
10
20
30
40
The shape of the first operand is conserved:
IDL> print,c+d
11 22 33 44
IDL> print,d+c
11
22
33
44
And we can loose part of the vector:
IDL> print,a+c
2 4 6
IDL> print,a+d
11 22 33
On the contrary, Python-numpy is adding some information, this is the broadcasting.
import numpy as np
a=np.array([1,2,3.])
b=np.array([10,20,30.,40])
a*b
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
#ValueError: shape mismatch: objects cannot be broadcast to a single shape
BUT:
a = a.reshape(3,1)
a
#array([[ 1.],
# [ 2.],
# [ 3.]])
b
#array([ 10., 20., 30., 40.])
a*b
#array([[ 10., 20., 30., 40.],
# [ 20., 40., 60., 80.],
# [ 30., 60., 90., 120.]])
Another example where Python is guessing in which dimension the array must be extended:
c= a*b
c.shape
# (3, 4)
c*a
#array([[ 10., 20., 30., 40.],
# [ 40., 80., 120., 160.],
# [ 90., 180., 270., 360.]])
c*b
#array([[ 100., 400., 900., 1600.],
# [ 200., 800., 1800., 3200.],
# [ 300., 1200., 2700., 4800.]])
b2==np.array([10,20,30.])
#array([False, False, False], dtype=bool)
d=a*b2
d.shape
#(3, 3)
d
#array([[ 1., 2., 3.],
# [ 2., 4., 6.],
3 [ 3., 6., 9.]])
d*a
#array([[ 1., 2., 3.],
# [ 4., 8., 12.],
# [ 9., 18., 27.]])
d*b2
#array([[ 1., 4., 9.],
# [ 2., 8., 18.],
# [ 3., 12., 27.]])
More details and nice figures in:
http://www.scipy.org/EricsBroadcastingDoc
Structure-like object (2): record arrays, access and views
Some complement to the previous message on structured arrays and record arrays:
import numpy as np
a = np.zeros((10,),dtype=[('name', str), ('ra', float), ('dec', float)])
a['ra'] = np.random.random_sample(10)*360
a['dec'] = np.random.random_sample(10)*180-90
tt = ((a['ra'] > 5.) & (abs(a['dec']) < 10.))
b = a[tt]
a.size
#10
tt.size
#10
tt.sum()
#1
b.size
#1
If no names age given to the different tags, it is set by default to f0,f1,...fN.
One can access the data without knowing the names of the tags:
a[a.dtype.names[2]]
is more complicated that IDL>a.(2), but at least it's possible ;-) And it as some advantage: you can change the names:
a.dtype.names = ('obs','ra','dec')
Be careful with subset, they are views:
b=a[1]
a['dec'][1]
# 0.0
b['dec']
# 0.0
b['dec'] = 2
a['dec'][1]
# 2.0
But it's not so easy to see it:
b['dec'] is a['dec'][1]
# False
Now we can turn the structured array a into a recarray:
>>> a2.dec
array([ 32.61106119, 82.72958898, -18.46190884, 44.79729473,
-54.65838972, -23.78818937, 3.56472044, -79.63061338,
15.81108779, 73.37221597])
Be careful, this is a view, it means that the data are NOT duplicated, they are the same:
>>> a2.dec[1] = 2
>>>
>>> a2.dec[1]
2.0
>>>
>>> a[1]['dec']
2.0
>>>
>>> a['dec'][1]
2.0
This can slow down the access to a2 AND to a !!! So not so useful, or for small tables.
Refs:
http://docs.scipy.org/doc/numpy/user/basics.rec.html
http://www.scipy.org/Cookbook/Recarray
import numpy as np
a = np.zeros((10,),dtype=[('name', str), ('ra', float), ('dec', float)])
a['ra'] = np.random.random_sample(10)*360
a['dec'] = np.random.random_sample(10)*180-90
tt = ((a['ra'] > 5.) & (abs(a['dec']) < 10.))
b = a[tt]
a.size
#10
tt.size
#10
tt.sum()
#1
b.size
#1
If no names age given to the different tags, it is set by default to f0,f1,...fN.
One can access the data without knowing the names of the tags:
a[a.dtype.names[2]]
is more complicated that IDL>a.(2), but at least it's possible ;-) And it as some advantage: you can change the names:
a.dtype.names = ('obs','ra','dec')
Be careful with subset, they are views:
b=a[1]
a['dec'][1]
# 0.0
b['dec']
# 0.0
b['dec'] = 2
a['dec'][1]
# 2.0
But it's not so easy to see it:
b['dec'] is a['dec'][1]
# False
Now we can turn the structured array a into a recarray:
a2 = a.view(np.recarray)This add a new access mode for the data:>>> a2.dec
array([ 32.61106119, 82.72958898, -18.46190884, 44.79729473,
-54.65838972, -23.78818937, 3.56472044, -79.63061338,
15.81108779, 73.37221597])
Be careful, this is a view, it means that the data are NOT duplicated, they are the same:
>>> a2.dec[1] = 2
>>>
>>> a2.dec[1]
2.0
>>>
>>> a[1]['dec']
2.0
>>>
>>> a['dec'][1]
2.0
This can slow down the access to a2 AND to a !!! So not so useful, or for small tables.
Refs:
http://docs.scipy.org/doc/numpy/user/basics.rec.html
http://www.scipy.org/Cookbook/Recarray
dimanche 5 juin 2011
Structure-like object
I really like the structure variable in IDL. Especially the arrays of structure. It allows to search for elements using the where function and to extract a sub-structure matching a give condition.
I mean, if I have an dataset like this:
IDL> a = replicate({name:'',ra:0.0,dec:0.0},1000)
I can search for all the elements matching for exemple:
IDL> tt = where(a.ra gt 10. and abs(a.dec) gt 5.)
IDL> b = a[tt]
The same (more or less) can be made using numpy (imported as np):
a = np.zeros((1000,),dtype=[('name', str), ('ra', float), ('dec', float)])
tt = ((a['ra'] > 5.) & (abs(a['dec']) < 10.))
b = a[tt]
I don't really know if this is the best way. And also don't know how to access for example the second tag without naming it, like in IDL a.(1)...
I can also create an object:
class obs(object):
def __init__(self,name='',ra=0.,dec=0.):
self.name=name
self.ra=ra
self.dec=decAnd even define an array of objects:
colec = np.empty( (3,3), dtype=object)
And then put the objects in the colec:
colec[:,:] = obs()
BUT this will create a collection of 9 times the same object!!!
colec[0,0].ra = 5.5
colec[1,1].ra
>>>5.5
Some loop needed here. But the worst is that one will loose all the power of linear algebra from numpy.
So stay with the first approach for now.
I mean, if I have an dataset like this:
IDL> a = replicate({name:'',ra:0.0,dec:0.0},1000)
I can search for all the elements matching for exemple:
IDL> tt = where(a.ra gt 10. and abs(a.dec) gt 5.)
IDL> b = a[tt]
The same (more or less) can be made using numpy (imported as np):
a = np.zeros((1000,),dtype=[('name', str), ('ra', float), ('dec', float)])
tt = ((a['ra'] > 5.) & (abs(a['dec']) < 10.))
b = a[tt]
I don't really know if this is the best way. And also don't know how to access for example the second tag without naming it, like in IDL a.(1)...
I can also create an object:
class obs(object):
def __init__(self,name='',ra=0.,dec=0.):
self.name=name
self.ra=ra
self.dec=decAnd even define an array of objects:
colec = np.empty( (3,3), dtype=object)
And then put the objects in the colec:
colec[:,:] = obs()
BUT this will create a collection of 9 times the same object!!!
colec[0,0].ra = 5.5
colec[1,1].ra
>>>5.5
Some loop needed here. But the worst is that one will loose all the power of linear algebra from numpy.
So stay with the first approach for now.
Row- or Column major arrays and loops order.
After a too long period of silence, I'm coming back to learn Python. I just want to point out a little difference between IDL and Python in the order arrays are stored in the computer memory.
There is two ways arrays can be stored: row- or column major. It has a direct impact on the way one has to loop on the arrays. IDL is like Fortran (column major) and Python is like C (row major). It means that in Python, as you move linearly through the memory of an array, the second dimension (rigthmost) changes the fastest, while in IDL the first (leftmost) dimension changes the fastest.
Consequence on the loop order:
There is two ways arrays can be stored: row- or column major. It has a direct impact on the way one has to loop on the arrays. IDL is like Fortran (column major) and Python is like C (row major). It means that in Python, as you move linearly through the memory of an array, the second dimension (rigthmost) changes the fastest, while in IDL the first (leftmost) dimension changes the fastest.
Consequence on the loop order:
for i in range(0,5): for j in range(0,4):
... a[i,j] ...
mercredi 13 octobre 2010
list comprehension
There is a way to write loops and test on lists in Python which is very condensate: the so-called list comprehension.
An example found in the French forum: http://www.developpez.net/forums/d962510/autres-langages/python-zope/general-python/operations-listes-dictionnaires/.
A guy wanted to transform a dictionary like this:
d= {'Ei': (1,3,4,4,6) , 'id' : ('r','r','t','t','t')}
into the list of occurence of each id:
An example found in the French forum: http://www.developpez.net/forums/d962510/autres-langages/python-zope/general-python/operations-listes-dictionnaires/.
A guy wanted to transform a dictionary like this:
d= {'Ei': (1,3,4,4,6) , 'id' : ('r','r','t','t','t')}
into the list of occurence of each id:
[('r', [1, 3]), ('t', [4, 4, 6])]
One of the answers was:
L=[(d['id'][i],d['Ei'][i]) for i in xrange(0,len(d['Ei']))] R=[(x,[y[1] for y in L if y[0]==x]) for x in set(d['id']) ]
Quite efficient!
The first step is to build a dictionary with the correspondances between the id and the Ei, the L:
[('r', 1), ('r', 3), ('t', 4), ('t', 4), ('t', 6)]
This is done with something like this:
This is done with something like this:
In [8]: L2 = []
In [9]: for i in xrange(0,len(d['Ei'])):
...: L2.append((d['id'][i],d['Ei'][i]))
Which can effectively be compacted as:
...: L2.append((d['id'][i],d['Ei'][i]))
Which can effectively be compacted as:
L=[(d['id'][i],d['Ei'][i]) for i in xrange(0,len(d['Ei']))]
The second step (R) is the list comprehension form of the following, where we are counting the occurences of each id. First find the set of the different and uniq values of id: set() gives the solution.
Then looping on these values and find the occurences for each values. Finally put all this into a dictionary. The expand form would be:
R2=[]
uniqid = set(d['id'])
for x in uniqid:
for y in L:
if y[0]==x:
R2.append([x,[y[1]]])
for x in uniqid:
for y in L:
if y[0]==x:
R2.append([x,[y[1]]])
What can also be obtained like this:
R=[(x,[y[1] for y in L if y[0]==x]) for x in set(d['id']) ]
This is more compact, in some sense more elegant, and I think more efficient (quicker), but not really sure of that...
lundi 11 octobre 2010
Save and Restore (2)
I guess I got it, not the same syntax as in IDL, but quite as fast in reading/writing:
def save(file,**kwargs):
"""
Save the value of some data in a file.
Usage: save('misdatos.pypic',a=a,b=b,test=test)
"""
import cPickle
f=open(file,"wb")
cPickle.dump(kwargs,f,protocol=2)
f.close
def restore(file):
"""
Read data saved with save function.
Usage: datos = restore('misdatos.pypic')
"""
import cPickle
f=open(file,"rb")
result = cPickle.load(f)
f.close
return result
For example (notice I use to import my stuff as CM):
CM.save('data3.pypic',data3=data3,a=a,b=b)
and
dd=CM.restore('data3.pypic')
take a small second to write and read.
Something interesting:
dd is a dictionary containing the 3 variables data3, a and b.
Now if I want to use data3, I can "extract" it:
In [15]: data3 is dd['data3']
Out[15]: True
In [16]: id(data3)
Out[16]: 4393756504
In [17]: id(dd['data3'])
Out[17]: 4393756504
Nice way to do the things ;-)
ADD:
Some people can find easier to save data using
def save(file,**kwargs):
"""
Save the value of some data in a file.
Usage: save('misdatos.pypic',a=a,b=b,test=test)
"""
import cPickle
f=open(file,"wb")
cPickle.dump(kwargs,f,protocol=2)
f.close
def restore(file):
"""
Read data saved with save function.
Usage: datos = restore('misdatos.pypic')
"""
import cPickle
f=open(file,"rb")
result = cPickle.load(f)
f.close
return result
For example (notice I use to import my stuff as CM):
CM.save('data3.pypic',data3=data3,a=a,b=b)
and
dd=CM.restore('data3.pypic')
take a small second to write and read.
Something interesting:
dd is a dictionary containing the 3 variables data3, a and b.
Now if I want to use data3, I can "extract" it:
data3 = dd['data3']
Nice, and very quick, as it's not a copy, but rather an object poiting to the same memory place:In [15]: data3 is dd['data3']
Out[15]: True
In [16]: id(data3)
Out[16]: 4393756504
In [17]: id(dd['data3'])
Out[17]: 4393756504
Nice way to do the things ;-)
ADD:
Some people can find easier to save data using
save(file,"data")
others will prefere:
save(file,data=data)
You can use both with the following save function:
others will prefere:
save(file,data=data)
You can use both with the following save function:
def save(file,*args,**kwargs):
"""
Save the value of some data in a file.
Usage: save('misdatos.pypic','a',b=b)
"""
import cPickle
f=open(file,"wb")
dico = kwargs
for name in args:
dico[name] = eval(name)
cPickle.dump(dico,f,protocol=2)
f.close
"""
Save the value of some data in a file.
Usage: save('misdatos.pypic','a',b=b)
"""
import cPickle
f=open(file,"wb")
dico = kwargs
for name in args:
dico[name] = eval(name)
cPickle.dump(dico,f,protocol=2)
f.close
dimanche 10 octobre 2010
Save and Restore
I use a lot the save/restore facilities in IDL. BTW, this is the lack of a complete save/restore set of tools that avoid me to use GDL in some projects. I was looking for an equivalent in Python, and realized that there are some few tools, the main problem now is choosing the right one ;-)
I found this page: http://kbyanc.blogspot.com/2007/07/python-serializer-benchmarks.html
and made a few tests with cPickle, which is part of Python (no need to install extra module).
It is actually very efficient when used with the protocol=2 option.
Marshal seems to be even faster, but cannot handle the rec.array objects (at least it doesn't work for me...).
Example of the use:
In [2]: import CMorisset as CM
In [3]: data3 = CM.ReadFortran('test3.dat','a10,1x,f6.2,1x,f6.2,1x,i2',['name', 'ra', 'dec','mag'])
In [4]: import cPickle
In [5]: cPickle.dump(data3, open("data3.pickle", "wb"),protocol=2)
In [6]: data3=cPickle.load(open("data3.pickle","rb"))
Reading the 27Mo of the test3.dat file take me 30 seconds with the Fortran format, and only 1 with the cPickle function! The main problems are that 1) one need to know the name of the store variable, and 2) only one object can be saved at a time.
I think it can be bypassed using a dictionary containing the variables and the names.
My main issue now is to build the dicionnary from the arguments passed to a function, so that I could just have:
I found this page: http://kbyanc.blogspot.com/2007/07/python-serializer-benchmarks.html
and made a few tests with cPickle, which is part of Python (no need to install extra module).
It is actually very efficient when used with the protocol=2 option.
Marshal seems to be even faster, but cannot handle the rec.array objects (at least it doesn't work for me...).
Example of the use:
In [2]: import CMorisset as CM
In [3]: data3 = CM.ReadFortran('test3.dat','a10,1x,f6.2,1x,f6.2,1x,i2',['name', 'ra', 'dec','mag'])
In [4]: import cPickle
In [5]: cPickle.dump(data3, open("data3.pickle", "wb"),protocol=2)
In [6]: data3=cPickle.load(open("data3.pickle","rb"))
Reading the 27Mo of the test3.dat file take me 30 seconds with the Fortran format, and only 1 with the cPickle function! The main problems are that 1) one need to know the name of the store variable, and 2) only one object can be saved at a time.
I think it can be bypassed using a dictionary containing the variables and the names.
My main issue now is to build the dicionnary from the arguments passed to a function, so that I could just have:
save(file='data',dat1,dat2,dat3)
Will se this latter...
Parameters in functions: take care!
I found a nice page with something really strange for me, I'll have to keep this in my mind because it's totally different from IDL.
The page: http://hetland.org/writing/instant-python.html
The "problem", as I rewrote it:
Let's define 2 functions:
def test(x):
x=2
def test2(x):
x[0]=2
Now, we'll call test and test2 with different variables:
In [3]: y=1
In [4]: test(y)
In [5]: y
Out[5]: 1
y is not changed. BUT:
In [7]: y=[1,2,3]
In [8]: test2(y)
In [9]: y
Out[9]: [2, 2, 3]
Now y[0] is changed!!! And even worst:
In [10]: y=[[4,5,6],[14,15,16],[24,25,26]]
In [11]: test2(y)
In [12]: y
Out[12]: [2, [14, 15, 16], [24, 25, 26]]
And the best for the end:
In [16]: y
Out[16]: [[2, 5, 6], [14, 15, 16], [24, 25, 26]]
So part of the table can be changed, but a single variable not: exactly the opposite of IDL...
The page: http://hetland.org/writing/instant-python.html
The "problem", as I rewrote it:
Let's define 2 functions:
def test(x):
x=2
def test2(x):
x[0]=2
Now, we'll call test and test2 with different variables:
In [3]: y=1
In [4]: test(y)
In [5]: y
Out[5]: 1
y is not changed. BUT:
In [7]: y=[1,2,3]
In [8]: test2(y)
In [9]: y
Out[9]: [2, 2, 3]
Now y[0] is changed!!! And even worst:
In [10]: y=[[4,5,6],[14,15,16],[24,25,26]]
In [11]: test2(y)
In [12]: y
Out[12]: [2, [14, 15, 16], [24, 25, 26]]
And the best for the end:
In [13]: y=[[4,5,6],[14,15,16],[24,25,26]]
In [15]: test2(y[0])In [16]: y
Out[16]: [[2, 5, 6], [14, 15, 16], [24, 25, 26]]
So part of the table can be changed, but a single variable not: exactly the opposite of IDL...
dimanche 3 octobre 2010
My first module! Still on reading ascii formatted file.
I did my first program in Python! Here it is:
def ReadFortran(file,format,names,comment="#"):
"""
Read a file using a Fortran-style format.
Return a NumPy rec.array with each column named following the given names.
Example: data = ReadFortran('test2.dat','a10,1x,f6.2,1x,f6.2,1x,i2',['name', 'ra', 'dec','mag'],comment="#")
Morisset, IA-UNAM, Oct. 2010
"""
import Scientific.IO.FortranFormat as FF
import numpy.core.records as nprec
FFformat = FF.FortranFormat(format)
f=open(file,'r')
rows=[]
for line in f:
if line[0] != comment:
row = FF.FortranLine(line,FFformat)
rows.append(row.data)
f.close()
return nprec.fromrecords(rows, names=names)
OK, it's not a very big one, but it took me a lot of time trying to avoid the list.append command. And I didn't found. But it seems that most of the execution time is on the FortranLine command.
It is very slower than the same in IDL: it reads a 1000000 lines file in some 45 seconds, while IDL take 5... The csv2rec takes 20 secs.
Perhaps one of these days I'll try to call a fortran routine to read the file...
ADD:
It seems that a more compact and pythonesk way of writing the loop is to change:
rows=[]
for line in f:
if line[0] != comment:
row = FF.FortranLine(line,FFformat)
rows.append(row.data)
into:
rows = [FF.FortranLine(line,FFformat).data for line in f if line[0] != comment]
The map function could also be used:
Got the tips from http://jaynes.colorado.edu/PythonIdioms.html
def ReadFortran(file,format,names,comment="#"):
"""
Read a file using a Fortran-style format.
Return a NumPy rec.array with each column named following the given names.
Example: data = ReadFortran('test2.dat','a10,1x,f6.2,1x,f6.2,1x,i2',['name', 'ra', 'dec','mag'],comment="#")
Morisset, IA-UNAM, Oct. 2010
"""
import Scientific.IO.FortranFormat as FF
import numpy.core.records as nprec
FFformat = FF.FortranFormat(format)
f=open(file,'r')
rows=[]
for line in f:
if line[0] != comment:
row = FF.FortranLine(line,FFformat)
rows.append(row.data)
f.close()
return nprec.fromrecords(rows, names=names)
OK, it's not a very big one, but it took me a lot of time trying to avoid the list.append command. And I didn't found. But it seems that most of the execution time is on the FortranLine command.
It is very slower than the same in IDL: it reads a 1000000 lines file in some 45 seconds, while IDL take 5... The csv2rec takes 20 secs.
Perhaps one of these days I'll try to call a fortran routine to read the file...
ADD:
It seems that a more compact and pythonesk way of writing the loop is to change:
rows=[]
for line in f:
if line[0] != comment:
row = FF.FortranLine(line,FFformat)
rows.append(row.data)
into:
rows = [FF.FortranLine(line,FFformat).data for line in f if line[0] != comment]
The map function could also be used:
rows = map(lambda line:FF.FortranLine(line,FFformat).data,f)
BUT in this latest case we can't manage the comment parameter.Got the tips from http://jaynes.colorado.edu/PythonIdioms.html
Reading formated ascii file a la fortran
I first learned to program in Fortran (after some introductions to Basic, ADA, Turbo pascal, in the early 80's). Then I meet IDL in 1994 (thanks to mi friend Philippe) and the life changed! Interactive + Data + Language was exactly what I needed. But as already said at the beginning of this blog, I now want to change for a free access open language.
But I feel very difficult this change, I'm like a baby learning to walk and talk... For example, I was looking since 2 weeks a way to read a simple formated ascii file, like I used to do in IDL.
The file is just:
alpha 193.63 18.40 19
beta 280.12 0.52 16
gamma 206.59 0.06 17
delta 23.74 17.92 19
eta 18.10 10.07 19
and the IDL process is:
et voilà!
The format string is using the Fortran convention, that is quite powerful in describing quite any fixed format. It seems that it's was not possible to do this in Python, 'till I found a module including this facility! Developped by french people from CNRS in Orleans, it is avilable here:
http://dirac.cnrs-orleans.fr/plone/software/scientificpython/
The part of the module I want is this one:
I used it to read the same file as previously in IDL
data=numpy.rec.array([' ',0.,0.,0], names=['name', 'ra', 'dec','mag'])
from Scientific.IO import FortranFormat as FF
format = FF.FortranFormat('a10,1x,f6.2,1x,f6.2,1x,i2')
f=open('test1.dat','r')
for line in f:
# data['name'],data['ra'],data['dec'],data['mag'] = FF.FortranLine(line,format)
data.name,data.ra,data.dec,data.mag = FF.FortranLine(line,format)
print data
The main problem is that I don't know how to have the whole array in the data variable. Anyway, the problem of reading fixed formatted ascii file is solved ;-)
But I feel very difficult this change, I'm like a baby learning to walk and talk... For example, I was looking since 2 weeks a way to read a simple formated ascii file, like I used to do in IDL.
The file is just:
alpha 193.63 18.40 19
beta 280.12 0.52 16
gamma 206.59 0.06 17
delta 23.74 17.92 19
eta 18.10 10.07 19
and the IDL process is:
data = replicate({name:'',ra:0.0,dec:0.0,mag:0},n_lines)
openr,lun,/get_lun,file
readf,lun,data,format='(a10,1x,f6.2,1x,f6.2,1x,i2)'
et voilà!
The format string is using the Fortran convention, that is quite powerful in describing quite any fixed format. It seems that it's was not possible to do this in Python, 'till I found a module including this facility! Developped by french people from CNRS in Orleans, it is avilable here:
http://dirac.cnrs-orleans.fr/plone/software/scientificpython/
The part of the module I want is this one:
Module FortranFormat
Fortran-style formatted input/output
This module provides two classes that aid in reading and writing Fortran-formatted text files.
Examples:
Input::
>>>s = ' 59999'
>>>format = FortranFormat('2I4')
>>>line = FortranLine(s, format)
>>>print line[0]
>>>print line[1]
prints::
>>>5
>>>9999
Output::
>>>format = FortranFormat('2D15.5')
>>>line = FortranLine([3.1415926, 2.71828], format)
>>>print str(line)
prints::
'3.14159D+00 2.71828D+00'
I used it to read the same file as previously in IDL
data=numpy.rec.array([' ',0.,0.,0], names=['name', 'ra', 'dec','mag'])
from Scientific.IO import FortranFormat as FF
format = FF.FortranFormat('a10,1x,f6.2,1x,f6.2,1x,i2')
f=open('test1.dat','r')
for line in f:
# data['name'],data['ra'],data['dec'],data['mag'] = FF.FortranLine(line,format)
data.name,data.ra,data.dec,data.mag = FF.FortranLine(line,format)
print data
The main problem is that I don't know how to have the whole array in the data variable. Anyway, the problem of reading fixed formatted ascii file is solved ;-)
mercredi 29 septembre 2010
Arrays and types: the rec.array type
Here are some example of unexpected behaviors, when coming from IDL:
In [4]: a
Out[4]: [1.0, 2.0, 3] #a is a list
In [5]: b
Out[5]: array([ 0.84147098, 0.90929743, 0.14112001])
In [6]: 2*b
Out[6]: array([ 1.68294197, 1.81859485, 0.28224002])
In [7]: 2*a
Out[7]: [1.0, 2.0, 3, 1.0, 2.0, 3] #this double the list, not the elements!!!
In [10]: c=array([1,2.,3])
In [11]: 2*c
Out[11]: array([ 2., 4., 6.]) #now it's OK
In [12]: d=[1,2.,'3'] #mixing int, float and string
In [13]: e=array(d)
In [14]: e
Out[14]: array(['1', '2.0', '3'], dtype='|S8') #converted to a single type: string
As you can see, the [] are not always defining arrays, sometime it needs explicitly the function array().
A list can contain different types, not an array.
Let's see now how the csv-reader can deal with different types in the same line (as when using structures in IDL):
The file to read is:
int flt str int
1 1 "test1" 1
2 2.3 "tralala" 2
5 3.14 "" 3
6 1e3 "double " 4
7 1e79 "big one" 5
The reading process:
In [43]: rec
Out[43]:
rec.array([(1, 1.0, 'test1', 1), (2, 2.2999999999999998, 'tralala', 2),
(5, 3.1400000000000001, '', 3), (6, 1000.0, 'double ', 4),
(7, 9.9999999999999997e+78, 'big one', 5)],
dtype=[('int', '<i8'), ('flt', '<f8'), ('str', '|S7'), ('int_1', '<i8')])
Note that no problems with the value of 1 for the 2nd elements in the first data row: it's an integer, but as the element of the same column in the 2nd data row is 2.3, it is not wrongly considered that the type of this row is integer (contrary to IDL read_ascii(), which only consider the first data row to determine the data types).
Also note the headers, defined using the first row: int is used twice, the second time the name is converted to int_1. So cute!
In [4]: a
Out[4]: [1.0, 2.0, 3] #a is a list
In [5]: b
Out[5]: array([ 0.84147098, 0.90929743, 0.14112001])
In [6]: 2*b
Out[6]: array([ 1.68294197, 1.81859485, 0.28224002])
In [7]: 2*a
Out[7]: [1.0, 2.0, 3, 1.0, 2.0, 3] #this double the list, not the elements!!!
In [10]: c=array([1,2.,3])
In [11]: 2*c
Out[11]: array([ 2., 4., 6.]) #now it's OK
In [12]: d=[1,2.,'3'] #mixing int, float and string
In [13]: e=array(d)
In [14]: e
Out[14]: array(['1', '2.0', '3'], dtype='|S8') #converted to a single type: string
As you can see, the [] are not always defining arrays, sometime it needs explicitly the function array().
A list can contain different types, not an array.
Let's see now how the csv-reader can deal with different types in the same line (as when using structures in IDL):
The file to read is:
int flt str int
1 1 "test1" 1
2 2.3 "tralala" 2
5 3.14 "" 3
6 1e3 "double " 4
7 1e79 "big one" 5
The reading process:
rec=csv2rec('test1.csv',delimiter=" ")
And the type is a rec.array, with mixing types:In [43]: rec
Out[43]:
rec.array([(1, 1.0, 'test1', 1), (2, 2.2999999999999998, 'tralala', 2),
(5, 3.1400000000000001, '', 3), (6, 1000.0, 'double ', 4),
(7, 9.9999999999999997e+78, 'big one', 5)],
dtype=[('int', '<i8'), ('flt', '<f8'), ('str', '|S7'), ('int_1', '<i8')])
Note that no problems with the value of 1 for the 2nd elements in the first data row: it's an integer, but as the element of the same column in the 2nd data row is 2.3, it is not wrongly considered that the type of this row is integer (contrary to IDL read_ascii(), which only consider the first data row to determine the data types).
Also note the headers, defined using the first row: int is used twice, the second time the name is converted to int_1. So cute!
lundi 27 septembre 2010
the basic syntax (1)
Following the IDL cookbook, I first explore some syntax of Python.
I use the ipython, so the keyboards inputs are transcript with "In [n]" and the corresponding output with "Out [n]". To print something, just type it and press Enter:
Parameters are separated by "," on the same line:
The blocks are defined by indentation. No begin, no end. In the following, the ....: are printed by ipython. The indentation is automatic in ipython, but not in python: you have to type at least one space to define the IF block. To finish a block, just empty lines (one in python, 2 in ipython...)
In [70]: a,b=5,6
In [71]: if a<b:
....: print a+b
....:
....:
11
I use the ipython, so the keyboards inputs are transcript with "In [n]" and the corresponding output with "Out [n]". To print something, just type it and press Enter:
In [4]: 'Hello mundo;-)'
Out[4]: 'Hello mundo;-)'
Out[4]: 'Hello mundo;-)'
In [5]: a=1
In [6]: a
Out[6]: 1
In [8]: a?
Type: int
Base Class: <type 'int'>
String Form: 1
Namespace: Interactive
Docstring:
int(x[, base]) -> integer
In [6]: a
Out[6]: 1
In [8]: a?
Type: int
Base Class: <type 'int'>
String Form: 1
Namespace: Interactive
Docstring:
int(x[, base]) -> integer
....
In [35]: 3*exp(-12/(27.*log(1.3)))
Out[35]: 0.55135006225210048
Out[35]: 0.55135006225210048
In [36]: 3*exp(-12/(27.*log10([12.,14.,15])))
Out[36]: array([ 2.5086749 , 2.53502116, 2.54592125])
Out[36]: array([ 2.5086749 , 2.53502116, 2.54592125])
Special characters:
; is use to have 2 comands on the same line (and is NOT starting a comment!)
a=5 ; b= 3
which actually can be done with:
a,b = 5,3
No matter spaces IF NOT AT THE BEGINNING OF THE LINE:
a , b = 5 , 3
BTW this can be very powerful:
a, b, c = b, a+b, c+1
Do you remember this one? Fibonnacci!# is starting a comment
a = b # a and b are pointing to different memory place
can = Canvas(f,width =250, height =250, bg ='ivory')
The blocks are defined by indentation. No begin, no end. In the following, the ....: are printed by ipython. The indentation is automatic in ipython, but not in python: you have to type at least one space to define the IF block. To finish a block, just empty lines (one in python, 2 in ipython...)
In [70]: a,b=5,6
In [71]: if a<b:
....: print a+b
....:
....:
11
In [65]: def f(x):
....: return x*2
....:
....: return x*2
....:
In [67]: f(5)
Out[67]: 10
Out[67]: 10
mercredi 22 septembre 2010
The same module in different libraries
One thing that I found nice in Python compared to IDL, is the amount of very complete and complex libraries that have been developed and are accessible so easily... And one thing I quickly found horrible is the amount os libraries!...
Just an example: I installed the Mayavi package (it means that I have to also install the vtk package, but hopefully all is already in the macport repositories...). and began to try playing with it.
And I found that sometimes some tutorial are talking about functions I don't have... For example, the points3d() function is not available. Well, I realized that it is in the mlab module and that actually I have... 6 mlab.py files in the directory where Python is looking for!!!
Just asking from a command line shell:
./enthought/mayavi/mlab.py
./enthought/mayavi/tools/mlab.py
./enthought/tvtk/tools/mlab.py
./matplotlib/mlab.py
./numpy/numarray/mlab.py
./numpy/oldnumeric/mlab.py
So I have to be very careful with which module I download and in which order, to be sure that I have the mlab module I want.
Or the best is to call it explicitely and to check what is in each:
To obtain the list of the functions available from one module, just type for example mlab_mayavi. and use the TAB to obtain the possible completions.
We can very quickly realize that the needed points3d() function is absent in all mlab modules except the mayavi one.
So be very careful with the modules, mlab is not always mlab...
Just an example: I installed the Mayavi package (it means that I have to also install the vtk package, but hopefully all is already in the macport repositories...). and began to try playing with it.
And I found that sometimes some tutorial are talking about functions I don't have... For example, the points3d() function is not available. Well, I realized that it is in the mlab module and that actually I have... 6 mlab.py files in the directory where Python is looking for!!!
Just asking from a command line shell:
find /opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages mlab.py
give me:./enthought/mayavi/mlab.py
./enthought/mayavi/tools/mlab.py
./enthought/tvtk/tools/mlab.py
./matplotlib/mlab.py
./numpy/numarray/mlab.py
./numpy/oldnumeric/mlab.py
So I have to be very careful with which module I download and in which order, to be sure that I have the mlab module I want.
Or the best is to call it explicitely and to check what is in each:
from enthought.mayavi import mlab as mlab_mayavi
from enthought.tvtk.tools import mlab as mlab_tvtkTo obtain the list of the functions available from one module, just type for example mlab_mayavi. and use the TAB to obtain the possible completions.
We can very quickly realize that the needed points3d() function is absent in all mlab modules except the mayavi one.
So be very careful with the modules, mlab is not always mlab...
mardi 21 septembre 2010
Arrays bounds using NumPy
NumPy is load by default when calling ipython -pylab. If not, it's always possible to import all the module by from numpy import * or import numpy as N (then you need to start any numpy function with N.).
To easy create arrays, just use:
The step can be specified:
a=r_[1:10:.1] or a=arange(1,10,.1).
In this case, the array latest element is 9.9, not 10.
It is also possible to give the number of elements, for this a "j" is added to the 3rd parameter:
b=r_[1:10:100j] or b=linspace(1,10,100).
BUT in these latest two equivalent cases, the latest element is actually 10!...
Another way to say this:
a=r_[1:10:.1] and b=r_[1:9.9:90j] are equivalent. Not obvious for me...
BTW, the same philosophy apply when selecting part of an array:
In [71]: a=r_[1:10]
In [72]: a
Out[72]: array([1, 2, 3, 4, 5, 6, 7, 8, 9])
In [73]: a[0:2]
Out[73]: array([1, 2])
I certainly would expect the answer to be a 3 elements sub-array. I'm sure this will be a big source of bug in my future Python codes ;-)
I found something quite powefull: accessing the latest elements of an array:
In [77]: a[-1]
Out[77]: 9
In [78]: a[-5:-1]
Out[78]: array([5, 6, 7, 8])
In [79]: a[-5::]
Out[79]: array([5, 6, 7, 8, 9])
I also saw that the indexing of arrays can be quite sophisticated: http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
To easy create arrays, just use:
a=r_[1:10]
It will create an array from 1 to... 9 !!! It is actually a kind of shortcut for:a=arange(1,10)
which also provides an array of 9 elements, from 1 to 9. The step can be specified:
a=r_[1:10:.1] or a=arange(1,10,.1).
In this case, the array latest element is 9.9, not 10.
It is also possible to give the number of elements, for this a "j" is added to the 3rd parameter:
b=r_[1:10:100j] or b=linspace(1,10,100).
BUT in these latest two equivalent cases, the latest element is actually 10!...
Another way to say this:
a=r_[1:10:.1] and b=r_[1:9.9:90j] are equivalent. Not obvious for me...
BTW, the same philosophy apply when selecting part of an array:
In [71]: a=r_[1:10]
In [72]: a
Out[72]: array([1, 2, 3, 4, 5, 6, 7, 8, 9])
In [73]: a[0:2]
Out[73]: array([1, 2])
I certainly would expect the answer to be a 3 elements sub-array. I'm sure this will be a big source of bug in my future Python codes ;-)
I found something quite powefull: accessing the latest elements of an array:
In [77]: a[-1]
Out[77]: 9
In [78]: a[-5:-1]
Out[78]: array([5, 6, 7, 8])
In [79]: a[-5::]
Out[79]: array([5, 6, 7, 8, 9])
I also saw that the indexing of arrays can be quite sophisticated: http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
lundi 20 septembre 2010
Quick function definition: lambda and "closure"
There is 2 ways to define a function in Python. The classical:
and with the use of lambda:
fitfunc = lambda p, x: p[0]*exp(-(x-p[1])**2/(2.0*p[2]**2))
Both can be used in any place:
plot(x,fitfunc([1.,0.7,.3],x),'.')
From what I saw on the net, the compact lambda definition is more used when the function is small and used locally...
BTW, while Googling around this concept, I found this:
The summer function return a function, which depend on the value of the nombre variable. And the sum10 function keep in mind the value 10, even after leaving the summer function. This is what the computing science people name a "closure"...
def fitfunc(p,x):
return p[0]*exp(-(x-p[1])**2/(2.0*p[2]**2))and with the use of lambda:
fitfunc = lambda p, x: p[0]*exp(-(x-p[1])**2/(2.0*p[2]**2))
Both can be used in any place:
plot(x,fitfunc([1.,0.7,.3],x),'.')
From what I saw on the net, the compact lambda definition is more used when the function is small and used locally...
BTW, while Googling around this concept, I found this:
In [114]: def summer(nombre):
.....: def sumit(value):
.....: return value+nombre
.....: return sumit
.....: In [115]: sum10 = summer(10)
In [116]: sum10(20)
Out[116]: 30The summer function return a function, which depend on the value of the nombre variable. And the sum10 function keep in mind the value 10, even after leaving the summer function. This is what the computing science people name a "closure"...
dimanche 19 septembre 2010
filtering data: the where() function
I'm now trying to use my favorite IDL function in Python: the where() function. It is used to select the subscripts of an array where a condition is fulfilled.
As I'm using the pylab version of ipython, it comes with a where function that can match more or less the IDL one. But it seems that another method can also be used...
Let's do some examples: I want to select from a table of 1000000 lines and 10 columns the elements that have a value for the 3rd and 7th columns bigger than 0.5.
I'm first creating a 2D-table on which I will apply my filter.
a=random((1e6,10))
I first had to realize that the order of the subscripts are in the inverse order than in IDL: first rows, then columns.
So the elements of the 3rd columns are a[:,2], and the ones for the 7th columns are a[:,6].
I first try:
tt = where(a[:,2] > 0.5 and a[:,6] > 0.5)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
OK, I'm not yet at the level of understanding what Python told me, but clearly it's not correct. I finally found that with parenthesis and & instead og and, things are going well:
tt = where((a[:,2] > 0.5) & (a[:,6] > 0.5))
tt is a so-called "tuple", which seems to be an array, it has a size:
In [90]: size(tt)
Out[90]: 250248
It's a credible value given the condition and the size of the input table.
I can now use this variable to extract the values from the initial table:
The main problem here is that the table I have in x and y are not correctly shaped:
In [112]: x.shape
Out[112]: (1, 250248)
If I try to plot this (using plot(x,y,'.')), it doesn't work (well, after some minutes waiting for a result I killed the plot!).
I can reshape the x and y tables using for example the transpose function:
plot(transpose(x),transpose(y),'.')
but the best is to transpose the filter before using it:
tt2 = transpose(where((a[:,2] > 0.5) & (a[:,6] > 0.5)))
plot(a[tt2,2],a[tt2,6],'.')
is working fine. BTW, tt2 is not anymore a tuple, it's not an array of integers, so for example:
Another way of filtering the data is to generate a table of booleans:
tt3 = (a[:,2] > 0.5) & (a[:,6] > 0.5)
This is an array:
In [147]: tt3.size
Out[147]: 1000000
In [148]: tt3.dtype
Out[148]: dtype('bool')
Contrary to IDL, it can directly be used in a table:
In [149]: a[tt3,2].size
Out[149]: 250248
In [150]: a[tt3,2].shape
Out[150]: (250248,)
Fine, the plot works also with this:
In [154]: plot(a[tt3,2],a[tt3,6],'.')
I tried both methods (where and boolean) on big table, but didn't saw any real difference on time execution. If some readers could tell me which one is really the more "python-way"...
As I'm using the pylab version of ipython, it comes with a where function that can match more or less the IDL one. But it seems that another method can also be used...
Let's do some examples: I want to select from a table of 1000000 lines and 10 columns the elements that have a value for the 3rd and 7th columns bigger than 0.5.
I'm first creating a 2D-table on which I will apply my filter.
a=random((1e6,10))
I first had to realize that the order of the subscripts are in the inverse order than in IDL: first rows, then columns.
So the elements of the 3rd columns are a[:,2], and the ones for the 7th columns are a[:,6].
I first try:
tt = where(a[:,2] > 0.5 and a[:,6] > 0.5)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
OK, I'm not yet at the level of understanding what Python told me, but clearly it's not correct. I finally found that with parenthesis and & instead og and, things are going well:
tt = where((a[:,2] > 0.5) & (a[:,6] > 0.5))
tt is a so-called "tuple", which seems to be an array, it has a size:
In [90]: size(tt)
Out[90]: 250248
It's a credible value given the condition and the size of the input table.
I can now use this variable to extract the values from the initial table:
x=a[tt,2]
y=a[tt,6]
The main problem here is that the table I have in x and y are not correctly shaped:
In [112]: x.shape
Out[112]: (1, 250248)
If I try to plot this (using plot(x,y,'.')), it doesn't work (well, after some minutes waiting for a result I killed the plot!).
I can reshape the x and y tables using for example the transpose function:
plot(transpose(x),transpose(y),'.')
but the best is to transpose the filter before using it:
tt2 = transpose(where((a[:,2] > 0.5) & (a[:,6] > 0.5)))
plot(a[tt2,2],a[tt2,6],'.')
is working fine. BTW, tt2 is not anymore a tuple, it's not an array of integers, so for example:
In [146]: tt2.size
Out[146]: 250248
Out[146]: 250248
tt3 = (a[:,2] > 0.5) & (a[:,6] > 0.5)
This is an array:
In [147]: tt3.size
Out[147]: 1000000
In [148]: tt3.dtype
Out[148]: dtype('bool')
Contrary to IDL, it can directly be used in a table:
In [149]: a[tt3,2].size
Out[149]: 250248
In [150]: a[tt3,2].shape
Out[150]: (250248,)
Fine, the plot works also with this:
In [154]: plot(a[tt3,2],a[tt3,6],'.')
I tried both methods (where and boolean) on big table, but didn't saw any real difference on time execution. If some readers could tell me which one is really the more "python-way"...
dimanche 12 septembre 2010
Reading an ascii file
I used to use the read_ascii() function in IDL (BTW I use my own version, which return an array of structures and not a structure containing arrays...), and it seems there is not an equivalent tool... or I didn't found it yet!
Nevertheless, I tried to make the job simpler by reading a Comma Separated Variable file (csv), as it can be output by any spreadsheet or downloaded from the net (e.g. Vizier tables).
I first found a module able to read such file: csv (!).
This is the first solution I used:
The problem is that I didn't succeed to apply simple filter to the data: I want to plot the log of the values, so I have to filter out the negative values... It seems that the format used for the x and y variables (namely "list") is not really the best one to be used with where.
Finally, I found another function to read the file, which outputs something very similar to a structure.
It is part of the pylab distribution (matplolib), so no need to import it as I use the pylab argument when calling ipython. So here my second (and successful) try to read, filter and plot my data:
rec=csv2rec('DIGEDA1.1.csv')
tt = where(logical_and(rec['3727']>0,rec['5007']>0))
rec2=rec[tt]
x=rec2['5007']
y=rec2['3727']
plot(log(y),log(x),'o')
The rec variable contains the whole file, in such a way very similar to IDL structure. A very nice thing is that the names of the different columns are directly taken from the first line of my file, which contains this information.
It is finally quite easy (well, it took me 3 hours to find all this in the Google jungle... it's why I'm doing this blog!).
Nevertheless, I tried to make the job simpler by reading a Comma Separated Variable file (csv), as it can be output by any spreadsheet or downloaded from the net (e.g. Vizier tables).
I first found a module able to read such file: csv (!).
This is the first solution I used:
import csv
from scipy import *
rr = csv.DictReader(open('DIGEDA1.1.csv'))
x=[]
y=[]
for row in rr:
x.append(row['5007'])
y.append(row['3727'])
plot(x,y)
from scipy import *
rr = csv.DictReader(open('DIGEDA1.1.csv'))
x=[]
y=[]
for row in rr:
x.append(row['5007'])
y.append(row['3727'])
plot(x,y)
The problem is that I didn't succeed to apply simple filter to the data: I want to plot the log of the values, so I have to filter out the negative values... It seems that the format used for the x and y variables (namely "list") is not really the best one to be used with where.
Finally, I found another function to read the file, which outputs something very similar to a structure.
It is part of the pylab distribution (matplolib), so no need to import it as I use the pylab argument when calling ipython. So here my second (and successful) try to read, filter and plot my data:
rec=csv2rec('DIGEDA1.1.csv')
tt = where(logical_and(rec['3727']>0,rec['5007']>0))
rec2=rec[tt]
x=rec2['5007']
y=rec2['3727']
plot(log(y),log(x),'o')
The rec variable contains the whole file, in such a way very similar to IDL structure. A very nice thing is that the names of the different columns are directly taken from the first line of my file, which contains this information.
It is finally quite easy (well, it took me 3 hours to find all this in the Google jungle... it's why I'm doing this blog!).
Inscription à :
Articles (Atom)