How to list all layers on Geopackage using pyqgis? - gis

I am studying about pyqgis (using the pyqgis cookbook and started loading a vector layer.
So far I was able to open a layer that I already knew exist on a geopackge.
iface.addVectorLayer("./bcim_2016_21_11_2018.gpkg|layername=lim_unidade_federacao_a", "Nome Vetor", "ogr")
Now, I am wondering how could I list all layers hosted on a geopackage, so a can define which layer to load?
Thansk in advance
Felipe

I have just found this possibility on PyQGIS CookBook - cheatsheet, which answer my question.
from qgis.core import QgsVectorLayer, QgsProject
fileName = "/path/to/gpkg/file.gpkg"
layer = QgsVectorLayer(fileName,"test","ogr")
subLayers =layer.dataProvider().subLayers()
for subLayer in subLayers:
name = subLayer.split('!!::!!')[1]
uri = "%s|layername=%s" % (fileName, name,)
# Create layer
sub_vlayer = QgsVectorLayer(uri, name, 'ogr')
# Add layer to map
QgsProject.instance().addMapLayer(sub_vlayer)

Felipe, all layers are stored into gpkg_geometry_columns. So you should query this table using either QSqlDatabase from Qt or sqlite3.
To query the table name, column name and geometry type you can do the following:
select table_name, column_name, geometry_type_name from gpkg_geometry_columns
Hope I could help you!
Philipe

Related

BentoML - Seving a CatBoostClassifier with cat_features

I am trying to create a BentoML service for a CatBoostClassifier model that was trained using a column as a categorical feature. If i save the model and I try to make some predictions with the saved model (not as a BentoML service) all works as expected, but when I create the service using BentML I get an error
_catboost.CatBoostError: Bad value for num_feature[non_default_doc_idx=0,feature_idx=2]="Tertiary": Cannot convert 'b'Tertiary'' to float
The value is found in a column named 'road_type' and the model was trained using 'object' as the data type for the column.
If I try to give a float or an integer for the 'road_type' column I get the following error
_catboost.CatBoostError: catboost/libs/data/model_dataset_compatibility.cpp:53: Feature road_type is Categorical in model but marked different in the dataset
If someone has encountered the same issue and found a solution I would appreciate it. Thanks!
I have tried different approaches for saving the model or loading the model but unfortunately it did not worked.
You can try to explicitly pass the cat_features to the bentoml runner.
It would be something like this:
from catboost import Pool
runner = bentoml.catboost.get("bentoml_catboost_model:latest").to_runner()
cat_features = [2] # specify your cat_features indexes
prediction = runner.predict.run(Pool(input_data, cat_features=cat_features))

Change GML geometry attribute from Linestring to Multicurve in FME

I am currently converting a shapefile into a GML file for an online Mapviewer. this application requires the geometry to be in a seperate attribute and needs to consist of multicurve features.
using GeometryExtractor, i get the following:
<rrgs:geometrie>
<gml:LineString gml:id="id-9f7691bb-868d-457e-9061-aceb37980a59-0" srsName="EPSG:28992" srsDimension="2">
<gml:posList>260471.21250000037 591380.1363999993 260457.43054999973 591385.7507499998</gml:posList>
</gml:LineString>
</rrgs:geometrie>
however, the application for uploading onto the online mapviewer requires the geometry as follows:
<rrgs:geometrie>
<gml:MultiCurve gml:id="…" srsName="EPSG:28992" srsDimension="2">
<gml:curveMember>
<gml:LineString gml:id="id-9f7691bb-868d-457e-9061-aceb37980a59-0">
<gml:posList>260471.21250000037 591380.1363999993 260457.43054999973 591385.7507499998</gml:posList>
</gml:LineString>
</gml:curveMember>
</gml:MultiCurve>
</rrgs:geometrie>
would it be possible in FME to convert linestring features into multicurve features?
Thanks in advance!
I would try just setting an Aggregator before writing so all geometries are multi-geometries.
You would need to use an attribute with a unique value in the Group By parameter so the different features aren't grouped together. If there's none try the UUIDGenerator.

Best Approach: qgis on mysql or reverse geocoding

i need to find out what is the best method for what i'm looking.
Basically, based on user position (lat and lng coords.), i need to find their corresponding city..
my first attempt was gmaps (reverse geocoding):
Pros:
easy to use
Cons:
use is limited to N requests
according to their policies, using reverse geocoding without any visual in frontend is prohibited.
Each country has their own typography ( there is no standart field to obtain):
my second scenario, was mysql geospational:
After download gadm shape files, i tried to convert them para mysql using shp2mysql but no success..
Pros:
there is no need any external service to retrieve city
My Cons:
Unable to use them correctly.
So, am i on a right way? is second approach better than one? i only need cities/countries based on a user location, nothing more..
Any sugestion or maybe a good tutorial?
After hours:
CREATE TABLE geom (g GEOMETRY NOT NULL, SPATIAL INDEX(g)) ENGINE=MyISAM;
Next:
C:\Program Files\FWTools2.4.7>ogr2ogr -f MySQL MySQL:dbname,user=root
,password=root C:\shape_pt\PRT_adm1.shp -nln geom -update -overwrite -lco GEOMET
RY_NAME=g
ERROR 1: MySQL error message:The used table type doesn't support SPATIAL indexes
Description: ALTER TABLE `geom` ADD SPATIAL INDEX(`g`)
ERROR 1: Terminating translation prematurely after failed
translation of layer PRT_adm1 (use -skipfailures to skip errors)
Any suggestion?

Storing 3d shapes in sql server using geometry data type and WKT

I'm looking at the geometry data type in Sql Server 2008 and it looks interesting but the documentation does not seem that good. Would I be able to store cones, cylinders and spheres in the WKT format? These features traditionally have a radius and not hundreds of points.
To the best of my knowledge your are going to have to use an external application to render your shape as a large number of points. See this blog for a technique for rendering circles.
One possibility to consider is a CLR proc to render the shapes you need and a view with indexes. I don't know how well that will perform, but it just might work.
sorry for the late reply. You could always write your own User-Defined-Type called Circle, with two properties namely Centroid and Radius.
Inside the newly formed UDT, create a method that takes the properties Centroid (Point3D), and Radius (Double). After this, create a method that uses both SqlGeometry and SqlGeometryBuilder to build the newly formed object.
First, create a Point instance of Geometry. Inherit the Centroid values from the class object, then, create another Geometry Polygon that's derived from the Point object, and STBuffer(Radius) it.
Below is my example: (written in 30min)
public SqlGeometry ToSQLGeometry()
{
int srid = this.SRID; // i.e. 4326
SqlGeometry geom = new SqlGeometry();
SqlGeometryBuilder gb = new SqlGeometryBuilder();
OpenGisGeometryType pt = OpenGisGeometryType.Point;
gb.SetSrid(srid);
gb.BeginGeometry(pt);
gb.BeginFigure(this.Centroid.X, this.Centroid.Y, this.Centroid.Z, this.Centroid.M);
gb.EndFigure();
gb.EndGeometry();
geom = gb.ConstructedGeometry;
geom = geom.MakeValid(); // Optional for Point data
SqlGeometry geomCircle = new SqlGeometry();
geomCircle = geom.STBuffer(this.Radius);
return geomCircle;
}
When you've done this in VS2010 by using the CLR project type, you can deploy it to your database.
In SQL, you can call the object as such:: Parse(X Y Z M,R)
declare #c Circle
set #c = Circle::Parse('5 6 7 8,2')
select 'Circle', #c.ToString(), #c.ToSQLGeometry()
Had a quick look around and found this MSDN page on Spatial Samples. It covers all the Methods to enter data in WKT, WKB & XML(GML) as well as functions to view the in Human Readable form. It also covers MakeValid, STIsValid & STSrid.
There looks to be a fair few SQL examples that you may find useful

How do you know what SRID to use for a shp file?

I am trying to put a SHP file into my PostGIS database, the the data is just a little off. I think this is because I am using the wrong SRID. The contents of the PRJ file are as follows:
GEOGCS["GCS_North_American_1983",
DATUM["D_North_American_1983",
SPHEROID["GRS_1980",6378137.0,298.257222101]],
PRIMEM["Greenwich",0.0],
UNIT["Degree",0.0174532925199433]]
What SRID does this correlate to? And more generally, how can I look up the SRID based on the information found in the PRJ file? Is there a lookup table somewhere that lists all SRID's and their 'geogcs' equivalents?
The data imported using srid=4269 and 4326 were the exact same results.
Does this mean I'm using the wrong SRID, or is this just expected margin of error?
The shp file is from here.
To elaborate on synecdoche's answer, the SRID is sometimes called an "EPSG" code. The SRID/EPSG code is a defacto short-hand for the Well-Known-Text representations of projections.
You can do a quick search on the SRID table to see if you can find an exact or similar match:
SELECT srid, srtext, proj4text FROM spatial_ref_sys WHERE srtext ILIKE '%BLAH%'
Above was found at http://www.bostongis.com/?content_name=postgis_tut01.
You can also search on spatialreference.org for these kinds of things. The search tool is primitive so you may have to use a Google search and specify the site, but any results will show you the ESRI PRJ contents, the PostGIS SQL INSERT, and a bunch of other representations.
I think your PRJ is at: http://spatialreference.org/ref/sr-org/15/
Prj2EPSG is a small website aimed at exactly this problem; paste in the PRJ contents and it does its best to find a matching EPSG. They also have a web service API. It's not an exact science. They seem to use Lucene and the EPSG database to do text searches for matches.
The data seems to be NAD83, which has an SRID of 4269. Your PostGIS database has a spatial_ref_sys table which is the SRID lookup table.
If the data looks the same with an SRID of 4269 (NAD83) and 4326 (WGS84), then there's something wrong.
Go and download the GDAL utilities , the ogrinfo (which would spit the projection information) and ogr2ogr utilities are invaluable.
James gave already a link to spatialreference.org. That helps to find spatial reference information... I assume you did load the spatial_ref_sys.sql when you prepared your postgis instance.
And to be honest, I don't think the problem is in the PostGIS side of things.
I usually keep my data in different SRIDs in my PostGIS dbs. However, I always need to project to the output SRS. You are showing OpenStreetMap pre-rendered tiles, and I bet they have been drawn using SRID 900913 (the Google Map's modified mercator projection that now everyone uses to render).
My recommendation to you is:
1- Set the right projection in the OpenLayers code which matches whatever tiles you are reading from.
2.- Keep the data in the database in whatever SRID you want (as long as it is correct of course).
3.- Make sure the server you are using to generate the images from your data (ArcGIS Server, Mapserver, GeoServer or whatever it is) is reprojecting to that same SRS.
Everything will match.
Cheers
Use GDAL's OSR Python module to determine the code:
from osgeo import osr
srsWkt = '''GEOGCS["GCS_North_American_1983",
DATUM["D_North_American_1983",
SPHEROID["GRS_1980",6378137.0,298.257222101]],
PRIMEM["Greenwich",0.0],
UNIT["Degree",0.0174532925199433]]'''
# Load in the projection WKT
sr = osr.SpatialReference(srsWkt)
# Try to determine the EPSG/SRID code
res = sr.AutoIdentifyEPSG()
if res == 0: # success
print('SRID=' + sr.GetAuthorityCode(None))
# SRID=4269
else:
print('Could not determine SRID')
Be sure to take a look at: http://www.epsg-registry.org/
Use the Query by Filter option and enter: North American Datum 1983.
This yields -> EPSG:6269.
Hope this works for you.