mirror of https://gitlab.com/pamhyr/pamhyr2
Compare commits
No commits in common. "b666162bdf1b64ed7fb741a5ab0a3146d7c7a11f" and "ceff5f3083ce3024e541d91bfd173f93c5eb3bc4" have entirely different histories.
b666162bdf
...
ceff5f3083
Binary file not shown.
|
Before Width: | Height: | Size: 42 KiB |
|
|
@ -1,368 +0,0 @@
|
||||||
# GeoTIFF.py -- Pamhyr
|
|
||||||
# Copyright (C) 2024-2025 INRAE
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import os
|
|
||||||
import struct
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
from tools import trace, timer
|
|
||||||
|
|
||||||
from Model.Tools.PamhyrDB import SQLSubModel
|
|
||||||
from Model.Except import NotImplementedMethodeError
|
|
||||||
from Model.Scenario import Scenario
|
|
||||||
|
|
||||||
try:
|
|
||||||
import rasterio
|
|
||||||
import rasterio.control
|
|
||||||
import rasterio.crs
|
|
||||||
import rasterio.sample
|
|
||||||
import rasterio.vrt
|
|
||||||
import rasterio._features
|
|
||||||
|
|
||||||
from rasterio.io import MemoryFile
|
|
||||||
_rasterio_loaded = True
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Module 'rasterio' is not available: {e}")
|
|
||||||
_rasterio_loaded = False
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
|
||||||
|
|
||||||
|
|
||||||
class GeoTIFF(SQLSubModel):
|
|
||||||
_sub_classes = []
|
|
||||||
|
|
||||||
def __init__(self, id: int = -1, enabled=True,
|
|
||||||
name="", description="",
|
|
||||||
path="", coordinates=None,
|
|
||||||
status=None, owner_scenario=-1):
|
|
||||||
super(GeoTIFF, self).__init__(
|
|
||||||
id=id, status=status,
|
|
||||||
owner_scenario=owner_scenario
|
|
||||||
)
|
|
||||||
|
|
||||||
self._enabled = enabled
|
|
||||||
self._name = f"GeoTIFF #{self._pamhyr_id}" if name == "" else name
|
|
||||||
self._description = description
|
|
||||||
|
|
||||||
self._file_bytes = b''
|
|
||||||
if coordinates is None:
|
|
||||||
self._coordinates = {
|
|
||||||
"bottom": 0.0,
|
|
||||||
"top": 0.0,
|
|
||||||
"left": 0.0,
|
|
||||||
"right": 0.0,
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
self._coordinates = coordinates
|
|
||||||
self._file_name = ""
|
|
||||||
|
|
||||||
if path != "":
|
|
||||||
self.read_file(path)
|
|
||||||
|
|
||||||
self._memfile = None
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
value = None
|
|
||||||
|
|
||||||
if key == "enabled":
|
|
||||||
value = self._enabled
|
|
||||||
elif key == "name":
|
|
||||||
value = self.name
|
|
||||||
elif key == "description":
|
|
||||||
value = self.description
|
|
||||||
elif key == "file_name":
|
|
||||||
value = self.file_name
|
|
||||||
elif key == "coordinates":
|
|
||||||
value = self.coordinates
|
|
||||||
elif key == "coordinates_bottom":
|
|
||||||
value = self.coordinates["bottom"]
|
|
||||||
elif key == "coordinates_top":
|
|
||||||
value = self.coordinates["top"]
|
|
||||||
elif key == "coordinates_left":
|
|
||||||
value = self.coordinates["left"]
|
|
||||||
elif key == "coordinates_right":
|
|
||||||
value = self.coordinates["right"]
|
|
||||||
elif key == "memfile":
|
|
||||||
value = self.memfile
|
|
||||||
|
|
||||||
return value
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
if key == "enabled":
|
|
||||||
self.enabled = value
|
|
||||||
elif key == "name":
|
|
||||||
self.name = value
|
|
||||||
elif key == "description":
|
|
||||||
self.description = value
|
|
||||||
elif key == "file_name":
|
|
||||||
if self._file_name != value:
|
|
||||||
self.read_file(value)
|
|
||||||
elif key == "coordinates":
|
|
||||||
self.coordinates = value
|
|
||||||
elif key == "coordinates_bottom" or key == "bottom":
|
|
||||||
self.coordinates["bottom"] = value
|
|
||||||
elif key == "coordinates_top" or key == "top":
|
|
||||||
self.coordinates["top"] = value
|
|
||||||
elif key == "coordinates_left" or key == "left":
|
|
||||||
self.coordinates["left"] = value
|
|
||||||
elif key == "coordinates_right" or key == "right":
|
|
||||||
self.coordinates["right"] = value
|
|
||||||
|
|
||||||
self.modified()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def enabled(self):
|
|
||||||
return self._enabled
|
|
||||||
|
|
||||||
@enabled.setter
|
|
||||||
def enabled(self, enabled):
|
|
||||||
self._enabled = enabled
|
|
||||||
self.modified()
|
|
||||||
|
|
||||||
def is_enabled(self):
|
|
||||||
return self._enabled
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
@name.setter
|
|
||||||
def name(self, name):
|
|
||||||
self._name = name
|
|
||||||
self.modified()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def description(self):
|
|
||||||
return self._description
|
|
||||||
|
|
||||||
@description.setter
|
|
||||||
def description(self, description):
|
|
||||||
self._description = description
|
|
||||||
self.modified()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def file_name(self):
|
|
||||||
return self._file_name
|
|
||||||
|
|
||||||
@file_name.setter
|
|
||||||
def file_name(self, file_name):
|
|
||||||
self._file_name = file_name
|
|
||||||
self.modified()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def coordinates(self):
|
|
||||||
return self._coordinates
|
|
||||||
|
|
||||||
@coordinates.setter
|
|
||||||
def coordinates(self, coordinates):
|
|
||||||
self._coordinates = coordinates
|
|
||||||
self.modified()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def coord_bottom(self):
|
|
||||||
if self._coordinates is None:
|
|
||||||
return 0.0
|
|
||||||
|
|
||||||
return self._coordinates["bottom"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def coord_top(self):
|
|
||||||
if self._coordinates is None:
|
|
||||||
return 0.0
|
|
||||||
|
|
||||||
return self._coordinates["top"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def coord_left(self):
|
|
||||||
if self._coordinates is None:
|
|
||||||
return 0.0
|
|
||||||
|
|
||||||
return self._coordinates["left"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def coord_right(self):
|
|
||||||
if self._coordinates is None:
|
|
||||||
return 0.0
|
|
||||||
|
|
||||||
return self._coordinates["right"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def memfile(self):
|
|
||||||
if not _rasterio_loaded:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if self._file_bytes == b'':
|
|
||||||
return None
|
|
||||||
|
|
||||||
if self._memfile is None:
|
|
||||||
self._memfile = MemoryFile()
|
|
||||||
self._memfile.write(self._file_bytes)
|
|
||||||
|
|
||||||
return self._memfile
|
|
||||||
|
|
||||||
def read_file(self, path):
|
|
||||||
logger.debug(f"Read GeoTIFF file at : '{path}'")
|
|
||||||
|
|
||||||
self._file_name = path
|
|
||||||
self._file_bytes = b''
|
|
||||||
self._memfile = None
|
|
||||||
|
|
||||||
nbytes = 0
|
|
||||||
|
|
||||||
with open(path, "rb") as f:
|
|
||||||
while True:
|
|
||||||
data = f.read(4096)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
|
|
||||||
nbytes += len(data)
|
|
||||||
self._file_bytes += data
|
|
||||||
|
|
||||||
logger.debug(f"Read GeoTIFF: {nbytes} bytes readed")
|
|
||||||
|
|
||||||
def write_file(self, path):
|
|
||||||
with open(path, "w+b") as f:
|
|
||||||
f.write(self._file_bytes)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _db_create(cls, execute, ext=""):
|
|
||||||
execute(f"""
|
|
||||||
CREATE TABLE geotiff{ext} (
|
|
||||||
{cls.create_db_add_pamhyr_id()},
|
|
||||||
enabled BOOLEAN NOT NULL,
|
|
||||||
deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
description TEXT NOT NULL,
|
|
||||||
file_name TEXT NOT NULL,
|
|
||||||
file_bytes BLOB NOT NULL,
|
|
||||||
coordinates_bottom REAL NOT NULL,
|
|
||||||
coordinates_top REAL NOT NULL,
|
|
||||||
coordinates_left REAL NOT NULL,
|
|
||||||
coordinates_right REAL NOT NULL,
|
|
||||||
{Scenario.create_db_add_scenario()},
|
|
||||||
{Scenario.create_db_add_scenario_fk()},
|
|
||||||
PRIMARY KEY(pamhyr_id, scenario)
|
|
||||||
)
|
|
||||||
""")
|
|
||||||
|
|
||||||
return cls._create_submodel(execute)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _db_update(cls, execute, version, data=None):
|
|
||||||
major, minor, release = version.strip().split(".")
|
|
||||||
|
|
||||||
if major == "0" and int(minor) < 2:
|
|
||||||
cls._db_create(execute)
|
|
||||||
|
|
||||||
if major == "0" and int(minor) == 2:
|
|
||||||
if int(release) < 3:
|
|
||||||
cls._db_create(execute)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _db_load(cls, execute, data=None):
|
|
||||||
new = []
|
|
||||||
scenario = data["scenario"]
|
|
||||||
loaded = data['loaded_pid']
|
|
||||||
|
|
||||||
if scenario is None:
|
|
||||||
return new
|
|
||||||
|
|
||||||
table = execute(
|
|
||||||
"SELECT pamhyr_id, enabled, deleted, " +
|
|
||||||
"name, description, file_name, file_bytes, " +
|
|
||||||
"coordinates_bottom, coordinates_top, " +
|
|
||||||
"coordinates_left, coordinates_right, " +
|
|
||||||
"scenario " +
|
|
||||||
"FROM geotiff " +
|
|
||||||
f"WHERE scenario = {scenario.id} " +
|
|
||||||
f"AND pamhyr_id NOT IN ({', '.join(map(str, loaded))})"
|
|
||||||
)
|
|
||||||
|
|
||||||
if table is not None:
|
|
||||||
for row in table:
|
|
||||||
it = iter(row)
|
|
||||||
|
|
||||||
id = next(it)
|
|
||||||
enabled = (next(it) == 1)
|
|
||||||
deleted = (next(it) == 1)
|
|
||||||
name = next(it)
|
|
||||||
description = next(it)
|
|
||||||
file_name = next(it)
|
|
||||||
file_bytes = next(it)
|
|
||||||
coordinates_bottom = next(it)
|
|
||||||
coordinates_top = next(it)
|
|
||||||
coordinates_left = next(it)
|
|
||||||
coordinates_right = next(it)
|
|
||||||
owner_scenario = next(it)
|
|
||||||
|
|
||||||
f = cls(
|
|
||||||
id=id, enabled=enabled, name=name,
|
|
||||||
description=description, coordinates={
|
|
||||||
"bottom": coordinates_bottom,
|
|
||||||
"top": coordinates_top,
|
|
||||||
"left": coordinates_left,
|
|
||||||
"right": coordinates_right,
|
|
||||||
},
|
|
||||||
status=data['status'],
|
|
||||||
owner_scenario=owner_scenario
|
|
||||||
)
|
|
||||||
if deleted:
|
|
||||||
f.set_as_deleted()
|
|
||||||
|
|
||||||
f._file_bytes = file_bytes
|
|
||||||
|
|
||||||
loaded.add(id)
|
|
||||||
new.append(f)
|
|
||||||
|
|
||||||
data["scenario"] = scenario.parent
|
|
||||||
new += cls._db_load(execute, data)
|
|
||||||
data["scenario"] = scenario
|
|
||||||
|
|
||||||
return new
|
|
||||||
|
|
||||||
def _db_save(self, execute, data=None):
|
|
||||||
if not self.must_be_saved():
|
|
||||||
return True
|
|
||||||
|
|
||||||
execute(
|
|
||||||
"INSERT INTO geotiff (" +
|
|
||||||
"pamhyr_id, enabled, deleted, " +
|
|
||||||
"name, description, file_name, file_bytes, " +
|
|
||||||
"coordinates_bottom, coordinates_top, " +
|
|
||||||
"coordinates_left, coordinates_right, " +
|
|
||||||
"scenario) " +
|
|
||||||
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?)",
|
|
||||||
self._pamhyr_id,
|
|
||||||
self._enabled,
|
|
||||||
self.is_deleted(),
|
|
||||||
self.name,
|
|
||||||
self.description,
|
|
||||||
self.file_name,
|
|
||||||
self._file_bytes,
|
|
||||||
self.coordinates['bottom'],
|
|
||||||
self.coordinates['top'],
|
|
||||||
self.coordinates['left'],
|
|
||||||
self.coordinates['right'],
|
|
||||||
self._status.scenario_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
# GeoTIFFList.py -- Pamhyr
|
|
||||||
# Copyright (C) 2024-2025 INRAE
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from tools import trace, timer
|
|
||||||
|
|
||||||
from Model.Except import NotImplementedMethodeError
|
|
||||||
from Model.Tools.PamhyrListExt import PamhyrModelList
|
|
||||||
from Model.GeoTIFF.GeoTIFF import GeoTIFF
|
|
||||||
|
|
||||||
|
|
||||||
class GeoTIFFList(PamhyrModelList):
|
|
||||||
_sub_classes = [GeoTIFF]
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _db_load(cls, execute, data=None):
|
|
||||||
new = cls(status=data["status"])
|
|
||||||
|
|
||||||
new._lst = GeoTIFF._db_load(execute, data)
|
|
||||||
|
|
||||||
return new
|
|
||||||
|
|
||||||
def _db_save(self, execute, data=None):
|
|
||||||
ok = True
|
|
||||||
|
|
||||||
# Delete previous data
|
|
||||||
execute(
|
|
||||||
"DELETE FROM geotiff " +
|
|
||||||
f"WHERE scenario = {self._status.scenario_id}"
|
|
||||||
)
|
|
||||||
|
|
||||||
for gt in self._lst:
|
|
||||||
ok &= gt._db_save(execute, data)
|
|
||||||
|
|
||||||
return ok
|
|
||||||
|
|
||||||
@property
|
|
||||||
def files(self):
|
|
||||||
return self.lst
|
|
||||||
|
|
||||||
def new(self, index):
|
|
||||||
n = GeoTIFF(status=self._status)
|
|
||||||
self.insert(index, n)
|
|
||||||
self._status.modified()
|
|
||||||
return n
|
|
||||||
|
|
@ -310,7 +310,7 @@ class Reservoir(SQLSubModel):
|
||||||
new_reservoir.set_as_deleted()
|
new_reservoir.set_as_deleted()
|
||||||
|
|
||||||
new_reservoir._node = None
|
new_reservoir._node = None
|
||||||
if node_id != -1 and node_id is not None:
|
if node_id != -1:
|
||||||
new_reservoir._node = next(
|
new_reservoir._node = next(
|
||||||
filter(
|
filter(
|
||||||
lambda n: n.id == node_id, data["nodes"]
|
lambda n: n.id == node_id, data["nodes"]
|
||||||
|
|
|
||||||
|
|
@ -29,134 +29,8 @@ from Model.Results.River.River import River
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
class AdditionalData(SQLSubModel):
|
|
||||||
_sub_classes = []
|
|
||||||
|
|
||||||
def __init__(self, id=-1, study=None, data=None):
|
|
||||||
super(AdditionalData, self).__init__(
|
|
||||||
id=id, status=study.status,
|
|
||||||
owner_scenario=study.status.scenario.id
|
|
||||||
)
|
|
||||||
|
|
||||||
self._study = study
|
|
||||||
self._data = data
|
|
||||||
|
|
||||||
@property
|
|
||||||
def data(self):
|
|
||||||
return self._data
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _db_create(cls, execute, ext=""):
|
|
||||||
execute(f"""
|
|
||||||
CREATE TABLE results_add_data{ext} (
|
|
||||||
{cls.create_db_add_pamhyr_id()},
|
|
||||||
result INTEGER NOT NULL,
|
|
||||||
type_x TEXT NOT NULL,
|
|
||||||
type_y TEXT NOT NULL,
|
|
||||||
legend TEXT NOT NULL,
|
|
||||||
unit TEXT NOT NULL,
|
|
||||||
data_len INTEGER NOT NULL,
|
|
||||||
x BLOB NOT NULL,
|
|
||||||
y BLOB NOT NULL,
|
|
||||||
{Scenario.create_db_add_scenario()},
|
|
||||||
{Scenario.create_db_add_scenario_fk()},
|
|
||||||
FOREIGN KEY(result) REFERENCES results(pamhyr_id),
|
|
||||||
PRIMARY KEY(pamhyr_id, result, scenario)
|
|
||||||
)
|
|
||||||
""")
|
|
||||||
|
|
||||||
if ext != "":
|
|
||||||
return True
|
|
||||||
|
|
||||||
return cls._create_submodel(execute)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _db_update(cls, execute, version, data=None):
|
|
||||||
major, minor, release = version.strip().split(".")
|
|
||||||
|
|
||||||
if major == "0" and int(minor) == 2 and int(release) <= 1:
|
|
||||||
cls._db_create(execute)
|
|
||||||
|
|
||||||
return cls._update_submodel(execute, version, data)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _db_load(cls, execute, data=None):
|
|
||||||
new = []
|
|
||||||
|
|
||||||
study = data['study']
|
|
||||||
status = data['status']
|
|
||||||
scenario = data["scenario"]
|
|
||||||
|
|
||||||
table = execute(
|
|
||||||
"SELECT pamhyr_id, type_x, type_y, " +
|
|
||||||
"legend, unit, data_len, x, y, " +
|
|
||||||
"scenario " +
|
|
||||||
"FROM results_add_data " +
|
|
||||||
f"WHERE scenario = {scenario.id}"
|
|
||||||
)
|
|
||||||
|
|
||||||
if table is None:
|
|
||||||
return new
|
|
||||||
|
|
||||||
for v in table:
|
|
||||||
it = iter(v)
|
|
||||||
|
|
||||||
pid = next(it)
|
|
||||||
type_x = next(it)
|
|
||||||
type_y = next(it)
|
|
||||||
legend = next(it)
|
|
||||||
unit = next(it)
|
|
||||||
data_len = next(it)
|
|
||||||
bx = next(it)
|
|
||||||
by = next(it)
|
|
||||||
owner_scenario = next(it)
|
|
||||||
|
|
||||||
data_format = ">" + ''.join(itertools.repeat("d", data_len))
|
|
||||||
x = struct.unpack(data_format, bx)
|
|
||||||
y = struct.unpack(data_format, by)
|
|
||||||
|
|
||||||
data = {
|
|
||||||
'type_x': type_x,
|
|
||||||
'type_y': type_y,
|
|
||||||
'legend': legend,
|
|
||||||
'unit': unit,
|
|
||||||
'x': x, 'y': y
|
|
||||||
}
|
|
||||||
|
|
||||||
new_data = cls(study=study)
|
|
||||||
new_data._data = data
|
|
||||||
new.append(new_data)
|
|
||||||
|
|
||||||
return new
|
|
||||||
|
|
||||||
def _db_save(self, execute, data=None):
|
|
||||||
if self._status.scenario.id != self._owner_scenario:
|
|
||||||
return
|
|
||||||
|
|
||||||
pid = self._pamhyr_id
|
|
||||||
data_len = len(self._data["x"])
|
|
||||||
|
|
||||||
data_format = ">" + ''.join(itertools.repeat("d", data_len))
|
|
||||||
bx = struct.pack(data_format, *self._data["x"])
|
|
||||||
by = struct.pack(data_format, *self._data["y"])
|
|
||||||
|
|
||||||
execute(
|
|
||||||
"INSERT INTO " +
|
|
||||||
"results_add_data (pamhyr_id, result, " +
|
|
||||||
"type_x, type_y, " +
|
|
||||||
"legend, unit, data_len, x, y, " +
|
|
||||||
"scenario) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
|
||||||
self._pamhyr_id, data["result"],
|
|
||||||
self._data["type_x"], self._data["type_y"],
|
|
||||||
self._data["legend"], self._data["unit"],
|
|
||||||
data_len, bx, by, self._owner_scenario
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class Results(SQLSubModel):
|
class Results(SQLSubModel):
|
||||||
_sub_classes = [River, AdditionalData]
|
_sub_classes = [River]
|
||||||
|
|
||||||
def __init__(self, id=-1, study=None, solver=None,
|
def __init__(self, id=-1, study=None, solver=None,
|
||||||
repertory="", name="0"):
|
repertory="", name="0"):
|
||||||
|
|
@ -176,7 +50,6 @@ class Results(SQLSubModel):
|
||||||
# Keep results creation date
|
# Keep results creation date
|
||||||
"creation_date": datetime.now(),
|
"creation_date": datetime.now(),
|
||||||
"study_revision": study.status.version,
|
"study_revision": study.status.version,
|
||||||
"additional_data": [],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if solver is not None:
|
if solver is not None:
|
||||||
|
|
@ -311,11 +184,6 @@ class Results(SQLSubModel):
|
||||||
data["timestamps"] = sorted(ts)
|
data["timestamps"] = sorted(ts)
|
||||||
new_results._river = River._db_load(execute, data)
|
new_results._river = River._db_load(execute, data)
|
||||||
|
|
||||||
new_results.set(
|
|
||||||
"additional_data",
|
|
||||||
AdditionalData._db_load(execute, data)
|
|
||||||
)
|
|
||||||
|
|
||||||
yield (solver_type, new_results)
|
yield (solver_type, new_results)
|
||||||
|
|
||||||
def _db_save_clear(self, execute, solver_type, data=None):
|
def _db_save_clear(self, execute, solver_type, data=None):
|
||||||
|
|
@ -338,11 +206,6 @@ class Results(SQLSubModel):
|
||||||
f"WHERE scenario = {self._owner_scenario} " +
|
f"WHERE scenario = {self._owner_scenario} " +
|
||||||
f"AND result = {pid}"
|
f"AND result = {pid}"
|
||||||
)
|
)
|
||||||
execute(
|
|
||||||
"DELETE FROM results_add_data " +
|
|
||||||
f"WHERE scenario = {self._owner_scenario} " +
|
|
||||||
f"AND result = {pid}"
|
|
||||||
)
|
|
||||||
|
|
||||||
def _db_save(self, execute, data=None):
|
def _db_save(self, execute, data=None):
|
||||||
if self._status.scenario.id != self._owner_scenario:
|
if self._status.scenario.id != self._owner_scenario:
|
||||||
|
|
@ -375,7 +238,4 @@ class Results(SQLSubModel):
|
||||||
data["result"] = self._pamhyr_id
|
data["result"] = self._pamhyr_id
|
||||||
self._river._db_save(execute, data)
|
self._river._db_save(execute, data)
|
||||||
|
|
||||||
for add_data in self.get("additional_data"):
|
|
||||||
add_data._db_save(execute, data)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,16 @@ class Profile(SQLSubModel):
|
||||||
@classmethod
|
@classmethod
|
||||||
def _db_update(cls, execute, version, data=None):
|
def _db_update(cls, execute, version, data=None):
|
||||||
major, minor, release = version.strip().split(".")
|
major, minor, release = version.strip().split(".")
|
||||||
|
create = False
|
||||||
|
|
||||||
|
if major == "0" and int(minor) < 2:
|
||||||
|
cls._db_create(execute)
|
||||||
|
create = True
|
||||||
|
|
||||||
|
if major == "0" and int(minor) == 2:
|
||||||
|
if int(release) < 1 and not create:
|
||||||
|
cls._db_create(execute)
|
||||||
|
create = True
|
||||||
|
|
||||||
return cls._update_submodel(execute, version, data)
|
return cls._update_submodel(execute, version, data)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,6 @@ from Model.LateralContributionsAdisTS.LateralContributionsAdisTSList \
|
||||||
import LateralContributionsAdisTSList
|
import LateralContributionsAdisTSList
|
||||||
from Model.D90AdisTS.D90AdisTSList import D90AdisTSList
|
from Model.D90AdisTS.D90AdisTSList import D90AdisTSList
|
||||||
from Model.DIFAdisTS.DIFAdisTSList import DIFAdisTSList
|
from Model.DIFAdisTS.DIFAdisTSList import DIFAdisTSList
|
||||||
from Model.GeoTIFF.GeoTIFFList import GeoTIFFList
|
|
||||||
from Model.Results.Results import Results
|
from Model.Results.Results import Results
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
@ -469,7 +468,6 @@ class River(Graph):
|
||||||
LateralContributionsAdisTSList,
|
LateralContributionsAdisTSList,
|
||||||
D90AdisTSList,
|
D90AdisTSList,
|
||||||
DIFAdisTSList,
|
DIFAdisTSList,
|
||||||
GeoTIFFList,
|
|
||||||
Results
|
Results
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -507,8 +505,6 @@ class River(Graph):
|
||||||
self._D90AdisTS = D90AdisTSList(status=self._status)
|
self._D90AdisTS = D90AdisTSList(status=self._status)
|
||||||
self._DIFAdisTS = DIFAdisTSList(status=self._status)
|
self._DIFAdisTS = DIFAdisTSList(status=self._status)
|
||||||
|
|
||||||
self._geotiff = GeoTIFFList(status=self._status)
|
|
||||||
|
|
||||||
self._results = {}
|
self._results = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -621,8 +617,6 @@ class River(Graph):
|
||||||
|
|
||||||
new._DIFAdisTS = DIFAdisTSList._db_load(execute, data)
|
new._DIFAdisTS = DIFAdisTSList._db_load(execute, data)
|
||||||
|
|
||||||
new._geotiff = GeoTIFFList._db_load(execute, data)
|
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
def _db_load_results(self, execute, data=None):
|
def _db_load_results(self, execute, data=None):
|
||||||
|
|
@ -656,8 +650,6 @@ class River(Graph):
|
||||||
objs.append(self._D90AdisTS)
|
objs.append(self._D90AdisTS)
|
||||||
objs.append(self._DIFAdisTS)
|
objs.append(self._DIFAdisTS)
|
||||||
|
|
||||||
objs.append(self._geotiff)
|
|
||||||
|
|
||||||
for solv_type in self.results:
|
for solv_type in self.results:
|
||||||
objs.append(self.results[solv_type])
|
objs.append(self.results[solv_type])
|
||||||
|
|
||||||
|
|
@ -734,7 +726,6 @@ class River(Graph):
|
||||||
self._BoundaryConditionsAdisTS,
|
self._BoundaryConditionsAdisTS,
|
||||||
self._LateralContributionsAdisTS,
|
self._LateralContributionsAdisTS,
|
||||||
self._D90AdisTS, self._DIFAdisTS,
|
self._D90AdisTS, self._DIFAdisTS,
|
||||||
self._geotiff,
|
|
||||||
]
|
]
|
||||||
|
|
||||||
for solver in self._parameters:
|
for solver in self._parameters:
|
||||||
|
|
@ -827,10 +818,6 @@ Last export at: @date."""
|
||||||
def additional_files(self):
|
def additional_files(self):
|
||||||
return self._additional_files
|
return self._additional_files
|
||||||
|
|
||||||
@property
|
|
||||||
def geotiff(self):
|
|
||||||
return self._geotiff
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rep_lines(self):
|
def rep_lines(self):
|
||||||
return self._rep_lines
|
return self._rep_lines
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
class Study(SQLModel):
|
class Study(SQLModel):
|
||||||
_version = "0.2.3"
|
_version = "0.2.1"
|
||||||
|
|
||||||
_sub_classes = [
|
_sub_classes = [
|
||||||
Scenario,
|
Scenario,
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@ class Modules(IterableFlag):
|
||||||
SEDIMENT_LAYER = auto()
|
SEDIMENT_LAYER = auto()
|
||||||
ADDITIONAL_FILES = auto()
|
ADDITIONAL_FILES = auto()
|
||||||
OUTPUT_RK = auto()
|
OUTPUT_RK = auto()
|
||||||
GEOTIFF = auto()
|
|
||||||
|
|
||||||
# Results
|
# Results
|
||||||
RESULTS = auto()
|
RESULTS = auto()
|
||||||
|
|
@ -82,7 +81,6 @@ class Modules(IterableFlag):
|
||||||
cls.RESULTS,
|
cls.RESULTS,
|
||||||
cls.WINDOW_LIST,
|
cls.WINDOW_LIST,
|
||||||
cls.OUTPUT_RK,
|
cls.OUTPUT_RK,
|
||||||
cls.GEOTIFF
|
|
||||||
]
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -101,7 +99,6 @@ class Modules(IterableFlag):
|
||||||
| cls.HYDRAULIC_STRUCTURES
|
| cls.HYDRAULIC_STRUCTURES
|
||||||
| cls.RESERVOIR
|
| cls.RESERVOIR
|
||||||
| cls.SEDIMENT_LAYER
|
| cls.SEDIMENT_LAYER
|
||||||
| cls.GEOTIFF
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -117,7 +114,6 @@ class Modules(IterableFlag):
|
||||||
cls.HYDRAULIC_STRUCTURES,
|
cls.HYDRAULIC_STRUCTURES,
|
||||||
cls.RESERVOIR,
|
cls.RESERVOIR,
|
||||||
cls.SEDIMENT_LAYER,
|
cls.SEDIMENT_LAYER,
|
||||||
cls.GEOTIFF,
|
|
||||||
]
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -133,7 +129,6 @@ class Modules(IterableFlag):
|
||||||
cls.HYDRAULIC_STRUCTURES: "Hydraulic structures",
|
cls.HYDRAULIC_STRUCTURES: "Hydraulic structures",
|
||||||
cls.RESERVOIR: "Reservoir",
|
cls.RESERVOIR: "Reservoir",
|
||||||
cls.SEDIMENT_LAYER: "Sediment layer",
|
cls.SEDIMENT_LAYER: "Sediment layer",
|
||||||
cls.GEOTIFF: "GeoTIFF",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def impact(self):
|
def impact(self):
|
||||||
|
|
@ -173,5 +168,4 @@ _impact = {
|
||||||
Modules.HYDRAULIC_STRUCTURES: [],
|
Modules.HYDRAULIC_STRUCTURES: [],
|
||||||
Modules.RESERVOIR: [],
|
Modules.RESERVOIR: [],
|
||||||
Modules.SEDIMENT_LAYER: [],
|
Modules.SEDIMENT_LAYER: [],
|
||||||
Modules.GEOTIFF: [],
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
|
||||||
|
|
||||||
from tools import trace, timer
|
from tools import trace, timer
|
||||||
|
|
||||||
|
|
@ -93,8 +92,7 @@ class ReplWindow(PamhyrWindow):
|
||||||
value = exec(rich_code)
|
value = exec(rich_code)
|
||||||
value = self.__debug_exec_result__
|
value = self.__debug_exec_result__
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
value = f"<font color=\"red\">" + str(e) + "</font>\n"
|
value = f"<font color=\"red\">" + str(e) + "</font>"
|
||||||
value += f"<font color=\"grey\">{traceback.format_exc()}</font>"
|
|
||||||
|
|
||||||
# Display code
|
# Display code
|
||||||
msg = f"<font color=\"grey\"> # " + code + " #</font>"
|
msg = f"<font color=\"grey\"> # " + code + " #</font>"
|
||||||
|
|
|
||||||
|
|
@ -1,289 +0,0 @@
|
||||||
# Window.py -- Pamhyr
|
|
||||||
# Copyright (C) 2024-2025 INRAE
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from Modules import Modules
|
|
||||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
|
||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
|
||||||
QLabel, QPlainTextEdit, QPushButton, QCheckBox,
|
|
||||||
QFileDialog, QVBoxLayout, QDoubleSpinBox,
|
|
||||||
)
|
|
||||||
|
|
||||||
from PyQt5.QtCore import (
|
|
||||||
QSettings
|
|
||||||
)
|
|
||||||
|
|
||||||
from View.GeoTIFF.Translate import GeoTIFFTranslate
|
|
||||||
from View.GeoTIFF.UndoCommand import (
|
|
||||||
SetCommand
|
|
||||||
)
|
|
||||||
|
|
||||||
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
|
||||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
|
||||||
from View.PlotXY import PlotXY
|
|
||||||
|
|
||||||
try:
|
|
||||||
import rasterio
|
|
||||||
import rasterio.control
|
|
||||||
import rasterio.crs
|
|
||||||
import rasterio.sample
|
|
||||||
import rasterio.vrt
|
|
||||||
import rasterio._features
|
|
||||||
|
|
||||||
from rasterio.io import MemoryFile
|
|
||||||
_rasterio_loaded = True
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Module 'rasterio' is not available: {e}")
|
|
||||||
_rasterio_loaded = False
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
|
||||||
|
|
||||||
|
|
||||||
class EditGeoTIFFWindow(PamhyrWindow):
|
|
||||||
_pamhyr_ui = "GeoTIFF"
|
|
||||||
_pamhyr_name = "Edit GeoTIFF"
|
|
||||||
|
|
||||||
def __init__(self, study=None, config=None, geotiff=None,
|
|
||||||
trad=None, undo=None, parent=None):
|
|
||||||
|
|
||||||
super(EditGeoTIFFWindow, self).__init__(
|
|
||||||
title=self._pamhyr_name,
|
|
||||||
study=study,
|
|
||||||
config=config,
|
|
||||||
trad=trad,
|
|
||||||
options=[],
|
|
||||||
parent=parent
|
|
||||||
)
|
|
||||||
|
|
||||||
self._geotiff = geotiff
|
|
||||||
self._file_name = geotiff.file_name
|
|
||||||
|
|
||||||
self._hash_data.append(self._geotiff)
|
|
||||||
|
|
||||||
self._undo = undo
|
|
||||||
|
|
||||||
self.setup_values()
|
|
||||||
self.setup_graph()
|
|
||||||
self.setup_connection()
|
|
||||||
|
|
||||||
def setup_graph(self):
|
|
||||||
self.canvas = MplCanvas(width=5, height=4, dpi=100)
|
|
||||||
self.canvas.setObjectName("canvas")
|
|
||||||
self.plot_layout = self.find(QVBoxLayout,
|
|
||||||
"verticalLayout_geotiff")
|
|
||||||
self._toolbar = PamhyrPlotToolbar(
|
|
||||||
self.canvas, self,
|
|
||||||
items=["home", "zoom", "save", "iso", "back/forward", "move"]
|
|
||||||
)
|
|
||||||
self.plot_layout.addWidget(self._toolbar)
|
|
||||||
self.plot_layout.addWidget(self.canvas)
|
|
||||||
|
|
||||||
self.plot = PlotXY(
|
|
||||||
canvas=self.canvas,
|
|
||||||
data=self._study.river.enable_edges(),
|
|
||||||
trad=self._trad,
|
|
||||||
toolbar=None,
|
|
||||||
parent=self
|
|
||||||
)
|
|
||||||
self.plot.update()
|
|
||||||
|
|
||||||
self._plot_img = None
|
|
||||||
|
|
||||||
memfile = self._geotiff.memfile
|
|
||||||
if memfile is not None:
|
|
||||||
self.draw_geotiff(memfile=memfile)
|
|
||||||
|
|
||||||
def setup_values(self):
|
|
||||||
self.set_check_box("checkBox", self._geotiff.enabled)
|
|
||||||
self.set_line_edit_text("lineEdit_name", self._geotiff.name)
|
|
||||||
self.set_line_edit_text("lineEdit_description",
|
|
||||||
self._geotiff.description)
|
|
||||||
|
|
||||||
bounds = list(self._geotiff.coordinates.values())
|
|
||||||
self._set_values_from_bounds(bounds)
|
|
||||||
self._set_default_values_from_bounds(bounds)
|
|
||||||
self._reset_spinboxes()
|
|
||||||
|
|
||||||
if self._study.is_read_only():
|
|
||||||
self.set_check_box_enable("checkBox", False)
|
|
||||||
self.set_line_edit_enable("lineEdit_name", False)
|
|
||||||
self.set_line_edit_enable("lineEdit_path", False)
|
|
||||||
self.set_plaintext_edit_enable("plainTextEdit", False)
|
|
||||||
|
|
||||||
def _set_values_from_bounds(self, bounds):
|
|
||||||
self._values = {
|
|
||||||
"bottom": bounds[0],
|
|
||||||
"top": bounds[1],
|
|
||||||
"left": bounds[2],
|
|
||||||
"right": bounds[3],
|
|
||||||
}
|
|
||||||
|
|
||||||
def _set_default_values_from_bounds(self, bounds):
|
|
||||||
self._values_default = {
|
|
||||||
"bottom": bounds[0],
|
|
||||||
"top": bounds[1],
|
|
||||||
"left": bounds[2],
|
|
||||||
"right": bounds[3],
|
|
||||||
}
|
|
||||||
|
|
||||||
def _reset_spinboxes(self):
|
|
||||||
for key in self._values:
|
|
||||||
self._reset_spinbox(key)
|
|
||||||
|
|
||||||
def _reset_spinbox(self, key):
|
|
||||||
self.set_double_spin_box(
|
|
||||||
f"doubleSpinBox_{key}", self._values_default[key]
|
|
||||||
)
|
|
||||||
|
|
||||||
def setup_connection(self):
|
|
||||||
self.find(QPushButton, "pushButton_cancel")\
|
|
||||||
.clicked.connect(self.close)
|
|
||||||
self.find(QPushButton, "pushButton_ok")\
|
|
||||||
.clicked.connect(self.accept)
|
|
||||||
self.find(QPushButton, "pushButton_import")\
|
|
||||||
.clicked.connect(self._import)
|
|
||||||
|
|
||||||
self.find(QPushButton, "pushButton_bottom")\
|
|
||||||
.clicked.connect(lambda: self._reset_spinbox("bottom"))
|
|
||||||
self.find(QPushButton, "pushButton_top")\
|
|
||||||
.clicked.connect(lambda: self._reset_spinbox("top"))
|
|
||||||
self.find(QPushButton, f"pushButton_left")\
|
|
||||||
.clicked.connect(lambda: self._reset_spinbox("left"))
|
|
||||||
self.find(QPushButton, f"pushButton_right")\
|
|
||||||
.clicked.connect(lambda: self._reset_spinbox("right"))
|
|
||||||
|
|
||||||
self.find(QDoubleSpinBox, f"doubleSpinBox_bottom")\
|
|
||||||
.valueChanged.connect(
|
|
||||||
lambda: self.update_values_from_spinbox("bottom")
|
|
||||||
)
|
|
||||||
self.find(QDoubleSpinBox, f"doubleSpinBox_top")\
|
|
||||||
.valueChanged.connect(
|
|
||||||
lambda: self.update_values_from_spinbox("top")
|
|
||||||
)
|
|
||||||
self.find(QDoubleSpinBox, f"doubleSpinBox_left")\
|
|
||||||
.valueChanged.connect(
|
|
||||||
lambda: self.update_values_from_spinbox("left")
|
|
||||||
)
|
|
||||||
self.find(QDoubleSpinBox, f"doubleSpinBox_right")\
|
|
||||||
.valueChanged.connect(
|
|
||||||
lambda: self.update_values_from_spinbox("right")
|
|
||||||
)
|
|
||||||
|
|
||||||
def update_values_from_spinbox(self, key):
|
|
||||||
self._values[key] = self.get_double_spin_box(f"doubleSpinBox_{key}")
|
|
||||||
|
|
||||||
left = self._values["left"]
|
|
||||||
right = self._values["right"]
|
|
||||||
bottom = self._values["bottom"]
|
|
||||||
top = self._values["top"]
|
|
||||||
|
|
||||||
self._plot_img.set_extent((left, right, bottom, top))
|
|
||||||
self.plot.idle()
|
|
||||||
|
|
||||||
def draw_geotiff(self, memfile=None):
|
|
||||||
if not _rasterio_loaded:
|
|
||||||
return
|
|
||||||
|
|
||||||
if memfile is None:
|
|
||||||
if self._file_name == "":
|
|
||||||
return
|
|
||||||
|
|
||||||
with rasterio.open(self._file_name) as data:
|
|
||||||
img = data.read()
|
|
||||||
b = data.bounds[:] # left, bottom, right, top
|
|
||||||
|
|
||||||
if b[2] > b[0] and b[1] < b[3]:
|
|
||||||
coord = [b[1], b[3], b[0], b[2]]
|
|
||||||
else:
|
|
||||||
xlim = self.canvas.axes.get_xlim()
|
|
||||||
ylim = self.canvas.axes.get_ylim()
|
|
||||||
coord = ylim + xlim
|
|
||||||
|
|
||||||
self._set_values_from_bounds(coord)
|
|
||||||
self._set_default_values_from_bounds(coord)
|
|
||||||
else:
|
|
||||||
with memfile.open() as gt:
|
|
||||||
img = gt.read()
|
|
||||||
|
|
||||||
if self._plot_img is not None:
|
|
||||||
self._plot_img.remove()
|
|
||||||
|
|
||||||
left = self._values["left"]
|
|
||||||
right = self._values["right"]
|
|
||||||
bottom = self._values["bottom"]
|
|
||||||
top = self._values["top"]
|
|
||||||
|
|
||||||
self._plot_img = self.canvas.axes.imshow(
|
|
||||||
img.transpose((1, 2, 0)),
|
|
||||||
extent=(left, right, bottom, top)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.plot.idle()
|
|
||||||
self._reset_spinboxes()
|
|
||||||
|
|
||||||
def _import(self):
|
|
||||||
options = QFileDialog.Options()
|
|
||||||
settings = QSettings(QSettings.IniFormat,
|
|
||||||
QSettings.UserScope, 'MyOrg', )
|
|
||||||
options |= QFileDialog.DontUseNativeDialog
|
|
||||||
|
|
||||||
file_types = [
|
|
||||||
self._trad["file_geotiff"],
|
|
||||||
self._trad["file_all"],
|
|
||||||
]
|
|
||||||
|
|
||||||
filename, _ = QFileDialog.getOpenFileName(
|
|
||||||
self,
|
|
||||||
self._trad["open_file"],
|
|
||||||
"",
|
|
||||||
";; ".join(file_types),
|
|
||||||
options=options
|
|
||||||
)
|
|
||||||
|
|
||||||
if filename != "":
|
|
||||||
self._file_name = filename
|
|
||||||
self.draw_geotiff()
|
|
||||||
|
|
||||||
def accept(self):
|
|
||||||
if self._study.is_editable():
|
|
||||||
is_enabled = self.get_check_box("checkBox")
|
|
||||||
name = self.get_line_edit_text("lineEdit_name")
|
|
||||||
description = self.get_line_edit_text("lineEdit_description")
|
|
||||||
|
|
||||||
coord_bottom = self.get_double_spin_box("doubleSpinBox_bottom")
|
|
||||||
coord_top = self.get_double_spin_box("doubleSpinBox_top")
|
|
||||||
coord_left = self.get_double_spin_box("doubleSpinBox_left")
|
|
||||||
coord_right = self.get_double_spin_box("doubleSpinBox_right")
|
|
||||||
|
|
||||||
self._undo.push(
|
|
||||||
SetCommand(
|
|
||||||
self._geotiff, enabled=is_enabled,
|
|
||||||
name=name, description=description,
|
|
||||||
coordinates_bottom=coord_bottom,
|
|
||||||
coordinates_top=coord_top,
|
|
||||||
coordinates_left=coord_left,
|
|
||||||
coordinates_right=coord_right,
|
|
||||||
file_name=self._file_name,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
self._propagate_update(key=Modules.GEOTIFF)
|
|
||||||
|
|
||||||
self.close()
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
# List.py -- Pamhyr
|
|
||||||
# Copyright (C) 2024-2025 INRAE
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from functools import reduce
|
|
||||||
from tools import trace, timer
|
|
||||||
|
|
||||||
from PyQt5.QtCore import (
|
|
||||||
Qt, QVariant,
|
|
||||||
)
|
|
||||||
|
|
||||||
from PyQt5.QtGui import (
|
|
||||||
QColor, QBrush,
|
|
||||||
)
|
|
||||||
|
|
||||||
from View.Tools.PamhyrList import PamhyrListModel
|
|
||||||
from View.GeoTIFF.UndoCommand import (
|
|
||||||
AddCommand, DelCommand
|
|
||||||
)
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
|
||||||
|
|
||||||
|
|
||||||
class ListModel(PamhyrListModel):
|
|
||||||
def get_true_data_row(self, row):
|
|
||||||
el = self._data.get(row)
|
|
||||||
|
|
||||||
return next(
|
|
||||||
map(
|
|
||||||
lambda e: e[0],
|
|
||||||
filter(
|
|
||||||
lambda e: e[1] == el,
|
|
||||||
enumerate(self._data._lst)
|
|
||||||
)
|
|
||||||
), 0
|
|
||||||
)
|
|
||||||
|
|
||||||
def data(self, index, role):
|
|
||||||
row = index.row()
|
|
||||||
column = index.column()
|
|
||||||
|
|
||||||
file = self._data.files[row]
|
|
||||||
|
|
||||||
if role == Qt.ForegroundRole:
|
|
||||||
color = Qt.gray
|
|
||||||
|
|
||||||
if file.is_enabled():
|
|
||||||
color = QColor("black")
|
|
||||||
else:
|
|
||||||
color = QColor("grey")
|
|
||||||
|
|
||||||
return QBrush(color)
|
|
||||||
|
|
||||||
if role == Qt.ItemDataRole.DisplayRole:
|
|
||||||
text = f"{file.name}: '{file.description}'"
|
|
||||||
|
|
||||||
if not file.is_enabled():
|
|
||||||
text += " (disabled)"
|
|
||||||
|
|
||||||
return text
|
|
||||||
|
|
||||||
return QVariant()
|
|
||||||
|
|
||||||
def add(self, row):
|
|
||||||
row = self.get_true_data_row(row)
|
|
||||||
|
|
||||||
self._undo.push(
|
|
||||||
AddCommand(
|
|
||||||
self._data, row
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
def delete(self, row):
|
|
||||||
self._undo.push(
|
|
||||||
DelCommand(
|
|
||||||
self._data, self._data.files[row]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.update()
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
# Translate.py -- Pamhyr
|
|
||||||
# Copyright (C) 2024-2025 INRAE
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from PyQt5.QtCore import QCoreApplication
|
|
||||||
from View.Translate import MainTranslate
|
|
||||||
|
|
||||||
_translate = QCoreApplication.translate
|
|
||||||
|
|
||||||
|
|
||||||
class GeoTIFFTranslate(MainTranslate):
|
|
||||||
def __init__(self):
|
|
||||||
super(GeoTIFFTranslate, self).__init__()
|
|
||||||
|
|
||||||
self._dict["GeoTIFF files"] = _translate(
|
|
||||||
"GeoTIFF", "GeoTIFF files"
|
|
||||||
)
|
|
||||||
|
|
||||||
self._dict["Edit additional file"] = _translate(
|
|
||||||
"GeoTIFF", "Edit GeoTIFF file"
|
|
||||||
)
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
# UndoCommand.py -- Pamhyr
|
|
||||||
# Copyright (C) 2024-2025 INRAE
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from tools import trace, timer
|
|
||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
|
||||||
QMessageBox, QUndoCommand, QUndoStack,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SetCommand(QUndoCommand):
|
|
||||||
def __init__(self, geotiff, **kwargs):
|
|
||||||
QUndoCommand.__init__(self)
|
|
||||||
|
|
||||||
self._geotiff = geotiff
|
|
||||||
self._new = kwargs
|
|
||||||
self._old = None
|
|
||||||
|
|
||||||
def undo(self):
|
|
||||||
f = self._geotiff
|
|
||||||
|
|
||||||
for key in self._old:
|
|
||||||
f[key] = self._old[key]
|
|
||||||
|
|
||||||
def redo(self):
|
|
||||||
f = self._geotiff
|
|
||||||
|
|
||||||
if self._old is None:
|
|
||||||
self._old = {}
|
|
||||||
for key in self._new:
|
|
||||||
self._old[key] = f[key]
|
|
||||||
|
|
||||||
for key in self._new:
|
|
||||||
f[key] = self._new[key]
|
|
||||||
|
|
||||||
|
|
||||||
class AddCommand(QUndoCommand):
|
|
||||||
def __init__(self, files, row):
|
|
||||||
QUndoCommand.__init__(self)
|
|
||||||
|
|
||||||
self._files = files
|
|
||||||
self._row = row
|
|
||||||
self._new = None
|
|
||||||
|
|
||||||
def undo(self):
|
|
||||||
self._new.set_as_deleted()
|
|
||||||
|
|
||||||
def redo(self):
|
|
||||||
if self._new is None:
|
|
||||||
self._new = self._files.new(self._row)
|
|
||||||
else:
|
|
||||||
self._new.set_as_not_deleted()
|
|
||||||
|
|
||||||
|
|
||||||
class DelCommand(QUndoCommand):
|
|
||||||
def __init__(self, files, line):
|
|
||||||
QUndoCommand.__init__(self)
|
|
||||||
|
|
||||||
self._files = files
|
|
||||||
self._line = line
|
|
||||||
|
|
||||||
def undo(self):
|
|
||||||
self._line.set_as_not_deleted()
|
|
||||||
|
|
||||||
def redo(self):
|
|
||||||
self._line.set_as_deleted()
|
|
||||||
|
|
@ -1,217 +0,0 @@
|
||||||
# Window.py -- Pamhyr
|
|
||||||
# Copyright (C) 2024-2025 INRAE
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from tools import trace, timer
|
|
||||||
|
|
||||||
from PyQt5.QtWidgets import (
|
|
||||||
QAction, QListView, QVBoxLayout,
|
|
||||||
)
|
|
||||||
|
|
||||||
from matplotlib.patches import Rectangle
|
|
||||||
|
|
||||||
from Modules import Modules
|
|
||||||
|
|
||||||
from View.Tools.PamhyrWindow import PamhyrWindow
|
|
||||||
|
|
||||||
from View.GeoTIFF.List import ListModel
|
|
||||||
from View.GeoTIFF.Translate import GeoTIFFTranslate
|
|
||||||
from View.GeoTIFF.Edit.Window import EditGeoTIFFWindow
|
|
||||||
|
|
||||||
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
|
||||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
|
||||||
from View.PlotXY import PlotXY
|
|
||||||
|
|
||||||
try:
|
|
||||||
import rasterio
|
|
||||||
import rasterio.control
|
|
||||||
import rasterio.crs
|
|
||||||
import rasterio.sample
|
|
||||||
import rasterio.vrt
|
|
||||||
import rasterio._features
|
|
||||||
|
|
||||||
from rasterio.io import MemoryFile
|
|
||||||
_rasterio_loaded = True
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Module 'rasterio' is not available: {e}")
|
|
||||||
_rasterio_loaded = False
|
|
||||||
|
|
||||||
|
|
||||||
class GeoTIFFListWindow(PamhyrWindow):
|
|
||||||
_pamhyr_ui = "GeoTIFFList"
|
|
||||||
_pamhyr_name = "GeoTIFF files"
|
|
||||||
|
|
||||||
def __init__(self, study=None, config=None,
|
|
||||||
parent=None):
|
|
||||||
trad = GeoTIFFTranslate()
|
|
||||||
name = trad[self._pamhyr_name] + " - " + study.name
|
|
||||||
|
|
||||||
super(GeoTIFFListWindow, self).__init__(
|
|
||||||
title=name,
|
|
||||||
study=study,
|
|
||||||
config=config,
|
|
||||||
trad=trad,
|
|
||||||
options=[],
|
|
||||||
parent=parent
|
|
||||||
)
|
|
||||||
|
|
||||||
self.setup_list()
|
|
||||||
self.setup_graph()
|
|
||||||
self.setup_connections()
|
|
||||||
|
|
||||||
def setup_list(self):
|
|
||||||
lst = self.find(QListView, "listView")
|
|
||||||
self._list = ListModel(
|
|
||||||
list_view=lst,
|
|
||||||
data=self._study.river.geotiff,
|
|
||||||
undo=self._undo_stack,
|
|
||||||
trad=self._trad,
|
|
||||||
)
|
|
||||||
|
|
||||||
def setup_graph(self):
|
|
||||||
self.canvas = MplCanvas(width=5, height=4, dpi=100)
|
|
||||||
self.canvas.setObjectName("canvas")
|
|
||||||
self._plot_layout = self.find(QVBoxLayout, "verticalLayout")
|
|
||||||
self._toolbar = PamhyrPlotToolbar(
|
|
||||||
self.canvas, self,
|
|
||||||
items=["home", "zoom", "save", "iso", "back/forward", "move"]
|
|
||||||
)
|
|
||||||
self._plot_layout.addWidget(self._toolbar)
|
|
||||||
self._plot_layout.addWidget(self.canvas)
|
|
||||||
|
|
||||||
self._plot = PlotXY(
|
|
||||||
canvas=self.canvas,
|
|
||||||
data=self._study.river.enable_edges(),
|
|
||||||
geotiff=self._study.river.geotiff,
|
|
||||||
trad=self._trad,
|
|
||||||
toolbar=None,
|
|
||||||
parent=self
|
|
||||||
)
|
|
||||||
self._plot_rect = []
|
|
||||||
|
|
||||||
self._plot.update()
|
|
||||||
|
|
||||||
def setup_connections(self):
|
|
||||||
if self._study.is_editable():
|
|
||||||
self.find(QAction, "action_add").triggered.connect(self.add)
|
|
||||||
self.find(QAction, "action_delete").triggered.connect(self.delete)
|
|
||||||
|
|
||||||
self.find(QAction, "action_edit").triggered.connect(self.edit)
|
|
||||||
|
|
||||||
self.find(QListView, "listView")\
|
|
||||||
.selectionModel()\
|
|
||||||
.selectionChanged\
|
|
||||||
.connect(self._update_rectangle)
|
|
||||||
|
|
||||||
def _propagated_update(self, key=Modules(0)):
|
|
||||||
if Modules.GEOMETRY not in key and Modules.GEOTIFF not in key:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
self._list.update()
|
|
||||||
self._plot.update()
|
|
||||||
|
|
||||||
self._update_rectangle()
|
|
||||||
|
|
||||||
def _update_rectangle(self):
|
|
||||||
for rect in self._plot_rect:
|
|
||||||
rect.remove()
|
|
||||||
|
|
||||||
self._plot_rect = []
|
|
||||||
|
|
||||||
rows = self.selected_rows()
|
|
||||||
if len(rows) <= 0:
|
|
||||||
return
|
|
||||||
|
|
||||||
for row in rows:
|
|
||||||
files = self._study.river.geotiff.files
|
|
||||||
if len(files) <= row:
|
|
||||||
continue
|
|
||||||
|
|
||||||
geotiff = files[row]
|
|
||||||
coord = geotiff.coordinates
|
|
||||||
|
|
||||||
xy = (coord["left"], coord["bottom"])
|
|
||||||
width = abs(coord["right"] - coord["left"])
|
|
||||||
height = abs(coord["top"] - coord["bottom"])
|
|
||||||
|
|
||||||
rect = Rectangle(
|
|
||||||
xy, width, height,
|
|
||||||
edgecolor='red', facecolor='none',
|
|
||||||
lw=2
|
|
||||||
)
|
|
||||||
|
|
||||||
self._plot_rect.append(rect)
|
|
||||||
|
|
||||||
self.canvas.axes.add_patch(
|
|
||||||
rect
|
|
||||||
)
|
|
||||||
|
|
||||||
self._plot.idle()
|
|
||||||
|
|
||||||
def selected_rows(self):
|
|
||||||
lst = self.find(QListView, f"listView")
|
|
||||||
return list(map(lambda i: i.row(), lst.selectedIndexes()))
|
|
||||||
|
|
||||||
def add(self):
|
|
||||||
rows = self.selected_rows()
|
|
||||||
if len(rows) > 0:
|
|
||||||
row = rows[0]
|
|
||||||
else:
|
|
||||||
row = 0
|
|
||||||
|
|
||||||
self._list.add(row)
|
|
||||||
|
|
||||||
def delete(self):
|
|
||||||
rows = self.selected_rows()
|
|
||||||
if len(rows) == 0:
|
|
||||||
return
|
|
||||||
|
|
||||||
self._list.delete(rows[0])
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
def edit(self):
|
|
||||||
rows = self.selected_rows()
|
|
||||||
|
|
||||||
for row in rows:
|
|
||||||
geotiff = self._study.river.geotiff.files[row]
|
|
||||||
|
|
||||||
if self.sub_window_exists(
|
|
||||||
EditGeoTIFFWindow,
|
|
||||||
data=[self._study, self._config, geotiff]
|
|
||||||
):
|
|
||||||
continue
|
|
||||||
|
|
||||||
win = EditGeoTIFFWindow(
|
|
||||||
study=self._study,
|
|
||||||
config=self._config,
|
|
||||||
geotiff=geotiff,
|
|
||||||
trad=self._trad,
|
|
||||||
undo=self._undo_stack,
|
|
||||||
parent=self,
|
|
||||||
)
|
|
||||||
win.show()
|
|
||||||
|
|
||||||
def _undo(self):
|
|
||||||
self._undo_stack.undo()
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
def _redo(self):
|
|
||||||
self._undo_stack.redo()
|
|
||||||
self.update()
|
|
||||||
|
|
@ -47,7 +47,7 @@ from PyQt5.QtWidgets import (
|
||||||
QMainWindow, QApplication, QAction,
|
QMainWindow, QApplication, QAction,
|
||||||
QFileDialog, QShortcut, QMenu, QToolBar,
|
QFileDialog, QShortcut, QMenu, QToolBar,
|
||||||
QMessageBox, QProgressDialog, QTabWidget,
|
QMessageBox, QProgressDialog, QTabWidget,
|
||||||
QDialog, QVBoxLayout, QLabel, QInputDialog,
|
QDialog, QVBoxLayout, QLabel,
|
||||||
)
|
)
|
||||||
from PyQt5.uic import loadUi
|
from PyQt5.uic import loadUi
|
||||||
|
|
||||||
|
|
@ -79,7 +79,6 @@ from View.Frictions.Window import FrictionsWindow
|
||||||
from View.SedimentLayers.Window import SedimentLayersWindow
|
from View.SedimentLayers.Window import SedimentLayersWindow
|
||||||
from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow
|
from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow
|
||||||
from View.AdditionalFiles.Window import AddFileListWindow
|
from View.AdditionalFiles.Window import AddFileListWindow
|
||||||
from View.GeoTIFF.Window import GeoTIFFListWindow
|
|
||||||
from View.REPLines.Window import REPLineListWindow
|
from View.REPLines.Window import REPLineListWindow
|
||||||
from View.SolverParameters.Window import SolverParametersWindow
|
from View.SolverParameters.Window import SolverParametersWindow
|
||||||
from View.RunSolver.Window import (
|
from View.RunSolver.Window import (
|
||||||
|
|
@ -158,7 +157,7 @@ define_model_action = [
|
||||||
"action_menu_boundary_conditions_sediment",
|
"action_menu_boundary_conditions_sediment",
|
||||||
"action_menu_rep_additional_lines", "action_menu_output_rk",
|
"action_menu_rep_additional_lines", "action_menu_output_rk",
|
||||||
"action_menu_run_adists", "action_menu_pollutants",
|
"action_menu_run_adists", "action_menu_pollutants",
|
||||||
"action_menu_d90", "action_menu_dif", "action_menu_edit_geotiff"
|
"action_menu_d90", "action_menu_dif",
|
||||||
]
|
]
|
||||||
|
|
||||||
action = (
|
action = (
|
||||||
|
|
@ -277,8 +276,8 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
"action_menu_new": self.open_new_study,
|
"action_menu_new": self.open_new_study,
|
||||||
"action_menu_edit": self.open_edit_study,
|
"action_menu_edit": self.open_edit_study,
|
||||||
"action_menu_open": self.open_model,
|
"action_menu_open": self.open_model,
|
||||||
"action_menu_save": lambda: self.save_study(),
|
"action_menu_save": self.save_study,
|
||||||
"action_menu_save_as": lambda: self.save_as_study(),
|
"action_menu_save_as": self.save_as_study,
|
||||||
"action_menu_numerical_parameter": self.open_solver_parameters,
|
"action_menu_numerical_parameter": self.open_solver_parameters,
|
||||||
"action_menu_edit_scenarios": self.open_scenarios,
|
"action_menu_edit_scenarios": self.open_scenarios,
|
||||||
"action_menu_edit_network": self.open_network,
|
"action_menu_edit_network": self.open_network,
|
||||||
|
|
@ -298,7 +297,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
self.open_reach_sediment_layers,
|
self.open_reach_sediment_layers,
|
||||||
"action_menu_additional_file": self.open_additional_files,
|
"action_menu_additional_file": self.open_additional_files,
|
||||||
"action_menu_rep_additional_lines": self.open_rep_lines,
|
"action_menu_rep_additional_lines": self.open_rep_lines,
|
||||||
"action_menu_edit_geotiff": self.open_geotiff,
|
|
||||||
"action_menu_close": self.close_model,
|
"action_menu_close": self.close_model,
|
||||||
"action_menu_results_last": self.open_last_results,
|
"action_menu_results_last": self.open_last_results,
|
||||||
"action_menu_open_results_from_file": self.open_results_from_file,
|
"action_menu_open_results_from_file": self.open_results_from_file,
|
||||||
|
|
@ -315,7 +313,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
"action_menu_about": self.open_about,
|
"action_menu_about": self.open_about,
|
||||||
# ToolBar action
|
# ToolBar action
|
||||||
"action_toolBar_open": self.open_model,
|
"action_toolBar_open": self.open_model,
|
||||||
"action_toolBar_save": lambda: self.save_study(),
|
"action_toolBar_save": self.save_study,
|
||||||
"action_toolBar_close": self.close_model,
|
"action_toolBar_close": self.close_model,
|
||||||
"action_toolBar_run_solver": self.run_lasest_solver,
|
"action_toolBar_run_solver": self.run_lasest_solver,
|
||||||
# Current actions
|
# Current actions
|
||||||
|
|
@ -608,16 +606,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_last_results(self, solver):
|
|
||||||
if self._study is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
results = self._study.results
|
|
||||||
if solver in results:
|
|
||||||
return self._study.results[solver]
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
@last_results.setter
|
@last_results.setter
|
||||||
def last_results(self, results):
|
def last_results(self, results):
|
||||||
if self._study is None:
|
if self._study is None:
|
||||||
|
|
@ -649,10 +637,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
logger.info(f"Open Study - {self._study.name}")
|
logger.info(f"Open Study - {self._study.name}")
|
||||||
self.set_title()
|
self.set_title()
|
||||||
|
|
||||||
def _save(self, source):
|
def save_study(self):
|
||||||
self.save_study(progress_parent=source)
|
|
||||||
|
|
||||||
def save_study(self, progress_parent=None):
|
|
||||||
"""Save current study
|
"""Save current study
|
||||||
|
|
||||||
Save current study, if study as no associate file, open a
|
Save current study, if study as no associate file, open a
|
||||||
|
|
@ -682,15 +667,11 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
self._backup_timer.blockSignals(True)
|
self._backup_timer.blockSignals(True)
|
||||||
self._save_mutex.lock()
|
self._save_mutex.lock()
|
||||||
|
|
||||||
parent = self
|
|
||||||
if progress_parent is not None:
|
|
||||||
parent = progress_parent
|
|
||||||
|
|
||||||
sql_request_count = self._study.sql_save_request_count()
|
sql_request_count = self._study.sql_save_request_count()
|
||||||
progress = QProgressDialog(
|
progress = QProgressDialog(
|
||||||
"Saving...", None,
|
"Saving...", None,
|
||||||
0, sql_request_count,
|
0, sql_request_count,
|
||||||
parent=parent
|
parent=self
|
||||||
)
|
)
|
||||||
progress.setWindowModality(Qt.WindowModal)
|
progress.setWindowModality(Qt.WindowModal)
|
||||||
progress.setValue(0)
|
progress.setValue(0)
|
||||||
|
|
@ -703,7 +684,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
progress=lambda: progress.setValue(progress.value() + 1)
|
progress=lambda: progress.setValue(progress.value() + 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
progress.close()
|
|
||||||
status += " Done"
|
status += " Done"
|
||||||
logger.info(status)
|
logger.info(status)
|
||||||
self.statusbar.showMessage(status, 3000)
|
self.statusbar.showMessage(status, 3000)
|
||||||
|
|
@ -778,8 +758,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
|
|
||||||
progress.setValue(progress.value() + 1)
|
progress.setValue(progress.value() + 1)
|
||||||
|
|
||||||
progress.close()
|
|
||||||
|
|
||||||
def save_as_study_single_scenario(self, sid=-1):
|
def save_as_study_single_scenario(self, sid=-1):
|
||||||
sql_request_count = self._study.sql_save_request_count()
|
sql_request_count = self._study.sql_save_request_count()
|
||||||
|
|
||||||
|
|
@ -804,7 +782,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
)
|
)
|
||||||
|
|
||||||
status += " Done"
|
status += " Done"
|
||||||
progress.close()
|
|
||||||
logger.info(status)
|
logger.info(status)
|
||||||
self.statusbar.showMessage(status, 3000)
|
self.statusbar.showMessage(status, 3000)
|
||||||
|
|
||||||
|
|
@ -1362,19 +1339,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
)
|
)
|
||||||
self.additonal_files.show()
|
self.additonal_files.show()
|
||||||
|
|
||||||
def open_geotiff(self):
|
|
||||||
if self._study is not None:
|
|
||||||
if self.sub_window_exists(
|
|
||||||
GeoTIFFListWindow,
|
|
||||||
data=[self._study, None]
|
|
||||||
):
|
|
||||||
return
|
|
||||||
|
|
||||||
self.geotiff = GeoTIFFListWindow(
|
|
||||||
study=self._study, parent=self
|
|
||||||
)
|
|
||||||
self.geotiff.show()
|
|
||||||
|
|
||||||
def open_rep_lines(self):
|
def open_rep_lines(self):
|
||||||
if self._study is not None:
|
if self._study is not None:
|
||||||
if self.sub_window_exists(
|
if self.sub_window_exists(
|
||||||
|
|
@ -1559,14 +1523,14 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
# If no specific results, get last results
|
# If no specific results, get last results
|
||||||
if results is None:
|
if results is None:
|
||||||
def reading_fn():
|
def reading_fn():
|
||||||
self._tmp_results = solver.results(
|
self._tmp_results = self.last_results
|
||||||
self._study,
|
|
||||||
self._solver_workdir(solver),
|
|
||||||
)
|
|
||||||
|
|
||||||
if solver == self._last_solver:
|
if self.last_results is None:
|
||||||
def reading_fn():
|
def reading_fn():
|
||||||
self._tmp_results = self.last_results
|
self._tmp_results = solver.results(
|
||||||
|
self._study,
|
||||||
|
self._solver_workdir(solver),
|
||||||
|
)
|
||||||
|
|
||||||
# Open from file
|
# Open from file
|
||||||
if type(results) is str:
|
if type(results) is str:
|
||||||
|
|
@ -1591,16 +1555,13 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
)
|
)
|
||||||
dlg.exec_()
|
dlg.exec_()
|
||||||
results = self._tmp_results
|
results = self._tmp_results
|
||||||
# self.last_results = results
|
|
||||||
|
|
||||||
# No results available
|
# No results available
|
||||||
if results is None:
|
if results is None:
|
||||||
self.msg_open_results_no_results()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# results does not have values, for example if geometry missmatch
|
# results does not have values, for example if geometry missmatch
|
||||||
if not results.is_valid:
|
if not results.is_valid:
|
||||||
self.msg_open_results_invalid_results()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if results.get('study_revision') != self._study.status.version:
|
if results.get('study_revision') != self._study.status.version:
|
||||||
|
|
@ -1626,20 +1587,6 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
)
|
)
|
||||||
res.show()
|
res.show()
|
||||||
|
|
||||||
def msg_open_results_no_results(self):
|
|
||||||
self.message_box(
|
|
||||||
window_title=self._trad["Warning"],
|
|
||||||
text=self._trad["mb_open_results_title"],
|
|
||||||
informative_text=self._trad["mb_open_results_no_results_msg"]
|
|
||||||
)
|
|
||||||
|
|
||||||
def msg_open_results_invalid_results(self):
|
|
||||||
self.message_box(
|
|
||||||
window_title=self._trad["Error"],
|
|
||||||
text=self._trad["mb_open_results_title"],
|
|
||||||
informative_text=self._trad["mb_open_results_invalid_results_msg"]
|
|
||||||
)
|
|
||||||
|
|
||||||
def open_solver_results_adists(self, solver, results=None):
|
def open_solver_results_adists(self, solver, results=None):
|
||||||
def reading_fn():
|
def reading_fn():
|
||||||
self._tmp_results = results
|
self._tmp_results = results
|
||||||
|
|
@ -1715,49 +1662,16 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
|
||||||
|
|
||||||
return workdir
|
return workdir
|
||||||
|
|
||||||
def is_solver_workdir_exists(self, solver, scenario=None):
|
|
||||||
return os.path.exists(
|
|
||||||
self._solver_workdir(solver, scenario)
|
|
||||||
)
|
|
||||||
|
|
||||||
def open_last_results(self):
|
def open_last_results(self):
|
||||||
if self._last_solver is None:
|
if self._last_solver is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
solver_type = self._study.results
|
|
||||||
|
|
||||||
solver_name, ok = QInputDialog.getItem(
|
|
||||||
self, self._trad['Solver'],
|
|
||||||
self._trad['Solver'] + ":",
|
|
||||||
list(
|
|
||||||
map(
|
|
||||||
lambda s: s.name,
|
|
||||||
filter(
|
|
||||||
lambda s: (self.is_solver_workdir_exists(s)
|
|
||||||
or s._type in solver_type),
|
|
||||||
self.conf.solvers
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if not ok:
|
|
||||||
return
|
|
||||||
|
|
||||||
solver = next(
|
|
||||||
filter(
|
|
||||||
lambda s: s.name == solver_name,
|
|
||||||
self.conf.solvers
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if self._last_solver._type == "mage8":
|
if self._last_solver._type == "mage8":
|
||||||
self.open_solver_results(
|
self.open_solver_results(self._last_solver,
|
||||||
solver, # self.last_results
|
self.last_results)
|
||||||
)
|
|
||||||
elif self._last_solver._type == "adistswc":
|
elif self._last_solver._type == "adistswc":
|
||||||
self.open_solver_results_adists(
|
self.open_solver_results_adists(self._last_solver,
|
||||||
solver, # self.last_results
|
self.last_results)
|
||||||
)
|
|
||||||
|
|
||||||
def open_results_from_file(self):
|
def open_results_from_file(self):
|
||||||
if self._study is None:
|
if self._study is None:
|
||||||
|
|
|
||||||
|
|
@ -27,20 +27,6 @@ from View.Tools.PamhyrWidget import PamhyrWidget
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QVBoxLayout
|
from PyQt5.QtWidgets import QVBoxLayout
|
||||||
|
|
||||||
try:
|
|
||||||
import rasterio
|
|
||||||
import rasterio.control
|
|
||||||
import rasterio.crs
|
|
||||||
import rasterio.sample
|
|
||||||
import rasterio.vrt
|
|
||||||
import rasterio._features
|
|
||||||
|
|
||||||
from rasterio.io import MemoryFile
|
|
||||||
_rasterio_loaded = True
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Module 'rasterio' is not available: {e}")
|
|
||||||
_rasterio_loaded = False
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -118,12 +104,10 @@ class WidgetInfo(PamhyrWidget):
|
||||||
self.plot = PlotXY(
|
self.plot = PlotXY(
|
||||||
canvas=self.canvas,
|
canvas=self.canvas,
|
||||||
data=self._study.river.enable_edges(),
|
data=self._study.river.enable_edges(),
|
||||||
geotiff=self._study.river.geotiff,
|
|
||||||
trad=self.parent._trad,
|
trad=self.parent._trad,
|
||||||
toolbar=self._toolbar_xy,
|
toolbar=self._toolbar_xy,
|
||||||
parent=self
|
parent=self
|
||||||
)
|
)
|
||||||
|
|
||||||
self.plot.update()
|
self.plot.update()
|
||||||
|
|
||||||
def set_network_values(self):
|
def set_network_values(self):
|
||||||
|
|
|
||||||
|
|
@ -27,26 +27,12 @@ from PyQt5.QtCore import (
|
||||||
)
|
)
|
||||||
from PyQt5.QtWidgets import QApplication, QTableView
|
from PyQt5.QtWidgets import QApplication, QTableView
|
||||||
|
|
||||||
try:
|
|
||||||
import rasterio
|
|
||||||
import rasterio.control
|
|
||||||
import rasterio.crs
|
|
||||||
import rasterio.sample
|
|
||||||
import rasterio.vrt
|
|
||||||
import rasterio._features
|
|
||||||
|
|
||||||
from rasterio.io import MemoryFile
|
|
||||||
_rasterio_loaded = True
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Module 'rasterio' is not available: {e}")
|
|
||||||
_rasterio_loaded = False
|
|
||||||
|
|
||||||
_translate = QCoreApplication.translate
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
|
|
||||||
class PlotXY(PamhyrPlot):
|
class PlotXY(PamhyrPlot):
|
||||||
def __init__(self, canvas=None, trad=None, data=None, geotiff=None,
|
def __init__(self, canvas=None, trad=None, data=None, toolbar=None,
|
||||||
toolbar=None, table=None, parent=None):
|
table=None, parent=None):
|
||||||
super(PlotXY, self).__init__(
|
super(PlotXY, self).__init__(
|
||||||
canvas=canvas,
|
canvas=canvas,
|
||||||
trad=trad,
|
trad=trad,
|
||||||
|
|
@ -57,14 +43,10 @@ class PlotXY(PamhyrPlot):
|
||||||
)
|
)
|
||||||
|
|
||||||
self._data = data
|
self._data = data
|
||||||
self._geotiff = geotiff
|
|
||||||
|
|
||||||
self.label_x = self._trad["x"]
|
self.label_x = self._trad["x"]
|
||||||
self.label_y = self._trad["y"]
|
self.label_y = self._trad["y"]
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
|
||||||
self._plot_img = {}
|
|
||||||
|
|
||||||
self._isometric_axis = True
|
self._isometric_axis = True
|
||||||
|
|
||||||
self._auto_relim_update = True
|
self._auto_relim_update = True
|
||||||
|
|
@ -87,12 +69,7 @@ class PlotXY(PamhyrPlot):
|
||||||
if data.reach.number_profiles != 0:
|
if data.reach.number_profiles != 0:
|
||||||
self.draw_xy(data.reach)
|
self.draw_xy(data.reach)
|
||||||
self.draw_lr(data.reach)
|
self.draw_lr(data.reach)
|
||||||
|
self.idle()
|
||||||
if self._geotiff is not None:
|
|
||||||
self.draw_geotiff(self._geotiff.files)
|
|
||||||
|
|
||||||
self.idle()
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def draw_xy(self, reach):
|
def draw_xy(self, reach):
|
||||||
|
|
@ -101,9 +78,9 @@ class PlotXY(PamhyrPlot):
|
||||||
line_xy.append(np.column_stack(xy))
|
line_xy.append(np.column_stack(xy))
|
||||||
|
|
||||||
line_xy_collection = collections.LineCollection(
|
line_xy_collection = collections.LineCollection(
|
||||||
line_xy,
|
line_xy,
|
||||||
colors=self.color_plot_river_bottom
|
colors=self.color_plot_river_bottom
|
||||||
)
|
)
|
||||||
self.canvas.axes.add_collection(line_xy_collection)
|
self.canvas.axes.add_collection(line_xy_collection)
|
||||||
|
|
||||||
def draw_lr(self, reach):
|
def draw_lr(self, reach):
|
||||||
|
|
@ -136,42 +113,6 @@ class PlotXY(PamhyrPlot):
|
||||||
)
|
)
|
||||||
self.line_lr.append(line)
|
self.line_lr.append(line)
|
||||||
|
|
||||||
def draw_geotiff(self, lst):
|
|
||||||
if not _rasterio_loaded:
|
|
||||||
return
|
|
||||||
|
|
||||||
for img in self._plot_img:
|
|
||||||
self._plot_img[img].remove()
|
|
||||||
|
|
||||||
self._plot_img = {}
|
|
||||||
|
|
||||||
for geotiff in lst:
|
|
||||||
if geotiff.is_deleted():
|
|
||||||
continue
|
|
||||||
|
|
||||||
memfile = geotiff.memfile
|
|
||||||
if memfile is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
with memfile.open() as gt:
|
|
||||||
img = gt.read()
|
|
||||||
coords = geotiff.coordinates
|
|
||||||
|
|
||||||
left = coords["left"]
|
|
||||||
right = coords["right"]
|
|
||||||
bottom = coords["bottom"]
|
|
||||||
top = coords["top"]
|
|
||||||
|
|
||||||
self._plot_img[geotiff] = self.canvas.axes.imshow(
|
|
||||||
img.transpose((1, 2, 0)),
|
|
||||||
extent=(left, right, bottom, top)
|
|
||||||
)
|
|
||||||
|
|
||||||
if not geotiff.is_enabled():
|
|
||||||
self._plot_img[geotiff].set(alpha=0.5)
|
|
||||||
|
|
||||||
self.idle()
|
|
||||||
|
|
||||||
@timer
|
@timer
|
||||||
def update(self):
|
def update(self):
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
|
||||||
|
|
@ -31,20 +31,6 @@ from PyQt5.QtCore import (
|
||||||
)
|
)
|
||||||
from PyQt5.QtWidgets import QApplication, QTableView
|
from PyQt5.QtWidgets import QApplication, QTableView
|
||||||
|
|
||||||
try:
|
|
||||||
import rasterio
|
|
||||||
import rasterio.control
|
|
||||||
import rasterio.crs
|
|
||||||
import rasterio.sample
|
|
||||||
import rasterio.vrt
|
|
||||||
import rasterio._features
|
|
||||||
|
|
||||||
from rasterio.io import MemoryFile
|
|
||||||
_rasterio_loaded = True
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Module 'rasterio' is not available: {e}")
|
|
||||||
_rasterio_loaded = False
|
|
||||||
|
|
||||||
_translate = QCoreApplication.translate
|
_translate = QCoreApplication.translate
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
@ -66,8 +52,6 @@ class PlotXY(PamhyrPlot):
|
||||||
self.line_gl = []
|
self.line_gl = []
|
||||||
self.overflow = []
|
self.overflow = []
|
||||||
|
|
||||||
self._plot_img = {}
|
|
||||||
|
|
||||||
self._timestamps = parent._timestamps
|
self._timestamps = parent._timestamps
|
||||||
self._current_timestamp = max(self._timestamps)
|
self._current_timestamp = max(self._timestamps)
|
||||||
self._current_reach_id = reach_id
|
self._current_reach_id = reach_id
|
||||||
|
|
@ -169,7 +153,6 @@ class PlotXY(PamhyrPlot):
|
||||||
reach = results.river.reach(self._current_reach_id)
|
reach = results.river.reach(self._current_reach_id)
|
||||||
reaches = results.river.reachs
|
reaches = results.river.reachs
|
||||||
|
|
||||||
self.draw_geotiff()
|
|
||||||
self.draw_profiles(reach, reaches)
|
self.draw_profiles(reach, reaches)
|
||||||
self.draw_water_elevation(reach)
|
self.draw_water_elevation(reach)
|
||||||
self.draw_water_elevation_max(reach)
|
self.draw_water_elevation_max(reach)
|
||||||
|
|
@ -183,7 +166,6 @@ class PlotXY(PamhyrPlot):
|
||||||
if reach.geometry.number_profiles == 0:
|
if reach.geometry.number_profiles == 0:
|
||||||
self._init = False
|
self._init = False
|
||||||
return
|
return
|
||||||
|
|
||||||
self.line_xy = []
|
self.line_xy = []
|
||||||
# TODO uncomment to draw all the reaches
|
# TODO uncomment to draw all the reaches
|
||||||
# self.draw_other_profiles(reaches)
|
# self.draw_other_profiles(reaches)
|
||||||
|
|
@ -324,41 +306,6 @@ class PlotXY(PamhyrPlot):
|
||||||
alpha=0.7
|
alpha=0.7
|
||||||
)
|
)
|
||||||
|
|
||||||
def draw_geotiff(self):
|
|
||||||
if not _rasterio_loaded:
|
|
||||||
return
|
|
||||||
|
|
||||||
lst = self._data[0]._study.river._geotiff.lst
|
|
||||||
|
|
||||||
for img in self._plot_img:
|
|
||||||
self._plot_img[img].remove()
|
|
||||||
|
|
||||||
self._plot_img = {}
|
|
||||||
|
|
||||||
for geotiff in lst:
|
|
||||||
memfile = geotiff.memfile
|
|
||||||
if memfile is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
with memfile.open() as gt:
|
|
||||||
img = gt.read()
|
|
||||||
coords = geotiff.coordinates
|
|
||||||
|
|
||||||
left = coords["left"]
|
|
||||||
right = coords["right"]
|
|
||||||
bottom = coords["bottom"]
|
|
||||||
top = coords["top"]
|
|
||||||
|
|
||||||
self._plot_img[geotiff] = self.canvas.axes.imshow(
|
|
||||||
img.transpose((1, 2, 0)),
|
|
||||||
extent=(left, right, bottom, top)
|
|
||||||
)
|
|
||||||
|
|
||||||
if not geotiff.is_enabled():
|
|
||||||
self._plot_img[geotiff].set(alpha=0.5)
|
|
||||||
|
|
||||||
self.idle()
|
|
||||||
|
|
||||||
def set_reach(self, reach_id):
|
def set_reach(self, reach_id):
|
||||||
self._current_reach_id = reach_id
|
self._current_reach_id = reach_id
|
||||||
self._current_profile_id = 0
|
self._current_profile_id = 0
|
||||||
|
|
|
||||||
|
|
@ -56,12 +56,9 @@ from PyQt5.QtWidgets import (
|
||||||
QFileDialog, QTableView, QAbstractItemView,
|
QFileDialog, QTableView, QAbstractItemView,
|
||||||
QUndoStack, QShortcut, QAction, QItemDelegate,
|
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||||
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||||
QSlider, QLabel, QWidget, QGridLayout, QTabBar,
|
QSlider, QLabel, QWidget, QGridLayout, QTabBar, QInputDialog
|
||||||
QInputDialog,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from Model.Results.Results import AdditionalData
|
|
||||||
|
|
||||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||||
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
|
||||||
|
|
||||||
|
|
@ -147,14 +144,11 @@ class ResultsWindow(PamhyrWindow):
|
||||||
profile_id=[0])
|
profile_id=[0])
|
||||||
|
|
||||||
self.update_table_selection_solver(0)
|
self.update_table_selection_solver(0)
|
||||||
self.update_plot_additional_data()
|
|
||||||
|
|
||||||
def setup_table(self):
|
def setup_table(self):
|
||||||
self._table = {}
|
self._table = {}
|
||||||
|
|
||||||
for t in ["reach", "profile", "raw_data", "solver"]:
|
for t in ["reach", "profile", "raw_data", "solver"]:
|
||||||
table = self.find(QTableView, f"tableView_{t}")
|
table = self.find(QTableView, f"tableView_{t}")
|
||||||
|
|
||||||
self._table[t] = TableModel(
|
self._table[t] = TableModel(
|
||||||
table_view=table,
|
table_view=table,
|
||||||
table_headers=self._trad.get_dict(f"table_headers_{t}"),
|
table_headers=self._trad.get_dict(f"table_headers_{t}"),
|
||||||
|
|
@ -163,11 +157,8 @@ class ResultsWindow(PamhyrWindow):
|
||||||
opt_data=t,
|
opt_data=t,
|
||||||
parent=self
|
parent=self
|
||||||
)
|
)
|
||||||
|
|
||||||
self._table[t]._timestamp = self._timestamps[
|
self._table[t]._timestamp = self._timestamps[
|
||||||
self._slider_time.value()
|
self._slider_time.value()]
|
||||||
]
|
|
||||||
|
|
||||||
if len(self._results) <= 1:
|
if len(self._results) <= 1:
|
||||||
table = self.find(QTableView, f"tableView_solver")
|
table = self.find(QTableView, f"tableView_solver")
|
||||||
table.hide()
|
table.hide()
|
||||||
|
|
@ -198,15 +189,12 @@ class ResultsWindow(PamhyrWindow):
|
||||||
|
|
||||||
def setup_plots(self):
|
def setup_plots(self):
|
||||||
self.canvas = MplCanvas(width=5, height=4, dpi=100)
|
self.canvas = MplCanvas(width=5, height=4, dpi=100)
|
||||||
|
|
||||||
tab_widget = self.find(QTabWidget, f"tabWidget")
|
tab_widget = self.find(QTabWidget, f"tabWidget")
|
||||||
|
|
||||||
tab_widget.setTabsClosable(True)
|
tab_widget.setTabsClosable(True)
|
||||||
tab_widget.tabCloseRequested.connect(self.delete_tab)
|
tab_widget.tabCloseRequested.connect(self.delete_tab)
|
||||||
tab_widget.tabBar().setTabButton(0, QTabBar.RightSide, None)
|
tab_widget.tabBar().setTabButton(0, QTabBar.RightSide, None)
|
||||||
tab_widget.tabBar().setTabButton(1, QTabBar.RightSide, None)
|
tab_widget.tabBar().setTabButton(1, QTabBar.RightSide, None)
|
||||||
tab_widget.tabBar().setTabButton(2, QTabBar.RightSide, None)
|
tab_widget.tabBar().setTabButton(2, QTabBar.RightSide, None)
|
||||||
|
|
||||||
self.canvas.setObjectName("canvas")
|
self.canvas.setObjectName("canvas")
|
||||||
self.toolbar = PamhyrPlotToolbar(
|
self.toolbar = PamhyrPlotToolbar(
|
||||||
self.canvas, self, items=[
|
self.canvas, self, items=[
|
||||||
|
|
@ -214,7 +202,6 @@ class ResultsWindow(PamhyrWindow):
|
||||||
"iso", "back/forward"
|
"iso", "back/forward"
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
|
self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
|
||||||
self.plot_layout.addWidget(self.toolbar)
|
self.plot_layout.addWidget(self.toolbar)
|
||||||
self.plot_layout.addWidget(self.canvas)
|
self.plot_layout.addWidget(self.canvas)
|
||||||
|
|
@ -1230,7 +1217,8 @@ class ResultsWindow(PamhyrWindow):
|
||||||
extent=[b[0], b[2], b[1], b[3]])
|
extent=[b[0], b[2], b[1], b[3]])
|
||||||
else:
|
else:
|
||||||
dlg = CoordinatesDialog(
|
dlg = CoordinatesDialog(
|
||||||
xlim, ylim,
|
xlim,
|
||||||
|
ylim,
|
||||||
trad=self._trad,
|
trad=self._trad,
|
||||||
parent=self
|
parent=self
|
||||||
)
|
)
|
||||||
|
|
@ -1243,6 +1231,7 @@ class ResultsWindow(PamhyrWindow):
|
||||||
return
|
return
|
||||||
|
|
||||||
def import_data(self):
|
def import_data(self):
|
||||||
|
|
||||||
file_types = [
|
file_types = [
|
||||||
self._trad["file_csv"],
|
self._trad["file_csv"],
|
||||||
self._trad["file_all"],
|
self._trad["file_all"],
|
||||||
|
|
@ -1253,61 +1242,41 @@ class ResultsWindow(PamhyrWindow):
|
||||||
callback=lambda f: self.read_csv_file(f[0]),
|
callback=lambda f: self.read_csv_file(f[0]),
|
||||||
default_suffix=".csv",
|
default_suffix=".csv",
|
||||||
file_filter=file_types,
|
file_filter=file_types,
|
||||||
directory=self._results[self._current_results[0]]._repertory,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def read_csv_file(self, filename):
|
def read_csv_file(self, filename):
|
||||||
if filename == "":
|
if filename == "":
|
||||||
return
|
return
|
||||||
|
|
||||||
x, y = self.read_csv_file_data(filename)
|
sep = " "
|
||||||
data = self.read_csv_file_format(x, y)
|
|
||||||
|
|
||||||
results = self._results[self._current_results[0]]
|
def is_float(string):
|
||||||
data_lst = results.get("additional_data")
|
if string.replace(".", "").isnumeric():
|
||||||
data_lst.append(
|
return True
|
||||||
AdditionalData(
|
else:
|
||||||
study=self._study,
|
return False
|
||||||
data=data
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.update_plot_additional_data()
|
|
||||||
|
|
||||||
def read_csv_file_data(self, filename):
|
|
||||||
sep = ","
|
|
||||||
x = []
|
|
||||||
y = []
|
|
||||||
|
|
||||||
with open(filename, 'r', newline='') as f:
|
with open(filename, 'r', newline='') as f:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
|
x = []
|
||||||
|
y = []
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if line[0] != "*" and line[0] != "#" and line[0] != "$":
|
if line[0] != "*" and line[0] != "#" and line[0] != "$":
|
||||||
row = line.split(sep)
|
row = line.split(sep)
|
||||||
|
if len(row) >= 2:
|
||||||
|
if is_float(row[0]) and is_float(row[1]):
|
||||||
|
x.append(float(row[0]))
|
||||||
|
y.append(float(row[1]))
|
||||||
|
|
||||||
if len(row) < 2:
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
fx, fy = float(row[0]), float(row[1])
|
|
||||||
x.append(fx)
|
|
||||||
y.append(fy)
|
|
||||||
except Exception as e:
|
|
||||||
continue
|
|
||||||
|
|
||||||
return x, y
|
|
||||||
|
|
||||||
def read_csv_file_format(self, x, y):
|
|
||||||
data_type_lst = ['Q(t)', 'Z(t)', 'Z(x)']
|
data_type_lst = ['Q(t)', 'Z(t)', 'Z(x)']
|
||||||
data_type, ok = QInputDialog.getItem(
|
data_type, ok = QInputDialog.getItem(
|
||||||
self, 'Data type',
|
self, 'Data type', 'Chose the type of data:', data_type_lst)
|
||||||
'Chose the type of data:',
|
|
||||||
data_type_lst
|
|
||||||
)
|
|
||||||
if not ok:
|
if not ok:
|
||||||
return
|
return
|
||||||
|
|
||||||
legend, ok = QInputDialog.getText(self, 'Legend', 'Legend:')
|
legend, ok = QInputDialog.getText(self, 'Legend', 'Legend:')
|
||||||
|
|
||||||
if not ok:
|
if not ok:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -1322,45 +1291,25 @@ class ResultsWindow(PamhyrWindow):
|
||||||
tmp_unit = {'Z': ' (m)',
|
tmp_unit = {'Z': ' (m)',
|
||||||
'Q': ' (m³/s)'}
|
'Q': ' (m³/s)'}
|
||||||
|
|
||||||
data = {
|
data = {'type_x': tmp_dict[data_type[2]],
|
||||||
'type_x': tmp_dict[data_type[2]],
|
'type_y': tmp_dict[data_type[0]],
|
||||||
'type_y': tmp_dict[data_type[0]],
|
'legend': legend,
|
||||||
'legend': legend,
|
'unit': tmp_unit[data_type[0]],
|
||||||
'unit': tmp_unit[data_type[0]],
|
'x': x,
|
||||||
'x': x, 'y': y
|
'y': y}
|
||||||
}
|
|
||||||
|
|
||||||
return data
|
if data_type == 'Z(x)':
|
||||||
|
line = self.canvas_2.axes.plot(x, y, marker="+",
|
||||||
|
label=legend + ' (m)')
|
||||||
|
self.plot_rkc.canvas.draw_idle()
|
||||||
|
self.plot_rkc.update_idle()
|
||||||
|
if data_type == 'Q(t)':
|
||||||
|
line = self.canvas_4.axes.plot(x, y, marker="+",
|
||||||
|
label=legend + ' (m³/s)')
|
||||||
|
self.plot_h._line.append(line)
|
||||||
|
self.plot_h.enable_legend()
|
||||||
|
self.plot_h.canvas.draw_idle()
|
||||||
|
self.plot_h.update_idle
|
||||||
|
|
||||||
def update_plot_additional_data(self):
|
for p in self._additional_plot:
|
||||||
results = self._results[self._current_results[0]]
|
self._additional_plot[p].add_imported_plot(data)
|
||||||
|
|
||||||
for data in results.get("additional_data"):
|
|
||||||
data = data._data
|
|
||||||
x, y = data['x'], data['y']
|
|
||||||
legend = data['legend']
|
|
||||||
unit = data['unit']
|
|
||||||
|
|
||||||
if (
|
|
||||||
data['type_x'] == 'water_elevation' and
|
|
||||||
data['type_y'] == 'time'
|
|
||||||
):
|
|
||||||
line = self.canvas_2.axes.plot(
|
|
||||||
x, y, marker="+",
|
|
||||||
label=legend + ' ' + unit
|
|
||||||
)
|
|
||||||
self.plot_rkc.canvas.draw_idle()
|
|
||||||
self.plot_rkc.update_idle()
|
|
||||||
|
|
||||||
if data['type_x'] == 'time' and data['type_y'] == 'discharge':
|
|
||||||
line = self.canvas_4.axes.plot(
|
|
||||||
x, y, marker="+",
|
|
||||||
label=legend + ' ' + unit
|
|
||||||
)
|
|
||||||
self.plot_h._line.append(line)
|
|
||||||
self.plot_h.enable_legend()
|
|
||||||
self.plot_h.canvas.draw_idle()
|
|
||||||
self.plot_h.update_idle()
|
|
||||||
|
|
||||||
for p in self._additional_plot:
|
|
||||||
self._additional_plot[p].add_imported_plot(data)
|
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,11 @@ class ResultsTranslate(MainTranslate):
|
||||||
"Results",
|
"Results",
|
||||||
"Max water elevation"
|
"Max water elevation"
|
||||||
)
|
)
|
||||||
|
self._dict["file_all"] = _translate("Results", "All files (*)")
|
||||||
|
self._dict["file_geotiff"] = _translate(
|
||||||
|
"Results", "GeoTIFF file (*.tiff *.tif)")
|
||||||
|
self._dict["file_csv"] = _translate(
|
||||||
|
"Results", "CSV file (*.csv)")
|
||||||
self._dict["ImageCoordinates"] = _translate(
|
self._dict["ImageCoordinates"] = _translate(
|
||||||
"Results", "Image coordinates"
|
"Results", "Image coordinates"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,6 @@ class PamhyrWindow(ASubMainWindow, ListedSubWindow, PamhyrWindowTools):
|
||||||
|
|
||||||
self._set_title()
|
self._set_title()
|
||||||
self._set_icon()
|
self._set_icon()
|
||||||
self._setup_save_sc()
|
|
||||||
|
|
||||||
def _set_title(self):
|
def _set_title(self):
|
||||||
title = self._title
|
title = self._title
|
||||||
|
|
@ -197,25 +196,12 @@ class PamhyrWindow(ASubMainWindow, ListedSubWindow, PamhyrWindowTools):
|
||||||
|
|
||||||
self.ui.setWindowTitle(title)
|
self.ui.setWindowTitle(title)
|
||||||
|
|
||||||
def _setup_save_sc(self):
|
|
||||||
if self._parent is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
self._save_sc = QShortcut(QKeySequence("Ctrl+S"), self)
|
|
||||||
self._save_sc.activated.connect(lambda: self._save(self))
|
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
self._close_sub_window()
|
self._close_sub_window()
|
||||||
self._propagate_update(Modules.WINDOW_LIST)
|
self._propagate_update(Modules.WINDOW_LIST)
|
||||||
|
|
||||||
super(PamhyrWindow, self).closeEvent(event)
|
super(PamhyrWindow, self).closeEvent(event)
|
||||||
|
|
||||||
def _save(self, source):
|
|
||||||
if self._parent is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
return self._parent._save(source)
|
|
||||||
|
|
||||||
|
|
||||||
class PamhyrDialog(ASubWindow, ListedSubWindow, PamhyrWindowTools):
|
class PamhyrDialog(ASubWindow, ListedSubWindow, PamhyrWindowTools):
|
||||||
_pamhyr_ui = "dummy"
|
_pamhyr_ui = "dummy"
|
||||||
|
|
|
||||||
|
|
@ -54,18 +54,6 @@ class CommonWordTranslate(PamhyrTranslate):
|
||||||
|
|
||||||
self._dict["method"] = _translate("CommonWord", "Method")
|
self._dict["method"] = _translate("CommonWord", "Method")
|
||||||
|
|
||||||
# Files
|
|
||||||
self._dict["open_file"] = _translate(
|
|
||||||
"CommonWord", "Open file"
|
|
||||||
)
|
|
||||||
self._dict["file_all"] = _translate("CommonWord", "All files (*)")
|
|
||||||
self._dict["file_geotiff"] = _translate(
|
|
||||||
"CommonWord", "GeoTIFF file (*.tiff *.tif)"
|
|
||||||
)
|
|
||||||
self._dict["file_csv"] = _translate(
|
|
||||||
"CommonWord", "CSV file (*.csv)"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class UnitTranslate(CommonWordTranslate):
|
class UnitTranslate(CommonWordTranslate):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
@ -192,9 +180,6 @@ class MainTranslate(UnitTranslate):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Message box
|
# Message box
|
||||||
self._dict["Error"] = _translate(
|
|
||||||
"MainWindow", "Error"
|
|
||||||
)
|
|
||||||
self._dict["Warning"] = _translate(
|
self._dict["Warning"] = _translate(
|
||||||
"MainWindow", "Warning"
|
"MainWindow", "Warning"
|
||||||
)
|
)
|
||||||
|
|
@ -249,17 +234,6 @@ class MainTranslate(UnitTranslate):
|
||||||
self._dict["mb_diff_results_param_msg"] = _translate(
|
self._dict["mb_diff_results_param_msg"] = _translate(
|
||||||
"MainWindow", "Results comparison parameters is invalid"
|
"MainWindow", "Results comparison parameters is invalid"
|
||||||
)
|
)
|
||||||
|
|
||||||
self._dict["mb_open_results_title"] = _translate(
|
|
||||||
"MainWindow", "Open results"
|
|
||||||
)
|
|
||||||
self._dict["mb_open_results_no_results_msg"] = _translate(
|
|
||||||
"MainWindow", "No results found"
|
|
||||||
)
|
|
||||||
self._dict["mb_open_results_invalid_results_msg"] = _translate(
|
|
||||||
"MainWindow", "Failed to read results"
|
|
||||||
)
|
|
||||||
|
|
||||||
self._dict["mb_diff_results_compatibility_msg"] = _translate(
|
self._dict["mb_diff_results_compatibility_msg"] = _translate(
|
||||||
"MainWindow",
|
"MainWindow",
|
||||||
"Results comparison with two "
|
"Results comparison with two "
|
||||||
|
|
@ -273,4 +247,3 @@ class MainTranslate(UnitTranslate):
|
||||||
self._dict["Cancel"] = _translate("MainWindow", "Cancel")
|
self._dict["Cancel"] = _translate("MainWindow", "Cancel")
|
||||||
self._dict["Save"] = _translate("MainWindow", "Save")
|
self._dict["Save"] = _translate("MainWindow", "Save")
|
||||||
self._dict["Close"] = _translate("MainWindow", "Close")
|
self._dict["Close"] = _translate("MainWindow", "Close")
|
||||||
self._dict["Solver"] = _translate("MainWindow", "Solver")
|
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ class WaitingDialog(PamhyrDialog):
|
||||||
". ", ". ",
|
". ", ". ",
|
||||||
".. ", ".. ",
|
".. ", ".. ",
|
||||||
"...", "..."],
|
"...", "..."],
|
||||||
["o ", " o ", " o ", " o", " o ", " o "],
|
["o ", " o ", " o ", " o", " o ", " o "],
|
||||||
["█▓▒░", "▓█▓▒", "▒▓█▓", "░▒▓█", "▒▓█▓", "▓█▓▒"],
|
["█▓▒░", "▓█▓▒", "▒▓█▓", "░▒▓█", "▒▓█▓", "▓█▓▒"],
|
||||||
"▖▘▝▗",
|
"▖▘▝▗",
|
||||||
"αβγδεζηθικλμνξοπρστυφχψω",
|
"αβγδεζηθικλμνξοπρστυφχψω",
|
||||||
|
|
|
||||||
|
|
@ -1,264 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>MainWindow</class>
|
|
||||||
<widget class="QMainWindow" name="MainWindow">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>896</width>
|
|
||||||
<height>504</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>MainWindow</string>
|
|
||||||
</property>
|
|
||||||
<property name="locale">
|
|
||||||
<locale language="English" country="Europe"/>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="centralwidget">
|
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
|
||||||
<item row="2" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="pushButton_cancel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Cancel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="pushButton_ok">
|
|
||||||
<property name="text">
|
|
||||||
<string>Ok</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0" colspan="2">
|
|
||||||
<widget class="QGroupBox" name="groupBox">
|
|
||||||
<property name="title">
|
|
||||||
<string>Informations</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Name</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QCheckBox" name="checkBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Enabled</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Description</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLineEdit" name="lineEdit_description">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>The relative file path on executable directory</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="lineEdit_name"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0" colspan="2">
|
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
|
||||||
<property name="title">
|
|
||||||
<string>GeoTIFF file</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="pushButton_import">
|
|
||||||
<property name="text">
|
|
||||||
<string>Import GeoTIFF file</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSplitter" name="splitter">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_geotiff"/>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
|
||||||
<item row="2" column="2">
|
|
||||||
<widget class="QPushButton" name="pushButton_left">
|
|
||||||
<property name="text">
|
|
||||||
<string>Reset</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_right">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Right coordinate</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="2">
|
|
||||||
<widget class="QPushButton" name="pushButton_right">
|
|
||||||
<property name="text">
|
|
||||||
<string>Reset</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_left">
|
|
||||||
<property name="decimals">
|
|
||||||
<number>4</number>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<double>-99999999.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<double>99999999.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="2">
|
|
||||||
<widget class="QPushButton" name="pushButton_bottom">
|
|
||||||
<property name="text">
|
|
||||||
<string>Reset</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QPushButton" name="pushButton_top">
|
|
||||||
<property name="text">
|
|
||||||
<string>Reset</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_right">
|
|
||||||
<property name="decimals">
|
|
||||||
<number>4</number>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<double>-99999999.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<double>99999999.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<double>1.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_top">
|
|
||||||
<property name="decimals">
|
|
||||||
<number>4</number>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<double>-99999999.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<double>99999999.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<double>1.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_top">
|
|
||||||
<property name="text">
|
|
||||||
<string>Top coordinate</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_bottom">
|
|
||||||
<property name="decimals">
|
|
||||||
<number>4</number>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<double>-99999999.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<double>99999999.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_left">
|
|
||||||
<property name="text">
|
|
||||||
<string>Left coordinate</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_bottom">
|
|
||||||
<property name="text">
|
|
||||||
<string>Bottom coordinate</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>MainWindow</class>
|
|
||||||
<widget class="QMainWindow" name="MainWindow">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>896</width>
|
|
||||||
<height>504</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>MainWindow</string>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="centralwidget">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QSplitter" name="splitter">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<widget class="QListView" name="listView"/>
|
|
||||||
<widget class="QWidget" name="verticalLayoutWidget">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout"/>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QToolBar" name="toolBar">
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>toolBar</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="toolBarArea">
|
|
||||||
<enum>TopToolBarArea</enum>
|
|
||||||
</attribute>
|
|
||||||
<attribute name="toolBarBreak">
|
|
||||||
<bool>false</bool>
|
|
||||||
</attribute>
|
|
||||||
<addaction name="action_add"/>
|
|
||||||
<addaction name="action_delete"/>
|
|
||||||
<addaction name="action_edit"/>
|
|
||||||
</widget>
|
|
||||||
<action name="action_add">
|
|
||||||
<property name="icon">
|
|
||||||
<iconset>
|
|
||||||
<normaloff>ressources/add.png</normaloff>ressources/add.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Add</string>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Add a new file</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="action_delete">
|
|
||||||
<property name="icon">
|
|
||||||
<iconset>
|
|
||||||
<normaloff>ressources/del.png</normaloff>ressources/del.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Delete</string>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Delete selected file(s)</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="action_edit">
|
|
||||||
<property name="icon">
|
|
||||||
<iconset>
|
|
||||||
<normaloff>ressources/edit.png</normaloff>ressources/edit.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Edit</string>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Edit file</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
||||||
|
|
@ -129,7 +129,6 @@
|
||||||
<string>&Geometry</string>
|
<string>&Geometry</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="action_menu_edit_geometry"/>
|
<addaction name="action_menu_edit_geometry"/>
|
||||||
<addaction name="action_menu_edit_geotiff"/>
|
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menu_run">
|
<widget class="QMenu" name="menu_run">
|
||||||
<property name="locale">
|
<property name="locale">
|
||||||
|
|
@ -812,11 +811,6 @@
|
||||||
<string>Compare results</string>
|
<string>Compare results</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_menu_edit_geotiff">
|
|
||||||
<property name="text">
|
|
||||||
<string>GeoTIFF</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue