예제 #1
0
def download_osm_features(place, osm_type, tag, values=None, by_poly=True, timeout=180):
    """ Download OSM features within given place

    :param place: single place name query (e.g: "London", "Bonn", etc.)
    :param osm_type: OSM geometry type str ('node', 'way', 'relation')
    :param tag: OSM tag to query
    :param values: str/list of possible values for the provided OSM tag
    :param by_poly: if True, retrieve features within polygon's list of coordinates, otherwise use bounds
    :param timeout:
    :return:
    """
    gdf_geometry = geocode_to_gdf(place)

    try:
        geometry = gdf_geometry.geometry[0]
    except AttributeError:  # Empty GeoDataFrame
        return None

    responses = []

    if by_poly:
        polygon_coord_strs = get_polygons_coordinates(geometry)
        for poly_coord_str in polygon_coord_strs:
            query = ql_query(osm_type, tag, values, polygon_coord=poly_coord_str, timeout=timeout)
            responses.append(overpass_request(data={'data': query}))
    else:
        query = ql_query(osm_type, tag, values, bounds=geometry.bounds, timeout=timeout)
        responses.append(overpass_request(data={'data': query}))

    return responses
예제 #2
0
                                                                                 len(list(G.edges())),
                                                                                 time.time() - start_time))

    # add length (great circle distance between nodes) attribute to each edge to
    # use as weight
    if len(G.edges) > 0:
        G = ox.add_edge_lengths(G)

    return G

punggol = (1.403948, 103.909048)
distance = 2000

G_walk = ox.graph_from_point(punggol, distance=distance, truncate_by_edge=True, network_type='drive', simplify=False)
mrt_query_str = '[out:json][timeout:180];(relation["network"="Singapore Rail"]["route"="monorail"](1.4011,103.8977,1.4154,103.9231);>;);out;'
mrt_response_json = overpass_request(data={'data': mrt_query_str}, timeout=180)
G_lrt = create_graph(mrt_response_json)


# storing all nodes into a list
walkNodeList = list(G_walk.nodes.values())
mrtNodeList = list(G_lrt.nodes.values())
mrtEdgeList = list(G_lrt.edges.items())

pe = []
pw = []
for k in mrtNodeList:  # check for nodes which are stations
    try:
        if "PE" in k.get('ref'):
            pe.append(k.get('osmid'))
        if "PW" in k.get('ref'):
예제 #3
0
        def overpass_request(data,
                             pause_duration=None,
                             timeout=180,
                             error_pause_duration=None):
            """
            Send a request to the Overpass API via HTTP POST and return the JSON
            response.
            Parameters
            ----------
            data : dict or OrderedDict
                key-value pairs of parameters to post to the API
            pause_duration : int
                how long to pause in seconds before requests, if None, will query API
                status endpoint to find when next slot is available
            timeout : int
                the timeout interval for the requests library
            error_pause_duration : int
                how long to pause in seconds before re-trying requests if error
            Returns
            -------
            dict
            """

            # define the Overpass API URL, then construct a GET-style URL as a string to
            # hash to look up/save to cache
            url = settings.overpass_endpoint.rstrip('/') + '/interpreter'
            prepared_url = requests.Request('GET', url,
                                            params=data).prepare().url
            cached_response_json = get_from_cache(prepared_url)

            if cached_response_json is not None:
                # found this request in the cache, just return it instead of making a
                # new HTTP call
                return cached_response_json

            else:
                # if this URL is not already in the cache, pause, then request it
                if pause_duration is None:
                    this_pause_duration = get_pause_duration()
                log('Pausing {:,.2f} seconds before making API POST request'.
                    format(this_pause_duration))
                time.sleep(this_pause_duration)
                start_time = time.time()
                log('Posting to {} with timeout={}, "{}"'.format(
                    url, timeout, data))
                response = requests.post(url,
                                         data=data,
                                         timeout=timeout,
                                         headers=get_http_headers())

                # get the response size and the domain, log result
                size_kb = len(response.content) / 1000.
                domain = re.findall(r'(?s)//(.*?)/', url)[0]
                log('Downloaded {:,.1f}KB from {} in {:,.2f} seconds'.format(
                    size_kb, domain,
                    time.time() - start_time))

                try:
                    response_json = response.json()
                    if 'remark' in response_json:
                        log('Server remark: "{}"'.format(
                            response_json['remark'], level=lg.WARNING))
                    save_to_cache(prepared_url, response_json)
                except Exception:
                    # 429 is 'too many requests' and 504 is 'gateway timeout' from server
                    # overload - handle these errors by recursively calling
                    # overpass_request until we get a valid response
                    if response.status_code in [429, 504]:
                        # pause for error_pause_duration seconds before re-trying request
                        if error_pause_duration is None:
                            error_pause_duration = get_pause_duration()
                        log('Server at {} returned status code {} and no JSON data. Re-trying request in {:.2f} seconds.'
                            .format(domain, response.status_code,
                                    error_pause_duration),
                            level=lg.WARNING)
                        time.sleep(error_pause_duration)
                        response_json = overpass_request(
                            data=data,
                            pause_duration=pause_duration,
                            timeout=timeout)

                    # else, this was an unhandled status_code, throw an exception
                    else:
                        log('Server at {} returned status code {} and no JSON data'
                            .format(domain, response.status_code),
                            level=lg.ERROR)
                        raise Exception(
                            'Server returned no JSON data.\n{} {}\n{}'.format(
                                response, response.reason, response.text))

                return response_json
예제 #4
0
    def bus_layer(start, end, results, case):
        """
        It generates a bus route with the bus numbers via greedy algorithm

        Parameters
        ----------
        start : node id
        end : node id
        results : dict (From lta datamall)
        case : int
        Returns
        -------
        final_route_list : list
        """
        def overpass_request(data,
                             pause_duration=None,
                             timeout=180,
                             error_pause_duration=None):
            """
            Send a request to the Overpass API via HTTP POST and return the JSON
            response.
            Parameters
            ----------
            data : dict or OrderedDict
                key-value pairs of parameters to post to the API
            pause_duration : int
                how long to pause in seconds before requests, if None, will query API
                status endpoint to find when next slot is available
            timeout : int
                the timeout interval for the requests library
            error_pause_duration : int
                how long to pause in seconds before re-trying requests if error
            Returns
            -------
            dict
            """

            # define the Overpass API URL, then construct a GET-style URL as a string to
            # hash to look up/save to cache
            url = settings.overpass_endpoint.rstrip('/') + '/interpreter'
            prepared_url = requests.Request('GET', url,
                                            params=data).prepare().url
            cached_response_json = get_from_cache(prepared_url)

            if cached_response_json is not None:
                # found this request in the cache, just return it instead of making a
                # new HTTP call
                return cached_response_json

            else:
                # if this URL is not already in the cache, pause, then request it
                if pause_duration is None:
                    this_pause_duration = get_pause_duration()
                log('Pausing {:,.2f} seconds before making API POST request'.
                    format(this_pause_duration))
                time.sleep(this_pause_duration)
                start_time = time.time()
                log('Posting to {} with timeout={}, "{}"'.format(
                    url, timeout, data))
                response = requests.post(url,
                                         data=data,
                                         timeout=timeout,
                                         headers=get_http_headers())

                # get the response size and the domain, log result
                size_kb = len(response.content) / 1000.
                domain = re.findall(r'(?s)//(.*?)/', url)[0]
                log('Downloaded {:,.1f}KB from {} in {:,.2f} seconds'.format(
                    size_kb, domain,
                    time.time() - start_time))

                try:
                    response_json = response.json()
                    if 'remark' in response_json:
                        log('Server remark: "{}"'.format(
                            response_json['remark'], level=lg.WARNING))
                    save_to_cache(prepared_url, response_json)
                except Exception:
                    # 429 is 'too many requests' and 504 is 'gateway timeout' from server
                    # overload - handle these errors by recursively calling
                    # overpass_request until we get a valid response
                    if response.status_code in [429, 504]:
                        # pause for error_pause_duration seconds before re-trying request
                        if error_pause_duration is None:
                            error_pause_duration = get_pause_duration()
                        log('Server at {} returned status code {} and no JSON data. Re-trying request in {:.2f} seconds.'
                            .format(domain, response.status_code,
                                    error_pause_duration),
                            level=lg.WARNING)
                        time.sleep(error_pause_duration)
                        response_json = overpass_request(
                            data=data,
                            pause_duration=pause_duration,
                            timeout=timeout)

                    # else, this was an unhandled status_code, throw an exception
                    else:
                        log('Server at {} returned status code {} and no JSON data'
                            .format(domain, response.status_code),
                            level=lg.ERROR)
                        raise Exception(
                            'Server returned no JSON data.\n{} {}\n{}'.format(
                                response, response.reason, response.text))

                return response_json

        def get_node(element):
            """
            Convert an OSM node element into the format for a networkx node.

            Parameters
            ----------
            element : dict
                an OSM node element

            Returns
            -------
            dict
            """
            useful_tags_node = ['ref', 'highway', 'route_ref', 'asset_ref']

            node = {}
            node['y'] = element['lat']
            node['x'] = element['lon']
            node['osmid'] = element['id']

            if 'tags' in element:
                for useful_tag in useful_tags_node:
                    if useful_tag in element['tags']:
                        node[useful_tag] = element['tags'][useful_tag]
            return node

        def get_path(element, element_r):
            """
            Convert an OSM way element into the format for a networkx graph path.

            Parameters
            ----------
            element : dict
                an OSM way element
            element_r : dict
                an OSM way element

            Returns
            -------
            dict
            """
            useful_tags_path_e = [
                'bridge', 'tunnel', 'oneway', 'lanes', 'name', 'highway',
                'maxspeed', 'service', 'access', 'area', 'landuse', 'width',
                'est_width', 'junction'
            ]

            useful_tags_path_r = [
                'bridge', 'tunnel', 'oneway', 'lanes', 'ref', 'direction',
                'from', 'to', 'name', 'highway', 'maxspeed', 'service',
                'access', 'area', 'landuse', 'width', 'est_width', 'junction'
            ]

            path = {}
            path['osmid'] = element['id']

            # remove any consecutive duplicate elements in the list of nodes
            grouped_list = groupby(element['nodes'])
            path['nodes'] = [group[0] for group in grouped_list]

            if 'tags' in element:
                # for relation in element_r['elements']:
                #     if relation['type'] == 'relation':
                #         for members in relation['members']:
                #             if members['ref'] == element['id']:
                for useful_tag in useful_tags_path_e:
                    if useful_tag in element['tags']:
                        path[useful_tag] = element['tags'][useful_tag]
                # for useful_tag in useful_tags_path_r:
                #     if useful_tag in relation['tags']:
                #         try:
                #             path[useful_tag] = path[useful_tag] + ";" + relation['tags'][useful_tag]
                #         except KeyError:
                #             path[useful_tag] = relation['tags'][useful_tag]
                #             pass

            return path

        def parse_osm_nodes_paths(osm_data):
            """
            Construct dicts of nodes and paths with key=osmid and value=dict of
            attributes.

            Parameters
            ----------
            osm_data : dict
                JSON response from from the Overpass API

            Returns
            -------
            nodes, paths : tuple
            """

            nodes = {}
            paths = {}
            relation = {}

            # for element in osm_data['elements']:
            #     if element['type'] == 'relation':

            for element in osm_data['elements']:
                if element['type'] == 'node':
                    key = element['id']
                    nodes[key] = get_node(element)

                elif element['type'] == 'way':  #osm calls network paths 'ways'
                    key = element['id']
                    # pp.pprint(element)
                    paths[key] = get_path(element, osm_data)

            return nodes, paths

        def create_graph(response_jsons,
                         name='unnamed',
                         retain_all=True,
                         bidirectional=False):
            """
            Create a networkx graph from Overpass API HTTP response objects.

            Parameters
            ----------
            response_jsons : list
                list of dicts of JSON responses from from the Overpass API
            name : string
                the name of the graph
            retain_all : bool
                if True, return the entire graph even if it is not connected
            bidirectional : bool
                if True, create bidirectional edges for one-way streets

            Returns
            -------
            networkx multidigraph
            """

            log('Creating networkx graph from downloaded OSM data...')
            start_time = time.time()

            # make sure we got data back from the server requests
            elements = []
            # for response_json in response_jsons:
            elements.extend(response_json['elements'])
            if len(elements) < 1:
                raise EmptyOverpassResponse(
                    'There are no data elements in the response JSON objects')

            # create the graph as a MultiDiGraph and set the original CRS to default_crs
            G = nx.MultiDiGraph(name=name, crs=settings.default_crs)

            # extract nodes and paths from the downloaded osm data
            nodes = {}
            paths = {}
            # for osm_data in response_jsons:
            nodes_temp, paths_temp = parse_osm_nodes_paths(response_jsons)
            for key, value in nodes_temp.items():
                nodes[key] = value
            for key, value in paths_temp.items():
                paths[key] = value

            # add each osm node to the graph
            for node, data in nodes.items():
                G.add_node(node, **data)

            # add each osm way (aka, path) to the graph
            G = ox.add_paths(G, paths, bidirectional=bidirectional)

            # retain only the largest connected component, if caller did not
            # set retain_all=True
            if not retain_all:
                G = get_largest_component(G)

            log('Created graph with {:,} nodes and {:,} edges in {:,.2f} seconds'
                .format(len(list(G.nodes())), len(list(G.edges())),
                        time.time() - start_time))

            # add length (great circle distance between nodes) attribute to each edge to
            # use as weight
            if len(G.edges) > 0:
                G = ox.add_edge_lengths(G)

            return G

        def calculate_H(s_lat, s_lon, e_lat, e_lon):
            """
            Calculate a distance with x,y coordinates with

            Parameters
            ----------
            s_lat : float (starting lat)
            s_lon : float (starting lon)
            e_lat : float (ending lat)
            e_lon : float (ending lon)

            Returns
            -------
            distance
            """
            R = 6371.0
            snlat = radians(s_lat)
            snlon = radians(s_lon)
            elat = radians(e_lat)
            elon = radians(e_lon)
            actual_dist = 6371.01 * acos(
                sin(snlat) * sin(elat) +
                cos(snlat) * cos(elat) * cos(snlon - elon))
            actual_dist = actual_dist * 1000
            return actual_dist

        def bus_details_SD(adjacent_list):
            """
            store all details from LTA data mall into dictionary

            Parameters
            ----------
            adjacent_list : dict

            Returns
            -------
            adjacent_list : dict
            """

            temp = 0
            for x in results:
                if temp != x.get('ServiceNo'):
                    temp = x.get('ServiceNo')
                    count = 0
                    adja_bus_stop = my_dictionary()
                    adjacent_list.add(temp, adja_bus_stop)
                    adja_bus_stop.add(
                        count, [x.get('BusStopCode'),
                                x.get('Distance')])
                    count += 1
                else:
                    adja_bus_stop.add(
                        count, [x.get('BusStopCode'),
                                x.get('Distance')])
                    count += 1
            return adjacent_list

        def get_nearestedge_node(osm_id, a, G):
            """
            Find the nearest node available in Open street map

            Parameters
            ----------
            osm_id : node ID
            a : plotting graph
            g : bus graph

            Returns
            -------
            temp_nearest_edge[1]/temp_nearest_edge[2] : nearest node to a way ID
            """
            temp_y = G.nodes.get(osm_id).get('y')
            temp_x = G.nodes.get(osm_id).get('x')
            temp_nearest_edge = ox.get_nearest_edge(a, (temp_y, temp_x))
            temp_1 = temp_nearest_edge[0].coords[0]
            temp_2 = temp_nearest_edge[0].coords[1]
            temp1_x = temp_1[0]
            temp1_y = temp_1[1]
            temp_1_distance = calculate_H(temp1_y, temp1_x, temp_y, temp_x)

            temp2_x = temp_2[0]
            temp2_y = temp_2[1]
            temp_2_distance = calculate_H(temp2_y, temp2_x, temp_y, temp_x)
            if temp_1_distance < temp_2_distance:
                return temp_nearest_edge[1]
            else:
                return temp_nearest_edge[2]

        def delete_duplicate(x):
            """
            Delete duplicate within a list

            Parameters
            ----------
            x : list

            Returns
            -------
            list
            """
            return list(dict.fromkeys(x))

        def request_busG():
            """
            Find all nodes that is a bus stop

            Returns
            -------
            busG : dict
            """
            busG = {}
            for x in G.nodes.items():
                if x[1].get('highway') == 'bus_stop':
                    xy = []
                    xy.append(x[1].get('osmid'))
                    xy.append(x[1].get('x'))
                    xy.append(x[1].get('y'))
                    busG[x[1].get('osmid')] = xy

            return busG

        # ---MAIN---#

        query_str = '[out:json][timeout:180];node["type"="route"](1.385700,103.887300,1.422000,103.925900);way["type"="route"](1.385700,103.887300,1.422000,103.925900);(relation["type"="route"](1.385700,103.887300,1.422000,103.925900);>;);out;'
        response_json = overpass_request(data={'data': query_str}, timeout=180)
        pp = pprint.PrettyPrinter(indent=4)
        # start = 1847853709
        # end = 410472575
        # end = 3737148763
        # bus transit
        # start = 2110621974
        # end = 2085845884

        adjacent_list = my_dictionary()

        G = ox.load_graphml('Bus_Overpass.graphml')

        if case == 1:
            return request_busG()
        n, e = ox.graph_to_gdfs(G)
        # e.to_csv("Edge_test_busstop.csv")
        if len(results) == 0:

            results = bus_details_all(
                results
            )  # Details from LTA Datamall, extracting all details such as service no, bus stop number

        adjacent_list = bus_details_SD(
            adjacent_list
        )  # From results, it extracts bus stop number and distance
        start_busstop = (G.nodes.get(start)).get('asset_ref')
        end_busstop = (G.nodes.get(end)).get('asset_ref')

        #Start finding common bus service within the start bus stop and end bus stop
        try:
            if ";" in (G.nodes.get(start).get('route_ref')):
                start_rr = (G.nodes.get(start).get('route_ref')).split(";")
            else:
                start_rr = []
                start_rr.append((G.nodes.get(start).get('route_ref')))
            print("TEST - G.nodes.get(end): ", G.nodes.get(end))
            if ";" in (G.nodes.get(end).get('route_ref')):
                end_rr = (G.nodes.get(end).get('route_ref')).split(";")
            else:
                end_rr = []
                end_rr.append((G.nodes.get(end).get('route_ref')))
            common = list(set(start_rr) & set(end_rr))
        except:
            return -1
        """
        This method strictly emphasis on greedy algorithm. Thus it will prioritze the numbers of transit rather than distance
        Check if any common bus service within start and end bus stop.
        If found, route_list will capture the entire route of the common bus service 
        No transit will occuer as it is a straight path, start busstop -> end busstop
        If not found, the program will proceed to find a common bus stop within the start and end bus services. 
        Thus a transit will occur, start busstop -> mid busstop -> end busstop
        """
        route_list = {}
        mid_route_list = {}
        # print("TEST - Start: ", start_busstop)
        # print("TEST - End: ", end_busstop)
        # print("TEST - start_rr: ", start_rr)
        # print("TEST - end_rr: ", end_rr)
        # print("TEST - Common: ", common)
        common_mid = []
        if len(common) == 0:  #No common bus service found
            while (len(common_mid) == 0):  #Start finding a common mid busstop
                rona_one = []
                rona_two = []
                for start_to_mid in start_rr:  #Capture all common mid busstop
                    print("TEST - start_to_mid: ", start_to_mid)
                    for bus_sequence in adjacent_list.get(start_to_mid):
                        rona_one.append(
                            str(
                                adjacent_list.get(start_to_mid).get(
                                    bus_sequence)[0]))
                    for mid_to_end in end_rr:
                        print("TEST - mid_to_end: ", mid_to_end)
                        for bus_sequence in adjacent_list.get(mid_to_end):
                            rona_two.append(
                                str(
                                    adjacent_list.get(mid_to_end).get(
                                        bus_sequence)[0]))
                        found_br = []
                        print("TEST rona 1:", rona_one)
                        print("TEST rona 2:", rona_two)
                        found_br.append(start_to_mid + ";" + mid_to_end)
                        found_br.extend(list(set(rona_one) & set(rona_two)))
                        common_mid.append(found_br)

                    print("TEST - common_mid: ", common_mid)

                    bus_service = start_to_mid
                    temp_bus = []
                    mid_busstop = 0
                    approved = 0
                    for bus_sequence in adjacent_list.get(
                            bus_service
                    ):  #Finding bus service for start busstop -> mid busstop
                        for x in range(0, len(common_mid)):
                            for i in common_mid[x]:
                                if str(
                                        adjacent_list.get(bus_service).get(
                                            bus_sequence)[0]) == str(
                                                start_busstop):
                                    temp_bus.append(
                                        adjacent_list.get(bus_service).get(
                                            bus_sequence)[0])
                                    approved = 1
                                if str(
                                        adjacent_list.get(bus_service).get(
                                            bus_sequence)[0]) == str(
                                                i) and approved == 1:
                                    mid_busstop = str(i)
                                    temp_bus.append(
                                        adjacent_list.get(bus_service).get(
                                            bus_sequence)[0])
                                    approved = 0
                                    break
                                if approved == 1:
                                    temp_bus.append(
                                        adjacent_list.get(bus_service).get(
                                            bus_sequence)[0])
                            if mid_busstop != 0:
                                break
                    if str(start_busstop) not in temp_bus or str(
                            mid_busstop
                    ) not in temp_bus:  #If not found, continue to next loop
                        continue
                    temp_bus = delete_duplicate(temp_bus)
                    mid_route_list[bus_service] = temp_bus

            for x in G.nodes:  #After finding bus service to mid busstop, start finding path mid busstop to end busstop
                if G.nodes.get(x).get('asset_ref') == mid_busstop:
                    if ";" in (G.nodes.get(x).get('route_ref')):
                        start_rr = (G.nodes.get(x).get('route_ref')).split(";")
                    else:
                        start_rr = []
                        start_rr.append((G.nodes.get(start).get('route_ref')))

            common = list(set(start_rr) & set(end_rr))
            start_busstop = mid_busstop
        if start == 1847853709:  #If bus service started from punggol interchange
            for bus_service in common:
                temp_bus = []
                approved = 0
                for bus_sequence in adjacent_list.get(
                        bus_service):  #Capture bus route
                    if str(
                            adjacent_list.get(bus_service).get(bus_sequence)
                        [0]) == str(start_busstop) and adjacent_list.get(
                            bus_service).get(bus_sequence)[1] == 0:
                        temp_bus.append(
                            adjacent_list.get(bus_service).get(bus_sequence)
                            [0])
                        approved = 1
                    if str(
                            adjacent_list.get(bus_service).get(bus_sequence)
                        [0]) == str(end_busstop) and approved == 1:
                        temp_bus.append(
                            adjacent_list.get(bus_service).get(bus_sequence)
                            [0])
                        approved = 0
                        break
                    if approved == 1:
                        temp_bus.append(
                            adjacent_list.get(bus_service).get(bus_sequence)
                            [0])
                if str(start_busstop) not in temp_bus or str(
                        end_busstop) not in temp_bus:
                    continue
                route_list[bus_service] = temp_bus
        else:
            for bus_service in common:  #If bus service does not start from punggol interchange
                temp_bus = []
                approved = 0
                for bus_sequence in adjacent_list.get(
                        bus_service):  #Capture bus route
                    if str(
                            adjacent_list.get(bus_service).get(bus_sequence)
                        [0]) == str(start_busstop):
                        temp_bus.append(
                            adjacent_list.get(bus_service).get(bus_sequence)
                            [0])
                        approved = 1
                    if str(
                            adjacent_list.get(bus_service).get(bus_sequence)
                        [0]) == str(end_busstop) and approved == 1:
                        temp_bus.append(
                            adjacent_list.get(bus_service).get(bus_sequence)
                            [0])
                        approved = 0
                        break
                    if approved == 1:
                        temp_bus.append(
                            adjacent_list.get(bus_service).get(bus_sequence)
                            [0])
                if str(start_busstop) not in temp_bus or str(
                        end_busstop) not in temp_bus:
                    continue
                route_list[bus_service] = temp_bus
        """
        After capturing all the bus serivce. A comparison is made in favor for the number of bus stops
        It will choose the least amount of bus stops and store in post_compare
        """
        compare = [0, 100]
        if len(route_list.keys()) > 1:
            for i in route_list:
                if len(route_list.get(i)) < compare[1]:
                    compare[0] = i
                    compare[1] = len(route_list.get(i))
        else:
            for i in route_list:
                compare[0] = i
                compare[1] = len(route_list.get(i))
        post_compare = []
        print("TEST - Mid route list: ", mid_route_list)
        if len(mid_route_list) != 0:
            for i in mid_route_list:
                post_compare.append(i)
                route_list[i] = mid_route_list.get(i)
            post_compare.append(compare[0])
        else:
            post_compare.append(compare[0])
        """
        Upon comparison, it will start capturing the nodes within the bus path and store in plot_list
        """
        plot_list = []
        try:
            print("TEST - post_Compare: ", post_compare)
            print("TEST - Route list: ", route_list)
            for count in range(0, len(post_compare)):
                for x in route_list.get(str(post_compare[count])):
                    for i in G.nodes:
                        if str(G.nodes.get(i).get('asset_ref')) == str(x):
                            plot_list.append(G.nodes.get(i).get('osmid'))
                            break
        except:
            return -1
        edge_list = []
        punggol = (1.403948, 103.909048)
        """
        It will generate out the list of node ID for the UI to plot
        """
        a = ox.load_graphml('Bus_graph.graphml')
        for x in plot_list:
            edge_list.append(get_nearestedge_node(x, a, G))

        print("TEST - Plot list: ", plot_list)
        print("TEST - Edge list: ", edge_list)
        final_route_list = []
        count_stops = len(plot_list)
        for x in range(0, len(edge_list) - 1):
            final_route_list.append(
                nx.shortest_path(a, edge_list[x], edge_list[x + 1]))
        print(final_route_list)
        return final_route_list