Skip to content

Commit

Permalink
Qgep swmm states (#55)
Browse files Browse the repository at this point in the history
* add state selection

* state choice

* check with gruner data

* check with gruner data

* check execute and extract functions

* bug with storage export

* change error message

* solve p8p errors

* solve p8p errors

* solve p8p errors

* solve p8p errors
  • Loading branch information
tproduit authored Dec 16, 2020
1 parent 35bd531 commit b46943e
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 36 deletions.
63 changes: 40 additions & 23 deletions qgepplugin/processing_provider/QgepSwmm.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,38 @@

class QgepSwmm:

def __init__(self, title, service, inpfile, inptemplate, outfile, logfile, binfile, db_model_path):
def __init__(self, title, service, state, inpfile, inptemplate, outfile, binfile, db_model_path):
"""
Initiate QgepSwmm
Parameters:
title (string): Title of the simulation
service (string): name of the service to be used to connect to the QGEP database
state (string): state for which the network is extracted (current or planned)
inpfile (path): path of the INP file (input file for swmm)
inptemplate (path): path of the INP file which store simulations parameters
outfile (path): path of the OUT file which contains swmm results
logfile (path): path of the log file which contains swmm log
binfile (path): path of the swmm executable
db_model_path (path): path of the folder which contains the db model
"""
self.title = title
self.service = service
self.input_file = inpfile
self.options_template_file = inptemplate
self.output_file = outfile
self.log_file = logfile
self.bin_file = binfile
self.db_model_path = db_model_path
self.feedbacks = []
self.state = state

def get_swmm_table(self, table_name):
def get_swmm_table(self, table_name, state, ws):
"""
Extract data from the swmm views in the database
Parameters:
table_name (string): Name of the view or table
state (string): current or planned
ws (boolean): if the origin table is a wastewater structure
Returns:
dic: table content
Expand All @@ -64,8 +67,16 @@ def get_swmm_table(self, table_name):
# Connects to service and get data and attributes from tableName
con = psycopg2.connect(service=self.service)
cur = con.cursor()
if (state == 'planned' and ws is True) or (state is None):
sql = 'select * from qgep_swmm.vw_{table_name}'.format(table_name=table_name)
else:
sql = """
select * from qgep_swmm.vw_{table_name}
where state = '{state}'
""".format(table_name=table_name, state=state)

try:
cur.execute('select * from qgep_swmm.vw_{table_name}'.format(table_name=table_name))
cur.execute(sql)
except psycopg2.ProgrammingError:
self.feedbacks.append('Table vw_{table_name} doesnt exists'.format(table_name=table_name))
return None, None
Expand All @@ -74,12 +85,16 @@ def get_swmm_table(self, table_name):

return data, attributes

def swmm_table(self, table_name):
def swmm_table(self, table_name, state=None, ws=False):
"""
Write swmm objects extracted from QGEP in swmm input file
Write swmm objects extracted from QGEP in swmm input file. Selects according
to the state planned or current. If the object is a qgep wastewater structure
when the state is "planned" both "planned" and "operational" wastewater structures are selected
Parameters:
table_name (string): Name of the swmm section
state (string): current or planned
ws (boolean): if the origin table is a wastewater structure
Returns:
String: table content
Expand All @@ -88,11 +103,11 @@ def swmm_table(self, table_name):

# Create commented line which contains the field names
fields = ""
data, attributes = self.get_swmm_table(table_name)
data, attributes = self.get_swmm_table(table_name, state, ws)
if data is not None:
for i, field in enumerate(attributes):
# Does not write values stored in columns descriptions, tags and geom
if field not in ('description', 'tag', 'geom'):
if field not in ('description', 'tag', 'geom', 'state'):
fields += field + "\t"

# Create input paragraph
Expand All @@ -108,7 +123,7 @@ def swmm_table(self, table_name):

for i, v in enumerate(feature):
# Does not write values stored in columns descriptions, tags and geom
if attributes[i] not in ('description', 'tag', 'geom'):
if attributes[i] not in ('description', 'tag', 'geom', 'state'):
if v is not None:
tbl += str(v) + '\t'
else:
Expand Down Expand Up @@ -158,6 +173,7 @@ def write_input(self):

# From qgis swmm
filename = self.input_file
state = self.state

with codecs.open(filename, 'w', encoding='utf-8') as f:

Expand All @@ -181,11 +197,11 @@ def write_input(self):

# Hydrology
# ----------
f.write(self.swmm_table('RAINGAGES'))
f.write(self.swmm_table('SUBCATCHMENTS'))
f.write(self.swmm_table('SUBAREAS'))
f.write(self.swmm_table('RAINGAGES', state))
f.write(self.swmm_table('SUBCATCHMENTS', state))
f.write(self.swmm_table('SUBAREAS', state))
f.write(self.swmm_table('AQUIFERS'))
f.write(self.swmm_table('INFILTRATION'))
f.write(self.swmm_table('INFILTRATION', state))
f.write(self.swmm_table('POLYGONS'))

f.write(self.copy_parameters_from_template('GROUNDWATER'))
Expand All @@ -196,26 +212,27 @@ def write_input(self):

# Hydraulics: nodes
# ------------------
f.write(self.swmm_table('JUNCTIONS'))
f.write(self.swmm_table('JUNCTIONS', state, ws=True))
# Create default junction to avoid errors
f.write('default_qgep_node\t0\t0\n\n')
f.write(self.swmm_table('OUTFALLS'))
f.write(self.swmm_table('STORAGE'))
f.write(self.swmm_table('OUTFALLS', state, ws=True))
f.write(self.swmm_table('STORAGES', state, ws=True))
f.write(self.swmm_table('COORDINATES'))
f.write(self.swmm_table('DWF'))
f.write(self.swmm_table('DWF', state))

f.write(self.copy_parameters_from_template('INFLOWS'))
f.write(self.copy_parameters_from_template('DIVIDERS'))

# Hydraulics: links
# ------------------
f.write(self.swmm_table('CONDUITS'))
f.write(self.swmm_table('PUMPS'))
f.write(self.swmm_table('CONDUITS', state, ws=True))
f.write(self.swmm_table('LOSSES', state, ws=True))
f.write(self.swmm_table('PUMPS', state, ws=True))
f.write(self.copy_parameters_from_template('ORIFICES'))
f.write(self.copy_parameters_from_template('WEIRS'))
f.write(self.copy_parameters_from_template('OUTLETS'))
f.write(self.swmm_table('XSECTIONS'))
f.write(self.swmm_table('LOSSES'))
f.write(self.swmm_table('XSECTIONS', state, ws=True))
f.write(self.swmm_table('LOSSES', state, ws=True))
f.write(self.swmm_table('VERTICES'))

f.write(self.copy_parameters_from_template('TRANSECTS'))
Expand Down Expand Up @@ -356,7 +373,7 @@ def execute_swmm(self):
"""

command = [self.bin_file, self.input_file, self.log_file, self.output_file]
command = [self.bin_file, self.input_file, self.output_file]
print('command', command)
proc = subprocess.run(
command,
Expand Down
20 changes: 15 additions & 5 deletions qgepplugin/processing_provider/swmm_create_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
QgsProcessingParameterString,
QgsProcessingParameterFile,
QgsProcessingParameterFileDestination,
QgsProcessingParameterEnum
)

from .qgep_algorithm import QgepAlgorithm
Expand All @@ -49,6 +50,7 @@ class SwmmCreateInputAlgorithm(QgepAlgorithm):
DATABASE = 'DATABASE'
TEMPLATE_INP_FILE = 'TEMPLATE_INP_FILE'
INP_FILE = 'INP_FILE'
STATE = 'STATE'

def name(self):
return 'swmm_create_input'
Expand All @@ -60,16 +62,20 @@ def initAlgorithm(self, config=None):
"""Here we define the inputs and output of the algorithm, along
with some other properties.
"""

self.stateOptions = ["current", "planned"]
# The parameters
description = self.tr('Database')
self.addParameter(QgsProcessingParameterString(
self.DATABASE, description=description, defaultValue="pg_qgep_demo_data"))

description = self.tr('State (current or planned)')
self.addParameter(QgsProcessingParameterEnum(
self.STATE, description=description, options=self.stateOptions, defaultValue=self.stateOptions[0]))

description = self.tr('Template INP File')
self.addParameter(QgsProcessingParameterFile(self.TEMPLATE_INP_FILE, description=description, extension="inp"))

description = self.tr('Result INP File')
description = self.tr('Destination INP File')
self.addParameter(QgsProcessingParameterFileDestination(
self.INP_FILE, description=description, fileFilter="inp (*.inp)"))

Expand All @@ -80,12 +86,16 @@ def processAlgorithm(self, parameters, context: QgsProcessingContext, feedback:

# init params
database = self.parameterAsString(parameters, self.DATABASE, context)
state = self.parameterAsString(parameters, self.STATE, context)
template_inp_file = self.parameterAsFile(parameters, self.TEMPLATE_INP_FILE, context)
inp_file = self.parameterAsFileOutput(parameters, self.INP_FILE, context)

state = self.stateOptions[int(state)]
if state not in ['current', 'planned']:
feedback.reportError('State must be "planned" or "current", state was set to "current"')
state = 'current'
# Connect to QGEP database and perform translation
qs = QgepSwmm(datetime.datetime.today().isoformat(), database,
inp_file, template_inp_file, None, None, None, None)
qs = QgepSwmm(datetime.datetime.today().isoformat(), database, state,
inp_file, template_inp_file, None, None, None)
qs.write_input()

if qs.feedbacks is not None:
Expand Down
13 changes: 6 additions & 7 deletions qgepplugin/processing_provider/swmm_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class SwmmExecuteAlgorithm(QgepAlgorithm):

INP_FILE = 'INP_FILE'
OUT_FILE = 'OUT_FILE'
LOG_FILE = 'LOG_FILE'
# LOG_FILE = 'LOG_FILE'

def name(self):
return 'swmm_execute'
Expand All @@ -72,15 +72,14 @@ def initAlgorithm(self, config=None):
self.addParameter(QgsProcessingParameterFileDestination(
self.OUT_FILE, description=description, fileFilter="out (*.out)"))

description = self.tr('LOG File')
self.addParameter(QgsProcessingParameterFileDestination(
self.LOG_FILE, description=description, fileFilter="log (*.log)"))
# description = self.tr('LOG File')
# self.addParameter(QgsProcessingParameterFileDestination(
# self.LOG_FILE, description=description, fileFilter="log (*.log)"))

def processAlgorithm(self, parameters, context: QgsProcessingContext, feedback: QgsProcessingFeedback):
"""Here is where the processing itself takes place."""

# init params
log_file = self.parameterAsFile(parameters, self.LOG_FILE, context)
output_file = self.parameterAsFile(parameters, self.OUT_FILE, context)
inp_file = self.parameterAsFileOutput(parameters, self.INP_FILE, context)
swmm_cli = os.path.abspath(ProcessingConfig.getSetting('SWMM_PATH'))
Expand All @@ -93,7 +92,7 @@ def processAlgorithm(self, parameters, context: QgsProcessingContext, feedback:
Please configure it before running Swmm algorithms.')
)

qs = QgepSwmm(None, None, inp_file, None, output_file, log_file, swmm_cli, None)
qs = QgepSwmm(None, None, None, inp_file, None, output_file, swmm_cli, None)
prompt = qs.execute_swmm()
if qs.feedbacks is not None:
for i in range(len(qs.feedbacks)):
Expand All @@ -103,7 +102,7 @@ def processAlgorithm(self, parameters, context: QgsProcessingContext, feedback:

if re.search('There are errors', prompt):
feedback.reportError(prompt)
feedback.reportError('There were errors, look into logs for details: {log_file}'.format(log_file=log_file))
feedback.reportError('There were errors, run the file in SWMM GUI for more details')

feedback.setProgress(100)

Expand Down
2 changes: 1 addition & 1 deletion qgepplugin/processing_provider/swmm_extract_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def processAlgorithm(self, parameters, context: QgsProcessingContext, feedback:
raise QgsProcessingException(self.invalidSinkError(parameters, self.NODE_SUMMARY))

# Get node summary from output file
qs = QgepSwmm(None, None, None, None, out_file, None, None, None)
qs = QgepSwmm(None, None, None, None, None, out_file, None, None)
if qs.feedbacks is not None:
for i in range(len(qs.feedbacks)):
feedback.reportError(qs.feedbacks[i])
Expand Down

0 comments on commit b46943e

Please sign in to comment.