meteortools.fileformats.kmlHandlers
1import xmltodict 2from shapely.geometry import Polygon 3import csv 4import simplekml 5import numpy as np 6import pandas as pd 7import os 8 9 10def readCameraKML(kmlFilename, return_poly=False): 11 """ Load a KML file and return either a list of lats and longs, or a Shapely polygon 12 13 Arguments: 14 kmlFilename: [string] full path to the KML file to consume 15 return_poly: [bool] return a Shapely polygon? Default False 16 17 18 Returns: 19 if return_poly is false, returns a tuple of (cameraname, lats, longs) where lats and longs are lists of the 20 latitudes and longitudes in the KML file. 21 22 If return_poly is true, returns a tuple of (cameranamem, shapely Polygon) 23 """ 24 25 with open(kmlFilename) as fd: 26 x = xmltodict.parse(fd.read()) 27 cname = x['kml']['Folder']['name'] 28 coords = x['kml']['Folder']['Placemark']['MultiGeometry']['Polygon']['outerBoundaryIs']['LinearRing']['coordinates'] 29 coords = coords.split('\n') 30 if return_poly is False: 31 lats = [] 32 lngs = [] 33 for lin in coords: 34 s = lin.split(',') 35 lngs.append(float(s[0])) 36 lats.append(float(s[1])) 37 return cname, lats, lngs 38 else: 39 ptsarr=[] 40 for lin in coords: 41 s = lin.split(',') 42 ptsarr.append((float(s[0]), float(s[1]))) 43 polyg = Polygon(ptsarr) 44 return cname, polyg 45 46 47def trackCsvtoKML(trackcsvfile, trackdata=None, saveOutput=True, outdir=None): 48 """ 49 Either reads a CSV file containing lat, long, height of an event and 50 creates a 3d KML file from it or, if trackdata is populated, converts a Pandas dataframe containing 51 the same data. Output is written to disk unless saveOutput is false. 52 53 Arguments: 54 trackcsvfile: [string] full path to the file to read from 55 trackdata: [array] pandas dataframe containing the data. Default None 56 saveOutput: [bool] write the KML file to disk. Default true 57 outdir: [string] where to save the file. Default same folder as the source file 58 59 Returns: 60 the KML file as a tuple 61 """ 62 kml=simplekml.Kml() 63 kml.document.name = trackcsvfile 64 if trackdata is None: 65 inputfile = csv.reader(open(trackcsvfile)) 66 for row in inputfile: 67 #columns are lat, long, height, times 68 kml.newpoint(name='', coords=[(row[1], row[0], row[2])]) 69 else: 70 intvl = int(len(trackdata)/100) 71 for i,r in trackdata.iterrows(): 72 if i % intvl == 0: 73 kml.newpoint(name=f'{r[3]:.5f}', coords=[(r[1], r[0], r[2])], extrude=1, altitudemode='absolute') 74 if len(trackdata) % intvl != 0: 75 r = trackdata.iloc[[-1]] 76 kml.newpoint(name=f'{r["times"].iloc[0]:.5f}', coords=[(r['lons'].iloc[0], r['lats'].iloc[0], r['alts'].iloc[0])], extrude=1, altitudemode='absolute') 77 if 'csv' in trackcsvfile: 78 outname = trackcsvfile.replace('.csv','.kml') 79 else: 80 outname = f'{trackcsvfile}.kml' 81 if saveOutput: 82 if outdir is None: 83 outdir, _ = os.path.split(trackcsvfile) 84 os.makedirs(outdir, exist_ok=True) 85 outname = os.path.join(outdir, outname) 86 kml.save(outname) 87 return kml 88 89 90def trackKMLtoCsv(kmlfile, kmldata = None, saveOutput=True, outdir=None): 91 """ convert a track KML retrieved by ukmondb.trajectoryKML to a 3 dimensional CSV file 92 containing coordinates of points on the trajectory. 93 94 Arguments: 95 kmlfile [string] full path to the KML file to read from. 96 kmldata [kml] the kml data if available. 97 saveOutput [bool] Default True, save the output to file. 98 outdir [string] where to save to if saveOutput is True. 99 100 Note: if kmldata is supplied, then kmlfile is ignored. 101 102 Returns: 103 a Pandas dataframe containing the lat, long, alt and time of each 104 point on the trajectory, sorted by time. 105 106 """ 107 with open(kmlfile) as fd: 108 x = xmltodict.parse(fd.read()) 109 placemarks=x['kml']['Document']['Placemark'] 110 lats = [] 111 lons = [] 112 alts = [] 113 tims = [] 114 for pm in placemarks: 115 tims.append(float(pm['name'])) 116 coords = pm['Point']['coordinates'].split(',') 117 lons.append(float(coords[0])) 118 lats.append(float(coords[1])) 119 alts.append(float(coords[2])) 120 df = pd.DataFrame({"lats": lats, "lons": lons, "alts": alts, "times": tims}) 121 df = df.sort_values(by=['times', 'lats']) 122 if saveOutput: 123 fname = kmlfile 124 if outdir is None: 125 outdir, fname = os.path.split(kmlfile) 126 outf = os.path.join(outdir, fname).replace('.kml', '.csv').replace('.KML','.csv') 127 df.to_csv(outf, index=False) 128 return df 129 130 131def getTrackDetails(traj): 132 """ Get track details from a WMPL trajectory object 133 134 Arguments: 135 traj: a WMPL trajectory object containing observations 136 137 Returns: 138 a Pandas dataframe containing the lat, long, alt and time of each point on the trajectory, sorted by time. 139 """ 140 lats = [] 141 lons = [] 142 alts = [] 143 lens = [] 144 # Go through observation from all stations 145 for obs in traj.observations: 146 # Go through all observed points 147 for i in range(obs.kmeas): 148 lats.append(np.degrees(obs.model_lat[i])) 149 lons.append(np.degrees(obs.model_lon[i])) 150 alts.append(obs.model_ht[i]) 151 lens.append(obs.time_data[i]) 152 df = pd.DataFrame({"lats": lats, "lons": lons, "alts": alts, "times": lens}) 153 df = df.sort_values(by=['times', 'lats']) 154 return df
11def readCameraKML(kmlFilename, return_poly=False): 12 """ Load a KML file and return either a list of lats and longs, or a Shapely polygon 13 14 Arguments: 15 kmlFilename: [string] full path to the KML file to consume 16 return_poly: [bool] return a Shapely polygon? Default False 17 18 19 Returns: 20 if return_poly is false, returns a tuple of (cameraname, lats, longs) where lats and longs are lists of the 21 latitudes and longitudes in the KML file. 22 23 If return_poly is true, returns a tuple of (cameranamem, shapely Polygon) 24 """ 25 26 with open(kmlFilename) as fd: 27 x = xmltodict.parse(fd.read()) 28 cname = x['kml']['Folder']['name'] 29 coords = x['kml']['Folder']['Placemark']['MultiGeometry']['Polygon']['outerBoundaryIs']['LinearRing']['coordinates'] 30 coords = coords.split('\n') 31 if return_poly is False: 32 lats = [] 33 lngs = [] 34 for lin in coords: 35 s = lin.split(',') 36 lngs.append(float(s[0])) 37 lats.append(float(s[1])) 38 return cname, lats, lngs 39 else: 40 ptsarr=[] 41 for lin in coords: 42 s = lin.split(',') 43 ptsarr.append((float(s[0]), float(s[1]))) 44 polyg = Polygon(ptsarr) 45 return cname, polyg
Load a KML file and return either a list of lats and longs, or a Shapely polygon
Arguments:
kmlFilename: [string] full path to the KML file to consume
return_poly: [bool] return a Shapely polygon? Default False
Returns:
if return_poly is false, returns a tuple of (cameraname, lats, longs) where lats and longs are lists of the
latitudes and longitudes in the KML file.
If return_poly is true, returns a tuple of (cameranamem, shapely Polygon)
48def trackCsvtoKML(trackcsvfile, trackdata=None, saveOutput=True, outdir=None): 49 """ 50 Either reads a CSV file containing lat, long, height of an event and 51 creates a 3d KML file from it or, if trackdata is populated, converts a Pandas dataframe containing 52 the same data. Output is written to disk unless saveOutput is false. 53 54 Arguments: 55 trackcsvfile: [string] full path to the file to read from 56 trackdata: [array] pandas dataframe containing the data. Default None 57 saveOutput: [bool] write the KML file to disk. Default true 58 outdir: [string] where to save the file. Default same folder as the source file 59 60 Returns: 61 the KML file as a tuple 62 """ 63 kml=simplekml.Kml() 64 kml.document.name = trackcsvfile 65 if trackdata is None: 66 inputfile = csv.reader(open(trackcsvfile)) 67 for row in inputfile: 68 #columns are lat, long, height, times 69 kml.newpoint(name='', coords=[(row[1], row[0], row[2])]) 70 else: 71 intvl = int(len(trackdata)/100) 72 for i,r in trackdata.iterrows(): 73 if i % intvl == 0: 74 kml.newpoint(name=f'{r[3]:.5f}', coords=[(r[1], r[0], r[2])], extrude=1, altitudemode='absolute') 75 if len(trackdata) % intvl != 0: 76 r = trackdata.iloc[[-1]] 77 kml.newpoint(name=f'{r["times"].iloc[0]:.5f}', coords=[(r['lons'].iloc[0], r['lats'].iloc[0], r['alts'].iloc[0])], extrude=1, altitudemode='absolute') 78 if 'csv' in trackcsvfile: 79 outname = trackcsvfile.replace('.csv','.kml') 80 else: 81 outname = f'{trackcsvfile}.kml' 82 if saveOutput: 83 if outdir is None: 84 outdir, _ = os.path.split(trackcsvfile) 85 os.makedirs(outdir, exist_ok=True) 86 outname = os.path.join(outdir, outname) 87 kml.save(outname) 88 return kml
Either reads a CSV file containing lat, long, height of an event and creates a 3d KML file from it or, if trackdata is populated, converts a Pandas dataframe containing the same data. Output is written to disk unless saveOutput is false.
Arguments:
trackcsvfile: [string] full path to the file to read from
trackdata: [array] pandas dataframe containing the data. Default None
saveOutput: [bool] write the KML file to disk. Default true
outdir: [string] where to save the file. Default same folder as the source file
Returns:
the KML file as a tuple
91def trackKMLtoCsv(kmlfile, kmldata = None, saveOutput=True, outdir=None): 92 """ convert a track KML retrieved by ukmondb.trajectoryKML to a 3 dimensional CSV file 93 containing coordinates of points on the trajectory. 94 95 Arguments: 96 kmlfile [string] full path to the KML file to read from. 97 kmldata [kml] the kml data if available. 98 saveOutput [bool] Default True, save the output to file. 99 outdir [string] where to save to if saveOutput is True. 100 101 Note: if kmldata is supplied, then kmlfile is ignored. 102 103 Returns: 104 a Pandas dataframe containing the lat, long, alt and time of each 105 point on the trajectory, sorted by time. 106 107 """ 108 with open(kmlfile) as fd: 109 x = xmltodict.parse(fd.read()) 110 placemarks=x['kml']['Document']['Placemark'] 111 lats = [] 112 lons = [] 113 alts = [] 114 tims = [] 115 for pm in placemarks: 116 tims.append(float(pm['name'])) 117 coords = pm['Point']['coordinates'].split(',') 118 lons.append(float(coords[0])) 119 lats.append(float(coords[1])) 120 alts.append(float(coords[2])) 121 df = pd.DataFrame({"lats": lats, "lons": lons, "alts": alts, "times": tims}) 122 df = df.sort_values(by=['times', 'lats']) 123 if saveOutput: 124 fname = kmlfile 125 if outdir is None: 126 outdir, fname = os.path.split(kmlfile) 127 outf = os.path.join(outdir, fname).replace('.kml', '.csv').replace('.KML','.csv') 128 df.to_csv(outf, index=False) 129 return df
convert a track KML retrieved by ukmondb.trajectoryKML to a 3 dimensional CSV file containing coordinates of points on the trajectory.
Arguments:
kmlfile [string] full path to the KML file to read from.
kmldata [kml] the kml data if available.
saveOutput [bool] Default True, save the output to file.
outdir [string] where to save to if saveOutput is True.
Note: if kmldata is supplied, then kmlfile is ignored.
Returns:
a Pandas dataframe containing the lat, long, alt and time of each
point on the trajectory, sorted by time.
132def getTrackDetails(traj): 133 """ Get track details from a WMPL trajectory object 134 135 Arguments: 136 traj: a WMPL trajectory object containing observations 137 138 Returns: 139 a Pandas dataframe containing the lat, long, alt and time of each point on the trajectory, sorted by time. 140 """ 141 lats = [] 142 lons = [] 143 alts = [] 144 lens = [] 145 # Go through observation from all stations 146 for obs in traj.observations: 147 # Go through all observed points 148 for i in range(obs.kmeas): 149 lats.append(np.degrees(obs.model_lat[i])) 150 lons.append(np.degrees(obs.model_lon[i])) 151 alts.append(obs.model_ht[i]) 152 lens.append(obs.time_data[i]) 153 df = pd.DataFrame({"lats": lats, "lons": lons, "alts": alts, "times": lens}) 154 df = df.sort_values(by=['times', 'lats']) 155 return df
Get track details from a WMPL trajectory object
Arguments:
traj: a WMPL trajectory object containing observations
Returns:
a Pandas dataframe containing the lat, long, alt and time of each point on the trajectory, sorted by time.