예제 #1
0
    def __init__(self,
                 id: Union[str, int],
                 x: Union[str, int, float],
                 y: Union[str, int, float],
                 epsg: str,
                 transformer: Transformer = None,
                 name: str = '',
                 **kwargs):
        self.id = id
        self.x = float(x)
        self.y = float(y)
        self.epsg = epsg
        self.name = name

        if ('lat' in kwargs) and ('lon' in kwargs):
            self.lat, self.lon = kwargs['lat'], kwargs['lon']
        else:
            if self.epsg == 'epsg:4326':
                self.lat, self.lon = float(x), float(y)
            else:
                if transformer is None:
                    transformer = Transformer.from_crs(self.epsg, 'epsg:4326')
                self.lat, self.lon = spatial.change_proj(x, y, transformer)
        if 's2_id' in kwargs:
            self.s2_id = kwargs['s2_id']
        else:
            self.s2_id = spatial.grab_index_s2(lat=self.lat, lng=self.lon)

        self.additional_attributes = []
        if kwargs:
            self.add_additional_attributes(kwargs)
예제 #2
0
def read_node(elem, g, node_id_mapping, transformer):
    """
    Adds node elem of the stream to the network
    :param elem:
    :param g: nx.MultiDiGraph
    :param node_id_mapping:
    :param transformer:
    :return:
    """
    duplicated_node_id = {}
    attribs = elem.attrib
    attribs['x'], attribs['y'] = float(attribs['x']), float(attribs['y'])

    if 'z' in attribs:
        attribs['z'] = float(attribs['z'])

    lon, lat = spatial.change_proj(attribs['x'], attribs['y'], transformer)
    # ideally we would check if the transformer was created with always_xy=True and swap
    # lat and long values if so, but there is no obvious way to interrogate the transformer
    attribs['lon'], attribs['lat'] = lon, lat
    attribs['s2_id'] = spatial.generate_index_s2(lat, lon)
    node_id = attribs['id']
    if node_id in node_id_mapping:
        logging.warning(
            'This MATSim network has a node that is not unique: {}. Generating a new id would'
            'be pointless as we don\'t know which links should be connected to this particular'
            'node. The node will cease to exist and the first encountered node with this id'
            'will be kept. Investigate the links connected to that node.'.
            format(node_id))
        duplicated_node_id[node_id] = attribs
    else:
        node_id_mapping[node_id] = attribs['s2_id']
        g.add_node(node_id, **attribs)
    return g, duplicated_node_id
예제 #3
0
def reproj(nodes_dict, from_proj, to_proj):
    transformer = Transformer.from_crs(from_proj, to_proj)
    new_attribs = {}
    for node, node_attrib in nodes_dict.items():
        x, y = spatial.change_proj(node_attrib['x'], node_attrib['y'],
                                   transformer)
        new_attribs[node] = {'x': x, 'y': y}
    return new_attribs
예제 #4
0
 def reproject(self, new_epsg, transformer: Transformer = None):
     """
     Changes projection of a stop. If doing many stops, it's much quicker to pass the transformer as well as epsg.
     :param new_epsg: 'epsg:12345'
     :param transformer:
     :return:
     """
     if transformer is None:
         transformer = Transformer.from_crs(self.epsg, new_epsg)
     self.x, self.y = spatial.change_proj(self.x, self.y, transformer)
     self.epsg = new_epsg
예제 #5
0
def generate_graph_nodes(nodes, epsg):
    input_to_output_transformer = Transformer.from_crs('epsg:4326', epsg)
    nodes_and_attributes = {}
    for node_id, attribs in nodes.items():
        x, y = spatial.change_proj(attribs['x'], attribs['y'], input_to_output_transformer)
        nodes_and_attributes[str(node_id)] = {
            'id': str(node_id),
            'x': x,
            'y': y,
            'lat': attribs['x'],
            'lon': attribs['y'],
            's2_id': attribs['s2id']
        }
    return nodes_and_attributes
예제 #6
0
def reproj_stops(schedule_element_nodes: dict, new_epsg):
    """
    :param schedule_element_nodes: dict stop ids : stop data including x, y, epsg
    :param new_epsg: 'epsg:1234', the epsg stops are being projected to
    :return: dict: stop ids from schedule_element_nodes: changed stop data in dict format new x, y and epsg
    """
    transformers = {
        epsg: Transformer.from_crs(epsg, new_epsg, always_xy=True)
        for epsg in DataFrame(schedule_element_nodes).T['epsg'].unique()
    }

    reprojected_node_attribs = {}
    for node_id, node_attribs in schedule_element_nodes.items():
        x, y = spatial.change_proj(node_attribs['x'], node_attribs['y'],
                                   transformers[node_attribs['epsg']])
        reprojected_node_attribs[node_id] = {'x': x, 'y': y, 'epsg': new_epsg}
    return reprojected_node_attribs
예제 #7
0
def write_matsim_schedule(output_dir, schedule, epsg=''):
    fname = os.path.join(output_dir, "schedule.xml")
    if not epsg:
        epsg = schedule.epsg
    transformer = Transformer.from_proj(Proj('epsg:4326'), Proj(epsg))
    logging.info('Writing {}'.format(fname))

    # Also makes vehicles
    vehicles = {}

    with open(fname, "wb") as f, etree.xmlfile(f, encoding='utf-8') as xf:
        xf.write_declaration(
            doctype='<!DOCTYPE transitSchedule '
            'SYSTEM "http://www.matsim.org/files/dtd/transitSchedule_v2.dtd">')
        with xf.element("transitSchedule"):
            # transitStops first
            with xf.element("transitStops"):
                for stop_facility in schedule.stops():
                    transit_stop_attrib = {'id': str(stop_facility.id)}
                    if stop_facility.epsg == epsg:
                        x = stop_facility.x
                        y = stop_facility.y
                    else:
                        x, y = change_proj(x=stop_facility.lat,
                                           y=stop_facility.lon,
                                           crs_transformer=transformer)
                    transit_stop_attrib['x'], transit_stop_attrib['y'] = str(
                        x), str(y)
                    for k in ADDITIONAL_STOP_FACILITY_ATTRIBUTES:
                        if stop_facility.has_attrib(k):
                            transit_stop_attrib[k] = str(
                                stop_facility.additional_attribute(k))
                    xf.write(etree.Element("stopFacility",
                                           transit_stop_attrib))

            # minimalTransferTimes, if present
            if schedule.minimal_transfer_times:
                with xf.element("minimalTransferTimes"):
                    for stop_1_id, val in schedule.minimal_transfer_times.items(
                    ):
                        minimal_transfer_times_attribs = {
                            'fromStop': str(stop_1_id),
                            'toStop': str(val['stop']),
                            'transferTime': str(val['transferTime'])
                        }
                        xf.write(
                            etree.Element("relation",
                                          minimal_transfer_times_attribs))

                        minimal_transfer_times_attribs['fromStop'] = str(
                            val['stop'])
                        minimal_transfer_times_attribs['toStop'] = str(
                            stop_1_id)
                        xf.write(
                            etree.Element("relation",
                                          minimal_transfer_times_attribs))

            # transitLine
            v_id = 0  # generating some ids for vehicles
            for service_id, service in schedule.services.items():
                transit_line_attribs = {
                    'id': service_id,
                    'name': str(service.name)
                }

                with xf.element("transitLine", transit_line_attribs):
                    for id, route in service._routes.items():
                        transit_route_attribs = {'id': id}

                        with xf.element("transitRoute", transit_route_attribs):
                            rec = etree.Element("transportMode")
                            rec.text = route.mode
                            xf.write(rec)

                            with xf.element("routeProfile"):
                                for j in range(len(route.ordered_stops)):
                                    stop_attribs = {
                                        'refId': str(route.ordered_stops[j])
                                    }

                                    if not (route.departure_offsets
                                            and route.arrival_offsets):
                                        logging.warning(
                                            'The stop(s) along your route don\'t have arrival and departure offsets. '
                                            'This is likely a route with one stop - consider validating your schedule.'
                                        )
                                    else:
                                        if j == 0:
                                            stop_attribs[
                                                'departureOffset'] = route.departure_offsets[
                                                    j]
                                        elif j == len(route.ordered_stops) - 1:
                                            stop_attribs[
                                                'arrivalOffset'] = route.arrival_offsets[
                                                    j]
                                        else:
                                            stop_attribs[
                                                'departureOffset'] = route.departure_offsets[
                                                    j]
                                            stop_attribs[
                                                'arrivalOffset'] = route.arrival_offsets[
                                                    j]

                                        if route.await_departure:
                                            stop_attribs[
                                                'awaitDeparture'] = str(
                                                    route.await_departure[j]
                                                ).lower()
                                    xf.write(
                                        etree.Element("stop", stop_attribs))

                            with xf.element("route"):
                                if not route.route:
                                    logging.warning(
                                        "Route needs to have a network route composed of a list of network links that "
                                        "the vehicle on this route traverses. If read the Schedule from GTFS, the "
                                        "resulting Route objects will not have reference to the network route taken."
                                    )
                                for link_id in route.route:
                                    route_attribs = {'refId': str(link_id)}
                                    xf.write(
                                        etree.Element("link", route_attribs))

                            with xf.element("departures"):
                                for trip_id, trip_dep in route.trips.items():
                                    vehicle_id = 'veh_{}_{}'.format(
                                        v_id, route.mode)
                                    trip_attribs = {
                                        'id': trip_id,
                                        'departureTime': trip_dep,
                                        'vehicleRefId': vehicle_id
                                    }
                                    vehicles[
                                        vehicle_id] = matsim_xml_values.MODE_DICT[
                                            route.mode]
                                    v_id += 1
                                    xf.write(
                                        etree.Element("departure",
                                                      trip_attribs))
    return vehicles