How to fill a liblas.point.Point object using Liblas module? - python

I am using liblas in Python to read, manipulate and write a special point format *.las. I have a string as
s = "309437.95 6959999.84 118.98 16 1 1 0 0 1 0 112.992 5.9881"
Where the first is the X, the second the Y, the third element the Z etc.
Using Liblas, I create an empty liblas.point.Point object
>>> pt = liblas.point.Point()
>>> pt
<liblas.point.Point object at 0x0000000005194470>
After that I need to fill this object because is empty.
>>> pt.x, pt.y,pt.z
(0.0, 0.0, 0.0)
probably using
>>> pt.get_x
<bound method Point.get_x of <liblas.point.Point object at 0x0000000005194470>>
I wish to say thanks for all help and suggestion, I really need to solve this step.
from suggestion of Martijn Pieters
s = "%s %s %s" % (s, value, nh)
>>> s
'309437.95 6959999.84 118.98 16 1 1 0 0 1 0 112.992 5.9881'
# create a liblas.point.Point
pt = liblas.point.Point()
pt.x = float(s.split()[0])
pt.y = float(s.split()[1])
pt.z = = float(s.split()[11]) # the new Z value
pt.intensity = = int(s.split()[3])
pt.return_number= int(s.split()[4])
pt.number_of_returns = int(s.split()[5])
pt.scan_direction = int(s.split()[6])
pt.flightline_edge = int(s.split()[7])
pt.classification = int(s.split()[8])
pt.scan_angle = int(s.split()[9])

There are raw_x, raw_y and raw_z properties on a Point object; simply set those:
pt.raw_x = 309437.95
pt.raw_y = 6959999.84
pt.raw_z = 118.98
There are also x, y and z properties; it is not immediately clear from the source code what the difference is between the two types:
pt.x = 309437.95
pt.y = 6959999.84
pt.z = 118.98
but the library can produce these objects directly from a .las file for you, can't it? The File class you had trouble with before certainly does return these objects already.
And since you updated to show some code, here is a more readable version of that:
pt = liblas.point.Point()
s = map(float, s.split())
pt.x, pt.y, pt.z = s[0], s[1], s[11]
pt.intensity, pt.return_number = s[3], s[4]
pt.number_of_returns, pt.scan_direction = s[5], s[6]
pt.flightline_edge, pt.classification = s[7], s[8]
pt.scan_angle = s[9]

Related

BFS - TypeError: 'ellipsis' object is not subscriptable - implementing algorithm

I am trying to implement the BFS algorithm but python is giving me an error that the ellipsis object is not sub scriptable.
I am unsure what these means because as far as I am aware this type should not be Ellipsis?
TypeError: 'ellipsis' object is not subscriptable
Causing error:
visited[starting_row][starting_col] = True
Function:
def findRoute(self, x1, y1, x2, y2):
grid = self.grid
print(grid)
starting_row, starting_col = x1, y1
# Creating 2 seperate queues for X and Y.
x_queue, y_queue = deque(), deque()
number_of_moves = 0
number_of_nodes_in_current_layer = 1
number_of_nodes_in_next_layer = 0
end_reached = False
# Up/Down/Right/Left directions
direction_row = [-1, 1, 0, 0]
direction_col = [0, 0, 1, -1]
visited = ...
x_queue.append(starting_row)
y_queue.append(starting_col)
visited[starting_row][starting_col] = True
while len(x_queue) > 0:
x = x_queue.dequeue()
y = y_queue.dequeue()
if x == x2 & y == y2:
end_reached = True
break
# for(i = 0; i < 4; i++):
# Loop through direction.
for i in range(0, 4):
new_row = x + direction_row[i]
new_col = x + direction_col[i]
#Validate position
# Skip locations not in grid.
if new_row < 0 or new_col < 0 or new_row >= self.height or new_col >= self.width:
continue
# Skip locations already visited / cells blocked by walls.
if visited[new_row][new_col] or grid[new_row][new_col]:
continue
x_queue.enqueue(new_row)
y_queue.enqueue(new_col)
visited[new_row][new_col] = True
number_of_nodes_in_next_layer += 1
if number_of_nodes_in_current_layer == 0:
number_of_nodes_in_current_layer = number_of_nodes_in_next_layer
number_of_nodes_in_next_layer = 0
number_of_moves += 1
if end_reached:
return number_of_moves
return -1
return grid[1][2]
Any help would be appreciated, thanks.
Your code has this line:
visited = ...
This ... is not commonly used, but it is a native object. The documentation on Ellipsis has:
The same as the ellipsis literal “...”. Special value used mostly in conjunction with extended slicing syntax for user-defined container data types. Ellipsis is the sole instance of the types.EllipsisType type.
As the error message states, this object is not subscriptable, yet that is exactly what you tried to do with:
visited[starting_row][starting_col] = True
I suppose you didn't really intend to use visited = ..., and that you were planning to complete this statement later and then forgot about it. It should be:
visited = [[False] * len(row) for row in grid]

Traversing through a list that has b' ahead

When I write
a1 = list([b'1,690569\n1,315892\n1,189226\n2,834328\n2,1615927\n2,1194519\n'])
print(a1)
for edge_ in a1:
print('edge =' + str(edge_))
z[(edge_[0], edge_[1])] = 1
print('edge_0 =' + str(edge_[0]))
print('edge_1 =' + str(edge_[1]))
print(z)
I get the output as
[b'1,690569\n1,315892\n1,189226\n2,834328\n2,1615927\n2,1194519\n']
edge =b'1,690569\n1,315892\n1,189226\n2,834328\n2,1615927\n2,1194519\n'
edge_0 =49
edge_1 =44
{(49, 44): 1}
Can anyone explain why it is 49 and 44? These values are coming irrespective of the element inside the list.
Firstly, as others have already mentioned, your array below is a byte array. This is evident due to the 'b' at the start. You don't need to use 'list()' by the way.
a1 = [b'1,690569\n1,315892\n1,189226\n2,834328\n2,1615927\n2,1194519\n']
Given that z is an empty dictionary (i.e. z = dict())
Below is just adding a tuple as a key and an integer as value:
z[(edge_[0], edge_[1])] = 1
We can see the following:
edge_ = a1[0] = b'1,690569\n1,315892\n1,189226\n2,834328\n2,1615927\n2,1194519\n'
edge_[0] = a1[0][0] = ord(b'1') = 49
edge_[1] = a1[0][1] = ord(b',') = 44
Hence z[(edge_[0], edge_[1])] = 1 becomes:
z[(49, 44)] = 1
z = {(49, 44): 1}

Python list generator not working as intended

First of all, I'm making a game in which the map is a list of lists:
P1.Cmap = [
['0,'0',0'],
['0,'0',0'],
['0,'0',0'],
]
and I have a function to print it:
def render(): #render the map to player
P1.Cmap[P1.y][P1.x] = P1.char
j = 40 - len(P1.Cmap)
p = int(j/2)
l = len(P1.Cmap[0])
print('\n' * p)
print('-' * l)
for r in P1.Cmap:
print(''.join(r))
print('\n' * p)
where P1 is the player object and char is the character to represent it (X)
and I also made a function to generate a map with the given parameters:
def newMap():
Nmn = input('What is the name of the map? ')
NmSx = input('What is the size you want?(X) ')
NmSy = input('What is the size you want?(Y) ')
Row = []
Map = []
for r in range(int(NmSx)):
Row.append('0')
for c in range(int(NmSy)):
Map.append(Row)
P1.Cmap = Map
print(P1.Cmap)
but when I set the player X and Y to be P1.x = 1, P1.y = 0 and I use the function to generate the map, it actually prints:
0X0
0X0
0X0
instead of what it "should" (When I make the map like the first code block above):
0X0
000
000
with that I thought that the problem is not in the render() but it is in the newMap(), but I can't seem to find it, any ideas?
You are creating P1.Cmap in the following way:
Row = []
Map = []
for r in range(int(NmSx)):
Row.append('0')
for c in range(int(NmSy)):
Map.append(Row)
P1.Cmap = Map
However, this makes Map equal to [Row, Row, Row], that is, Row is always referencing the same list you created above with Row = [], therefore any time you modify Row the changes will be reflected in Map in all three "rows", since each "row" is Row!.
Instead, try something like :
X = int(NmSx)
Y = int(NmSy)
Map = [['0' for _ in range(X)] for _ in range(Y)]

How to use object as value in dictionary in python?

Here's the code:
import datetime
local = {};
class name:
x = 0
y = 0
time = 0
PCH = []
FCC_Queue = []
t = datetime.time(0, 0, 0)
p = name()
p.x = 10
p.y = 20.0
p.time = t.second
PCH.append('xyz','abc',1,15.0)
FCC_Queue.append(10.0,20.0,30.0)
local['Obj1'] = p
How do I access the value of p.x from the dict local['Obj1']?
Also, how do I access a list value e.g. PCH[1] from the dict local['Obj1']?
Of course you can and your code works.
To access the x of your object is as simple as
localhostrecord['Obje1'].x
To access the list you do the same and then treat this as a simple list
localhostrecord['Obje1'].PCH
# e.g. access second element of PCH list
localhostrecord['Obje1'].PCH[1]

I want my parser to return a list of strings, but it returns a blank list

I have a parser that reads in a long octet string, and I want it to print out smaller strings based on the parsing details. It reads in a hexstring which is as follows
The string will be in a format like so:
01046574683001000004677265300000000266010000
The format of the interface contained in the hex is like so:
version:length_of_name:name:op_status:priority:reserved_byte
==
01:04:65746830:01:00:00
== (when converted from hex)
01:04:eth0:01:00:00
^ this is 1 segment of the string , represents eth0 (I inserted the : to make it easier to read). At the minute, however, my code returns a blank list, and I don't know why. Can somebody help me please!
def octetChop(long_hexstring, from_ssh_):
startpoint_of_interface_def=0
# As of 14/8/13 , the network operator has not been implemented
network_operator_implemented=False
version_has_been_read = False
position_of_interface=0
chopped_octet_list = []
#This while loop moves through the string of the interface, based on the full length of the container
try:
while startpoint_of_interface_def < len(long_hexstring):
if version_has_been_read == True:
pass
else:
if startpoint_of_interface_def == 0:
startpoint_of_interface_def = startpoint_of_interface_def + 2
version_has_been_read = True
endpoint_of_interface_def = startpoint_of_interface_def+2
length_of_interface_name = long_hexstring[startpoint_of_interface_def:endpoint_of_interface_def]
length_of_interface_name_in_bytes = int(length_of_interface_name) * 2 #multiply by 2 because its calculating bytes
end_of_interface_name_point = endpoint_of_interface_def + length_of_interface_name_in_bytes
hex_name = long_hexstring[endpoint_of_interface_def:end_of_interface_name_point]
text_name = hex_name.decode("hex")
print "the text_name is " + text_name
operational_status_hex = long_hexstring[end_of_interface_name_point:end_of_interface_name_point+2]
startpoint_of_priority = end_of_interface_name_point+2
priority_hex = long_hexstring[startpoint_of_priority:startpoint_of_priority+2]
#Skip the reserved byte
network_operator_length_startpoint = startpoint_of_priority+4
single_interface_string = long_hexstring[startpoint_of_interface_def:startpoint_of_priority+4]
print single_interface_string + " is chopped from the octet string"# - keep for possible debugging
startpoint_of_interface_def = startpoint_of_priority+4
if network_operator_implemented == True:
network_operator_length = long_hexstring[network_operator_length_startpoint:network_operator_length_startpoint+2]
network_operator_length = int(network_operator_length) * 2
network_operator_start_point = network_operator_length_startpoint+2
network_operator_end_point = network_operator_start_point + network_operator_length
network_operator = long_hexstring[network_operator_start_point:network_operator_end_point]
#
single_interface_string = long_hexstring[startpoint_of_interface_def:network_operator_end_point]
#set the next startpoint if there is one
startpoint_of_interface_def = network_operator_end_point+1
else:
self.network_operator = None
print single_interface_string + " is chopped from the octet string"# - keep for possible debugging
#This is where each individual interface is stored, in a list for comparison.
chopped_octet_list.append(single_interface_string)
finally:
return chopped_octet_list
The reason your code is returning a blank list is the following: In this line:
else:
self.network_operator = None
self is not defined so you get a NameError exception. This means that the try jumps directly to the the finally clause without ever executing the part where you:
chopped_octet_list.append(single_interface_string)
As a consequence the list remains empty. In any case the code is overly complicated for such a task, I would follow one of the other answers.
I hope I got you right. You got a hex-string which contains various interface definition. Inside each interface definition the second octet describes the length of the name of the interface.
Lets say the string contains the interfaces eth0 and eth01 and looks like this (length 4 for eth0 and length 5 for eth01):
01046574683001000001056574683031010000
Then you can split it like this:
def splitIt (s):
tokens = []
while s:
length = int (s [2:4], 16) * 2 + 10 #name length * 2 + 10 digits for rest
tokens.append (s [:length] )
s = s [length:]
return tokens
This yields:
['010465746830010000', '01056574683031010000']
To add onto Hyperboreus's answer, here's a simple way to parse the interface strings once you split them:
def parse(s):
version = int(s[:2], 16)
name_len = int(s[2:4], 16)
name_end = 4 + name_len * 2
name = s[4:name_end].decode('hex')
op_status = int(s[name_end:name_end+2], 16)
priority = int(s[name_end+2:name_end+4], 16)
reserved = s[name_end+4:name_end+6]
return version, name_len, name, op_status, priority, reserved
Here's the output:
>>> parse('010465746830010000')
(1, 4, 'eth0', 1, 0, '00')
Check if the following helps. Call parse method below and pass a string stream into it, then iterate to get card infos (hope I got you right :)) parse will return you tuple(s) of the desired info.
>>> def getbytes(hs):
"""Returns a generator of bytes from a hex string"""
return (int(hs[i:i+2],16) for i in range(0,len(hs)-1,2))
>>> def get_single_card_info(g):
"""Fetches a single card info from a byte generator"""
v = g.next()
l = g.next()
name = "".join(chr(x) for x in map(lambda y: y.next(),[g]*l))
return (str(v),name,g.next(),g.next(),g.next())
>>> def parse(hs):
"""Parses a hex string stream and returns a generator of card infos"""
bs = getbytes(hs)
while True:
yield get_single_card_info(bs)
>>> c = 1
>>> for card in parse("01046574683001000001056574683031010000"):
print "Card:{0} -> Version:{1}, Id:{2}, Op_stat:{3}, priority:{4}, reserved:{5} bytes".format(c,*card)
c = c + 1
Card:1 -> Version:1, Id:eth0, Op_stat:1, priority:0, reserved:0 bytes
Card:2 -> Version:1, Id:eth01, Op_stat:1, priority:0, reserved:0 bytes
Pyparsing includes a built-in expression for parsing a counted array of elements, so this would take care of your 'name' field nicely. Here's the whole parser:
from pyparsing import Word,hexnums,countedArray
# read in 2 hex digits, convert to integer at parse time
octet = Word(hexnums,exact=2).setParseAction(lambda t:int(t[0],16))
# read in a counted array of octets, convert to string
nameExpr = countedArray(octet, intExpr=octet)
nameExpr.setParseAction(lambda t: ''.join(map(chr,t[0])))
# define record expression, with named results
recordExpr = (octet('version') + nameExpr('name') + octet('op_status') +
octet('priority') #+ octet('reserved'))
Parsing your sample:
sample = "01046574683001000004677265300000000266010000"
for rec in recordExpr.searchString(sample):
print rec.dump()
Gives:
[1, 'eth0', 1, 0]
- name: eth0
- op_status: 1
- priority: 0
- version: 1
[0, 'gre0', 0, 0]
- name: gre0
- op_status: 0
- priority: 0
- version: 0
[0, 'f\x01', 0, 0]
- name: f
- op_status: 0
- priority: 0
- version: 0
The dump() method shows results names that you can use to access the individually parsed bits, like rec.name or rec.version.
(I commented out the reserved byte, else the second entry wouldn't parse correctly. Also, the third entry contains a name with a \x01 byte.)

Categories

Resources