#!/usr/bin/env python3 # -*- coding: utf-8 -*- ############################################################################ # # MODULE: circleKill.py # AUTHOR(S): Julien Veyssier # # # COPYRIGHT: (C) 2020 UR RIVERLY - INRAE # # This program is free software under the GNU General Public # License (>=v2). Read the file LICENSE that comes with # HRU-DELIN for details. # ############################################################################# import sys try: import dbf DBF=True except Exception as e: DBF=False print('!!! Warning, dbf python3 module not found, no topology dbf file will be generated') print('Install dbf module with: sudo apt install python3-dbf') print('or if you don\'t have superuser access: pip3 install dbf\n') separator=',' class Hru(): id = None toSubbasin = None toHruId = None def __init__(self, id, toSubbasin, toHruId): self.id = id self.toSubbasin = toSubbasin self.toHruId = toHruId def circleKill(inputPath, outputPath): hruList = importFile(inputPath) solveCircles(hruList) writeResult(hruList, outputPath) def importFile(path): hruList = [] with open(path, 'r') as f: line = f.readline() while line.startswith('#'): line = f.readline() while line and not line.startswith('#'): lineSpl = line.split(separator) hruId = int(lineSpl[0].strip()) toSubbasin = int(lineSpl[1].strip()) toHruId = int(lineSpl[2].strip()) hruList.append(Hru(hruId, toSubbasin, toHruId)) line = f.readline() return hruList def writeResult(hruList, path): parOutput = '%s.par' % path dbfOutput = '%s.dbf' % path # write .par file with open(parOutput, 'w') as fo: fo.write('# Adjusted flow relations\n') fo.write('# hruId "emergency exit" toHru\n') for hru in hruList: fo.write('%i,%i,%i\n' % (hru.id, hru.toSubbasin, hru.toHruId)) fo.write('# End of records') # write dbf file if possible if DBF: table = dbf.Table(dbfOutput, 'hruID N(8,0); notausgang N(8,0); to_hruID N(8,0)') table.open(mode=dbf.READ_WRITE) for hru in hruList: table.append((hru.id, hru.toSubbasin, hru.toHruId)) table.close() def solveCircles(hruList): # indexed by hru id => HRU hruMap = {} # indexed by hru id => int statusMap = {} for hru in hruList: hruMap[hru.id] = hru for currentHru in hruList: #print('Checking HRU %s for circles' % currentHru.id) for hru2 in hruList: statusMap[hru2.id] = 0 targetHru = currentHru continueSearch = True while continueSearch: if statusMap[targetHru.id] == 2: if currentHru.id == targetHru.id: # Circle detected. The drainage is diverted to the "emergency exit" toId = targetHru.toSubbasin targetHru.toHruId = toId continueSearch = False else: # However, not starting from the HRU studied, but in the further course of the flow cascade continueSearch = False elif targetHru.toHruId < 0: # No circle. Dewatering into a watercourse segment continueSearch = False else: # Continue searching in the flow cascade statusMap[targetHru.id] = 2 targetHru = hruMap[targetHru.toHruId] if __name__ == '__main__': if len(sys.argv) > 2: inPath = sys.argv[1] outPath = sys.argv[2] circleKill(inPath, outPath) else: sys.exit('Please provide two arguments: INPUT_PATH OUTPUT_PATH_PREFIX')