PyQGIS changing basemap crs when importing a csv - python

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))

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!

Plot points in google map with python with google api

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", ...)

Error reading Kepler FITS file using astropy

I was trying to read fits files from Kepler FITS files (Received from this URL https://archive.stsci.edu/pub/kepler/lightcurves/0007/000757076/) using astropy. Below are the set of commands I was trying to read the file:
from astropy.io import fits
fits_image_filename = fits.util.get_testdata_filepath(r'O:\MyWorks\keplar-test\kplr100000925-2009166043257_llc.fits')
But the above command produced this error:
I am not sure how to solve this error. My target is to read keplar data then plot this and/or convert this to CSV.
This: fits.util.get_testdata_filepath(r'O:\MyWorks\keplar-test\kplr100000925-2009166043257_llc.fits') is not the correct function for opening a file.
You should use fits.open('file.fits'), or if this is table data, as you imply, Table.read('file.fits')
See the note at the top of the FITS documentation
%matplotlib inline
from astropy.io import fits
import matplotlib
import matplotlib.pyplot as plt
#My required file has been downloaded in the following path of my HD,
"~/projects/eclipsing_binary/A/mastDownload/HLSP/hlsp_qlp_tess_ffi_s0018-0000000346784049_tess_v01_llc/hlsp_qlp_tess_ffi_s0018-000000346784049_tess_v01_llc.fits". Using linux command open and see the list
of the files in the directory.
%cd ~/projects/eclipsing_binary/A/mastDownload/HLSP/
hlsp_qlp_tess_ffi_s0018-0000000346784049_tess_v01_llc/
%ls
#Now plot the required file in simple way,
import lightkurve as lk
file_r = 'hlsp_qlp_tess_ffi_s0018-0000000346784049_tess_v01_llc.fits'
lr = lk.read(file_r)
lr.plot()

.plot() command does not display anything

I have this code based on this question, just a different point Extract constrained polygon using OSMnx
I am trying to plot the block in which the point is located but it does nothing, it just prints "Done" but I cannot see any image
import osmnx as ox
import geopandas as gpd
import shapely
point = (50.090464, 14.400070)
streets_graph = ox.graph_from_point(point, distance=500, network_type='drive')
streets_graph = ox.project_graph(streets_graph)
streets = ox.save_load.graph_to_gdfs(streets_graph, nodes=False, edges=True,
node_geometry=False, fill_edge_geometry=True)
point = streets.unary_union.centroid
polygons = shapely.ops.polygonize(streets.geometry)
polygons = gpd.GeoSeries(polygons)
target = polygons.loc[polygons.contains(point)]
target_streets = streets.loc[streets.intersection(target.iloc[0]).type == 'MultiLineString']
ax = target_streets.plot()
gpd.GeoSeries([point]).plot(ax=ax, color='r')
print("Done")
I do not think this may help but I am using Visual Studio Code
Thank you very much
Since my comment answered your question, I will summarize it here for other people:
When using plotting library dependent on matplotlib, like geopandas or seaborn, you will need to import matplotlib in order to show the plot. The way matplotlib is imported will depend on whether you are using Jupyter or simple scripting (.py) files.
For Jupyter you need to import it like this:
%matplotlib inline
For simple scripting (.py) file you need to import it like this:
import matplotlib.pyplot as plt
Then when you want to show your plot you simply do
plt.show()
Hope it helps!

Python module to merge DXF files

I am looking for a python module that will merge dxf files. I have found dxfgrabber and ezdxf, however they seem to be used for different applications then what I am after.
I am using ExpressPCB, which outputs each layer of the PCB, the holes, and the silkscreen separately. For my application I want to combine all of these individual DXF into a single. See photo
As far as I know, the origins, etc are the same so it should all line up as it would in real life.
Currently, neither of these modules have any tutorials for this type of application. Some psudo code to get the idea across in a pythonic way:
dxf_file1 = read(file1)
dxf_file2 = read(file2)
dxf_file3 = read(file3)
out_file.append(dxf_file1)
out_file.append(dxf_file2)
out_file.append(dxf_file3)
outfile.save()
In my application, the files will all have the same origin point and will never overlap, so you should be able to easily merge the files somehow. Thank you for the help in advance!
You can use the rewritten Importer add-on in ezdxf v0.10:
import ezdxf
from ezdxf.addons import Importer
def merge(source, target):
importer = Importer(source, target)
# import all entities from source modelspace into target modelspace
importer.import_modelspace()
# import all required resources and dependencies
importer.finalize()
base_dxf = ezdxf.readfile('file1.dxf')
for filename in ('file2.dxf', 'file3.dxf'):
merge_dxf = ezdxf.readfile(filename)
merge(merge_dxf, base_dxf)
# base_dxf.save() # to save as file1.dxf
base_dxf.saveas('merged.dxf')
This importer supports just basic graphics like LINE, CIRCLE, ARC and DIMENSION (without dimension style override) and so on.
All XDATA and 3rd party data will be ignored, but your files seems to be simple enough to work.
Documentation of the Importer add-on can be found here.
import sys
import ezdxf
from ezdxf.addons import geo
from shapely.geometry import shape
from shapely.ops import unary_union
def dxf2shapley(filename):
doc = ezdxf.readfile(filename)
msp = doc.modelspace()
entities = msp.query('LINE')
proxy = geo.proxy(entities)
shapley_polygon = shape(proxy)
if !shapley_polygon.is_valid:
raise Exception('polygon is not valid')
return shapley_polygon
h0 = dxf2shapley('test-0.dxf')
h1 = dxf2shapley('test-1.dxf')
polygons = [h0, h1]
polyout = unary_union(polygons)
result = ezdxf.addons.geo.dxf_entities(polyout, polygon=2)
doc = ezdxf.new('R2010')
msp = doc.modelspace()
for entity in result:
msp.add_entity(entity)
doc.saveas('test_merged.dxf')

Categories