示例#1
0
    def _draw_stations(self):
        with client.session(keyspace=settings.keyspace) as session:
            with session.transaction(grakn.TxType.WRITE) as transaction:
                """
                Render a map of the London Underground Stations based on their grid coordinates.
                :return:
                """

                station_name_labels = dict()
                suffix = " Underground Station"

                # Get the stations, but limit them to those which have at least one tunnel
                station_query = match_get(
                    "$s isa station, has name $name, has lon $lon, has lat $lat; ($s) isa tunnel;"
                )
                response = self.perform_query(station_query, transaction)

                for match in response:
                    station_id = match.get('s').id
                    name = match.get('name').value()
                    if name.endswith(suffix):
                        name = name[:-len(suffix)]

                    print("drawing station: {}".format(station_id))

                    lon, lat = self._transform_coords(
                        float(match.get('lon').value()),
                        float(match.get('lat').value()))

                    self._station_canvas_coords[station_id] = (lon, lat)
                    station_tag = self._canvas.create_circle(
                        lon,
                        lat,
                        self.STATION_CIRCLE_RADIUS,
                        fill="white",
                        outline="black")
                    self._station_point_ids[station_id] = station_tag

                    # We need to identify the station selected, so we should build a function for each station to hold this
                    def callback_wrapper(event, id=station_id):
                        return self._on_station_select(id)

                    event_sequence = "<Shift-ButtonPress-1>"

                    self._canvas.tag_bind(self._station_point_ids[station_id],
                                          event_sequence, callback_wrapper)

                    station_label_tag = self._canvas.create_text(
                        lon + self.STATION_CIRCLE_RADIUS,
                        lat + self.STATION_CIRCLE_RADIUS,
                        text=name,
                        anchor=tk.NW,
                        font=('Johnston', self.STATION_FONT_SIZE, 'bold'),
                        fill="#666")
                    station_name_labels[station_id] = station_label_tag
                    self._canvas.tag_bind(station_label_tag, event_sequence,
                                          callback_wrapper)
def import_query_generator(perform_query, timetables_dir_path):
    """
    Builds the Graql statements required to import the transportation data contained in all_routes.json
    :param perform_query: function to call to query the grakn server
    :param timetables_dir_path: path to
    :return:
    """

    # Get the locations of the downloaded timetable json data
    timetable_paths = os.listdir(timetables_dir_path)

    station_query = "$s1 isa station, has naptan-id \"{}\";"

    def add_route_stop_relationship(naptan_id, role_played, route_id):
        match_query = station_query.format(naptan_id)
        insert_query = "$r({}: $s1) isa route, id {};".format(
            role_played, route_id)

        response = list(perform_query(match_insert(match_query, insert_query)))
        check_response_length(response, min_length=1, max_length=1)

    for timetable_path in timetable_paths:
        with open(timetables_dir_path + "/" + timetable_path, 'r') as f:
            data = json.load(f)

            tube_line_query = "$tl isa tube-line, has name \"{}\";".format(
                data['lineName'])
            response = list(perform_query(match_get(tube_line_query)))

            if len(response) < 1:
                # In this case we haven't already added this tube-line before
                # We do it this way so that we have explicitly asked the database if the tube-line exists, and if not
                # then we use the same query body but as an insert

                response = list(perform_query(insert(tube_line_query)))
                check_response_length(
                    response, min_length=1,
                    max_length=1)  # Exactly one concept should be inserted

            for station in data["stops"]:

                response = list(
                    perform_query(
                        match_get(station_query.format(station["id"]))))

                if len(response) < 1:
                    # Only proceed if there is this station isn't already in the database
                    station_insert_query = (
                        station_query.format(station["id"]) +
                        "$s1 has name \"{}\", "
                        "has lat {}, has lon {};\n").format(
                            station["name"],
                            station["lat"],
                            station["lon"],
                        )
                    response = list(perform_query(
                        insert(station_insert_query)))
                    check_response_length(response, min_length=1, max_length=1)

                    try:
                        zone_name = station["zone"]
                    except KeyError:
                        # In the case that there is no zone information
                        zone_name = -1

                    response = list(
                        perform_query(
                            match_get("$z isa zone, has name \"{}\";\n".format(
                                zone_name))))

                    if len(response) < 1:
                        # If the zone doesn't already exist then insert it
                        zone_query = "$z(contained-station: $s1) isa zone, has name \"{}\";\n".format(
                            zone_name)
                        response = list(
                            perform_query(
                                match_insert(
                                    station_query.format(station["id"]),
                                    zone_query)))
                        check_response_length(
                            response, min_length=1,
                            max_length=1)  # Exactly one concept should be
                        # inserted
            """
            Get the time between stops
            """
            for routes in data['timetable']["routes"]:

                for station_intervals in routes["stationIntervals"]:
                    # This actually iterates over the routes, in TFL's infinite wisdom

                    last_naptan_id = data['timetable']["departureStopId"]
                    last_time_to_arrival = 0
                    route_query = "$r(route-operator: $tl) isa route;"

                    response = list(
                        perform_query(
                            match_insert(tube_line_query, route_query)))
                    check_response_length(response, min_length=1, max_length=1)
                    route_id = get_match_id(response, "r")
                    # TODO Here we need to execute the query in order to get the ID of the route inserted, since that's
                    # the only way to uniquely identify it for the insertion of the route-sections below

                    add_route_stop_relationship(last_naptan_id, "origin",
                                                route_id)

                    for i, interval in enumerate(
                            station_intervals['intervals']):

                        # === TUNNELS ===
                        # Now we need to insert a tunnel that can make the connection if there isn't one, or if there
                        # is one then don't add one and instead use its ID
                        station_pair_query = (
                            "$s1 isa station, has naptan-id \"{}\";\n"
                            "$s2 isa station, has naptan-id \"{}\";\n").format(
                                last_naptan_id, interval["stopId"])

                        tunnel_query = "$t(beginning: $s1, end: $s2) isa tunnel;"

                        response = list(
                            perform_query(
                                match_get(station_pair_query + tunnel_query)))

                        if len(response) < 1:
                            response = list(
                                perform_query(
                                    match_insert(station_pair_query,
                                                 tunnel_query)))

                        # Get the ID of either the pre-existing tunnel or the one just inserted
                        tunnel_id = get_match_id(response, "t")

                        # === Connect Stations to Routes ===
                        if i == len(station_intervals['intervals']) - 1:
                            # In this case we're at the last route-section of the route, ending at the last station
                            role_played = "destination"
                        else:
                            role_played = "stop"

                        add_route_stop_relationship(interval["stopId"],
                                                    role_played, route_id)

                        # === Link routes to tunnels with route-sections ===
                        duration = int(interval["timeToArrival"] -
                                       last_time_to_arrival)
                        match_query = "$t id {};\n$r id {};".format(
                            tunnel_id, route_id)
                        # insert_query = "$rs(section: $t, service: $r) isa route-section, has duration {};".format(duration)
                        insert_query = (
                            "$rs isa route-section, has duration {}; "
                            "$r(section: $rs);"
                            "$t(service: $rs);").format(duration)

                        response = list(
                            perform_query(
                                match_insert(match_query, insert_query)))
                        check_response_length(response,
                                              min_length=1,
                                              max_length=1)

                        # Update variables for the next iteration
                        last_time_to_arrival = interval["timeToArrival"]
                        last_naptan_id = interval["stopId"]
示例#3
0
            # If you try b_name = "Upminster Underground Station"  # Tries to return 1048576 paths, which is 2^20, because most
            # stations are connected by 2 tunnels. We need a different return type from compute path before we can practically
            # query for this many paths
            # If you need to kill a query that is taking too long, you may need:
            # ./grakn server engine stop
            # ./grakn server engine start

            # Choose whether to find paths via the fewest stations, or via the fewest changes between routes
            FEWEST_STOPS = 0
            FEWEST_ROUTES = 1
            score_by = FEWEST_STOPS

            a_id = get_match_id(
                list(
                    transaction.query(
                        match_get("$s1 isa station, has name \"{}\";".format(
                            a_name)))), "s1")
            b_id = get_match_id(
                list(
                    transaction.query(
                        match_get("$s1 isa station, has name \"{}\";".format(
                            b_name)))), "s1")

            if score_by == FEWEST_STOPS:
                compute_query = "compute path from {}, to {}, in [station, tunnel];".format(
                    a_id, b_id)  # Fewest stops
            elif score_by == FEWEST_ROUTES:
                compute_query = "compute path from {}, to {}, in [station, route];".format(
                    a_id, b_id)  # Fewest changes
            else:
                raise ValueError("No method has been selected")
            print("Finding shortest paths...")