Plot points in google map with python with google api - python

I'm trying to plot some points on a map, and when searching on the internet, I found [this][1] tutorial with Google Maps and Bokeh library. The problem is that, after doing all the steps to get a key in google api, to set the environment variable, when I try to plot, it says that google maps weren't able to load.
Since I don't have much time, and I really need to plot some data (UTM coordinates, that I Intend to transform to latitude and longitude with pyproj), I was wondering if someone knows, another library, with examples, easy to work, with where I could plot my data (is a pandas dataframe with East, Northing, Elevation).
This is the code from the example I'm trying to reproduce:
import os
ACCESS_KEY_ID = os.environ.get('ACCESS_KEY_ID')
api_key = os.environ['SECRET_ACCESS_KEY']
import pandas as pd
from bokeh.io import output_notebook
df = pd.read_csv('dvf_gex.csv')
lat, lon = 46.2437, 6.0251
from bokeh.io import show
from bokeh.plotting import gmap
from bokeh.models import GMapOptions
bokeh_width=500
bokeh_height=500
def plot(lat, lng, zoom=10, map_type='roadmap'):
gmap_options = GMapOptions(lat=lat, lng=lng,
map_type=map_type, zoom=zoom)
p = gmap(api_key, gmap_options, title='Pays de Gex',
width=bokeh_width, height=bokeh_height)
show(p)
return p
this is the error I got:
[![enter image description here][2]][2]
The error I get on my browser console is:
[![enter image description here][3]][3]
I have activated the Maps Embed API, is that enough? should I have another API activated?
[1]: https://thedatafrog.com/en/articles/show-data-google-map-python/#commento-login-box-container
[2]: https://i.stack.imgur.com/SxoXS.png
[3]: https://i.stack.imgur.com/rjqc2.png

I guess Google has retired the GMap version that Bokeh 2.4.2 specifies by default? That is pretty annoying and user-unfriendly of them. However, you can specify any API version to use by passing it to gmap, e.g.
gmap(api_key, api_version="3.47", ...)

Related

Interactive Xarray dataset raster visualisation app using Panel and hvplot

I am trying to replicate the Glaciers Demo using an Xarray of geospatial data. I am able to create pretty much exactly what I want but I am trying to create a Panel app that allows the user to select the data_vars, each of which has different dimensions that I want make interactable, and visualize on an interactive map with at least the continents contour. Here is what my Xarray Dataset looks like :
def plot(field):
return xds[field].hvplot.image().opts(cmap='jet',height=650,width=1300,data_aspect=1)
interact(plot, field = list(xds.data_vars))
and here is what the code above produces in a notebook :
I would like to integrate the selector for the data_vars and then depending on its dimensions have interactive maps with controls for all its dimensions (ES has (time, pres1, lat, lon) while P0 has only (time, lat, lon)) and I would like to have the controls in the sidebar and the plots in the main of the following template :
from turtle import width
from matplotlib.pyplot import title
import panel as pn
import numpy as np
import holoviews as hv
from panel.template import DefaultTheme
from pathlib import Path
import fstd2nc
import hvplot.xarray
import xarray as xr
from unicodedata import name
import hvplot
import param
from panel.interact import interact
pn.extension(sizing_mode='stretch_width')
bootstrap = pn.template.MaterialTemplate(title='Material Template', theme=DefaultTheme, )
glob_path = Path(r"C:\Users\spart\Documents\Anaconda-Work-Dir")
file_list = [str(pp).split('\\')[-1] for pp in glob_path.glob("2022*")]
phase = pn.widgets.FloatSlider(name="Phase", start=0, end=np.pi)
fileSel = pn.widgets.Select(name='Select File', options=file_list)
#pn.depends(fileSel=fileSel)
def selectedFile(fileSel):
base_path = r"C:\Users\spart\Documents\Anaconda-Work-Dir\{}".format(fileSel)
return pn.widgets.StaticText(name='Selected', value=base_path)
#pn.depends(fileSel=fileSel)
def dataXArray(fileSel):
base_path = r"C:\Users\spart\Documents\Anaconda-Work-Dir\{}".format(fileSel)
xds = fstd2nc.Buffer(base_path).to_xarray()
return xds.ES.hvplot( width=500)
bootstrap.sidebar.append(fileSel)
bootstrap.sidebar.append(selectedFile)
bootstrap.main.append(
pn.Row(
pn.Card(hv.DynamicMap(dataXArray), title='Plot'),
)
)
bootstrap.show()
EDIT : Here is a link to an example dataset which can be loaded with the following code
xds = fstd2nc.Buffer(PATH_TO_FILE).to_xarray()
Without the data file I can't easily run the code, but some observations:
If using bare functions like this rather than classes, I'd recommend using pn.bind rather than pn.depends; it really helps get the code organized better.
For a simple application like this, I'd use hvPlot .interactive: https://hvplot.holoviz.org/user_guide/Interactive.html
I can't seem to find this in the docs, but you can pull out the widgets from the result of dataXArray (or any other hvplot or holoviews object) using .widgets(), and you can then put that in the sidebar. You can then pull out just the plot using .panel(), and put that in the main area.
If that helps you get it done, then great; if not please post a sample data file or two so that it's runnable, and I can look into it further. And please submit a PR to the docs once you get it working so that future users have less trouble!

PyQGIS changing basemap crs when importing a csv

I am using PyQGIS to import a csv file with a lat and long, when doing this I am using the appropriate crs of EPSG:4326.
I'm plotting this onto Google Maps.
I load my basemap, then import my CSV. The issue is that my basemap projection then changes to 4326 and I need it to remain on 3857.
I've tried importing the basemap after the CSV and moving it down in the layers, however this still changes the projections.
import requests
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from qgis.core import *
from qgis.utils import iface
from qgis import core
#Use Google Street Map as QGIS basemap.
service_url = "mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}"
service_uri = "type=xyz&zmin=0&zmax=21&url=https://"+requests.utils.quote(service_url)
tms_layer = iface.addRasterLayer(service_uri, "GoogleSat", "wms")
#Import CSV and plot.
uri = 'file:///home/user/fred.csv?type=csv&xField=%s&yField=%s&crs=%s' % ("Site Longitude", "Site Latitude", "EPSG:4326")
layer_csv = QgsVectorLayer(uri, 'fred', 'delimitedtext')
layer_csv.isValid()
QgsProject.instance().addMapLayer(layer_csv)
I'll be the first to admit I'm a novice with QGIS!
It seems this has something to do with the application not refreshing properly as mentioned in this answer on gis stack. You may want to look into it for details.
To answer your question in brief, you can add QApplication.instance().processEvents() after QgsProject.instance().addMapLayer(layer_csv) and then use setCrs() to set your basemap CRS to whatever value you need. It will hold.
proj = QgsProject.instance()
proj.addMapLayer(layer_csv)
# This line makes the difference
QApplication.instance().processEvents()
# This sets the project CRS back to 3857
proj.setCrs(QgsCoordinateReferenceSystem(3857))

Python mapping: plotting an electoral boundary over a street map?

I would have thought this would be so simple it would be almost example 1 in any mapping documentation. But it seems not... I want to map the boundary of an electorate over a street map, using cartopy. I can download the GIS data of the electorates in either MapInfo or ShapeFile form. When I tried to do this a year ago, the only way I could find to do it was to extract the lat/long coordinates of the MapInfo polygon, and plot them with matplotlib.
I'm trying to be a bit more elegant this year. With the MapInfo file, I can isolate my particular electorate with
import geopandas as gpd
v = gpd.read_file('VicMaps/vic-july-2018-mid-mif/E_VIC18.MIF')
cg = v.loc[7].geometry
My efforts to extract a particular single boundary from a shapefile are given below.
The other issue is that when I try to run this in jupyter, attempts at plotting a map causes the kernel (python 3.4) to crash.
There must be examples of this somewhere, but so far I haven't found an example which works with my data. This is what I have so far, cobbled together from various helpful answers to other people's questions:
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.io.shapereader import Reader
from cartopy.io.img_tiles import OSM
shp = Reader('VicMaps/E_AUGFN3_region.shp')
fig = plt.figure(figsize=(16,16))
tiler = OSM()
ax = plt.axes(projection=tiler.crs)
ax.set_extent([144.956158, 145.085398, -37.813662, -37.690999])
for r, g in zip(shp.records(), shp.geometries()):
if r.attributes['Elect_div'] == 'Cooper':
ax.add_geometries(g, ccrs.Geodetic())
plt.show()
But what happens is that the kernel just dies "unexpectedly".
If anybody could point me in the direction of a solution, I'd be delighted! Also: I'm not wedded to cartopy; if there's a better package I'll use it.
Thanks!

Embedding Google Earth with Python

Is there a way to embed Google Earth or Google Earth Engine in a Python desktop application?
As of now, I've created a kml file with longitude/latitude data that can be manually dropped into Google Earth Pro to trace the path of the GPS.
I've seen a lot of forum posts where Google Earth was embedded in webpages but not desktop applications so I was wondering if it could be done.
Any suggestions would be appreciated
Yes, you can add Google Earth Engine results to a desktop application as long as it supports WMS tile layers, images, or graphs.
Here are some examples assuming your have already gone through these preprocesing steps:
import ee
ee.Initialize() # note: may have initialize with a service account within an application
# ee Image object of the Global SRTM data
img = ee.Image("USGS/SRTMGL1_003")
Get WMS tiles:
# get map tile id and token with specific color palette
# arguments into "getMapId" are the same as the JavaScript API "Map.addLayer"
result = img.getMapId({'min': 0, 'max': 3000})
url = "https://earthengine.googleapis.com/map/{mapid}/{{z}}/{{x}}/{{y}}?token={token}"
tiles = url.format(**result)
print(tiles)
# visualize in your favorite application that supports WMS
Get static Image:
# Generate a URL that displays a static Image from Global DEM
url = img.getThumbUrl({'min':0, 'max':3000})
# create a file-like object from the url
import urllib2
f = urllib2.ulropen(url)
# Display the image using matplotlib
import matplotlib.pyplot as plt
result = plt.imread(f)
plt.imshow(result)
plt.show()
Displaying a time series graph may be a little more involved:
# get a collection with time series
collection = ee.ImageCollection('MODIS/006/MOD11A2')\
.filterDate('2016-01-01','2018-01-01')
# create a geometry of area to show time series
atl = ee.Geometry.Point([-84.3880,33.7490])
# get a time series over the point
result = collection.select('LST_Day_1km').getRegion(atl,1000).getInfo()
# turn the result into a pandas dataframe and manipulate results for plotting
import pandas as pd
df = pd.DataFrame(result[1:])
df.columns = result[0]
# convert epoch time to a format for pandas
dates = [pd.Timestamp(t*1000000) for t in df.time]
# make new pandas series object with scaled LST values
ts = pd.Series(np.array(df.LST_Day_1km)*0.02-273.15,index=dates,name='lst')
ts.index.name = 'Date'
# finally display results
ts.plot()
There are probably more efficient ways to get the results and display in an application, however, this may be a way to get you started.
Two second google search found this! So in answer to your question, yes you can use Google Earth in Python
https://developers.google.com/earth-engine/python_install

Line Graphs in Anaconda

I am writing a Python program to generate line graphs of cryptocurrency prices.
The goal is to be able to overlay multiple arbitrary pairs, i.e., BTC/USD + ETH/BTC, or BTC/USD + BCH/LTC + XRP/BTG, across the same horizontal timeline, similar to https://coinmarketcap.com/currencies/ethereum/
The bells and whistles in the above example are not required. It doesn't need click-to-zoom technology, the log-scale button, or fancy tool tips, if these features increase the implementation difficulty. Separate colors for each line would be helpful. This is the format of the data I have to work with:
https://min-api.cryptocompare.com/data/histominute?fsym=BTC&tsym=USD&limit=60&aggregate=1&e=Coinbase
https://min-api.cryptocompare.com/data/histominute?fsym=ETH&tsym=BCH&limit=30&aggregate=1&e=CCCAGG
Currently, I have Anaconda 3.6 on Visual Studio, which according to https://docs.anaconda.com/anaconda/packages/py3.6_win-64.html should include multiple packages to plot this data without needing to manually install third party code through a command line. However, when I try to import any of them (i.e., matplotlib, bokeh, seaborn), I receive a "ModuleNotFoundError" message, so I'm not sure if my Anaconda is functioning properly. What is the easiest way to graph this data with Anaconda?
The python interpreter in VSCode is probably not using your Anaconda installation. In the VSCode python shell, type import sys and then sys.version and it should tell you the version of python you are using.
Here is some code to get you started with doing this in bokeh, a library that comes with Anaconda. Instead of using Visual Studio (or Visual Studio Code--I'm not sure which one you are referring to), I used jupyter notebook, and some of the import here are specific to that environment (to show the bokeh graph inline). You may want to format the date differently.
from bokeh.plotting import figure, output_file, show
from bokeh.io import output_notebook
import numpy as np
output_notebook()
import requests
import datetime
from math import pi
def format_date(utc_time):
time = datetime.datetime.fromtimestamp(int(utc_time))
return time
url1 = "https://min-api.cryptocompare.com/data/histominute?fsym=BTC&tsym=USD&limit=60&aggregate=1&e=Coinbase"
url2 = "https://min-api.cryptocompare.com/data/histominute?fsym=ETH&tsym=BCH&limit=30&aggregate=1&e=CCCAGG"
r1 = requests.get(url1)
r2 = requests.get(url2)
r1_source = r1.json()["Data"]
r2_source = r2.json()["Data"]
r1_data = [i["close"] for i in r1_source]
r1_time = [format_date(i["time"]) for i in r1_source]
# r2_data = [i["close"] for i in r2_source]
# r2_time = [i["time"] for i in r2_source]
p = figure(plot_width=800, plot_height=400)
p.line(r1_time,r1_data, line_width=2)
# p.line(r2_time, r2_data, line_width=2, line_color="red")
p.xaxis.major_label_orientation = pi/4

Categories