Repair 'Extract islands' operation; add automatic recalculation of mwm size estimation after some operations
This commit is contained in:
parent
ce461536a4
commit
d46dca1df1
5 changed files with 87 additions and 21 deletions
web/app
|
@ -25,7 +25,11 @@ from countries_structure import (
|
|||
create_countries_initial_structure,
|
||||
get_osm_border_name_by_osm_id,
|
||||
)
|
||||
from subregions import get_subregions_info
|
||||
from subregions import (
|
||||
get_subregions_info,
|
||||
update_border_mwm_size_estimation,
|
||||
)
|
||||
|
||||
|
||||
try:
|
||||
from lxml import etree
|
||||
|
@ -279,6 +283,7 @@ def split():
|
|||
base_name = name
|
||||
# insert new geometries
|
||||
counter = 1
|
||||
new_ids = []
|
||||
free_id = get_free_id()
|
||||
for geom in geometries:
|
||||
cur.execute(f"""
|
||||
|
@ -286,8 +291,11 @@ def split():
|
|||
VALUES (%s, %s, ST_GeomFromText(%s, 4326), %s, -1, now(), %s)
|
||||
""", (free_id, f'{base_name}_{counter}', geom, disabled, parent_id)
|
||||
)
|
||||
new_ids.append(free_id)
|
||||
counter += 1
|
||||
free_id -= 1
|
||||
for border_id in new_ids:
|
||||
update_border_mwm_size_estimation(g.conn, border_id)
|
||||
g.conn.commit()
|
||||
|
||||
return jsonify(status='ok')
|
||||
|
@ -430,6 +438,7 @@ def copy_from_osm():
|
|||
""", (osm_id,)
|
||||
)
|
||||
assign_region_to_lowerst_parent(osm_id)
|
||||
update_border_mwm_size_estimation(g.conn, osm_id)
|
||||
g.conn.commit()
|
||||
return jsonify(status='ok')
|
||||
|
||||
|
@ -818,23 +827,35 @@ def divide_into_clusters(region_ids, next_level, mwm_size_thr):
|
|||
def chop_largest_or_farthest():
|
||||
if config.READONLY:
|
||||
abort(405)
|
||||
name = request.args.get('name').encode('utf-8')
|
||||
region_id = int(request.args.get('id'))
|
||||
table = config.TABLE
|
||||
cur = g.conn.cursor()
|
||||
cur.execute('select ST_NumGeometries(geom) from {} where name = %s;'.format(config.TABLE), (name,))
|
||||
cur.execute(f"""SELECT ST_NumGeometries(geom)
|
||||
FROM {table}
|
||||
WHERE id = {region_id}""")
|
||||
res = cur.fetchone()
|
||||
if not res or res[0] < 2:
|
||||
return jsonify(status='border should have more than one outer ring')
|
||||
cur.execute("""INSERT INTO {table} (name, disabled, modified, geom)
|
||||
SELECT name, disabled, modified, geom from
|
||||
free_id1 = get_free_id()
|
||||
free_id2 = free_id1 - 1
|
||||
cur.execute(f"""
|
||||
INSERT INTO {table} (id, parent_id, name, disabled, modified, geom)
|
||||
SELECT id, region_id, name, disabled, modified, geom FROM
|
||||
(
|
||||
(WITH w AS (SELECT name, disabled, (ST_Dump(geom)).geom AS g FROM {table} WHERE name = %s)
|
||||
(SELECT name||'_main' as name, disabled, now() as modified, g as geom, ST_Area(g) as a FROM w ORDER BY a DESC LIMIT 1)
|
||||
UNION ALL
|
||||
SELECT name||'_small' as name, disabled, now() as modified, ST_Collect(g) AS geom, ST_Area(ST_Collect(g)) as a
|
||||
FROM (SELECT name, disabled, g, ST_Area(g) AS a FROM w ORDER BY a DESC OFFSET 1) ww
|
||||
GROUP BY name, disabled)
|
||||
) x;""".format(table=config.TABLE), (name,))
|
||||
cur.execute('delete from {} where name = %s;'.format(config.TABLE), (name,))
|
||||
(WITH w AS (SELECT name, disabled, (ST_Dump(geom)).geom AS g
|
||||
FROM {table} WHERE id = {region_id})
|
||||
(SELECT {free_id1} id, {region_id} region_id, name||'_main' as name, disabled,
|
||||
now() as modified, g as geom, ST_Area(g) as a
|
||||
FROM w ORDER BY a DESC LIMIT 1)
|
||||
UNION ALL
|
||||
SELECT {free_id2} id, {region_id} region_id, name||'_small' as name, disabled,
|
||||
now() as modified, ST_Collect(g) AS geom,
|
||||
ST_Area(ST_Collect(g)) as a
|
||||
FROM (SELECT name, disabled, g, ST_Area(g) AS a FROM w ORDER BY a DESC OFFSET 1) ww
|
||||
GROUP BY name, disabled)
|
||||
) x""")
|
||||
for border_id in (free_id1, free_id2):
|
||||
update_border_mwm_size_estimation(g.conn, border_id)
|
||||
g.conn.commit()
|
||||
return jsonify(status='ok')
|
||||
|
||||
|
|
|
@ -12,7 +12,14 @@ class MwmSizePredictor:
|
|||
with open(config.MWM_SIZE_PREDICTION_MODEL_SCALER_PATH, 'rb') as f:
|
||||
self.scaler = pickle.load(f)
|
||||
|
||||
def predict(self, features_array):
|
||||
@classmethod
|
||||
def _get_instance(cls):
|
||||
if not hasattr(cls, '_instance'):
|
||||
cls._instance = cls()
|
||||
return cls._instance
|
||||
|
||||
@classmethod
|
||||
def predict(cls, features_array):
|
||||
"""1D or 2D array of feature values for predictions. Features are
|
||||
'urban_pop', 'area', 'city_cnt', 'hamlet_cnt' as defined for the
|
||||
prediction model.
|
||||
|
@ -21,8 +28,10 @@ class MwmSizePredictor:
|
|||
one_prediction = (X.ndim == 1)
|
||||
if one_prediction:
|
||||
X = X.reshape(1, -1)
|
||||
X_scaled = self.scaler.transform(X)
|
||||
predictions = self.model.predict(X_scaled)
|
||||
|
||||
predictor = cls._get_instance()
|
||||
X_scaled = predictor.scaler.transform(X)
|
||||
predictions = predictor.model.predict(X_scaled)
|
||||
if one_prediction:
|
||||
return predictions[0]
|
||||
else:
|
||||
|
|
|
@ -1040,8 +1040,8 @@ function bLargest() {
|
|||
if( !selectedId || !(selectedId in borders) )
|
||||
return;
|
||||
$.ajax(getServer('chop1'), {
|
||||
data: { 'name': selectedId },
|
||||
success: updateBorders
|
||||
data: { 'id': selectedId },
|
||||
success: makeAnswerHandler(updateBorders)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ from mwm_size_predictor import MwmSizePredictor
|
|||
|
||||
osm_table = config.OSM_TABLE
|
||||
osm_places_table = config.OSM_PLACES_TABLE
|
||||
size_predictor = MwmSizePredictor()
|
||||
|
||||
|
||||
def get_subregions_info(conn, region_id, region_table,
|
||||
|
@ -93,10 +92,47 @@ def _add_mwm_size_estimation(subregions):
|
|||
]
|
||||
|
||||
feature_array = [x[1] for x in subregions_sorted]
|
||||
predictions = size_predictor.predict(feature_array)
|
||||
predictions = MwmSizePredictor.predict(feature_array)
|
||||
|
||||
for subregion_id, mwm_size_prediction in zip(
|
||||
(x[0] for x in subregions_sorted),
|
||||
predictions
|
||||
):
|
||||
subregions[subregion_id]['mwm_size_est'] = mwm_size_prediction
|
||||
|
||||
|
||||
def update_border_mwm_size_estimation(conn, border_id):
|
||||
table = config.TABLE
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(f"""
|
||||
SELECT ST_Area(geography(geom))/1.0E+6 area
|
||||
FROM {table}
|
||||
WHERE id = %s""", (border_id, ))
|
||||
rec = cursor.fetchone()
|
||||
border_data = {
|
||||
'area': rec[0],
|
||||
'urban_pop': 0,
|
||||
'city_cnt': 0,
|
||||
'hamlet_cnt': 0
|
||||
}
|
||||
cursor.execute(f"""
|
||||
SELECT COALESCE(p.population, 0), p.place
|
||||
FROM {table} b, {config.OSM_PLACES_TABLE} p
|
||||
WHERE id = %s
|
||||
AND ST_CONTAINS(b.geom, p.center)
|
||||
""", (border_id, ))
|
||||
for place_population, place_type in cursor:
|
||||
if place_type in ('city', 'town'):
|
||||
border_data['city_cnt'] += 1
|
||||
border_data['urban_pop'] += place_population
|
||||
else:
|
||||
border_data['hamlet_cnt'] += 1
|
||||
|
||||
feature_array = [
|
||||
border_data[f] for f in
|
||||
('urban_pop', 'area', 'city_cnt', 'hamlet_cnt')
|
||||
]
|
||||
mwm_size_est = MwmSizePredictor.predict(feature_array)
|
||||
cursor.execute(f"UPDATE {table} SET mwm_size_est = %s WHERE id = %s",
|
||||
(mwm_size_est, border_id))
|
||||
conn.commit()
|
||||
|
|
|
@ -121,7 +121,7 @@
|
|||
<button onclick="bSplit()">Разрезать</button>
|
||||
<button onclick="bJoin()">Склеить</button><br>
|
||||
<button onclick="bJoinToParent()">Склеить всё до родителя</button><br>
|
||||
<button disabled onclick="bLargest()">Выделить острова</button>
|
||||
<button onclick="bLargest()">Выделить острова</button>
|
||||
<button disabled onclick="bHull()">Единый контур</button><br>
|
||||
<button id="b_divide" onclick="bDivide()">Заменить регионами</button><br>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Reference in a new issue