Search code examples
pythonfolium

Is it possible to save a folium object in Python?


I am trying to write a script that uses folium to show two gpx traces. One is already computed (previsional trace) and another one that I update everyday (actual trace).

However, the script that generate the folium.PolyLine object Frome the GPX trace trace is quite long to run and therefore, I want to save the folium.PolyLine object that contains this trace. However, I don't find a way to save this object via folium' documentation.

How can I save this kind of Object ?

I have tried using the pickle package to save the folium.PolyLine object doing so :

#[...]

line = folium.PolyLine(points)

path = os.path(...)

with open(path, "w")as f:

    pickle.dump(line, path, -1)

But I get this error :

Traceback (most recent call last):

    File "/storage/emulated/0/Documents/Pydroid3/script.py", line 372, in <module>

    pickle.dump(m, outp, -1)

_pickle.PicklingError: Can't pickle <function root at 0x75a65af0d0>: attribute lookup root on __main__ failed

/storage/emulated/0 $


Solution

  • We can save a folium map image as an html file:

    import folium
    m = folium.Map(location=[26, -80], height=500, width=750, zoom_start=8)
    file_name = '/content/drive/My Drive/Colab Notebooks/DATA_FOLDERS/IMAGES/my_folium_map'
    m.save(file_name + '.html')
    

    then convert it to a pdf file, and then convert the pdf file to a png file:

    !pip install pdfkit
    !sudo apt-get install wkhtmltopdf
    import pdfkit
    !pip install PyMuPDF
    import fitz
    options = {'javascript-delay': 500, 'page-size': 'Letter', 'margin-top': '0.0in', 'margin-right': '0.0in', 'margin-bottom': '0.0in', 'margin-left': '0.0in', 'encoding': "UTF-8", 'custom-header': [('Accept-Encoding', 'gzip')]}
    pdfkit.from_file(file_name + '.html',  (file_name + '.pdf'), options=options)
    pdf_file = fitz.open(file_name + '.pdf')
    page = pdf_file.load_page(0)
    pixels = page.get_pixmap()
    pixels.save(file_name + '.png')
    pdf_file.close()
    

    saved png file:

    from PIL import Image
    folium_png = Image.open(file_name + '.png')
    display(folium_png)
    

    enter image description here

    Note: the folium height and width arguments determine the size of the image being saved:

    folium.Map(..., height=500, width=750, ...)
    

    Now if we want the actual folium.Map object we can save that as an html file:

    import folium
    m = folium.Map(location=[26, -80])
    m.save('/content/drive/My Drive/Colab Notebooks/DATA_FOLDERS/IMAGES/some_folium_map.html')
    

    then to retrieve that saved folium.Map object we read the html file:

    file_name = '/content/drive/My Drive/Colab Notebooks/DATA_FOLDERS/IMAGES/some_folium_map.html'
    a = open(file_name, 'r', encoding='UTF-8')
    a = a.read()
    

    parse the string to find the attribution dictionary:

    b = a[a.find('attribution') - 1:a.find('attribution') + (a[a.find('attribution') - 1:]).find('}') - 1]
    

    then pythonicize the string and pass it as a dictionary to the folium.Map function:

    import ast
    def pythonicize(some_string):
        some_new_string = some_string
        while some_string == some_new_string:
            if some_string.find('false') >= 0:
                some_new_string = some_string[:some_string.find('false')] + 'F' + some_string[some_string.find('false') + 1:]
            if some_new_string.find('true') >= 0:
                some_new_string = some_new_string[:some_new_string.find('true')] + 'T' + some_new_string[some_new_string.find('true') + 1:]
            if some_new_string.find('false') >= 0 or some_new_string.find('true') >= 0:
                some_string = some_new_string
        return ast.literal_eval('{' + some_new_string + '}')
    
    m = folium.Map(**pythonicize(b))
    m
    

    where m is (again) the folium.Map object:

    enter image description here