Python: Problems with a list comprehension using module laspy - python

recently i understand the great advantage to use the list comprehension. I am working with several milion of points (x,y,z) stored in a special format *.las file. In python there are two way to work with this format:
Liblas module [http://www.liblas.org/tutorial/python.html][1] (in a C++/Python)
laspy module [http://laspy.readthedocs.org/en/latest/tut_part_1.html][2] (pure Python)
I had several problem with liblas and i wish to test laspy.
in liblas i can use list comprehension as:
from liblas import file as lasfile
f = lasfile.File(inFile,None,'r') # open LAS
points = [(p.x,p.y) for p in f] # read in list comprehension
in laspy i cannot figurate how do the same:
from laspy.file import File
f = file.File(inFile, mode='r')
f
<laspy.file.File object at 0x0000000013939080>
(f[0].X,f[0].Y)
(30839973, 696447860)
i tryed several combination as:
points = [(p.X,p.Y) for p in f]
but i get this message
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: Point instance has no attribute 'x'
I tryed in uppercase and NOT-uppercase because Python is case sensitive:
>>> [(p.x,p.y) for p in f]
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: Point instance has no attribute 'x'
>>> [(p.X,p.Y) for p in f]
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: Point instance has no attribute 'X'
this is in interactive prompt:
C:\Python27>python.exe
Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> from laspy.file import File
>>> inFile="C:\\04-las_clip_inside_area\\Ku_018_class.las"
>>> f = File(inFile, None, 'r')
>>> f
<laspy.file.File object at 0x00000000024D5E10>
>>> points = [(p.X,p.Y) for p in f]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: Point instance has no attribute 'X'
>>>
the print p after the list is:
print dir(p)
['__doc__', '__init__', '__module__', 'make_nice', 'pack', 'packer', 'reader', 'unpacked']
in a loop format i have always the same error
>>> for p in f:
... print dir(p)
... print p.X,p.Y
...
['__doc__', '__init__', '__module__', 'make_nice', 'pack', 'packer', 'reader', 'unpacked']
Traceback (most recent call last):
File "<interactive input>", line 3, in <module>
AttributeError: Point instance has no attribute 'X'
using this code suggested by nneonneo
import numpy as np
for p in f:
... points = np.array([f.X, f.Y]).T
i can store in an array
points
array([[ 30839973, 696447860],
[ 30839937, 696447890],
[ 30839842, 696447832],
...,
[ 30943795, 695999984],
[ 30943695, 695999922],
[ 30943960, 695999995]])
but miss the way to create a list comprehension
points = [np.array(p.X,p.Y).T for p in f]
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: Point instance has no attribute 'X'
thanks in advance for help.
Gianni

Python is case-sensitive. Too me it looks like you ask for attribute x, but it should be an uppercase X.

Try
import numpy as np
...
points = np.array([f.X, f.Y]).T

It looks like Point has a make_nice() method that makes more attributes show up.
for p in f: p.make_nice()
Now your list comp should work (with uppercase X and Y--see comments below).
[(p.X,p.Y) for p in f]
note: This answer is not tested. It is based on reading the source of laspy.util.Point.
Relevant source:
def make_nice(self):
'''Turn a point instance with the bare essentials (an unpacked list of data)
into a fully populated point. Add all the named attributes it possesses,
including binary fields.
'''
i = 0
for dim in self.reader.point_format.specs:
self.__dict__[dim.name] = self.unpacked[i]
i += 1
# rest of method snipped

Related

Tuple index out of range error with .format(list)

I have a strange problem I don't get. I have a format string with a lot of fields. I want to supply the content for the fields using a list. The following simple demo below shows the issue:
>>> formatstr = "Hello {}, you are my {} fried since {}"
>>> list = ["John", "best", 2020]
>>> print formatstr.format(list)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
>>>
The format string has 3 fields and the list has also 3 elements.
So I don't understand the error message.
Even when I try to address the indexes within the format string:
>>>
>>> formatstr = "Hello {0:}, you are my {1:} fried since {2:}"
>>>
>>> print formatstr.format(list)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
>>>
Can you please help me? I think I blocked somewhere in my thinking.
Thanks.

unpickle a python 2 object in python 3 raises ValueError

In python 2.7.6:
# the data i'm trying to pickle
>>> x[0:5]
[494.12804680901604, 641.9374923706055, 778.293918918919, 470.2265625, 237.21332017010934]
>>> y[0:5]
[236.99996948242188, 381.6793310733242, 685.0, 409.0909090909091, 658.0]
>>> z[0:5]
[23, 20, 98, 24, 78]
>>> holder = [x,y,z]
How i'm pickling:
with open('holderData.obj','wb') as f:
pickle.dump(holder,f)
f.close()
In python 3.6.2
with open('holderData.obj','rb') as f:
d = pickle.load(f, encoding='bytes')
Yet, this returns:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError: could not convert string to float
The only question/answer I could found related to this issue, tells me to add the encoding='bytes' bit which doesn't work in this instance.
The pickle itself print(repr(pickle.dumps(holder))):
'(lp0\n(lp1\nF494.12804680901604\naF641.9374923706055\naF778.293918918919\naF470.2265625\naF237.21332017010934\naF372.76081123737373\naF396.15337968952133\naF615.2265625\naF470.2265625\naF581.2155330882352\naF488.40675200803213\naF475.47189597315435\naF92.0511279585

Python regexp \n issue

This searched ok:
>>> re.search(r'(.*?)\r\n(.+?)\r\n', 'aaa\r\r\nbbb\r\n').groups()
('aaa\r', 'bbb')
But when I replace one of three b to \n it not searched:
>>> re.search(r'(.*?)\r\n(.+?)\r\n', 'aaa\r\r\nb\nc\r\n').groups()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'groups'
But I want to parse in second case:
('aaa\r', 'b\nc')
You need the DOTALL flag:
import re
re.search(r'(.*?)\r\n(.+?)\r\n', 'aaa\r\r\nb\nc\r\n', flags=re.DOTALL).groups()
result:
('aaa\r', 'b\nc')

Python recognizes the function count as a name

I am viewing the Python tutorials from the Pascal institute BDFL says are the best to start and i have a very basic question
While in the tutorial says:
How many of each base does this sequence contains?
>>> count(seq, 'a')
35
>>> count(seq, 'c')
21
>>> count(seq, 'g')
44
>>> count(seq, 't')
12
When i try to do is it does not work
>>> count(seq, 'a')
Traceback (most recent call last):
File "<pyshell#140>", line 1, in <module>
count(seq, 'a')
NameError: name 'count' is not defined
Why this is happening?
I' ve searched Stack resoures BTW and I didn't find anything.
COMMENT
Take a look at the start of the section 1.1.3. You have to type first from string import *
>>> from string import*
>>> nb_a = count(seq, 'a')
Traceback (most recent call last):
File "<pyshell#73>", line 1, in <module>
nb_a = count(seq, 'a')
NameError: name 'count' is not defined
>>> from string import *
>>> nb_a = count(seq, 'a')
Traceback (most recent call last):
File "<pyshell#75>", line 1, in <module>
nb_a = count(seq, 'a')
NameError: name 'count' is not defined
I did.
ANSWER
>>> from string import *
>>> from string import count
Traceback (most recent call last):
File "<pyshell#93>", line 1, in <module>
from string import count
ImportError: cannot import name count
>>> from string import count
Traceback (most recent call last):
File "<pyshell#94>", line 1, in <module>
from string import count
ImportError: cannot import name count
I did. Didn' t work.
The tutorial you linked to is very old:
Python 2.4.2 (#1, Dec 20 2005, 16:25:40)
You're probably using a more modern Python (>= 3) in which case there are no longer string functions like count in the string module. We used to have
Python 2.7.5+ (default, Feb 27 2014, 19:39:55)
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from string import count
>>> count("abcc", "c")
2
but today:
Python 3.3.2+ (default, Feb 28 2014, 00:53:38)
[GCC 4.8.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from string import count
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: cannot import name count
>>> import string
>>> dir(string)
['ChainMap', 'Formatter', 'Template', '_TemplateMetaclass', '__builtins__',
'__cached__', '__doc__', '__file__', '__initializing__', '__loader__', '__name__',
'__package__', '_re', '_string', 'ascii_letters', 'ascii_lowercase',
'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable',
'punctuation', 'whitespace']
These days we use the string methods instead, the ones that live in str itself:
>>> 'abcc'.count('c')
2
or even
>>> str.count('abcc','c')
2
While the other answers are correct, current Python releases propose another way to call count, as it is usable for str but also any type of sequence, as advised inside the documentation:
>>> seq.count('a')
35
As seq is as string object, it also have the count method.
This methodcount() is defined in string package. For using this method in your code, you need to import the definition.
Adding the following import statement before using the method will solve your problem
from string import count
>>> seq='acdaacc'
>>> count(seq,'a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'count' is not defined
>>> from string import count
>>> count(seq,'a')
3
count is a method in the string module, meaning that at the top of your file (before you use the function) you need to "import" it so that your interpreter knows what you're talking about. Add the line from string import count as the first line of your file and it should work.

The right and elegant way to split a join a string in Python

I have the following list:
>>> poly
'C:\\04-las_clip_inside_area\\16x16grids_1pp_fsa.shp'
>>> record
1373155
and I wish to create:
'C:\\04-las_clip_inside_area\\16x16grids_1pp_fsa_1373155.txt'
I wish to split in order to get the part "C:\04-las_clip_inside_area\16x16grids_1pp_fsa16x16grids_1pp_fsa".
I have tried this two-code-lines solution:
mylist = [poly.split(".")[0], "_", record, ".txt"]
>>> mylist
['C:\\04-las_clip_inside_area\\16x16grids_1pp_fsa', '_', 1373155, '.txt']
from here, reading the example in Python join, why is it string.join(list) instead of list.join(string)?.
I find this solution to joint, but I get this error message:
>>> mylist.join("")
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
AttributeError: 'list' object has no attribute 'join'
Also if I use:
>>> "".join(mylist)
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
TypeError: sequence item 2: expected string, int found
Python join: why is it string.join(list) instead of list.join(string)?
So there is
"".join(mylist)
instead of
mylist.join("")
There's your error.
To solve your int/string problem, convert the int to string:
mylist= [poly.split(".")[0],"_",str(record),".txt"]
or write directly:
"{}_{}.txt".format(poly.split(".")[0], record)
>>> from os import path
>>>
>>> path.splitext(poly)
('C:\\04-las_clip_inside_area\\16x16grids_1pp_fsa', '.shp')
>>>
>>> filename, ext = path.splitext(poly)
>>> "{0}_{1}.txt".format(filename, record)
'C:\\04-las_clip_inside_area\\16x16grids_1pp_fsa_1373155.txt'
>>> poly = 'C:\\04-las_clip_inside_area\\16x16grids_1pp_fsa.shp'
>>> record = 1373155
>>> "{}_{}.txt".format(poly.rpartition('.')[0], record)
'C:\\04-las_clip_inside_area\\16x16grids_1pp_fsa_1373155.txt'
or if you insist on using join()
>>> "".join([poly.rpartition('.')[0], "_", str(record), ".txt"])
'C:\\04-las_clip_inside_area\\16x16grids_1pp_fsa_1373155.txt'
It's important to use rpartition() (or rsplit()) as otherwise it won't work properly if the path has any other '.''s in it
You need to convert record into a string.
mylist= [poly.split(".")[0],"_",str(record),".txt"]

Categories

Resources