Commit f90c74f1 authored by Christine Plumejeaud's avatar Christine Plumejeaud
Browse files

Few changes for ports to export all ports, including homeports that are not in...

Few changes for ports to export all ports, including homeports that are not in pointcalls and to send back a geojson file that can be used directly for web mapping in EPSG 4326.
parent 1e1d42c2
......@@ -24,6 +24,8 @@ import pandas as pd
import psycopg2 as pg
import re
from geojson import Feature, FeatureCollection, Point
#import flask_ext
#import flask_excel as excel
#import pyexcel as pe
......@@ -40,7 +42,7 @@ CORS(app, origins='*', send_wildcard=True)
#port = app.config['PORT']
port = '80'
postgresport = '5432'
database = 'portic_v6'
database = 'portic_v7'
# API documentation as statically generated website
@app.route('/')
......@@ -107,11 +109,60 @@ def formatJSON(dataframe):
json_str = json.dumps(dataframe.to_json(orient='records'))
return json.loads(json_str)
def df_to_geojson(df, properties, id = 'ogc_fid', lat='y', lon='x'):
""" From https://geoffboeing.com/2015/10/exporting-python-data-geojson/
Some few enhancements : float(row[lon]),float(row[lat]) is required to have a valid GEOJSON
(else coordinates in quotes like strings are wrong)
Added an id.
"""
geojson = {'type':'FeatureCollection', 'features':[]}
for _, row in df.iterrows():
feature = {'type':'Feature',
'id': row[id],
'properties':{},
'geometry':{'type':'Point',
'coordinates':[]}}
feature['geometry']['coordinates'] = [float(row[lon]),float(row[lat])]
for prop in properties:
feature['properties'][prop] = row[prop]
geojson['features'].append(feature)
return geojson
def formatGEOJSON(dataframe):
"""
Internal method to output dataframe as GEOJSON
We suppose it is called with /api/ports, so that the resulting dataframe has x, y, point and ogc_fid columns.
Not well because it will bug if called for another path (travels, pointcalls, etc...).
However I don't have much time to do it well.
"""
'''
#This is not working since properties are not nested inside features.
#https://stackoverflow.com/questions/47308984/how-to-use-python-with-pandas-exporting-data-to-geojson-for-google-map
features = dataframe.apply(
lambda row: Feature(geometry=Point((float(row['x']), float(row['y'])))),
axis=1).tolist()
properties = dataframe.drop(['y', 'x', 'point'], axis=1).to_dict('records')
feature_collection = FeatureCollection(features=features, properties=properties)
'''
properties_names = dataframe.columns.tolist()
properties_names.remove('x')
properties_names.remove('y')
properties_names.remove('point')
properties_names.remove('ogc_fid')
feature_collection = df_to_geojson(dataframe, properties_names, 'ogc_fid', 'y', 'x')
json_str = json.dumps(feature_collection, ensure_ascii=False )#allow_nan=False #, ignore_nan=True
output = make_response(json_str)
output.headers["Content-type"] = "application/geo+json"
#output.headers["Content-Disposition"] = "attachment; filename=ports1789.json"
return output
#return json.loads(json_str)
def formatOutput(dfcsv, api='travels'):
"""
Internal method
Apply various formatting on dataframe for output by processing request parameters
- format : csv | **json**
- format : csv | **json** | geojson
- zipped : true | **false**
- shortenfields : true | **false**
NB :
......@@ -141,6 +192,8 @@ def formatOutput(dfcsv, api='travels'):
format = request.args.get("format")
if (format != None and format == 'csv') :
return formatCSV(dfcsv)
elif (format != None and format == 'geojson') :
return formatGEOJSON(dfcsv)
else:
return formatJSON(dfcsv)
......@@ -758,17 +811,21 @@ def getPorts():
export list of ports_points (in 900013 projection or what is specified by user) in json format,
with all required attributes for visualisations (selection of parameters is not possible for the moment)
List of attributes :
ogc_fid, uhgs_id, total, toponym, belonging_states, belonging_substates, status, geonameid, admiralty, province, shiparea , point
#ogc_fid, uhgs_id, total, toponym, belonging_states, belonging_substates, status, geonameid, admiralty, province, shiparea , point
ogc_fid, uhgs_id, x, y, total, toponym, toponyme_standard_fr, toponyme_standard_en , substate_1789_fr , state_1789_fr, substate_1789_en ,
state_1789_en, belonging_states, belonging_substates, status, has_a_clerk, geonameid, amiraute as admiralty, province, shiparea, point
User can get a description of the attributes by using /api/fieldnames?api=ports
Default srid is 900913
You get another by specifying a srid param
Default srid is 900913, except if asked in format=geojson (it will be then sended as WGS84 projection, EPSG 4326)
You get another projection by specifying a srid param
Will be extracted from postgres, schema ports, table port_points (see navigocorpus/ETL)
Tested alone : http://localhost/api/ports?srid=4326 ou http://localhost/api/ports?
http://localhost/api/ports?srid=4326&format=geojson
and by using explorex.portic.fr application (code alphaportic for visualisation)
Test OK on 06 June 2020
Test ok on 04 april 2022
"""
# select the srid given by user for geometry transformation
srid = request.args.get("srid")
......@@ -778,11 +835,22 @@ def getPorts():
date = request.args.get("date")
filterDate=getFilterdateForPointcall(date)
#Old request was not sending geocoded homeports.
'''
query = """SELECT ogc_fid, uhgs_id, total, toponyme as toponym, belonging_states, belonging_substates, status, geonameid, amiraute as admiralty, province, shiparea , ST_AsGeoJSON(ST_Transform(geom, %s)) as point
FROM ports.port_points p,
(select pointcall_uhgs_id, count( *) as total
from navigoviz.pointcall gg %s group by pointcall_uhgs_id) as k
where p.toponyme is not null and p.uhgs_id = k.pointcall_uhgs_id""" %(srid, filterDate)
'''
query = """SELECT ogc_fid, uhgs_id, p.longitude as x, p.latitude as y, coalesce(total, 0) as total, toponyme as toponym, p.toponyme_standard_fr, p.toponyme_standard_en , p.substate_1789_fr , p.state_1789_fr, p.substate_1789_en , p.state_1789_en, belonging_states, belonging_substates,
status, has_a_clerk, geonameid, amiraute as admiralty, province, shiparea, ferme_direction, ferme_bureau, partner_balance_1789, partner_balance_supp_1789,
ST_AsGeoJSON(ST_Transform(geom, %s)) as point
FROM ports.port_points p left join
(select pointcall_uhgs_id, count( *) as total from navigoviz.pointcall gg %s group by pointcall_uhgs_id) as k
on p.uhgs_id = k.pointcall_uhgs_id
where geom is not null"""%(srid, filterDate)
return retrieveDataAndFormatOutput(query, api='ports')
......
......@@ -18,7 +18,7 @@ Trois grands types de requêtes :
Liste des paramètres communs à chaque requête et valeurs par défaut en gras:
- params : **all** | tableau des noms longs des attributs de l'API à renvoyer
- format : csv | **json**
- format : csv | **json** | geojson
- shortenfields : true | **false**
- both_to : true | **false**
- date : YYYY | **1787**
......@@ -73,6 +73,8 @@ Pour avoir les mêmes données en JSON :
- <http://data.portic.fr/api/travels/?format=json>
- <http://data.portic.fr/api/pointcalls/?format=json>
Le format GEOJSON est pour l'instant réservé à l'API ports et il renvoie des coordonnées géographiques (WGS84, EPSG 4326) quelque soit le SRID spécifié
- http://data.portic.fr/api/ports?format=geojson
**shortenfields** permet de raccourcir les noms des attributs et donc d'alléger la taille du JSON téléchargé. L'API permet de récupérer le mapping entre ces noms courts et longs avec :
......@@ -406,6 +408,12 @@ List of attributes :
- uhgs_id,
- total,
- toponym,
- toponyme_standard_fr,
- toponyme_standard_en ,
- substate_1789_fr ,
- state_1789_fr,
- substate_1789_en ,
- state_1789_en,
- belonging_states,
- belonging_substates,
- status,
......@@ -413,14 +421,18 @@ List of attributes :
- admiralty,
- province,
- shiparea,
- point
- point,
- ferme_direction,
- ferme_bureau,
- partner_balance_1789,
- partner_balance_supp_1789
User can get a description of the attributes by using :
`/api/fieldnames?api=ports`
Default srid is 900913
You get another by specifying a srid param
You get another by specifying a srid param. Except if you request format=geojson (4326 will be sent back then)
Will be extracted from postgres, schema ports, table port_points (see navigocorpus/ETL).
......@@ -428,6 +440,7 @@ Tested alone in a browser:
http://data.portic.fr/api/ports?srid=4326
http://data.portic.fr/api/ports?
http://data.portic.fr/api/ports?format=geojson
and by using [explorex.portic.fr](http://explorex.portic.fr) application (code alphaportic for visualisation) as client : it works
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment