Export Adis to csv

adists_release
Theophile Terraz 2024-12-20 10:05:56 +01:00
parent e4bffce6f4
commit 5edcf15072
4 changed files with 386 additions and 58 deletions

View File

@ -0,0 +1,129 @@
# CustomPlotValuesSelectionDialog.py -- Pamhyr
# Copyright (C) 2023-2024 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 View.Tools.PamhyrWindow import PamhyrDialog
from PyQt5.QtWidgets import (
QRadioButton, QCheckBox, QVBoxLayout,
)
from View.Results.translate import ResultsTranslate
class CustomExportAdisDialog(PamhyrDialog):
_pamhyr_ui = "CustomExportAdisDialog"
_pamhyr_name = "Custom Plot Selection"
def __init__(self, pollutants, parent=None):
trad = ResultsTranslate()
super(CustomExportAdisDialog, self).__init__(
title=trad[self._pamhyr_name],
options=[],
trad=trad,
parent=parent
)
if pollutants is not None:
self.pollutants = pollutants
if "total_sediment" in self.pollutants:
self.pollutants.remove("total_sediment")
else:
self.pollutants = pollutants
self._available_values_x = self._trad.get_dict("values_x")
self._available_values_y = self._trad.get_dict("values_y_pol")
self.setup_radio_buttons_x()
self.setup_radio_buttons_pol()
self.setup_check_boxes()
self.value = None
def setup_radio_buttons_x(self):
self._radio = []
layout = self.find(QVBoxLayout, "verticalLayout_x")
for value in self._available_values_x:
btn = QRadioButton(
self._available_values_x[value],
parent=self
)
self._radio.append((value, btn))
layout.addWidget(btn)
self._radio[0][1].setChecked(True)
layout.addStretch()
def setup_radio_buttons_pol(self):
self._radio2 = []
layout = self.find(QVBoxLayout, "verticalLayout_pol")
for value in self.pollutants:
btn = QRadioButton(
value,
parent=self
)
self._radio2.append((value, btn))
layout.addWidget(btn)
self._radio2[0][1].setChecked(True)
layout.addStretch()
def setup_check_boxes(self):
self._check = []
layout = self.find(QVBoxLayout, "verticalLayout_y")
for value in self._available_values_y:
btn = QCheckBox(
self._available_values_y[value],
parent=self
)
self._check.append((value, btn))
layout.addWidget(btn)
self._check[0][1].setChecked(True)
layout.addStretch()
def accept(self):
x = next(
filter(
lambda r: r[1].isChecked(),
self._radio
)
)[0]
y = list(
map(
lambda b: b[0],
filter(
lambda b: b[1].isChecked(),
self._check
)
)
)
pol = next(
filter(
lambda r: r[1].isChecked(),
self._radio2
)
)[0]
self.value = x, y, pol
super().accept()

View File

@ -614,13 +614,13 @@ class ResultsWindow(PamhyrWindow):
if x == "rk": if x == "rk":
timestamp = self._get_current_timestamp() timestamp = self._get_current_timestamp()
first_line.append(f"Time: {timestamp}s") first_line.append(f"Time: {timestamp}s")
val_dict = self._export_rk(timestamp, y, envelop, filename) val_dict = self._export_rk(timestamp, y, envelop)
elif x == "time": elif x == "time":
profile_id = self._get_current_profile() profile_id = self._get_current_profile()
profile = reach.profile(profile_id) profile = reach.profile(profile_id)
pname = profile.name if profile.name != "" else profile.rk pname = profile.name if profile.name != "" else profile.rk
first_line.append(f"Profile: {pname}") first_line.append(f"Profile: {pname}")
val_dict = self._export_time(profile_id, y, filename) val_dict = self._export_time(profile_id, y)
with open(filename, 'w', newline='') as csvfile: with open(filename, 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=',', writer = csv.writer(csvfile, delimiter=',',
@ -675,7 +675,7 @@ class ResultsWindow(PamhyrWindow):
self._additional_plot.pop(tab_widget.tabText(index)) self._additional_plot.pop(tab_widget.tabText(index))
tab_widget.removeTab(index) tab_widget.removeTab(index)
def _export_rk(self, timestamp, y, envelop, filename): def _export_rk(self, timestamp, y, envelop):
reach = self._results.river.reachs[self._get_current_reach()] reach = self._results.river.reachs[self._get_current_reach()]
dict_x = self._trad.get_dict("values_x") dict_x = self._trad.get_dict("values_x")
dict_y = self._trad.get_dict("values_y") dict_y = self._trad.get_dict("values_y")
@ -807,7 +807,7 @@ class ResultsWindow(PamhyrWindow):
return my_dict return my_dict
def _export_time(self, profile, y, filename): def _export_time(self, profile, y):
reach = self._results.river.reachs[self._get_current_reach()] reach = self._results.river.reachs[self._get_current_reach()]
profile = reach.profile(profile) profile = reach.profile(profile)
ts = list(self._results.get("timestamps")) ts = list(self._results.get("timestamps"))

View File

@ -49,8 +49,8 @@ from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
from View.Results.PlotSedAdis import PlotAdis_dx, PlotAdis_dt from View.Results.PlotSedAdis import PlotAdis_dx, PlotAdis_dt
from View.Results.CustomPlot.Plot import CustomPlot from View.Results.CustomPlot.Plot import CustomPlot
from View.Results.CustomPlot.CustomPlotValuesSelectionDialog import ( from View.Results.CustomExportAdis import (
CustomPlotValuesSelectionDialog, CustomExportAdisDialog,
) )
from View.Results.TableAdisTS import TableModel from View.Results.TableAdisTS import TableModel
@ -100,7 +100,7 @@ class ResultsWindowAdisTS(PamhyrWindow):
self._hash_data.append(self._results) self._hash_data.append(self._results)
self._additional_plot = {} self._additional_plot = {}
self._pol_id = [1] self._current_pol_id = [1]
self._reach_id = 0 self._reach_id = 0
self._profile_id = 0 self._profile_id = 0
@ -114,22 +114,25 @@ class ResultsWindowAdisTS(PamhyrWindow):
self.setup_connections() self.setup_connections()
self.update_table_selection_reach(self._reach_id) self.update_table_selection_reach(self._reach_id)
self.update_table_selection_profile(self._profile_id) self.update_table_selection_profile(self._profile_id)
self.update_table_selection_pol(self._pol_id) self.update_table_selection_pol(self._current_pol_id)
except Exception as e: except Exception as e:
logger_exception(e) logger_exception(e)
return return
def set_type_pol(self): def set_type_pol(self):
self._type_pol = [] self._type_pol = []
self._pol_id_dict = {}
tmp_list = self._results.river.reach(0).profiles tmp_list = self._results.river.reach(0).profiles
for pol_index in range(self._results.nb_pollutants): for pol_index in range(self._results.nb_pollutants):
if self._results.pollutants_list[pol_index] == "total_sediment": pol_name = self._results.pollutants_list[pol_index]
if pol_name == "total_sediment":
self._type_pol.append(-1) self._type_pol.append(-1)
else: else:
self._type_pol.append(len( self._type_pol.append(len(
tmp_list[0].get_ts_key( tmp_list[0].get_ts_key(
self._timestamps[0], "pols")[pol_index]) self._timestamps[0], "pols")[pol_index])
) )
self._pol_id_dict[pol_name] = pol_index
def setup_table(self): def setup_table(self):
self._table = {} self._table = {}
@ -187,7 +190,7 @@ class ResultsWindowAdisTS(PamhyrWindow):
results=self._results, results=self._results,
reach_id=self._reach_id, reach_id=self._reach_id,
profile_id=self._profile_id, profile_id=self._profile_id,
pol_id=self._pol_id, pol_id=self._current_pol_id,
key="C", key="C",
type_pol=self._type_pol, type_pol=self._type_pol,
trad=self._trad, trad=self._trad,
@ -213,7 +216,7 @@ class ResultsWindowAdisTS(PamhyrWindow):
results=self._results, results=self._results,
reach_id=self._reach_id, reach_id=self._reach_id,
profile_id=self._profile_id, profile_id=self._profile_id,
pol_id=self._pol_id, pol_id=self._current_pol_id,
key="C", key="C",
type_pol=self._type_pol, type_pol=self._type_pol,
trad=self._trad, trad=self._trad,
@ -239,7 +242,7 @@ class ResultsWindowAdisTS(PamhyrWindow):
results=self._results, results=self._results,
reach_id=self._reach_id, reach_id=self._reach_id,
profile_id=self._profile_id, profile_id=self._profile_id,
pol_id=self._pol_id, pol_id=self._current_pol_id,
key="M", key="M",
type_pol=self._type_pol, type_pol=self._type_pol,
trad=self._trad, trad=self._trad,
@ -266,7 +269,7 @@ class ResultsWindowAdisTS(PamhyrWindow):
results=self._results, results=self._results,
reach_id=self._reach_id, reach_id=self._reach_id,
profile_id=self._profile_id, profile_id=self._profile_id,
pol_id=self._pol_id, pol_id=self._current_pol_id,
key="M", key="M",
type_pol=self._type_pol, type_pol=self._type_pol,
trad=self._trad, trad=self._trad,
@ -475,6 +478,7 @@ class ResultsWindowAdisTS(PamhyrWindow):
def update(self, reach_id=None, profile_id=None, def update(self, reach_id=None, profile_id=None,
pol_id=None, timestamp=None): pol_id=None, timestamp=None):
if reach_id is not None: if reach_id is not None:
self._reach_id = reach_id
self.plot_cdt.set_reach(reach_id) self.plot_cdt.set_reach(reach_id)
self.plot_cdx.set_reach(reach_id) self.plot_cdx.set_reach(reach_id)
self.plot_mdx.set_reach(reach_id) self.plot_mdx.set_reach(reach_id)
@ -486,6 +490,7 @@ class ResultsWindowAdisTS(PamhyrWindow):
self.update_table_selection_profile(0) self.update_table_selection_profile(0)
if profile_id is not None: if profile_id is not None:
self._profile_id = profile_id
self.plot_cdt.set_profile(profile_id) self.plot_cdt.set_profile(profile_id)
self.plot_cdx.set_profile(profile_id) self.plot_cdx.set_profile(profile_id)
self.plot_mdx.set_profile(profile_id) self.plot_mdx.set_profile(profile_id)
@ -496,11 +501,11 @@ class ResultsWindowAdisTS(PamhyrWindow):
self.update_table_selection_profile(profile_id) self.update_table_selection_profile(profile_id)
if pol_id is not None: if pol_id is not None:
self._pol_id = [p+1 for p in pol_id] # remove total_sediment self._current_pol_id = [p+1 for p in pol_id] # remove total_sediment
self.plot_cdt.set_pollutant(self._pol_id) self.plot_cdt.set_pollutant(self._current_pol_id)
self.plot_cdx.set_pollutant(self._pol_id) self.plot_cdx.set_pollutant(self._current_pol_id)
self.plot_mdx.set_pollutant(self._pol_id) self.plot_mdx.set_pollutant(self._current_pol_id)
self.plot_mdt.set_pollutant(self._pol_id) self.plot_mdt.set_pollutant(self._current_pol_id)
if timestamp is not None: if timestamp is not None:
self.plot_cdt.set_timestamp(timestamp) self.plot_cdt.set_timestamp(timestamp)
@ -635,53 +640,143 @@ class ResultsWindowAdisTS(PamhyrWindow):
self._button_play.setIcon(self._icon_start) self._button_play.setIcon(self._icon_start)
def export(self): def export(self):
pols = self._results.pollutants_list.copy()
dlg = CustomExportAdisDialog(pollutants=pols,
parent=self)
if dlg.exec():
x, y, pol = dlg.value
else:
return
self.file_dialog( self.file_dialog(
select_file=False, select_file="AnyFile",
callback=lambda d: self.export_to(d[0]) callback=lambda f: self.export_to(f[0], x, y, pol),
default_suffix=".csv",
file_filter=["CSV (*.csv)"],
) )
def export_to(self, directory): def export_to(self, filename, x, y, pol):
for reach in self._results.river.reachs: timestamps = sorted(self._results.get("timestamps"))
self.export_reach(reach, directory) reach = self._results.river.reachs[self._reach_id]
first_line = [f"Study: {self._results.study.name}",
def export_reach(self, reach, directory): f"Reach: {reach.name}"]
name = reach.name if x == "rk":
name = name.replace(" ", "-") timestamp = self._get_current_timestamp()
first_line.append(f"Time: {timestamp}s")
file_name = os.path.join( val_dict = self._export_rk(timestamp, y, pol)
directory, elif x == "time":
f"reach_{name}.csv" profile = reach.profile(self._profile_id)
) pname = profile.name if profile.name != "" else profile.rk
first_line.append(f"Profile: {pname}")
with open(file_name, 'w', newline='') as csvfile: val_dict = self._export_time(self._profile_id, y, pol)
with open(filename, 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=',', writer = csv.writer(csvfile, delimiter=',',
quotechar='|', quoting=csv.QUOTE_MINIMAL) quotechar='|', quoting=csv.QUOTE_MINIMAL)
writer.writerow(["name", "rk", "data-file"]) dict_x = self._trad.get_dict("values_x")
for profile in reach.profiles: header = []
p_file_name = os.path.join( writer.writerow(first_line)
directory, for text in val_dict.keys():
f"cs_{profile.geometry.id}.csv" header.append(text)
) writer.writerow(header)
for row in range(len(val_dict[dict_x[x]])):
line = []
for var in val_dict.keys():
line.append(val_dict[var][row])
writer.writerow(line)
writer.writerow([ def _export_rk(self, timestamp, y, pol):
profile.name, reach = self._results.river.reachs[self._reach_id]
profile.rk, dict_x = self._trad.get_dict("values_x")
p_file_name dict_y = self._trad.get_dict("values_y_pol")
]) my_dict = {}
my_dict[dict_x["rk"]] = reach.geometry.get_rk()
val_id = {}
val_id["unit_C"] = 0
val_id["unit_M"] = 2
val_id["unit_thickness"] = 2
for unit in y:
if unit == "unit_thickness":
pol_id = 0
else:
pol_id = self._pol_id_dict[pol]
if unit == "unit_M" and self._type_pol[pol_id] == 1:
my_dict[dict_y[unit]] = [0.0]*len(reach.profiles)
else:
my_dict[dict_y[unit]] = list(map(lambda p:
p.get_ts_key(
timestamp, "pols"
)[pol_id][val_id[unit]],
reach.profiles))
self.export_profile(reach, profile, p_file_name) return my_dict
def export_profile(self, reach, profile, file_name): def _export_time(self, profile, y, pol):
with open(file_name, 'w', newline='') as csvfile: reach = self._results.river.reachs[self._reach_id]
writer = csv.writer(csvfile, delimiter=',', profile = reach.profile(profile)
quotechar='|', quoting=csv.QUOTE_MINIMAL) ts = list(self._results.get("timestamps"))
ts.sort()
dict_x = self._trad.get_dict("values_x")
dict_y = self._trad.get_dict("values_y_pol")
my_dict = {}
my_dict[dict_x["time"]] = ts
val_id = {}
val_id["unit_C"] = 0
val_id["unit_M"] = 2
val_id["unit_thickness"] = 2
for unit in y:
if unit == "unit_thickness":
pol_id = 0
else:
pol_id = self._pol_id_dict[pol]
if unit == "unit_M" and self._type_pol[pol_id] == 1:
my_dict[dict_y[unit]] = [0.0]*len(ts)
else:
my_dict[dict_y[unit]] = list(map(lambda data_el:
data_el[pol_id][val_id[unit]],
profile.get_key("pols")
))
writer.writerow(["timestamp", "z", "q"]) return my_dict
timestamps = sorted(self._results.get("timestamps"))
for ts in timestamps: #def export_reach(self, reach, directory):
writer.writerow([ #name = reach.name
ts, #name = name.replace(" ", "-")
profile.get_ts_key(ts, "Z"),
profile.get_ts_key(ts, "Q"), #file_name = os.path.join(
]) #directory,
#f"reach_{name}.csv"
#)
#with open(file_name, 'w', newline='') as csvfile:
#writer = csv.writer(csvfile, delimiter=',',
#quotechar='|', quoting=csv.QUOTE_MINIMAL)
#writer.writerow(["name", "rk", "data-file"])
#for profile in reach.profiles:
#p_file_name = os.path.join(
#directory,
#f"cs_{profile.geometry.id}.csv"
#)
#writer.writerow([
#profile.name,
#profile.rk,
#p_file_name
#])
#self.export_profile(reach, profile, p_file_name)
#def export_profile(self, reach, profile, file_name):
#with open(file_name, 'w', newline='') as csvfile:
#writer = csv.writer(csvfile, delimiter=',',
#quotechar='|', quoting=csv.QUOTE_MINIMAL)
#writer.writerow(["timestamp", "z", "q"])
#timestamps = sorted(self._results.get("timestamps"))
#for ts in timestamps:
#writer.writerow([
#ts,
#profile.get_ts_key(ts, "Z"),
#profile.get_ts_key(ts, "Q"),
#])

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>194</width>
<height>70</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_x">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>X axis:</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="verticalLayoutWidget_2">
<layout class="QVBoxLayout" name="verticalLayout_y">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Y axis:</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="verticalLayoutWidget_3">
<layout class="QVBoxLayout" name="verticalLayout_pol">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Pollutant:</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>