maurobio
maurobio

Reputation: 1587

Python - Export a Matplotlib plot to KML file

I have to code below, which reads a file of (geographic) coordinates (longitudes, latitudes), computes a minimum spanning tree from a distance matrix among these points and plots the resulting tree using Matplotlib.

import warnings
import numpy as np
from scipy.spatial.distance import pdist, squareform
import matplotlib.pyplot as plt
import simplekml

warnings.filterwarnings("ignore")

def minimum_spanning_tree(X, copy_X=True):
    """X are edge weights of fully connected graph"""
    if copy_X:
        X = X.copy()

    if X.shape[0] != X.shape[1]:
        raise ValueError("X needs to be square matrix of edge weights")
    n_vertices = X.shape[0]
    spanning_edges = []

    # initialize with node 0:                                                                                        
    visited_vertices = [0]                                                                                           
    num_visited = 1
    # exclude self connections:
    diag_indices = np.arange(n_vertices)
    X[diag_indices, diag_indices] = np.inf

    while num_visited != n_vertices:
        new_edge = np.argmin(X[visited_vertices], axis=None)
        # 2d encoding of new_edge from flat, get correct indices                                                     
        new_edge = divmod(new_edge, n_vertices)
        new_edge = [visited_vertices[new_edge[0]], new_edge[1]]                                                      
        # add edge to tree
        spanning_edges.append(new_edge)
        visited_vertices.append(new_edge[1])
        # remove all edges inside current tree
        X[visited_vertices, new_edge[1]] = np.inf
        X[new_edge[1], visited_vertices] = np.inf                                                                    
        num_visited += 1
    return np.vstack(spanning_edges)

def test_mst():
    P = np.loadtxt("testdata.csv", delimiter=',', skiprows=1)

    X = squareform(pdist(P))

    edge_list = minimum_spanning_tree(X)
    plt.scatter(P[:, 0], P[:, 1], c='b')

    edges = []
    for edge in edge_list:
        i, j = edge
        plt.plot([P[i, 0], P[j, 0]], [P[i, 1], P[j, 1]], c='b')
        edges.append([(P[i, 0], P[j, 0]), (P[i, 1], P[j, 1])])
    plt.show()

    # Save KML file
    kml = simplekml.Kml()
    for i in range(len(edges)):
        line = kml.newlinestring(name="Track" + str(i + 1), coords=edges[i])
        line.style.linestyle.width = 3
        line.style.linestyle.color = simplekml.Color.red
    kml.save("mst.kml")

if __name__ == "__main__":
    test_mst()

And here is my test data:

Longitude,Latitude
-61.05,10.4
-79.4333333333,9.15
-70.6666666667,9.5333333333
-63.1166666667,7.9166666667
-63.1166666667,10.55
-81.1833333333,7.5166666667
-56.4833333333,3.1
-60.5,3.9333333333
-81.0166666667,7.6666666667
-67.4333333333,8.9333333333
-65.9666666667,10.3166666667
-78.9333333333,8.3833333333
-72.8666666667,9.8333333333
-68.4,10.6166666667
-72.9833333333,10.6166666667

It works fine and shows the plot below:

enter image description here

However, I also want to save the coordinates of the resulting tree into a KML format for plotting it using Google Earth. I am then storing the same coordinates passed to construct the plot into a list of tuples, which I then pass to a simpleKml object. It does not work and the tree is not correctly displyed by Google Earth.

So, in general terms, my question is: how could I save (in whatever format) the coordinates of the plot, in order to be able to reconstruct it exactly as it is displayed by Matplotlib?

Thanks in advance for any assistance you can provide.

EDIT: Below is the KML file as it appears in Google Earth:

enter image description here

And here is how it should appear (this plot was created using Matplotlib and Basemap):

enter image description here

Upvotes: 2

Views: 2932

Answers (2)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339795

Looking at the simplekml documentation, coordinates need to be given as pairs of (lon,lat).

So instead of

 # edges.append([(P[i, 0], P[j, 0]), (P[i, 1], P[j, 1])])

you need

 edges.append([(P[i, 0], P[i, 1]), (P[j, 0],P[j, 1] )])

Screenshot of google earth:

enter image description here

Upvotes: 1

ShaneCalder
ShaneCalder

Reputation: 346

The only other option would be to convert to a .csv then an xml
https://developers.google.com/kml/articles/csvtokml
Not sure if this was what you are looking for

Upvotes: 1

Related Questions