Example #1
0
def create_example(path: str, from_model='sioux_falls') -> Project:
    """Copies an example model to a new project project and returns the project handle

    Args:
        *path* (:obj:`str`): Path where to create a new model. must be a non-existing folder/directory.
        *from_model path* (:obj:`str`, `Optional`): Example to create from *sioux_falls* or *nauru*. Defaults to
        *sioux_falls*
    Returns:
        *project* (:obj:`Project`): Aequilibrae Project handle (open)

        """
    if os.path.isdir(path):
        raise FileExistsError('Cannot overwrite an existing directory')

    if not os.path.isfile(
            join(dirname(__file__), f'../reference_files/{from_model}.zip')):
        raise FileExistsError('Example not found')

    os.mkdir(path)
    zipfile.ZipFile(
        join(dirname(__file__),
             f'../reference_files/{from_model}.zip')).extractall(path)
    proj = Project()
    proj.open(path)
    return proj
Example #2
0
class TestModes(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(siouxfalls_project, self.temp_proj_folder)
        self.proj = Project()
        self.proj.open(self.temp_proj_folder)
        self.curr = self.proj.conn.cursor()

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

    def test_add(self):
        new_mode = Mode('F')
        name = [
            random.choice(string.ascii_letters + '_')
            for x in range(random.randint(1, 20))
        ]
        name = ''.join(name)
        new_mode.mode_name = name
        self.proj.network.modes.add(new_mode)

        self.curr.execute('select mode_name from modes where mode_id="F"')
        self.assertEqual(self.curr.fetchone()[0], name,
                         'Could not save the mode properly to the database')

    def test_drop(self):
        self.proj.network.modes.delete('b')

        with self.assertRaises(IntegrityError):
            self.proj.network.modes.delete('c')

    def test_get(self):
        c = self.proj.network.modes.get('c')
        self.assertEqual('All motorized vehicles', c.description)
        del c

        with self.assertRaises(ValueError):
            _ = self.proj.network.modes.get('f')

    def test_new(self):
        modes = self.proj.network.modes
        self.assertIsInstance(modes.new('h'), Mode, 'Returned wrong type')

        m = list(modes.all_modes().keys())[0]
        with self.assertRaises(ValueError):
            modes.new(m)

    def test_fields(self):
        fields = self.proj.network.modes.fields()
        fields.all_fields()
        self.assertEqual(fields._table, 'modes',
                         'Returned wrong table handler')
Example #3
0
class TestZone(TestCase):
    def setUp(self) -> None:
        self.temp_proj_folder = join(gettempdir(), uuid4().hex)
        copytree(siouxfalls_project, self.temp_proj_folder)
        self.proj = Project()
        self.proj.open(self.temp_proj_folder)

    def tearDown(self) -> None:
        self.proj.close()
        try:
            rmtree(self.temp_proj_folder)
        except Exception as e:
            warn(f'Error: {e.args}')

    def test_delete(self):
        zones = self.proj.zoning
        zone_downtown = zones.get(3)
        zone_downtown.delete()

        with self.assertRaises(ValueError):
            _ = zones.get(3)

    def test_save(self):
        zones = self.proj.zoning
        zn = zones.get(2)
        area = randint(0, 9999999999)
        zn.area = area
        zn.save()

        curr = self.proj.conn.cursor()
        curr.execute('Select area from Zones where zone_id=2')
        self.assertEqual(curr.fetchone()[0], area,
                         "Zone didn't save area properly")

        geo = Point(0, 0).buffer(1)
        zn.geometry = geo
        zn.save()
        curr = self.proj.conn.cursor()
        curr.execute('Select asBinary(geometry) from Zones where zone_id=2')
        wkb = curr.fetchone()[0]
        self.assertEqual(shapely.wkb.loads(wkb), MultiPolygon([geo]),
                         "Zone didn't save geometry properly")

        zn2 = zones.get(1)
        geo = MultiPolygon([Point(0, 0).buffer(1)])
        zn2.geometry = geo
        zn2.save()
        curr = self.proj.conn.cursor()
        curr.execute('Select asBinary(geometry) from Zones where zone_id=1')
        wkb = curr.fetchone()[0]
        self.assertEqual(shapely.wkb.loads(wkb), geo,
                         "Zone didn't save geometry properly")

    def __change_project(self):
        self.proj.close()
        self.proj = Project()
        self.proj = create_example(join(gettempdir(), uuid4().hex), 'nauru')
        zones = 5
        network = self.proj.network
        nodes = network.nodes

        geo = network.convex_hull()

        zone_area = geo.area / zones
        zone_side = sqrt(2 * sqrt(3) * zone_area / 9)

        extent = network.extent()

        curr = self.proj.conn.cursor()
        b = extent.bounds
        curr.execute(
            'select st_asbinary(HexagonalGrid(GeomFromWKB(?), ?, 0, GeomFromWKB(?)))',
            [extent.wkb, zone_side,
             Point(b[2], b[3]).wkb])
        grid = curr.fetchone()[0]
        grid = shapely.wkb.loads(grid)

        grid = [p for p in grid if p.intersects(geo)]

        zoning = self.proj.zoning
        for i, zone_geo in enumerate(grid):
            zone = zoning.new(i + 1)
            zone.geometry = zone_geo
            zone.save()

            node = nodes.get(i + 1)
            node.renumber(i + 10001)

    def test_add_centroid(self):
        self.__change_project()
        zones = self.proj.zoning
        nodes = self.proj.network.nodes
        network = self.proj.network
        zone1 = zones.get(1)
        tot = network.count_centroids()
        zone1.add_centroid(None)
        self.assertEqual(tot + 1, network.count_centroids(),
                         "Added less than it should've")

        tot = network.count_centroids()
        zone1.add_centroid(None)
        zone1.add_centroid(Point(0, 0))
        self.assertEqual(tot, network.count_centroids(),
                         "Added more than should've")
        node1 = nodes.get(1)
        self.assertEqual(node1.geometry, zone1.geometry.centroid)

        zone2 = zones.get(2)
        zone2.add_centroid(Point(0, 0))

        node2 = nodes.get(2)
        self.assertEqual(node2.geometry, Point(0, 0))

    def test_connect_mode(self):
        self.__change_project()
        curr = self.proj.conn.cursor()
        zones = self.proj.zoning

        zone1 = zones.get(1)
        zone1.add_centroid(None)

        zone1.connect_mode('c')

        curr.execute('Select count(*) from links where a_node=?', [1])
        self.assertIsNot(0, curr.fetchone()[0], 'failed to add connectors')

        zone1.connect_mode('t')
        curr.execute(
            '''Select count(*) from links where a_node=? and instr(modes,'t')>0''',
            [1])
        self.assertIsNot(0,
                         curr.fetchone()[0],
                         'failed to add connectors for mode t')

        # Cannot connect a centroid that does not exist
        with self.assertRaises(ValueError):
            zone2 = zones.get(2)
            zone2.connect_mode('c')

    def test_disconnect_mode(self):
        self.__change_project()
        curr = self.proj.conn.cursor()
        zones = self.proj.zoning
        zone1 = zones.get(1)
        zone1.add_centroid(None)

        zone1.connect_mode('c')
        zone1.connect_mode('w')
        curr.execute('''select COUNT(*) from links where a_node=1''')
        tot = curr.fetchone()[0]
        curr.execute(
            '''Update links set modes = modes || 'w' where instr(modes,'w')=0'''
        )
        self.proj.conn.commit()
        zone1.disconnect_mode('w')

        curr.execute('''select COUNT(*) from links where a_node=1''')
        self.assertIsNot(tot, curr.fetchone()[0], 'failed to delete links')

        curr.execute(
            '''Select count(*) from links where a_node=1 and instr(modes,'w')>0'''
        )
        self.assertEqual(curr.fetchone()[0], 0,
                         'Failed to remove mode from all connectors')
Example #4
0
class TestBlockingTrianglePathResults(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(triangle_graph_blocking, self.proj_dir)
        self.project = Project()
        self.project.open(self.proj_dir)
        self.project.network.build_graphs(modes=["c"])
        self.g = self.project.network.graphs["c"]  # type: Graph
        self.g.set_graph("free_flow_time")
        self.g.set_blocked_centroid_flows(True)

        self.r = PathResults()
        self.r.prepare(self.g)

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

    def test_compute_paths(self):
        self.r.compute_path(1, 2)
        self.assertEqual(list(self.r.path_nodes), [1, 3, 2])
        self.assertEqual(list(self.r.path), [1, 2])

        self.r.compute_path(2, 1)
        self.assertEqual(list(self.r.path_nodes), [2, 1])
        self.assertEqual(list(self.r.path), [3])

        self.r.compute_path(3, 1)
        self.assertEqual(list(self.r.path_nodes), [3, 2, 1])
        self.assertEqual(list(self.r.path), [2, 3])

        self.r.compute_path(3, 2)
        self.assertEqual(list(self.r.path_nodes), [3, 2])
        self.assertEqual(list(self.r.path), [2])

        self.r.compute_path(1, 3)
        self.assertEqual(list(self.r.path_nodes), [1, 3])
        self.assertEqual(list(self.r.path), [1])

        self.r.compute_path(2, 3)
        self.assertEqual(list(self.r.path_nodes), [2, 1, 3])
        self.assertEqual(list(self.r.path), [3, 1])

    def test_compute_blocking_paths(self):
        self.r.compute_path(4, 5)
        self.assertEqual(list(self.r.path_nodes), [4, 1, 3, 2, 5])
        self.assertEqual(list(self.r.path), [4, 1, 2, 5])

        self.r.compute_path(5, 4)
        self.assertEqual(list(self.r.path_nodes), [5, 2, 1, 4])
        self.assertEqual(list(self.r.path), [5, 3, 4])

        self.r.compute_path(6, 4)
        self.assertEqual(list(self.r.path_nodes), [6, 3, 2, 1, 4])
        self.assertEqual(list(self.r.path), [6, 2, 3, 4])

        self.r.compute_path(6, 5)
        self.assertEqual(list(self.r.path_nodes), [6, 3, 2, 5])
        self.assertEqual(list(self.r.path), [6, 2, 5])

        self.r.compute_path(4, 6)
        self.assertEqual(list(self.r.path_nodes), [4, 1, 3, 6])
        self.assertEqual(list(self.r.path), [4, 1, 6])

        self.r.compute_path(5, 6)
        self.assertEqual(list(self.r.path_nodes), [5, 2, 1, 3, 6])
        self.assertEqual(list(self.r.path), [5, 3, 1, 6])

    def test_update_trace(self):
        self.r.compute_path(1, 2)
        self.assertEqual(list(self.r.path_nodes), [1, 3, 2])
        self.assertEqual(list(self.r.path), [1, 2])

        self.r.update_trace(3)
        self.assertEqual(list(self.r.path_nodes), [1, 3])
        self.assertEqual(list(self.r.path), [1])

    def test_update_blocking_trace(self):
        self.r.compute_path(4, 5)
        self.assertEqual(list(self.r.path_nodes), [4, 1, 3, 2, 5])
        self.assertEqual(list(self.r.path), [4, 1, 2, 5])

        self.r.update_trace(6)
        self.assertEqual(list(self.r.path_nodes), [4, 1, 3, 6])
        self.assertEqual(list(self.r.path), [4, 1, 6])
class TestFieldEditor(TestCase):
    my_tables = ["link_types", "links", "modes", "nodes"]

    def setUp(self) -> None:
        os.environ["PATH"] = os.path.join(
            gettempdir(), "temp_data") + ";" + os.environ["PATH"]
        self.temp_proj_folder = join(gettempdir(), uuid4().hex)
        copytree(siouxfalls_project, self.temp_proj_folder)
        self.proj = Project()
        self.proj.open(self.temp_proj_folder)

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

    def randomword(self, length):
        val = "".join(choice(ALLOWED_CHARACTERS) for i in range(length))
        if val[0] == "_" or val[-1] == "_":
            return self.randomword(length)
        return val

    def test_building(self):
        for tab in ["modes", "links", "nodes", "link_types"]:
            table = FieldEditor(tab)
            qry = f'select count(*) from "attributes_documentation" where name_table="{tab}"'
            q = self.proj.conn.execute(qry).fetchone()[0]
            self.assertEqual(
                q, len(table._original_values),
                "Meta table populated with the wrong number of elements")

    def test_add(self):
        for tab in self.my_tables:
            table = FieldEditor(tab)
            qry = f'select count(*) from "attributes_documentation" where name_table="{tab}"'
            q = self.proj.conn.execute(qry).fetchone()[0]
            one = choice(list(table._original_values.keys()))
            self.proj.conn.commit()
            with self.assertRaises(ValueError) as em:
                table.add(one, self.randomword(30))
            self.assertEqual("attribute_name already exists",
                             str(em.exception), "failed in the wrong place")

            with self.assertRaises(ValueError) as em:
                table.add(f"{self.randomword(5)} {5}", self.randomword(30))
            self.assertEqual(
                'attribute_name can only contain letters, numbers and "_"',
                str(em.exception),
                "failed in the wrong place",
            )

            with self.assertRaises(ValueError):
                table.add(
                    choice("0123456789") + self.randomword(20),
                    self.randomword(30))
            new_one = self.randomword(20)
            while new_one[0] in "0123456789":
                new_one = self.randomword(20)
            table.add(new_one, self.randomword(30))
            self.proj.conn.commit()
            curr = self.proj.conn.cursor()
            curr.execute(
                f'select count(*) from "attributes_documentation" where name_table="{tab}"'
            )
            q2 = curr.fetchone()[0]
            self.assertEqual(q + 1, q2, "Adding element did not work")

            # If query fails, we failed to add new field to the database
            curr.execute(
                f'select "{new_one}" from "attributes_documentation" where name_table="{tab}"'
            )

            if "alpha" in table._original_values.keys():
                self.assertEqual(table.alpha, "Available for user convenience",
                                 "not being able to retrieve values")

            self.proj.conn.commit()
            del curr

    def test_check_completeness(self):
        for table in self.my_tables:
            curr = self.proj.conn.cursor()

            # We add a bogus record to the attribute list
            val = self.randomword(30).lower()
            qry = 'INSERT INTO "attributes_documentation" VALUES (?,?," ");'
            curr.execute(qry, (table, val))
            self.proj.conn.commit()

            curr.execute(
                f'Select name_table from "attributes_documentation" where attribute="{val}"'
            )
            self.assertEqual(curr.fetchone()[0], table,
                             "Failed to insert bogus value")

            # Then we add a new field to the table
            val2 = self.randomword(10)
            curr.execute(f'Alter table "{table}" add column "{val2}" NUMERIC;')
            curr.execute(f"pragma table_info({table})")
            fields = [x[1] for x in curr.fetchall() if x[1] == val2]
            self.assertEqual([val2], fields, "failed to add a new field")

            table = FieldEditor(table)
            self.proj.conn.commit()
            curr = self.proj.conn.cursor()
            curr.execute(
                f'Select count(*) from "attributes_documentation" where attribute="{val}"'
            )
            self.assertEqual(curr.fetchone()[0], 0,
                             f"clean the table on loading failed {val}")

            curr.execute(
                f'Select count(*) from "attributes_documentation" where attribute="{val2}"'
            )
            self.assertEqual(curr.fetchone()[0], 1,
                             "clean the table on loading failed")
            print(table._original_values[val2])

            self.proj.conn.commit()
            del curr

    def test_save(self):
        for tab in ["modes", "links", "nodes", "link_types"]:
            table = FieldEditor(tab)
            random_val = self.randomword(30)
            if "alpha" in table._original_values.keys():
                table.alpha = random_val
                table.save()
                table2 = FieldEditor(tab)

                self.assertEqual(table2.alpha, random_val,
                                 "Did not save values properly")

            if "link_id" in table._original_values.keys():
                table.link_id = random_val
                table.save()
                table2 = FieldEditor(tab)

                self.assertEqual(table2.link_id, random_val,
                                 "Did not save values properly")

            if "node_id" in table._original_values.keys():
                table.node_id = random_val
                table.save()
                table2 = FieldEditor(tab)

                self.assertEqual(table2.node_id, random_val,
                                 "Did not save values properly")

            self.proj.conn.commit()
Example #6
0
class TestAbout(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(siouxfalls_project, self.temp_proj_folder)
        self.proj = Project()
        self.proj.open(self.temp_proj_folder)
        self.curr = self.proj.conn.cursor()

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

    def test_create_and_list(self):
        self.proj.about.create()

        with self.assertWarns(expected_warning=Warning):
            self.proj.about.create()

        list = self.proj.about.list_fields()
        expected = ['model_name', 'region', 'description', 'author', 'license', 'scenario_name', 'year',
                    'scenario_description', 'model_version', 'project_id', 'aequilibrae_version', 'projection']

        failed = set(list).symmetric_difference(set(expected))
        if failed:
            self.fail('About table does not have all expected fields')

    # idea from https://stackoverflow.com/a/2030081/1480643
    def randomword(self, length):
        letters = string.ascii_lowercase + '_'
        return ''.join(random.choice(letters) for i in range(length))

    def test_add_info_field(self):
        self.proj.about.create()

        all_added = set()
        for t in range(30):
            k = self.randomword(random.randint(1, 15))
            if k not in all_added:
                all_added.add(k)
                self.proj.about.add_info_field(k)

        curr = self.proj.conn.cursor()
        curr.execute("select infoname from 'about'")

        charac = [x[0] for x in curr.fetchall()]
        for k in all_added:
            if k not in charac:
                self.fail(f'Failed to add {k}')

        # Should fail when trying to add a repeated guy
        with self.assertRaises(sqlite3.IntegrityError):
            self.proj.about.add_info_field('description')

        # Should fail when trying to add a repeated guy
        with self.assertRaises(ValueError):
            self.proj.about.add_info_field('descr1ption')

    def test_write_back(self):
        self.proj.about.create()
        self.proj.about.add_info_field('good_info_field_perhaps')

        val = self.randomword(random.randint(1, 15))
        self.proj.about.good_info_field_perhaps = val

        val2 = self.randomword(random.randint(30, 250))
        self.proj.about.description = val2

        self.proj.about.write_back()

        self.proj.close()
        del self.proj

        self.proj = Project()
        self.proj.open(self.temp_proj_folder)
        self.assertEqual(val, self.proj.about.good_info_field_perhaps, 'failed to save data to about table')
        self.assertEqual(val2, self.proj.about.description, 'failed to save data to about table')
Example #7
0
    def test_fit(self):
        proj = Project()
        proj.open(self.proj_dir)
        mats = proj.matrices
        mats.update_database()
        seed = mats.get_matrix('SiouxFalls_omx')
        seed.computational_view('matrix')
        # row vector
        args = {
            "entries": seed.zones,
            "field_names": ["rows"],
            "data_types": [np.float64],
            "memory_mode": True
        }
        row_vector = AequilibraeData()
        row_vector.create_empty(**args)
        row_vector.rows[:] = np.random.rand(seed.zones)[:] * 1000
        row_vector.index[:] = seed.index[:]
        # column vector
        args["field_names"] = ["columns"]
        column_vector = AequilibraeData()
        column_vector.create_empty(**args)
        column_vector.columns[:] = np.random.rand(seed.zones)[:] * 1000
        column_vector.index[:] = seed.index[:]
        # balance vectors
        column_vector.columns[:] = column_vector.columns[:] * (
            row_vector.rows.sum() / column_vector.columns.sum())

        # The IPF per se
        args = {
            "matrix": seed,
            "rows": row_vector,
            "row_field": "rows",
            "columns": column_vector,
            "column_field": "columns",
            "nan_as_zero": False,
        }

        with self.assertRaises(TypeError):
            fratar = Ipf(data='test', test='data')
            fratar.fit()

        with self.assertRaises(ValueError):
            fratar = Ipf(**args)
            fratar.parameters = ['test']
            fratar.fit()

        fratar = Ipf(**args)
        fratar.fit()

        result = fratar.output

        self.assertAlmostEqual(np.nansum(result.matrix_view),
                               np.nansum(row_vector.data["rows"]), 4,
                               "Ipf did not converge")
        self.assertGreater(fratar.parameters["convergence level"], fratar.gap,
                           "Ipf did not converge")

        mr = fratar.save_to_project('my_matrix_ipf', 'my_matrix_ipf.aem')

        self.assertTrue(
            os.path.isfile(os.path.join(mats.fldr, 'my_matrix_ipf.aem')),
            'Did not save file to the appropriate place')

        self.assertEqual(mr.procedure_id, fratar.procedure_id,
                         'procedure ID saved wrong')
        proj.close()