示例#1
0
    def setUp(self) -> None:
        os.environ['PATH'] = os.path.join(
            tempfile.gettempdir(), 'temp_data') + ';' + os.environ['PATH']
        self.temp_proj_folder = os.path.join(tempfile.gettempdir(),
                                             uuid.uuid4().hex)
        copytree(no_triggers_project, self.temp_proj_folder)
        self.proj = Project()
        self.proj.open(self.temp_proj_folder)
        self.curr = self.proj.conn.cursor()

        # Modes to add
        sql = 'INSERT INTO modes (mode_name, mode_id) VALUES (?, ?);'
        for mid in ['p', 'l', 'g', 'x', 'y', 'd', 'k', 'a', 'r', 'n', 'm']:
            self.curr.execute(sql, [f'mode_{mid}', mid])

        self.proj.conn.commit()

        curr = self.proj.conn.cursor()
        self.rtree = True
        try:
            curr.execute("SELECT rtreecheck('idx_nodes_geometry');")
        except Exception as e:
            self.rtree = False
            warn(f'RTREE not available --> {e.args}')

        root = os.path.dirname(os.path.realpath(__file__)).replace('tests', '')
        qry_file = os.path.join(
            root, "database_specification/triggers/modes_table_triggers.sql")
        with open(qry_file, "r") as sql_file:
            self.queries = sql_file.read()
        self.queries = [cmd for cmd in self.queries.split("#")]
示例#2
0
 def setUp(self) -> None:
     self.file = os.path.join(gettempdir(),
                              "aequilibrae_project_test.sqlite")
     self.project = Project()
     self.project.new(self.file)
     self.source = self.file
     self.file2 = os.path.join(gettempdir(),
                               "aequilibrae_project_test2.sqlite")
     self.conn = sqlite3.connect(self.file2)
     self.conn.enable_load_extension(True)
     plat = platform.platform()
     pth = os.getcwd()
     if "WINDOWS" in plat.upper():
         par = Parameters()
         spatialite_path = par.parameters["system"]["spatialite_path"]
         if os.path.isfile(
                 os.path.join(spatialite_path, "mod_spatialite.dll")):
             os.chdir(spatialite_path)
     try:
         self.conn.load_extension("mod_spatialite")
     except Exception as e:
         warn(
             f"AequilibraE might not work as intended without spatialite. {e.args}"
         )
     os.chdir(pth)
     self.network = Network(self)
示例#3
0
    def doWork(self):
        self.emit_messages(message="Initializing project", value=0, max_val=1)
        self.project = Project()
        self.project.new(self.output_file)
        self.project.conn.close()
        self.project.conn = qgis.utils.spatialite_connect(self.output_file)
        self.project.network.conn = self.project.conn
        self.project.network.create_empty_tables()

        # Add the required extra fields to the link layer
        self.emit_messages(
            message="Adding extra network data fields to database",
            value=0,
            max_val=1)
        self.additional_fields_to_layers('links', self.link_layer,
                                         self.link_fields)
        self.additional_fields_to_layers('nodes', self.node_layer,
                                         self.node_fields)

        conn = qgis.utils.spatialite_connect(self.output_file)

        self.transfer_layer_features("links", self.link_layer,
                                     self.link_fields)
        self.transfer_layer_features("nodes", self.node_layer,
                                     self.node_fields)

        self.emit_messages(message="Creating layer triggers",
                           value=0,
                           max_val=1)
        self.project.network.add_triggers()
        self.emit_messages(message="Spatial indices", value=0, max_val=1)
        self.project.network.add_spatial_index()
        self.ProgressText.emit("DONE")
示例#4
0
    def setUp(self) -> None:
        os.environ['PATH'] = os.path.join(gettempdir(), 'temp_data') + ';' + os.environ['PATH']
        self.proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex)
        copytree(siouxfalls_project, self.proj_dir)

        self.project = Project()
        self.project.open(self.proj_dir)
示例#5
0
 def setUp(self) -> None:
     os.environ['PATH'] = os.path.join(gettempdir(), 'temp_data') + ';' + os.environ['PATH']
     self.proj_path = os.path.join(gettempdir(), f'aeq_{uuid.uuid4().hex}')
     copytree(siouxfalls_project, self.proj_path)
     self.siouxfalls = Project()
     self.siouxfalls.open(self.proj_path)
     remove_triggers(self.siouxfalls.conn)
     add_triggers(self.siouxfalls.conn)
示例#6
0
 def test_opening_wrong_folder(self):
     temp_proj_folder = os.path.join(tempfile.gettempdir(),
                                     uuid.uuid4().hex)
     self.proj.close()
     with self.assertRaises(FileNotFoundError):
         proj = Project()
         proj.open(temp_proj_folder)
     self.proj.open(self.temp_proj_folder)
示例#7
0
class TestNetworkTriggers(TestCase):
    def setUp(self) -> None:
        os.environ['PATH'] = os.path.join(gettempdir(), 'temp_data') + ';' + os.environ['PATH']
        self.proj_path = os.path.join(gettempdir(), f'aeq_{uuid.uuid4().hex}')
        copytree(siouxfalls_project, self.proj_path)
        self.siouxfalls = Project()
        self.siouxfalls.open(self.proj_path)
        remove_triggers(self.siouxfalls.conn)
        add_triggers(self.siouxfalls.conn)

    def tearDown(self) -> None:
        self.siouxfalls.close()

    def test_delete_links_delete_nodes(self):
        items = self.siouxfalls.network.count_nodes()
        self.assertEqual(24, items, 'Wrong number of nodes found')
        links = self.siouxfalls.network.links
        nodes = self.siouxfalls.network.nodes

        node = nodes.get(1)
        node.is_centroid = 0
        node.save()

        # We have completely disconnected 2 nodes (1 and 2)
        for i in [1, 2, 3, 4, 5, 14]:
            link = links.get(i)
            link.delete()
        # Since node 1 is no longer a centroid, we should have only 23 nodes in the network
        items = self.siouxfalls.network.count_nodes()
        self.assertEqual(23, items, 'Wrong number of nodes found')

    def test_add_regular_link(self):
        # Add a regular link to see if it fails when creating it
        # It happened at some point
        curr = self.siouxfalls.conn.cursor()
        data = [123456, 'c', 'default', LineString([Point(0, 0), Point(1, 1)]).wkb]

        sql = 'insert into links (link_id, modes, link_type, geometry) Values(?,?,?,GeomFromWKB(?, 4326));'
        curr.execute(sql, data)
        self.siouxfalls.conn.commit()

    def test_add_regular_node_change_centroid_id(self):
        # Add a regular link to see if it fails when creating it
        # It happened at some point
        curr = self.siouxfalls.conn.cursor()
        network = self.siouxfalls.network
        nodes = network.count_nodes()

        data = [987654, 1, Point(0, 0).wkb]

        sql = 'insert into nodes (node_id, is_centroid, geometry) Values(?,?,GeomFromWKB(?, 4326));'
        curr.execute(sql, data)
        self.siouxfalls.conn.commit()
        self.assertEqual(nodes + 1, network.count_nodes(), 'Failed to insert node')

        curr.execute('Update nodes set is_centroid=0 where node_id=?', data[:1])
        self.siouxfalls.conn.commit()
        self.assertEqual(nodes, network.count_nodes(), 'Failed to delete node when changing centroid flag')
示例#8
0
    def setUp(self) -> None:
        proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex)
        copytree(siouxfalls_project, proj_dir)

        self.project = Project()
        self.project.open(proj_dir)
        self.matrices = self.project.matrices
        self.matrices.reload()
        self.curr = self.project.conn.cursor()
示例#9
0
 def setUp(self) -> None:
     os.environ["PATH"] = os.path.join(
         tempfile.gettempdir(), "temp_data") + ";" + os.environ["PATH"]
     self.temp_proj_folder = os.path.join(tempfile.gettempdir(),
                                          uuid4().hex)
     copytree(siouxfalls_project, self.temp_proj_folder)
     self.project = Project()
     self.project.open(self.temp_proj_folder)
     self.project.network.build_graphs()
     self.graph = self.project.network.graphs["c"]
示例#10
0
    def setUp(self) -> None:
        os.environ["PATH"] = os.path.join(gettempdir(), "temp_data") + ";" + os.environ["PATH"]

        self.proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex)
        copytree(siouxfalls_project, self.proj_dir)

        self.project = Project()
        self.project.open(self.proj_dir)
        self.network = self.project.network
        self.curr = self.project.conn.cursor()
示例#11
0
 def setUp(self) -> None:
     self.file = os.path.join(gettempdir(),
                              "aequilibrae_project_test.sqlite")
     self.project = Project()
     self.project.new(self.file)
     self.source = self.file
     self.file2 = os.path.join(gettempdir(),
                               "aequilibrae_project_test2.sqlite")
     self.conn = sqlite3.connect(self.file2)
     self.conn = spatialite_connection(self.conn)
     self.network = Network(self)
示例#12
0
class TestProject(TestCase):
    def setUp(self) -> None:
        self.temp_proj_folder = os.path.join(tempfile.gettempdir(),
                                             uuid.uuid4().hex)
        self.proj = Project()
        self.proj.new(self.temp_proj_folder)

    def tearDown(self) -> None:
        self.proj.close()

    def test_opening_wrong_folder(self):
        temp_proj_folder = os.path.join(tempfile.gettempdir(),
                                        uuid.uuid4().hex)
        self.proj.close()
        with self.assertRaises(FileNotFoundError):
            proj = Project()
            proj.open(temp_proj_folder)
        self.proj.open(self.temp_proj_folder)

    def test_create_when_already_exists(self):
        with self.assertRaises(Exception):
            q = Project()
            q.new(os.path.join(tempfile.gettempdir(), uuid.uuid4().hex))

        with self.assertRaises(Exception):
            q = Project()
            q.open(os.path.join(tempfile.gettempdir(), uuid.uuid4().hex))

    def test_creation(self):

        curr = self.proj.conn.cursor()
        curr.execute("""PRAGMA table_info(links);""")
        fields = curr.fetchall()
        fields = [x[1] for x in fields]

        if 'distance' not in fields:
            self.fail("Table LINKS was not created correctly")

        curr = self.proj.conn.cursor()
        curr.execute("""PRAGMA table_info(nodes);""")
        nfields = curr.fetchall()
        nfields = [x[1] for x in nfields]

        if 'is_centroid' not in nfields:
            self.fail('Table NODES was not created correctly')

    def test_close(self):

        _ = database_connection()

        self.proj.close()
        with self.assertRaises(FileExistsError):
            _ = database_connection()
    def setUp(self) -> None:
        self.temp_proj_folder = os.path.join(tempfile.gettempdir(),
                                             uuid.uuid4().hex)
        copytree(no_triggers_project, self.temp_proj_folder)
        self.proj = Project()
        self.proj.open(self.temp_proj_folder)
        self.curr = self.proj.conn.cursor()

        letters = [
            random.choice(string.ascii_letters + '_') for x in range(20)
        ]
        self.random_string = ''.join(letters)
示例#14
0
class TestLinkType(TestCase):
    def setUp(self) -> None:
        self.temp_proj_folder = os.path.join(tempfile.gettempdir(),
                                             uuid.uuid4().hex)
        copytree(no_triggers_project, self.temp_proj_folder)
        self.proj = Project()
        self.proj.open(self.temp_proj_folder)
        self.curr = self.proj.conn.cursor()

        letters = [
            random.choice(string.ascii_letters + '_') for x in range(20)
        ]
        self.random_string = ''.join(letters)

    def tearDown(self) -> None:
        self.proj.close()

    def test_changing_link_type_id(self):
        ltypes = self.proj.network.link_types

        lt = random.choice([x for x in ltypes.all_types().values()])

        with self.assertRaises(ValueError):
            lt.link_type_id = 'test my description'

        with self.assertRaises(ValueError):
            lt.link_type_id = 'K'

    def test_empty(self):
        ltypes = self.proj.network.link_types

        newt = ltypes.new('Z')
        # a.link_type = 'just a_test'
        with self.assertRaises(IntegrityError):
            newt.save()

    def test_save(self):
        ltypes = self.proj.network.link_types

        newt = ltypes.new('Z')
        newt.link_type = self.random_string
        newt.description = self.random_string[::-1]
        newt.save()

        self.curr.execute(
            'select description, link_type from link_types where link_type_id="Z"'
        )

        desc, mname = self.curr.fetchone()
        self.assertEqual(desc, self.random_string[::-1],
                         "Didn't save the mode description correctly")
        self.assertEqual(mname, self.random_string,
                         "Didn't save the mode name correctly")
示例#15
0
    def run_load_project(self):
        formats = ["AequilibraE Project(*.sqlite)"]
        path, dtype = GetOutputFileName(
            QtWidgets.QDialog(),
            "AequilibraE Project",
            formats,
            ".sqlite",
            standard_path(),
        )

        # Cleans the project descriptor
        tab_count = 1
        for i in range(tab_count):
            self.projectManager.removeTab(i)

        if dtype is not None:
            self.contents = []
            self.showing.setVisible(True)
            self.project = Project()
            self.project.load(path)
            self.project.conn = qgis.utils.spatialite_connect(path)
            self.project.network.conn = self.project.conn

            uri = QgsDataSourceUri()
            uri.setDatabase(path)
            uri.setDataSource('', 'links', 'geometry')
            self.link_layer = QgsVectorLayer(uri.uri(), 'links', 'spatialite')
            QgsProject.instance().addMapLayer(self.link_layer)

            uri.setDataSource('', 'nodes', 'geometry')
            self.node_layer = QgsVectorLayer(uri.uri(), 'nodes', 'spatialite')
            QgsProject.instance().addMapLayer(self.node_layer)

            descr = QWidget()
            descrlayout = QVBoxLayout()
            # We create a tab with the main description of the project
            p1 = QLabel('Project: {}'.format(path))
            p2 = QLabel('Modes: {}'.format(', '.join(
                self.project.network.modes())))
            p3 = QLabel('Total Links: {:,}'.format(
                self.project.network.count_links()))
            p4 = QLabel('Total Nodes: {:,}'.format(
                self.project.network.count_nodes()))

            for p in [p1, p2, p3, p4]:
                descrlayout.addWidget(p)

            descr.setLayout(descrlayout)
            self.tabContents = [(descr, "Project")]
            self.projectManager.addTab(descr, "Project")
示例#16
0
    def setUp(self) -> None:
        self.matrix = AequilibraeMatrix()
        self.matrix.load(siouxfalls_demand)
        self.matrix.computational_view()

        self.project = Project()
        self.project.load(siouxfalls_project)
        self.project.network.build_graphs()
        self.car_graph = self.project.network.graphs['c']  # type: Graph
        self.car_graph.set_graph('free_flow_time')
        self.car_graph.set_blocked_centroid_flows(False)

        self.assignment = TrafficAssignment()
        self.assigclass = TrafficClass(self.car_graph, self.matrix)
示例#17
0
    def test_create_when_already_exists(self):
        with self.assertRaises(Exception):
            q = Project()
            q.new(os.path.join(tempfile.gettempdir(), uuid.uuid4().hex))

        with self.assertRaises(Exception):
            q = Project()
            q.open(os.path.join(tempfile.gettempdir(), uuid.uuid4().hex))
示例#18
0
    def test_creation(self):
        test_file = temp_proj_name
        with self.assertRaises(FileNotFoundError):
            p = Project()
            p.load(test_file)

        p = Project()
        p.new(test_file)
        p.conn.close()
示例#19
0
    def setUp(self) -> None:
        os.environ['PATH'] = os.path.join(
            gettempdir(), '../../temp_data') + ';' + os.environ['PATH']

        self.proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex)
        copytree(siouxfalls_project, self.proj_dir)

        self.project = Project()
        self.project.open(self.proj_dir)
        self.network = self.project.network
        self.curr = self.project.conn.cursor()

        self.links = self.network.links
        self.modes = self.network.modes
        self.links = self.network.links
        self.lid = randint(1, 24)
        self.link = self.links.get(self.lid)
 def final_steps(self):
     self.project = Project(self.output_path.text(), True)
     self.project.network.create_empty_tables()
     curr = self.project.conn.cursor()
     curr.execute("""ALTER TABLE links ADD COLUMN osm_id integer""")
     curr.execute("""ALTER TABLE nodes ADD COLUMN osm_id integer""")
     self.project.conn.commit()
     self.project.conn.close()
     self.builder = OSMBuilder(self.downloader.json, self.project.source)
     self.run_thread()
示例#21
0
    def test_create_from_osm(self):
        thresh = 0.05
        if os.environ.get('GITHUB_WORKFLOW', 'ERROR') == 'Code coverage':
            thresh = 1.01

        if random() < thresh:
            self.siouxfalls.close()
            self.project = Project()
            self.project.new(self.proj_path2)
            # self.network.create_from_osm(west=153.1136245, south=-27.5095487, east=153.115, north=-27.5085, modes=["car"])
            self.project.network.create_from_osm(west=-112.185,
                                                 south=36.59,
                                                 east=-112.179,
                                                 north=36.60)
            curr = self.project.conn.cursor()

            curr.execute("""select count(*) from links""")
            lks = curr.fetchone()[0]

            curr.execute("""select count(distinct osm_id) from links""")
            osmids = curr.fetchone()[0]

            if osmids == 0:
                warn('COULD NOT RETRIEVE DATA FROM OSM')
                return

            if osmids >= lks:
                self.fail("OSM links not broken down properly")

            curr.execute("""select count(*) from nodes""")
            nds = curr.fetchone()[0]

            if lks > nds:
                self.fail(
                    "We imported more links than nodes. Something wrong here")
            self.project.close()
            self.siouxfalls.open(self.proj_path)
        else:
            print('Skipped check to not load OSM servers')
示例#22
0
    def test_exclude_links(self):
        p = Project()
        p.load(siouxfalls_project)
        p.network.build_graphs()

        g = p.network.graphs['c']  # type: Graph

        # excludes a link before any setting or preparation
        g.exclude_links([12])

        g.set_graph('distance')
        r1 = PathResults()
        r1.prepare(g)
        r1.compute_path(1, 14)
        self.assertEqual(list(r1.path), [2, 6, 10, 34])

        # We exclude one link that we know was part of the last shortest path
        g.exclude_links([10])
        r2 = PathResults()
        r2.prepare(g)
        r2.compute_path(1, 14)
        self.assertEqual(list(r2.path), [2, 7, 36, 34])

        p.conn.close()
 def signal_handler(self, val):
     if val[0] == "Value":
         self.progressbar.setValue(val[1])
     elif val[0] == "maxValue":
         self.progressbar.setRange(0, val[1])
     elif val[0] == "text":
         self.progress_label.setText(val[1])
     elif val[0] == "finished_threaded_procedure":
         self.project = Project(self.output_path.text())
         self.progress_label.setText('Adding spatial indices')
         self.project.network.add_spatial_index()
         self.project.network.add_triggers()
         l = self.project.network.count_links()
         n = self.project.network.count_nodes()
         self.report.append(reporter(f'{l:,} links generated'))
         self.report.append(reporter(f'{n:,} nodes generated'))
         self.leave()
示例#24
0
class TestLog(TestCase):
    def setUp(self) -> None:
        os.environ['PATH'] = os.path.join(gettempdir(), 'temp_data') + ';' + os.environ['PATH']
        self.proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex)
        copytree(siouxfalls_project, self.proj_dir)

        self.project = Project()
        self.project.open(self.proj_dir)

    def tearDown(self) -> None:
        self.project.close()

    def test_contents(self):
        log = self.project.log()
        cont = log.contents()
        self.assertEqual(len(cont), 4, 'Returned the wrong amount of data from the log')

    def test_clear(self):
        log = self.project.log()
        log.clear()

        with open(os.path.join(self.proj_dir, "aequilibrae.log"), 'r') as file:
            q = file.readlines()
        self.assertEqual(len(q), 0, 'Failed to clear the log file')
class TestLinkTypes(TestCase):
    def setUp(self) -> None:
        self.temp_proj_folder = os.path.join(tempfile.gettempdir(),
                                             uuid.uuid4().hex)
        copytree(no_triggers_project, self.temp_proj_folder)
        self.proj = Project()
        self.proj.open(self.temp_proj_folder)
        self.curr = self.proj.conn.cursor()

        letters = [
            random.choice(string.ascii_letters + '_') for x in range(20)
        ]
        self.random_string = ''.join(letters)

    def tearDown(self) -> None:
        self.proj.close()

    def test_add(self):
        lt = self.proj.network.link_types
        existing = list(lt.all_types().keys())

        newlt = lt.new('G')
        newlt.link_type = 'unique_link_type'
        newlt.save()

        nowexisting = list(lt.all_types().keys())

        n = [x for x in nowexisting if x not in existing][0]
        self.assertEqual('G', n, 'Failed to add link type')

    def test_delete(self):
        lt = self.proj.network.link_types
        existing = list(lt.all_types().keys())
        deleted = random.choice(existing)
        lt.delete(deleted)
        remaining = list(lt.all_types().keys())

        difference = [x for x in existing if x not in remaining]

        self.assertEqual(deleted, difference[0], 'Failed to delete link type')

    def test_get_and_get_by_name(self):
        lt = self.proj.network.link_types
        ltget = lt.get('y')
        ltgetbn = lt.get_by_name('default')

        self.assertEqual(ltget.link_type_id, ltgetbn.link_type_id,
                         'Get methods returned different things')
        self.assertEqual(ltget.link_type, ltgetbn.link_type,
                         'Get methods returned different things')
        self.assertEqual(ltget.description, ltgetbn.description,
                         'Get methods returned different things')
        self.assertEqual(ltget.lanes, ltgetbn.lanes,
                         'Get methods returned different things')
        self.assertEqual(ltget.lane_capacity, ltgetbn.lane_capacity,
                         'Get methods returned different things')
        self.assertEqual(ltget.link_type, 'default',
                         'Get methods returned different things')

    def test_all_types(self):
        lt = self.proj.network.link_types
        all_lts = set([x for x in lt.all_types().keys()])

        c = self.proj.conn.cursor()
        c.execute('select link_type_id from link_types')
        reallts = set([x[0] for x in c.fetchall()])

        diff = all_lts.symmetric_difference(reallts)
        self.assertEqual(diff, set(), 'Getting all link_types failed')
示例#26
0
class TestMatrices(TestCase):
    def setUp(self) -> None:
        proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex)
        copytree(siouxfalls_project, proj_dir)

        self.project = Project()
        self.project.open(proj_dir)
        self.matrices = self.project.matrices
        self.matrices.reload()
        self.curr = self.project.conn.cursor()

    def tearDown(self) -> None:
        self.project.close()
        del self.project
        del self.matrices

    def randomword(self, length):
        allowed_characters = string.ascii_letters + '_123456789@!()[]{};:"    -'
        val = "".join(choice(allowed_characters) for i in range(length))
        if val[0] == "_" or val[-1] == "_":
            return self.randomword(length)
        return val

    def test_set_record(self):
        rec = self.matrices.get_record("omx2")
        with self.assertRaises(ValueError):
            rec.name = "omx"

        with self.assertRaises(ValueError):
            rec.file_name = "sfalls_skims.omx"

        rec.file_name = "SiouxFalls.omx"
        self.assertEqual(
            rec.cores, 1,
            "Setting a file that exists did not correct the number of cores")

    def test_clear_database(self):
        self.__mat_count(3, "The test data started wrong")

        self.matrices.clear_database()
        self.__mat_count(2, "Did not clear the database appropriately")

    def test_update_database(self):
        self.__mat_count(3, "The test data started wrong")

        self.matrices.update_database()
        self.__mat_count(4, "Did not add to the database appropriately")

        rec = self.matrices.get_record("omx")
        existing = join(rec.fldr, rec.file_name)
        new_name = "test_name.omx"
        new_name1 = "test_name1.omx"

        copyfile(existing, join(rec.fldr, new_name))
        record = self.matrices.new_record("test_name1.omx", new_name)
        record.save()

        copyfile(existing, join(rec.fldr, new_name1))
        self.matrices.update_database()

    def test_get_matrix(self):
        with self.assertRaises(Exception):
            _ = self.matrices.get_matrix("omxq")

        mat = self.matrices.get_matrix("oMx")
        mat.computational_view()
        self.assertEqual(floor(mat.matrix_view.sum()), 20309,
                         "Matrix loaded incorrectly")

    def test_get_record(self):
        rec = self.matrices.get_record("omx")
        self.assertEqual(rec.cores, 4,
                         "record populated wrong. Number of cores")
        self.assertEqual(rec.description, None,
                         "record populated wrong. Description")

    def test_record_update_cores(self):
        rec = self.matrices.get_record("omx")
        rec.update_cores()
        self.assertEqual(rec.cores, 2, "Cores update did not work")

    def test_save_record(self):
        rec = self.matrices.get_record("omx")

        text = self.randomword(randint(30, 100))
        rec.description = text
        rec.save()

        self.curr.execute('select description from matrices where name="omx";')
        self.assertEqual(text,
                         self.curr.fetchone()[0],
                         "Saving matrix record description failed")

    def test_delete(self):
        self.matrices.delete_record("omx")
        self.curr.execute('select count(*) from matrices where name="omx";')

        self.assertEqual(0,
                         self.curr.fetchone()[0],
                         " Deleting matrix record failed")

        with self.assertRaises(Exception):
            self.matrices.get_record("omx")

    def test_list(self):
        df = self.matrices.list()
        self.curr.execute("select count(*) from Matrices")
        self.assertEqual(
            df.shape[0],
            self.curr.fetchone()[0],
            "Returned the wrong number of matrices in the database")

        self.assertEqual(df[df.status == "file missing"].shape[0], 1,
                         "Wrong # of records for missing matrix files")

    def __mat_count(self, should_have: int, error_message: str) -> None:
        self.curr.execute("Select count(*) from Matrices;")
        self.assertEqual(self.curr.fetchone()[0], should_have, error_message)
示例#27
0
class CreatesTranspoNetProcedure(WorkerThread):
    def __init__(
        self,
        parentThread,
        output_file,
        node_layer,
        node_fields,
        link_layer,
        link_fields,
    ):
        WorkerThread.__init__(self, parentThread)

        self.output_file = output_file
        self.node_fields = node_fields
        self.link_fields = link_fields
        self.node_layer = node_layer
        self.link_layer = link_layer
        self.report = []
        self.project: Project

    def doWork(self):
        self.emit_messages(message="Initializing project", value=0, max_val=1)
        self.project = Project()
        self.project.new(self.output_file)
        self.project.conn.close()
        self.project.conn = qgis.utils.spatialite_connect(self.output_file)
        self.project.network.conn = self.project.conn
        self.project.network.create_empty_tables()

        # Add the required extra fields to the link layer
        self.emit_messages(
            message="Adding extra network data fields to database",
            value=0,
            max_val=1)
        self.additional_fields_to_layers('links', self.link_layer,
                                         self.link_fields)
        self.additional_fields_to_layers('nodes', self.node_layer,
                                         self.node_fields)

        conn = qgis.utils.spatialite_connect(self.output_file)

        self.transfer_layer_features("links", self.link_layer,
                                     self.link_fields)
        self.transfer_layer_features("nodes", self.node_layer,
                                     self.node_fields)

        self.emit_messages(message="Creating layer triggers",
                           value=0,
                           max_val=1)
        self.project.network.add_triggers()
        self.emit_messages(message="Spatial indices", value=0, max_val=1)
        self.project.network.add_spatial_index()
        self.ProgressText.emit("DONE")

    # Adds the non-standard fields to a layer
    def additional_fields_to_layers(self, table, layer, layer_fields):
        curr = self.project.conn.cursor()
        fields = layer.dataProvider().fields()
        string_fields = []

        curr.execute(f'PRAGMA table_info({table});')
        field_names = curr.fetchall()
        existing_fields = [f[1].lower() for f in field_names]

        for f in set(layer_fields.keys()):
            if f in existing_fields:
                continue
            field = fields[layer_fields[f]]
            field_length = field.length()
            if not field.isNumeric():
                field_type = "char"
                string_fields.append(f)
            else:
                if "Int" in field.typeName():
                    field_type = "INTEGER"
                else:
                    field_type = "REAL"
            try:
                sql = "alter table " + table + " add column " + f + " " + field_type + "(" + str(
                    field_length) + ")"
                curr.execute(sql)
                self.project.conn.commit()
            except:
                logger.error(sql)
                self.report.append("field " + str(f) + " could not be added")
        curr.close()
        return string_fields

    def transfer_layer_features(self, table, layer, layer_fields):
        self.emit_messages(message=f"Transferring features from {table} layer",
                           value=0,
                           max_val=layer.featureCount())
        curr = self.project.conn.cursor()

        field_titles = ", ".join(list(layer_fields.keys()))
        all_modes = set()
        for j, f in enumerate(layer.getFeatures()):
            self.emit_messages(value=j)
            attrs = []
            for k, val in layer_fields.items():
                if val < 0:
                    attrs.append("NULL")
                else:
                    attr_val = self.convert_data(f.attributes()[val])
                    if not str(attr_val).isnumeric():
                        attrs.append(f'"{attr_val}"')
                    else:
                        attrs.append(attr_val)

            attrs = ", ".join(attrs)
            geom = f.geometry().asWkt().upper()
            crs = str(layer.crs().authid().split(":")[1])

            sql = f"INSERT INTO {table} ({field_titles} , geometry)  VALUES ({attrs} , GeomFromText('{geom}', {crs}))"

            if table == 'links':
                all_modes.update(list(f.attributes()[layer_fields['modes']]))
            try:
                curr.execute(sql)
            except:
                logger.info(f'Failed inserting link {f.id()}')
                logger.info(sql)
                if f.id():
                    msg = f"feature with id {f.id()} could not be added to layer {table}"
                else:
                    msg = f"feature with no node id present. It could not be added to layer {table}"
                self.report.append(msg)

        # We check if all modes exist
        a = self.project.network.modes()
        for x in all_modes:
            if x not in a:
                par = [
                    f'"automatic_{x}"', f'"{x}"',
                    '"Mode automatically added during project creation from layers"'
                ]
                curr.execute(
                    f'INSERT INTO "modes" (mode_name, mode_id, description) VALUES({",".join(par)})'
                )
                logger.info(f'New mode inserted during project creation {x}')
        self.project.conn.commit()
        curr.close()

    def convert_data(self, value):
        if type(value) == NULL:
            return "NULL"
        else:
            return str(value).replace('"', "'")

    def emit_messages(self, message="", value=-1, max_val=-1):
        if len(message) > 0:
            self.ProgressText.emit(message)
        if value >= 0:
            self.ProgressValue.emit(value)
        if max_val >= 0:
            self.ProgressMaxValue.emit(max_val)
示例#28
0
class TestNetwork(TestCase):
    def setUp(self) -> None:
        self.file = os.path.join(gettempdir(),
                                 "aequilibrae_project_test.sqlite")
        self.project = Project()
        self.project.new(self.file)
        self.source = self.file
        self.file2 = os.path.join(gettempdir(),
                                  "aequilibrae_project_test2.sqlite")
        self.conn = sqlite3.connect(self.file2)
        self.conn = spatialite_connection(self.conn)
        self.network = Network(self)

    def tearDown(self) -> None:
        try:
            self.project.conn.close()
            os.unlink(self.file)

            self.conn.close()
            os.unlink(self.file2)
        except Exception as e:
            warn(f'Could not delete. {e.args}')

    def test_create_from_osm(self):
        thresh = 0.05
        if os.environ.get('GITHUB_WORKFLOW', 'ERROR') == 'Code coverage':
            thresh = 1.01

        if random() < thresh:
            # self.network.create_from_osm(west=153.1136245, south=-27.5095487, east=153.115, north=-27.5085, modes=["car"])
            self.project.network.create_from_osm(west=-112.185,
                                                 south=36.59,
                                                 east=-112.179,
                                                 north=36.60)
            curr = self.project.conn.cursor()

            curr.execute("""select count(*) from links""")
            lks = curr.fetchone()

            curr.execute("""select count(distinct osm_id) from links""")
            osmids = curr.fetchone()

            if osmids >= lks:
                self.fail("OSM links not broken down properly")

            curr.execute("""select count(*) from nodes""")
            nds = curr.fetchone()

            if lks > nds:
                self.fail(
                    "We imported more links than nodes. Something wrong here")
        else:
            print('Skipped check to not load OSM servers')

    def test_create_empty_tables(self):
        self.network.create_empty_tables()
        p = Parameters().parameters["network"]

        curr = self.conn.cursor()
        curr.execute("""PRAGMA table_info(links);""")
        fields = curr.fetchall()
        fields = [x[1] for x in fields]

        oneway = reduce(lambda a, b: dict(a, **b),
                        p["links"]["fields"]["one-way"])
        owf = list(oneway.keys())
        twoway = reduce(lambda a, b: dict(a, **b),
                        p["links"]["fields"]["two-way"])
        twf = []
        for k in list(twoway.keys()):
            twf.extend([f"{k}_ab", f"{k}_ba"])

        for f in owf + twf:
            if f not in fields:
                self.fail(f"Field {f} not added to links table")

        curr = self.conn.cursor()
        curr.execute("""PRAGMA table_info(nodes);""")
        nfields = curr.fetchall()
        nfields = [x[1] for x in nfields]

        flds = reduce(lambda a, b: dict(a, **b), p["nodes"]["fields"])
        flds = list(flds.keys())

        for f in flds:
            if f not in nfields:
                self.fail(f"Field {f} not added to nodes table")
示例#29
0
class TestProject(TestCase):
    def setUp(self) -> None:
        os.environ['PATH'] = os.path.join(
            tempfile.gettempdir(), 'temp_data') + ';' + os.environ['PATH']
        self.temp_proj_folder = os.path.join(tempfile.gettempdir(),
                                             uuid.uuid4().hex)
        copytree(no_triggers_project, self.temp_proj_folder)
        self.proj = Project()
        self.proj.open(self.temp_proj_folder)
        self.curr = self.proj.conn.cursor()

        # Modes to add
        sql = 'INSERT INTO modes (mode_name, mode_id) VALUES (?, ?);'
        for mid in ['p', 'l', 'g', 'x', 'y', 'd', 'k', 'a', 'r', 'n', 'm']:
            self.curr.execute(sql, [f'mode_{mid}', mid])

        self.proj.conn.commit()

        curr = self.proj.conn.cursor()
        self.rtree = True
        try:
            curr.execute("SELECT rtreecheck('idx_nodes_geometry');")
        except Exception as e:
            self.rtree = False
            warn(f'RTREE not available --> {e.args}')

        root = os.path.dirname(os.path.realpath(__file__)).replace('tests', '')
        qry_file = os.path.join(
            root, "database_specification/triggers/modes_table_triggers.sql")
        with open(qry_file, "r") as sql_file:
            self.queries = sql_file.read()
        self.queries = [cmd for cmd in self.queries.split("#")]

    def tearDown(self) -> None:
        self.proj.close()

    def __get_query(self, qry: str) -> str:
        for query in self.queries:
            if qry in query:
                return query
        raise FileNotFoundError('QUERY DOES NOT EXIST')

    def test_all_tests_considered(self):
        tests_added = list(self.__dir__())
        tests_added = [x[5:] for x in tests_added if x[:5] == 'test_']

        for trigger in self.queries:
            if 'TRIGGER' in trigger.upper():
                found = [x for x in tests_added if x in trigger]
                if not found:
                    self.fail(f'Trigger not tested. {trigger}')

    def test_mode_single_letter_update(self):
        cmd = self.__get_query('mode_single_letter_update')

        sql = "UPDATE 'modes' SET mode_id= 'ttt' where mode_id='b'"
        self.curr.execute(sql)

        self.curr.execute(cmd)

        with self.assertRaises(sqlite3.IntegrityError):
            sql = "UPDATE 'modes' SET mode_id= 'gg' where mode_id='w'"
            self.curr.execute(sql)

    def test_mode_single_letter_insert(self):
        cmd = self.__get_query('mode_single_letter_insert')

        sql = "INSERT INTO 'modes' (mode_name, mode_id) VALUES(?, ?)"
        self.curr.execute(sql, ['testasdasd', 'pp'])

        self.curr.execute(cmd)

        with self.assertRaises(sqlite3.IntegrityError):
            self.curr.execute(sql, ['test1b', 'mm'])

    def test_mode_keep_if_in_use_updating(self):
        cmd = self.__get_query('mode_keep_if_in_use_updating')

        sql = "UPDATE 'modes' SET mode_id= 'h' where mode_id='g'"
        self.curr.execute(sql)

        self.curr.execute(cmd)

        sql = "UPDATE 'modes' SET mode_id= 'j' where mode_id='l'"
        with self.assertRaises(sqlite3.IntegrityError):
            self.curr.execute(sql)

    def test_mode_keep_if_in_use_deleting(self):
        cmd = self.__get_query('mode_keep_if_in_use_deleting')

        sql = "DELETE FROM 'modes' where mode_id='p'"
        self.curr.execute(sql)

        self.curr.execute(cmd)

        sql = "DELETE FROM 'modes' where mode_id='c'"
        with self.assertRaises(sqlite3.IntegrityError):
            self.curr.execute(sql)

    def test_modes_on_links_update(self):
        cmd = self.__get_query('modes_on_links_update')

        sql = "UPDATE 'links' SET modes= 'qwerty' where link_id=55"
        self.curr.execute(sql)

        self.curr.execute(cmd)

        sql = "UPDATE 'links' SET modes= 'azerty' where link_id=56"
        with self.assertRaises(sqlite3.IntegrityError):
            self.curr.execute(sql)

    def test_modes_length_on_links_update(self):
        cmd = self.__get_query('modes_length_on_links_update')

        sql = "UPDATE 'links' SET modes= '' where modes='wb'"
        self.curr.execute(sql)

        self.curr.execute(cmd)

        sql = "UPDATE 'links' SET modes= '' where modes='bw'"
        with self.assertRaises(sqlite3.IntegrityError):
            self.curr.execute(sql)

    def test_modes_on_nodes_table_update_a_node(self):
        cmd = self.__get_query('modes_on_nodes_table_update_a_node')

        sql = "UPDATE 'links' SET a_node= 1 where a_node=3"
        self.curr.execute(sql)

        sql = "SELECT modes from nodes where node_id=1"
        self.curr.execute(sql)
        i = self.curr.fetchone()[0]
        self.assertEqual(i, 'ct')

        self.curr.execute(cmd)

        k = ''
        for n in [2, 5]:
            for f in ['a_node', 'b_node']:
                self.curr.execute(f"SELECT modes from links where {f}={n}")
                k += self.curr.fetchone()[0]

        existing = set(k)

        sql = "UPDATE 'links' SET a_node= 2 where a_node=5"
        self.curr.execute(sql)

        sql = "SELECT modes from nodes where node_id=2"
        self.curr.execute(sql)
        i = set(self.curr.fetchone()[0])
        self.assertEqual(i, existing)

    def test_modes_on_nodes_table_update_b_node(self):
        cmd = self.__get_query('modes_on_nodes_table_update_b_node')
        sql = "UPDATE 'links' SET b_node= 1 where b_node=3"
        self.curr.execute(sql)

        sql = "SELECT modes from nodes where node_id=1"
        self.curr.execute(sql)
        i = self.curr.fetchone()[0]
        self.assertEqual(i, 'ct')

        self.curr.execute(cmd)

        sql = "UPDATE 'links' SET b_node= 2 where b_node=4"
        self.curr.execute(sql)

        sql = "SELECT modes from nodes where node_id=2"
        self.curr.execute(sql)
        i = self.curr.fetchone()[0]
        self.assertEqual(i, 'ctw')

    def test_modes_on_nodes_table_update_links_modes(self):
        cmd = self.__get_query('modes_on_nodes_table_update_links_modes')
        sql = "UPDATE 'links' SET modes= 'x' where a_node=24"
        self.curr.execute(sql)

        sql = "SELECT modes from nodes where node_id=24"
        self.curr.execute(sql)
        i = self.curr.fetchone()[0]
        self.assertEqual(i, 'c')

        self.curr.execute(cmd)

        sql = "UPDATE 'links' SET 'modes'= 'y' where a_node=24"
        self.curr.execute(sql)

        sql = "SELECT modes from nodes where node_id=24"
        self.curr.execute(sql)
        i = self.curr.fetchone()[0]
        self.assertIn('c', i)
        self.assertIn('y', i)

        sql = "UPDATE 'links' SET 'modes'= 'r' where b_node=24"
        self.curr.execute(sql)

        sql = "SELECT modes from nodes where node_id=24"
        self.curr.execute(sql)
        i = self.curr.fetchone()[0]
        self.assertIn('r', i)
        self.assertIn('y', i)

    def test_modes_on_links_insert(self):
        cmd = self.__get_query('modes_on_links_insert')
        if self.rtree:
            self.curr.execute('pragma table_info(links)')
            f = self.curr.fetchall()
            fields = {x[1]: x[0] for x in f}

            sql = 'select * from links where link_id=10'
            self.curr.execute(sql)
            a = [x for x in self.curr.fetchone()]
            a[fields['modes']] = 'as12'
            a[fields['link_id']] = 1234
            a[fields['a_node']] = 999
            a[fields['b_node']] = 888
            a[0] = 1234

            idx = ','.join(['?'] * len(a))
            self.curr.execute(f'insert into links values ({idx})', a)
            self.curr.execute('delete from links where link_id=1234')

            self.curr.execute(cmd)

            with self.assertRaises(sqlite3.IntegrityError):
                self.curr.execute(f'insert into links values ({idx})', a)

    def test_modes_length_on_links_insert(self):
        cmd = self.__get_query('modes_length_on_links_insert')
        if self.rtree:
            self.curr.execute('pragma table_info(links)')
            f = self.curr.fetchall()
            fields = {x[1]: x[0] for x in f}

            sql = 'select * from links where link_id=70'
            self.curr.execute(sql)
            a = [x for x in self.curr.fetchone()]
            a[fields['modes']] = ''
            a[fields['link_id']] = 4321
            a[fields['a_node']] = 888
            a[fields['b_node']] = 999
            a[0] = 4321

            idx = ','.join(['?'] * len(a))
            self.curr.execute(f'insert into links values ({idx})', a)
            self.curr.execute('delete from links where link_id=4321')

            self.curr.execute(cmd)

            with self.assertRaises(sqlite3.IntegrityError):
                self.curr.execute(f'insert into links values ({idx})', a)

    def test_keep_at_least_one(self):
        cmd = self.__get_query('mode_keep_at_least_one')

        self.curr.execute('Delete from modes;')
        self.curr.execute('select count(*) from modes;')
        self.assertEqual(
            self.curr.fetchone()[0], 0,
            'We were not able to clear the m odes table as expected')

        self.curr.execute(
            'insert into modes(mode_id, mode_name) VALUES("k", "some_name")')
        self.curr.execute(cmd)
        with self.assertRaises(sqlite3.IntegrityError):
            self.curr.execute('Delete from modes;')

    def test_modes_on_nodes_table_update_nodes_modes(self):
        cmd = self.__get_query('modes_on_nodes_table_update_nodes_modes')
        self.curr.execute(
            'select node_id, modes from nodes where length(modes)>0')
        dt = self.curr.fetchall()

        x = choice(dt)

        self.curr.execute(
            f'update nodes set modes="abcdefgq" where node_id={x[0]}')
        self.curr.execute(
            f'select node_id, modes from nodes where node_id={x[0]}')
        z = self.curr.fetchone()
        if z == x:
            self.fail(
                'Modes field on nodes layer is being preserved by unknown mechanism'
            )

        self.curr.execute(cmd)

        y = choice(dt)
        while y == x:
            y = choice(dt)

        # We try to force the change to make sure it was correctly filled to begin with
        self.curr.execute(
            f'update nodes set modes="hgfedcba" where node_id={y[0]}')

        self.curr.execute(
            f'select node_id, modes from nodes where node_id={y[0]}')
        k = self.curr.fetchone()

        self.curr.execute(
            f'update nodes set modes="abcdefgq" where node_id={y[0]}')

        self.curr.execute(
            f'select node_id, modes from nodes where node_id={y[0]}')
        z = self.curr.fetchone()

        self.assertEqual(
            z, k, 'Failed to preserve the information on modes for the nodes')
class TestNetwork_skimming(TestCase):
    def setUp(self) -> None:
        os.environ['PATH'] = os.path.join(
            gettempdir(), 'temp_data') + ';' + os.environ['PATH']

        self.proj_dir = os.path.join(gettempdir(), uuid.uuid4().hex)
        copytree(siouxfalls_project, self.proj_dir)

        self.project = Project()
        self.project.open(self.proj_dir)
        self.network = self.project.network
        self.curr = self.project.conn.cursor()

    def tearDown(self) -> None:
        self.project.close()
        del self.curr
        try:
            rmtree(self.proj_dir)
        except Exception as e:
            print(f'Failed to remove at {e.args}')

    def test_network_skimming(self):

        self.network.build_graphs()
        graph = self.network.graphs['c']
        graph.set_graph(cost_field="distance")
        graph.set_skimming("distance")

        # skimming results
        res = SkimResults()
        res.prepare(graph)
        aux_res = MultiThreadedNetworkSkimming()
        aux_res.prepare(graph, res)
        _ = skimming_single_origin(12, graph, res, aux_res, 0)

        skm = NetworkSkimming(graph)
        skm.execute()

        tot = np.nanmax(skm.results.skims.distance[:, :])
        if tot > np.sum(graph.cost):
            self.fail(
                "Skimming was not successful. At least one np.inf returned.")

        if skm.report:
            self.fail("Skimming returned an error:" + str(skm.report))

        skm.save_to_project('tEst_Skimming')

        if not os.path.isfile(
                os.path.join(self.proj_dir, 'matrices', 'test_skimming.omx')):
            self.fail('Did not save project to project')

        matrices = self.project.matrices
        mat = matrices.get_record('TEsT_Skimming')
        self.assertEqual(mat.name, 'tEst_Skimming',
                         'Matrix record name saved wrong')
        self.assertEqual(mat.file_name, 'tEst_Skimming.omx',
                         'matrix file_name saved  wrong')
        self.assertEqual(mat.cores, 1,
                         'matrix saved number of matrix cores wrong')
        self.assertEqual(mat.procedure, 'Network skimming',
                         'Matrix saved wrong procedure name')
        self.assertEqual(mat.procedure_id, skm.procedure_id,
                         'Procedure ID saved  wrong')
        self.assertEqual(mat.timestamp, skm.procedure_date,
                         'Procedure ID saved  wrong')