I am trying to convert a .las file from WGS84 to UTM17. I have some drone imagery that was used to generate a 3d point cloud/ .las file, but it is in latitude/ longitude instead of easting/ northing.
I tried using laspy, a great python API for reading las files. I was able to use this to convert the XYZ info from the .las to a csv file. I then used this csv file and a package in R to convert the coordinates. Now I am trying to use laspy to write a new .las file with the correct coordinates.
Here's my code so far:
import numpy
import laspy
#pandas used here to convert csv to array
import pandas
#Import a .las file and name it something
van_taken = laspy.file.File("C:\Users\Mainframe2\PycharmProjects\LAS Conversion\Coordinate Conversion\Taken.Lands.Points.las", mode="rw")
converted_csv = pandas.read_csv("C:\Users\Mainframe2\PycharmProjects\LAS Conversion\Coordinate Conversion\Taken.Lands.UTM.csv")
converted_csv = converted_csv.as_matrix()
#get individual column from array using Pandas
converted_x = converted_csv[:,1]
converted_y = converted_csv[:,2]
converted_z = converted_csv[:,3]
#Convert original points to new points
van_taken.x = converted_x
van_taken.y = converted_y
van_taken.z = converted_z
This is where the problem arises.
van_taken.x
array([-83.0830127, -83.0830128, -83.0830127, ..., -83.0830927,
-83.0830926, -83.0830929])
converted_x
array([ 269873.21570411, 269872.62699301, 269873.32416573, ...,
269073.15716998, 269074.64298861, 269071.18083953])
van_taken.x = converted_x
But then!!!!
van_taken.x
array([-297.8583648, -297.8583648, -297.8583648, ..., -297.8583648,
-297.8583648, -297.8583648])
For some reason, it appears that when I try to set them equal, van_taken.x refuses to be equal to what it says.
I've looked through the documentation and can't seem to find anything. Is there some scale or offset that is causing this to happen? Once I figure this out I will be able to save the .las file and convert to the correct coordinate system.
>>> van_taken.header.scale
[1e-07, 1e-07, 0.01]
>>> van_taken.header.offset
[-83.11, 10.0, -1000.0]
I changed the scale to
van_taken.header.scale = [1,1,1]
>>> van_taken.x
array([ 269872.89, 269872.89, 269872.89, ..., 269072.89, 269074.89,
269070.89])
>>> converted_x
array([ 269873.21570411, 269872.62699301, 269873.32416573, ...,
Changing the scale seemed to make the number more realistic, but they are still different now. I'm going to experiment with a couple different scales.
Update
Grant Brown's answer works like a charm. I copied and pasted it. For some reason when I ran the whole code at once in Pycharm, it gave me some syntax errors. But I just ran it line by line and it didn't have a problem.
The results:
>>> converted_x
array([ 269873.2157 , 269872.62699, 269873.32417, ..., 269073.15717,
269074.64299, 269071.18084])
>>> van_taken.x
array([ 269873.2157 , 269872.62699011, 269873.32417004, ...,
269073.15716974, 269074.64298997, 269071.18084039])
Grant's answer is accurate at least to the number of decimal places we have in our file. (I reduced the number of decimals I originally had from 10 places to 5, since 5 is sub milimeter precision.)
Finally, I just want to say remember to close the file. I was a complete noob here, but after closing the file I noticed the file size was exactly the same size. I therefore incorrectly concluded that the file was not overwritten. But, as Grant explains.
"Unless you changed the number of points, the file is guaranteed to remain the same size. It's a binary file, and everything in it takes up a very precise amount of space. No matter what you do, LAS files store coordinates as integers. This is not something you can change or convert, ever. What you can do is change the scale and offset value, which allows you to construct coordinates in whatever system you want; they're the map between the data storage format and the coordinates you're actually interested in."
I got this one sorted out.