Exemple #1
0
 def visualise(self):
     """Run visualise form."""
     # avoid getting second window
     if self.vis is not None and self.vis._dlg.isEnabled():
         self.vis._dlg.close()
     self.vis = Visualise(self._gv)
     self.vis.run()
Exemple #2
0
def main():
    if len(sys.argv) != 2:
        err_exit("Usage: ./app.py [QUERY_STRING]")

    total = {}
    duct = make_search(sys.argv[1])
    total.update(duct)
    for x in range(1):
        total.update(make_iteration(total))
    visu = Visualise()
    visu.visualise_data(total)
Exemple #3
0
class Engine(object):
    """
    classdocs
    """

    def __init__(self):
        """
        Constructor
        """
        self._logger = None
        self._board = None
        self._players = []

        self.validity_test_id = 0
        self.validity_testing = False
        self.validity_test_last_result = 0
        self.validity_test_results = []

        # number of captured stones (not the positions of captures)
        self._captures = [0, 0]
        # list of Move objects
        self._moves = []
        # visualisation utilities
        self._vis = None

    # ---------------------------
    # gtp interface functions
    # ---------------------------

    def boardsize(self, size):
        """ set the board size. """
        self._board.resize(int(size))

    def clear_board(self):
        self._board.reset()
        # TODO: reset other state stuff here if necessary

    def komi(self, value):
        pass

    def play(self, color, vertex):
        vertex = Utils.parse_vertex(vertex, self._board.size)  # may be None
        color = 1 if color[0].lower() == "b" else 2
        self.apply_move(vertex, color)

    def genmove(self, colour):
        """ Ask the appropriate player to generate a move. """
        colour = Utils.parse_colour(colour)

        # generate move
        move = self._players[colour - 1].genmove()

        self.apply_move(move, colour)
        # make GTP result string ...
        return Utils.make_vertex(move[0], move[1], self._board.size)

    def apply_move(self, vertex, colour):
        """ apply move to engine (and players). """
        captures = []

        self.validity_test_last_result = Utils.valid_coord(vertex, self.board.size)

        # check the validity of the move and determine any resulting captures
        self.validity_test_last_result = self.validity_test_last_result and Utils.check_move(
            self._board, vertex, colour, captures
        )

        if not self.validity_test_last_result:
            raise Exception("you played an invalid move: " + str(colour) + " " + str(vertex))

        self._moves.append(Move(vertex, colour, captures))

        # place the stone
        self._board.set_stone(vertex, colour)

        # apply any resulting captures
        self._board.remove_stones(captures)

        # apply influence values to board squares
        Utils.calc_influence(self._board)

        self._players[0].play(vertex, colour)
        self._players[1].play(vertex, colour)

    def show_influence(self):
        return Utils.show_influence(self._board)

    def vis_influence(self):
        if self._vis is None:
            self._vis = Visualise()
        self._vis.visualise_influence(self._board, 0)

    def quit(self):
        sys.exit(0)

    def showboard(self):
        """ print board to stdout. """
        self._logger.log_console(str(self._board))

    def name(self):
        return "meijin"

    # ---------------------------
    # non gtp interface functions
    # ---------------------------

    def set_logger(self, logger):
        self._logger = logger
        Utils.set_logger(logger)

    def get_logger(self):
        return self._logger

    logger = property(get_logger, set_logger)

    def set_board(self, board):
        self._board = board

    def get_board(self):
        """ get a clone of the current board."""
        """inefficient but the dup here prevents accidental modification of my board instance."""
        return self._board  # .dup()

    board = property(get_board, set_board)

    def set_players(self, p1, p2):
        self._players = [p1, p2]

    def undo(self):
        m = self._moves.pop()
        enemy_colour = 1 if m.c == 2 else 2
        # remove the stone that was placed
        self._board.set_stone(m.p, 3)
        # replace captured stones
        for c in m.caps:
            self._board.set_stone(c, enemy_colour)
        # tell players to update their state
        for p in self._players:
            p.undo()

    def start_validity_test(self, id):
        self.validity_test_id = int(id)
        self.validity_testing = True
        self.validity_test_last_result = 0

    def check_validity_test(self, result):
        if self.validity_test_last_result == int(result):
            self.validity_test_results.append((self.validity_test_id, True))
        else:
            self.validity_test_results.append((self.validity_test_id, False))

    def print_validity_test_results(self):
        for id_, result in self.validity_test_results:
            self._logger.logTestout("[" + str(id) + "] ")
            if result:
                self._logger.logTestout("PASS\n")
            else:
                self._logger.logTestout("FAIL\n")

    def set_testout_only(self):
        self._logger.set_testout_only()
Exemple #4
0
 def vis_influence(self):
     if self._vis is None:
         self._vis = Visualise()
     self._vis.visualise_influence(self._board, 0)
Exemple #5
0
class QSWATPlus(QObject):
    """QGIS plugin to prepare geographic data for SWAT+ Editor."""
    
    __version__ = '1.2.2'

    def __init__(self, iface):
        """Constructor."""
        
        QObject.__init__(self)
        
        # this import is a dependency on a Cython produuced .pyd or .so file which will fail if the wrong architecture
        # and so gives an immediate exit before the plugin is loaded
        ## flag to show if init ran successfully
        self.loadFailed = False
        try:
            import dataInC  # @UnusedImport
        except Exception:
            QSWATUtils.loginfo('Failed to load Cython module: wrong architecture?: {0}'.format(traceback.format_exc()))
            self.loadFailed = True
            return
        # uncomment next line for debugging
        # import pydevd; pydevd.settrace()
        # Save reference to the QGIS interface
        self._iface = iface
        # initialize plugin directory
        ## plugin directory
        self.plugin_dir = os.path.dirname(__file__)
        # add to PYTHONPATH
        sys.path.append(self.plugin_dir)
        settings = QSettings()
        # initialize locale
        # in testing with a dummy iface object this settings value can be None
        try:
            locale = settings.value("locale/userLocale")[0:2]
        except Exception:
            locale = 'en'
        localePath = os.path.join(self.plugin_dir, 'i18n', 'qswat_{}.qm'.format(locale))
        # set default behaviour for loading files with no CRS to prompt - the safest option
        settings.setValue('Projections/defaultBehaviour', 'prompt')
        ## translator
        if os.path.exists(localePath):
            self.translator = QTranslator()
            self.translator.load(localePath)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)
                
        self._gv = None  # set later
        # font = QFont('MS Shell Dlg 2', 8)
        try:
            pointSize = int(settings.value('/QSWATPlus/FontSize'))
        except Exception:
            pointSize = 8
        self.setUbuntuFont(pointSize)
        # an experiment - probably not use
        # self.setStyles()
        # Create the dialog (after translation) and keep reference
        self._odlg = QSwatDialog()
        self._odlg.setWindowFlags(self._odlg.windowFlags() & ~Qt.WindowContextHelpButtonHint & Qt.WindowMinimizeButtonHint)
        self._odlg.move(0, 0)
        #=======================================================================
        # font = self._odlg.font()
        # fm = QFontMetrics(font)
        # txt = 'The quick brown fox jumps over the lazy dog.'
        # family = font.family()
        # size = font.pointSize()
        # QSWATUtils.information('Family: {2}.  Point size: {3!s} (intended {4!s}).\nWidth of "{0}" is {1} pixels.'.format(txt, fm.width(txt), family, size, pointSize), False)
        #=======================================================================
        self._odlg.setWindowTitle('QSWAT+ {0}'.format(QSWATPlus.__version__))
        # flag used in initialising delineation form
        self._demIsProcessed = False
        ## deineation window
        self.delin = None
        ## create hrus window
        self.hrus = None
        ## visualise window
        self.vis = None
        
        # report QGIS version
        QSWATUtils.loginfo('QGIS version: {0}; QSWAT+ version: {1}'.format(Qgis.QGIS_VERSION, QSWATPlus.__version__))

    def initGui(self):
        """Create QSWAT button in the toolbar."""
        if self.loadFailed:
            return
        ## Action that will start plugin configuration
        self.action = QAction(
            QIcon(":/plugins/QSWATPlus/swatplus32.png"),
            '{0}'.format(QSWATUtils._QSWATNAME), self._iface.mainWindow())
        # connect the action to the run method
        self.action.triggered.connect(self.run)

        # Add toolbar button and menu item
        self._iface.addToolBarIcon(self.action)
        self._iface.addPluginToMenu('&{0}'.format(QSWATUtils._QSWATNAME), self.action)

    def unload(self):
        """Remove the QSWAT menu item and icon."""
        # allow for it not to have been loaded
        try:
            self._iface.removePluginMenu('&{0}'.format(QSWATUtils._QSWATNAME), self.action)
            self._iface.removeToolBarIcon(self.action)
        except Exception:
            pass

    def run(self):
        """Run QSWAT."""
        self._odlg.reportsBox.setVisible(False)
        self._odlg.reportsLabel.setVisible(False)
        self._odlg.reportsBox.clear()
        self._odlg.reportsBox.addItem(QSWATUtils.trans('Select report to view'))
        self._odlg.finished.connect(self.finish)
        # connect buttons
        self._odlg.aboutButton.clicked.connect(self.about)
        self._odlg.newButton.clicked.connect(self.newProject)
        self._odlg.existingButton.clicked.connect(self.existingProject)
        self._odlg.delinButton.clicked.connect(self.doDelineation)
        self._odlg.hrusButton.clicked.connect(self.doCreateHRUs)
        self._odlg.editButton.clicked.connect(self.startEditor)
        self._odlg.visualiseButton.clicked.connect(self.visualise)
        self._odlg.paramsButton.clicked.connect(self.runParams)
        self._odlg.reportsBox.activated.connect(self.showReport)
        self._odlg.exportButton.clicked.connect(self.exportTable)
        self.initButtons()
        self._odlg.projPath.setText('')
        # make sure we clear data from previous runs
        self.delin = None
        self.hrus = None
        self.vis = None
        # show the dialog
        self._odlg.show()
        # initially only new/existing project buttons visible if project not set
        proj = QgsProject.instance()
        if proj.fileName() == '':
            self._odlg.mainBox.setVisible(False)
            self._odlg.exportButton.setVisible(False)
        else:
            self._iface.mainWindow().setCursor(Qt.WaitCursor)
            self.setupProject(proj, False)
            self._iface.mainWindow().setCursor(Qt.ArrowCursor)
        # Run the dialog event loop
        result = self._odlg.exec_()
        # See if OK was pressed
        if result == 1:
            proj.write()
        
    def initButtons(self):
        """Initial button settings."""
        self._odlg.delinLabel.setText('Step 1')
        self._odlg.hrusLabel.setText('Step 2')
        self._odlg.hrusLabel.setEnabled(False)
        self._odlg.hrusButton.setEnabled(False)
        self._odlg.editLabel.setEnabled(False)
        self._odlg.editButton.setEnabled(False)
        self._odlg.visualiseLabel.setVisible(False)
        self._odlg.visualiseButton.setVisible(False)

    def about(self):
        """Show information about QSWAT."""
        form = AboutQSWAT(self._gv)
        form.run(QSWATPlus.__version__)
        
    def setUbuntuFont(self, ptSize):
        """Set Ubuntu font."""
        QFontDatabase.addApplicationFont(":/fonts/Ubuntu-B.ttf")
        QFontDatabase.addApplicationFont(":/fonts/Ubuntu-BI.ttf")
        QFontDatabase.addApplicationFont(":/fonts/Ubuntu-C.ttf")
        QFontDatabase.addApplicationFont(":/fonts/Ubuntu-L.ttf")
        QFontDatabase.addApplicationFont(":/fonts/Ubuntu-LI.ttf")
        QFontDatabase.addApplicationFont(":/fonts/Ubuntu-M.ttf")
        QFontDatabase.addApplicationFont(":/fonts/Ubuntu-MI.ttf")
        QFontDatabase.addApplicationFont(":/fonts/Ubuntu-R.ttf")
        QFontDatabase.addApplicationFont(":/fonts/Ubuntu-RI.ttf")
        ufont = QFont("Ubuntu", ptSize, 1)
        QApplication.setFont(ufont)
        QSWATUtils.loginfo('Ubuntu {0} point font set'.format(ptSize))
        
#     def setStyles(self):
#         """Set stle sheet values"""
#         QApplication.instance().setStyleSheet("""
#             QDialog[QSWATDialog=true] {
#                 background-color: white
#                 }
#             QPushButton {
#                 color: white
#                 }
#             QPushButton[browseButton=true] {
#                 color: white;
#                 background-color: blue
#                 }
#             QPushButton[okButton=true] {
#                 color: white;
#                 background-color: green
#                 }
#             QPushButton[cancelButton=true] {
#                 background-color: grey
#                 }
#         """)
        
    def newProject(self):
        """Call QGIS actions to create and name a new project."""
        settings = QSettings()
        if settings.contains('/QSWATPlus/LastInputPath'):
            path = settings.value('/QSWATPlus/LastInputPath')
        else:
            path = ''
        title = 'Select parent directory'
        parentDir = QFileDialog.getExistingDirectory(None, title, path)
        if parentDir is not None and os.path.isdir(parentDir):
            projName, ok = QInputDialog.getText(None, 'Project name', 'Please enter the project name, starting with a letter:')
            if not ok:
                return
            if not projName[0].isalpha():
                QSWATUtils.error('Project name must start with a letter', False)
                return
            projDir = QSWATUtils.join(parentDir, projName)
            if os.path.exists(projDir):
                response = QSWATUtils.question('Project directory {0} already exists.  Do you wish to delete it?'.format(projDir), False, False)
                if response != QMessageBox.Yes:
                    return
                shutil.rmtree(projDir, True)
            try: 
                os.mkdir(projDir)
            except Exception:
                QSWATUtils.exceptionError('Failed to create project directory {0}'.format(projDir), False)
                return
            self._iface.newProject()
            projFile = QSWATUtils.join(projDir, projName + '.qgs')
            proj = QgsProject.instance()
            proj.setFileName(projFile)
            QSWATUtils.loginfo('Project file is {0}'.format(projFile))
            self._iface.actionSaveProject().trigger()
            # allow time for project to be created
            time.sleep(2)
            self.initButtons()
            settings.setValue('/QSWATPlus/LastInputPath', str(projDir))
            self._odlg.raise_()
            self.setupProject(proj, False)
            self._gv.writeProjectConfig(0, 0)
        
    def existingProject(self):
        """Open an existing QGIS project."""
        self._iface.actionOpenProject().trigger()
        # allow time for project to be opened
        time.sleep(2)
        proj = QgsProject.instance()
        if proj.fileName() == '':
            QSWATUtils.error('No project opened', False)
            return
        self._odlg.raise_()
        self.setupProject(proj, False)
    
    def setupProject(self, proj, isBatch):
        """Set up the project."""
        self._odlg.mainBox.setVisible(True)
        self._odlg.mainBox.setEnabled(False)
        self._odlg.setCursor(Qt.WaitCursor)
        self._odlg.projPath.setText('Restarting project ...')
        proj.setTitle(QFileInfo(proj.fileName()).baseName())
        # now have project so initiate global vars
        # if we do this earlier we cannot for example find the project database
        self._gv = GlobalVars(self._iface, QSWATPlus.__version__, self.plugin_dir, isBatch)
        if self._gv.SWATPlusDir == '':
            # failed to find SWATPlus directory
            return
        self._odlg.projPath.repaint()
        self.checkReports()
        self.setLegendGroups()
        # enable edit button if converted from Arc with 'No GIS' option
        title = proj.title()
        choice, found = proj.readNumEntry(title, 'fromArc', -1)
        if found:
            self._gv.fromArcChoice = choice
            if choice == 2:  # NB value from convertFromArc.py
                self._odlg.editLabel.setEnabled(True)
                self._odlg.editButton.setEnabled(True)
        if self.demProcessed():
            self._demIsProcessed = True
            self.allowCreateHRU()
            self.hrus = HRUs(self._gv, self._odlg.reportsBox)
            #result = hrus.tryRun()
            #if result == 1:
            if self.hrus.HRUsAreCreated():
                QSWATUtils.progress('Done', self._odlg.hrusLabel)
                self.showReports()
                self._odlg.editLabel.setEnabled(True)
                self._odlg.editButton.setEnabled(True)
        if os.path.exists(QSWATUtils.join(self._gv.resultsDir, Parameters._OUTPUTDB)):
            self._odlg.visualiseLabel.setVisible(True)
            self._odlg.visualiseButton.setVisible(True)
        self._odlg.projPath.setText(self._gv.projDir)
        self._odlg.mainBox.setEnabled(True)
        self._odlg.exportButton.setVisible(True)
        self._odlg.setCursor(Qt.ArrowCursor)
            
    def runParams(self):
        """Run parameters form."""
        params = Parameters(self._gv)
        params.run()
        
    def showReport(self):
        """Display selected report."""
        if not self._odlg.reportsBox.hasFocus():
            return
        item = self._odlg.reportsBox.currentText()
        if item == Parameters._TOPOITEM:
            report = Parameters._TOPOREPORT
        elif item == Parameters._BASINITEM:
            report = Parameters._BASINREPORT
        elif item == Parameters._HRUSITEM:
            report = Parameters._HRUSREPORT
        else:
            return
        report = QSWATUtils.join(self._gv.textDir, report)
        if not os.path.exists(report):
            QSWATUtils.error('Cannot find report {0}'.format(report))
            return
        if Parameters._ISWIN : # Windows
            os.startfile(report)
        elif os.name == 'posix': # Linux
            subprocess.call(('xdg-open', report))
        self._odlg.reportsBox.setCurrentIndex(0)
        
    def exportTable(self):
        """Run export table form."""
        export = ExportTable(self._gv)
        export.run()
        
    def checkReports(self):
        """Add existing reports to reports box and if there are some make it visible."""
        makeVisible = False
        topoReport = QSWATUtils.join(self._gv.textDir, Parameters._TOPOREPORT)
        if os.path.exists(topoReport) and self._odlg.reportsBox.findText(Parameters._TOPOITEM) < 0:
            makeVisible = True
            self._odlg.reportsBox.addItem(Parameters._TOPOITEM)
        basinReport = QSWATUtils.join(self._gv.textDir, Parameters._BASINREPORT)
        if os.path.exists(basinReport) and self._odlg.reportsBox.findText(Parameters._BASINITEM) < 0:
            makeVisible = True
            self._odlg.reportsBox.addItem(Parameters._BASINITEM)
        hrusReport = QSWATUtils.join(self._gv.textDir, Parameters._HRUSREPORT)
        if os.path.exists(hrusReport) and self._odlg.reportsBox.findText(Parameters._HRUSITEM) < 0:
            makeVisible = True
            self._odlg.reportsBox.addItem(Parameters._HRUSITEM)
        if makeVisible:
            self._odlg.reportsBox.setVisible(True)
            self._odlg.reportsLabel.setVisible(True)
            self._odlg.reportsBox.setCurrentIndex(0)

    def doDelineation(self):
        """Run the delineation dialog."""
        # avoid getting second window
        if self.delin is not None and self.delin._dlg.isEnabled():
            self.delin._dlg.close()
        self.delin = Delineation(self._gv, self._demIsProcessed)
        result = self.delin.run()
        if result == 1 and self._gv.isDelinDone():
            self._demIsProcessed = True
            self.allowCreateHRU()
            # remove old data so cannot be reused
            self._gv.db.clearTable('BASINSDATA')
            # make sure HRUs starts from scratch
            if self.hrus and self.hrus._dlg is not None:
                self.hrus._dlg.close()
            self.hrus = None
        elif result == 0:
            self._demIsProcessed = False
            self._odlg.delinLabel.setText('Step 1')
            self._odlg.hrusLabel.setText('Step 2')
            self._odlg.hrusLabel.setEnabled(False)
            self._odlg.hrusButton.setEnabled(False)
            self._odlg.editLabel.setEnabled(False)
            self._odlg.editButton.setEnabled(False)
        self._odlg.raise_()
        
    def doCreateHRUs(self):
        """Run the HRU creation dialog."""
        # avoid getting second window
        if self.hrus is not None and self.hrus._dlg.isEnabled():
            self.hrus._dlg.close()
        self.hrus = HRUs(self._gv, self._odlg.reportsBox)
        result = self.hrus.run()
        if result == 1:
            QSWATUtils.progress('Done', self._odlg.hrusLabel)
            self._odlg.editLabel.setEnabled(True)
            self._odlg.editButton.setEnabled(True)
        self._odlg.raise_()
            
    def demProcessed(self):
        """
        Return true if we can proceed with HRU creation.
        
        Return false if any required project setting is not found 
        in the project file
        Return true if:
        Using existing watershed and watershed grid exists and 
        is newer than dem
        or
        Not using existing watershed and filled dem exists and 
        is no older than dem, and
        watershed shapefile exists and is no older than filled dem
        """
        proj = QgsProject.instance()
        if not proj:
            QSWATUtils.loginfo('demProcessed failed: no project')
            return False
        title = proj.title()
        root = proj.layerTreeRoot()
        demFile, found = proj.readEntry(title, 'delin/DEM', '')
        if not found or demFile == '':
            QSWATUtils.loginfo('demProcessed failed: no DEM')
            return False
        demFile = proj.readPath(demFile)
        demLayer, _ = QSWATUtils.getLayerByFilename(root.findLayers(), demFile, FileTypes._DEM,
                                                    self._gv, None, QSWATUtils._WATERSHED_GROUP_NAME)
        if not demLayer:
            QSWATUtils.loginfo('demProcessed failed: no DEM layer')
            return False
        self._gv.demFile = demFile
        units = demLayer.crs().mapUnits()
        factor = 1 if units == QgsUnitTypes.DistanceMeters else Parameters._FEETTOMETRES if units == QgsUnitTypes.DistanceFeet else 0
        if factor == 0:
            QSWATUtils.loginfo('demProcessed failed: units are {0!s}'.format(units))
            return False
        self._gv.cellArea = demLayer.rasterUnitsPerPixelX() * demLayer.rasterUnitsPerPixelY() * factor * factor
        # hillshade
        Delineation.addHillshade(demFile, root, demLayer, self._gv)
        outletFile, found = proj.readEntry(title, 'delin/outlets', '')
        if found and outletFile != '':
            outletFile = proj.readPath(outletFile)
            outletLayer, _ = \
                QSWATUtils.getLayerByFilename(root.findLayers(), outletFile, FileTypes._OUTLETS,
                                              self._gv, None, QSWATUtils._WATERSHED_GROUP_NAME)
            if not outletLayer:
                QSWATUtils.loginfo('demProcessed failed: no outlet layer')
                return False
        else:
            outletLayer = None
        self._gv.outletFile = outletFile
        self._gv.existingWshed = proj.readBoolEntry(title, 'delin/existingWshed', False)[0]
        self._gv.useGridModel = proj.readBoolEntry(title, 'delin/useGridModel', False)[0]
        self._gv.useLandscapes = proj.readBoolEntry(title, 'lsu/useLandscapes', False)[0]
        streamFile, found = proj.readEntry(title, 'delin/net', '')
        if self._gv.useGridModel or not self._gv.existingWshed:
            if not found or streamFile == '':
                QSWATUtils.loginfo('demProcessed failed: no streams shapefile')
                return False
            streamFile = proj.readPath(streamFile)
            ft = FileTypes._GRIDSTREAMS if self._gv.useGridModel else FileTypes._STREAMS
            streamLayer, _ = \
                QSWATUtils.getLayerByFilename(root.findLayers(), streamFile, ft, 
                                              self._gv, None, QSWATUtils._WATERSHED_GROUP_NAME)
            if not streamLayer:
                QSWATUtils.loginfo('demProcessed failed: no streams layer')
                return False
            self._gv.streamFile = streamFile
        if self._gv.useGridModel:
            self._gv.gridSize, found = proj.readNumEntry(title, 'delin/gridSize', 0)
            if not found or self._gv.gridSize <= 0:
                QSWATUtils.loginfo('demProcessed failed: grid size not set')
                return False
        else:
            channelFile, found = proj.readEntry(title, 'delin/channels', '')
            if not found or channelFile == '':
                QSWATUtils.loginfo('demProcessed failed: no channels shapefile')
                return False
            channelFile = proj.readPath(channelFile)
            channelLayer, _ = \
                QSWATUtils.getLayerByFilename(root.findLayers(), channelFile, FileTypes._CHANNELS, 
                                              self._gv, None, QSWATUtils._WATERSHED_GROUP_NAME)
            if not channelLayer:
                QSWATUtils.loginfo('demProcessed failed: no channels layer')
                return False
            self._gv.channelFile = channelFile
        subbasinsFile, found = proj.readEntry(title, 'delin/subbasins', '')
        if not found or subbasinsFile == '':
            QSWATUtils.loginfo('demProcessed failed: no subbasins shapefile')
            return False
        subbasinsFile = proj.readPath(subbasinsFile)
        subbasinsInfo = QFileInfo(subbasinsFile)
        subbasinsTime = subbasinsInfo.lastModified()
        subbasinsLayer, _ = \
            QSWATUtils.getLayerByFilename(root.findLayers(), subbasinsFile, FileTypes._SUBBASINS, 
                                          self._gv, None, QSWATUtils._WATERSHED_GROUP_NAME)
        if not subbasinsLayer:
            QSWATUtils.loginfo('demProcessed failed: no subbasins layer')
            return False
        self._gv.subbasinsFile = subbasinsFile
        if not self._gv.useGridModel:
            wshedFile, found = proj.readEntry(title, 'delin/wshed', '')
            if not found or wshedFile == '':
                QSWATUtils.loginfo('demProcessed failed: no wshed shapefile')
                return False
            wshedFile = proj.readPath(wshedFile)
            if self._gv.existingWshed:
                wshedLayer, _ = \
                    QSWATUtils.getLayerByFilename(root.findLayers(), wshedFile, FileTypes._EXISTINGWATERSHED, 
                                                  self._gv, None, QSWATUtils._WATERSHED_GROUP_NAME)
                if not wshedLayer:
                    QSWATUtils.loginfo('demProcessed failed: no wshed layer')
                    return False
            self._gv.wshedFile = wshedFile
        demInfo = QFileInfo(demFile)
        if not demInfo.exists():
            QSWATUtils.loginfo('demProcessed failed: no DEM info')
            return False
        base = QSWATUtils.join(demInfo.absolutePath(), demInfo.baseName())
        if not self._gv.existingWshed:
            burnFile, found = proj.readEntry(title, 'delin/burn', '')
            if found and burnFile != '':
                burnFile = proj.readPath(burnFile)
                if not os.path.exists(burnFile):
                    QSWATUtils.loginfo('demProcessed failed: no burn file')
                    return False
                self._gv.slopeFile = base + 'slope.tif'
            else:
                self._gv.slopeFile = base + 'slp.tif'
        else:
            self._gv.slopeFile = base + 'slp.tif'
        if not os.path.exists(self._gv.slopeFile):
            QSWATUtils.loginfo('demProcessed failed: no slope raster')
            return False
        self._gv.basinFile = base + 'wStream.tif'
        if not self._gv.useGridModel:
            self._gv.channelBasinFile = base + 'wChannel.tif'
            self._gv.srcChannelFile = base + 'srcChannel.tif'
        streamDrainage = proj.readBoolEntry(title, 'delin/streamDrainage', False)[0]
        if self._gv.existingWshed:
            if not self._gv.useGridModel:
                if not os.path.exists(self._gv.basinFile):
                    QSWATUtils.loginfo('demProcessed failed: no subbasins raster')
                    return False
        else:
            self._gv.pFile = base + 'p.tif'
            if not os.path.exists(self._gv.pFile):
                QSWATUtils.loginfo('demProcessed failed: no p raster')
                return False
            self._gv.felFile = base + 'fel.tif'
            felInfo = QFileInfo(self._gv.felFile)
            if not (felInfo.exists() and subbasinsInfo.exists()):
                QSWATUtils.loginfo('demProcessed failed: no filled raster')
                return False
            self._gv.ad8File = base + 'ad8.tif'
            if not os.path.exists(self._gv.ad8File):
                QSWATUtils.loginfo('demProcessed failed: no D8 accumulation raster')
                return False
            demTime = demInfo.lastModified()
            felTime = felInfo.lastModified()
            if not (demTime <= felTime <= subbasinsTime):
                QSWATUtils.loginfo('demProcessed failed: not up to date')
                return False
            self._gv.distStFile = base + 'distst.tif'
            if not os.path.exists(self._gv.distStFile):
                QSWATUtils.loginfo('demProcessed failed: no distance to outlet raster')
                return False
            self._gv.distChFile = base + 'distch.tif'
            if not self._gv.useGridModel:
                if not os.path.exists(self._gv.distChFile):
                    QSWATUtils.loginfo('demProcessed failed: no distance to channel raster')
                    return False
            valleyDepthsFile = base + 'depths.tif'
            if os.path.exists(valleyDepthsFile):
                self._gv.valleyDepthsFile = valleyDepthsFile
            # no longer compulsory
#             if not os.path.exists(self._gv.valleyDepthsFile):
#                 QSWATUtils.loginfo('demProcessed failed: no valley depths raster')
#                 return False
        if not self._gv.useGridModel:
            if not os.path.exists(self._gv.channelBasinFile):
                QSWATUtils.loginfo('demProcessed failed: no channel basins raster')
                return False
        snapFile, found = proj.readEntry(title, 'delin/snapOutlets', '')
        if found and snapFile != '':
            snapFile = proj.readPath(snapFile)
            if os.path.exists(snapFile):
                self._gv.snapFile = snapFile
            else:
                snapFile = ''
        else:
            snapFile = ''
        lakeLayer = None
        lakeFile, found = proj.readEntry(title, 'delin/lakes', '')
        if found and lakeFile != '':
            lakeFile = proj.readPath(lakeFile)
            if os.path.exists(lakeFile):
                self._gv.lakeFile = lakeFile
                lakeLayer = QgsVectorLayer(lakeFile, 'Lakes', 'ogr')
                if self._gv.useGridModel:
                    gridLakesAdded = proj.readBoolEntry(title, 'delin/gridLakesAdded', False)[0]
                    if not gridLakesAdded:
                        QSWATUtils.loginfo('demProcessed failed: grid lakes not added')
                        return False
                else:
                    chBasinNoLakeFile = base + 'wChannelNoLake.tif'
                    if os.path.exists(chBasinNoLakeFile):
                        self._gv.chBasinNoLakeFile = chBasinNoLakeFile
                        if not self._gv.existingWshed:
                            lakePointsAdded = proj.readBoolEntry(title, 'delin/lakePointsAdded', False)[0]
                            if not lakePointsAdded:
                                QSWATUtils.loginfo('demProcessed failed: lake points not added')
                                return False
                    else:
                        QSWATUtils.loginfo('demProcessed failed: no channel basins without lakes raster')
                        return False
        snapLayer = outletLayer if snapFile == '' else QgsVectorLayer(self._gv.snapFile, 'Snapped outlets', 'ogr')
        chanLayer = streamLayer if self._gv.useGridModel else channelLayer
        if self._gv.existingWshed:
            ad8Layer = None
        else:
            ad8Layer = QgsRasterLayer(self._gv.ad8File, 'Accumulation')
        if not self._gv.topo.setUp0(demLayer, chanLayer, snapLayer, ad8Layer, self._gv.verticalFactor, self._gv.useGridModel):
            return False
        basinIndex = self._gv.topo.getIndex(subbasinsLayer, QSWATTopology._POLYGONID)
        if basinIndex < 0:
            return False
        for feature in subbasinsLayer.getFeatures():
            basin = feature.attributes()[basinIndex]
            centroid = feature.geometry().centroid().asPoint()
            self._gv.topo.basinCentroids[basin] = (centroid.x(), centroid.y())
        if lakeLayer is not None:
            if not self._gv.topo.readLakesData(self._gv.db):
                QSWATUtils.loginfo('demProcessed failed: lakes data not read')
                return False
        # this can go wrong if eg the streams and watershed files exist but are inconsistent
        try:
            if not self._gv.topo.setUp(demLayer, chanLayer, subbasinsLayer, snapLayer, lakeLayer,
                                       self._gv, self._gv.existingWshed, False, self._gv.useGridModel, streamDrainage, False):
                QSWATUtils.loginfo('demProcessed failed: topo setup failed')
                return False
            if len(self._gv.topo.inlets) == 0:
                # no inlets, so no need to expand subbasins layer legend
                treeSubbasinsLayer = root.findLayer(subbasinsLayer.id())
                treeSubbasinsLayer.setExpanded(False)
        except Exception:
            QSWATUtils.loginfo('demProcessed failed: topo setup raised exception: {0}'.format(traceback.format_exc()))
            return False
        return True
            
    def allowCreateHRU(self):
        """Mark delineation as Done and make create HRUs option visible."""
        QSWATUtils.progress('Done', self._odlg.delinLabel)
        QSWATUtils.progress('Step 2', self._odlg.hrusLabel)
        self._odlg.hrusLabel.setEnabled(True)
        self._odlg.hrusButton.setEnabled(True)
        self._odlg.editLabel.setEnabled(False)
        self._odlg.editButton.setEnabled(False)
        
    def showReports(self):
        """Show reports combo box and add items if necessary."""
        self._odlg.reportsBox.setVisible(True)
        if self._odlg.reportsBox.findText(Parameters._TOPOITEM) < 0:
            self._odlg.reportsBox.addItem(Parameters._TOPOITEM)
        if self._odlg.reportsBox.findText(Parameters._BASINITEM) < 0:
            self._odlg.reportsBox.addItem(Parameters._BASINITEM)
        if self._odlg.reportsBox.findText(Parameters._HRUSITEM) < 0:
            self._odlg.reportsBox.addItem(Parameters._HRUSITEM)
            
    def setLegendGroups(self):
        """Legend groups are used to keep legend in reasonable order.  
        Create them if necessary.
        """
        root = QgsProject.instance().layerTreeRoot()
        groups = [QSWATUtils._ANIMATION_GROUP_NAME,
                  QSWATUtils._RESULTS_GROUP_NAME,
                  QSWATUtils._WATERSHED_GROUP_NAME,
                  QSWATUtils._LANDUSE_GROUP_NAME,
                  QSWATUtils._SOIL_GROUP_NAME,
                  QSWATUtils._SLOPE_GROUP_NAME]
        for i in range(len(groups)):
            group = groups[i]
            node = root.findGroup(group)
            if node is None:
                root.insertGroup(i, group)

    def startEditor(self):
        """Start the SWAT Editor, first setting its initial parameters."""
        # self._gv.setSWATEditorParams()
        editor = self._gv.findSWATPlusEditor()
        if editor is None:
            return
        QSWATUtils.loginfo('Starting SWAT+ editor with command: "{0}" "{1}"'.format(editor, self._gv.db.dbFile))
        subprocess.call('"{0}" "{1}"'.format(editor, self._gv.db.dbFile), shell=True)
        if os.path.exists(QSWATUtils.join(self._gv.resultsDir, Parameters._OUTPUTDB)):
            self._odlg.visualiseLabel.setVisible(True)
            self._odlg.visualiseButton.setVisible(True)
        
    def visualise(self):
        """Run visualise form."""
        # avoid getting second window
        if self.vis is not None and self.vis._dlg.isEnabled():
            self.vis._dlg.close()
        self.vis = Visualise(self._gv)
        self.vis.run()
                    
    def finish(self):   
        """Close the database connections and subsidiary forms."""
        if QSWATUtils is not None:
            QSWATUtils.loginfo('Closing databases')
        try:
            self.delin = None
            self.hrus = None
            self.vis = None
            if self._gv and self._gv.db:
                if self._gv.db.conn:
                    self._gv.db.conn.close()
                if self._gv.db.connRef:
                    self._gv.db.connRef.close() 
            if QSWATUtils is not None:
                QSWATUtils.loginfo('Databases closed') 
        except Exception:
            pass
Exemple #6
0
 def __init__(self, config):
     self.frog_pond = FrogPond(config)
     self.vis = Visualise(self.frog_pond)