strands-project/strands_qsr_lib

[QSRlib] What is the dictionary representation a.k.a future good for?

Closed this issue · 8 comments

I am currently testing a new probabilistic version of arg_distance (opening a PR soon) which I want to get together with my QTC relation. I thought, since future=True returns a dict with the name of the QSR and the computed relations, that the future option would let me request multiple QSR with one service call, getting the response in a merged dict. Looking at how the QSR for the current request is chosen this only works when self.request_message.which_qsr is a single string. I think this would be easy to transform into a loop if future==True and type(self.request_message.which_qsr)==list to run the request for an array of QSRs, merge the dicts and then send one reply. This would not alter the default behaviour but enable the new one.

This would, in my case, allow to make one service call instead of two which saves a bit of computation and traffic. I could get cracking at implementing this but I wanted to ask what you have envisioned for the future option @yianni as currently it just turns a string into a dict and I have no real clue what you want to do with it.

Yes that was the point of trying to push to --future and I already have the merging function so I can have a look at some point today or tomorrow.

Find below the merge function. You can still go ahead with what you want to do, it's only gonna be slower by: n_qsrlib_requests x (t_transfer + t_setup)

def merge_world_qsr_traces(traces, qsr_type=""):
    """
    Merge a list of traces into one world_qsr_trace. It offers no protection versus overwriting previously
    existing relation.
    :param traces: list of World_QSR_Trace objects
    :param qsr_type: the qsr_type of the returned merged World_QSR_Trace object; if nothing given it is retrieved
    from the qsr_type of the first object in the traces list
    :return: a World_QSR_Trace that is the merge of all World_QSR_Trace objects in traces
    """
    world_qsr_trace = World_QSR_Trace(qsr_type=qsr_type)
    for trace in traces:
        for t, s in trace.trace.items():
            for k, qsr in s.qsrs.items():
                world_qsr_trace.add_qsr(qsr, t)
    return world_qsr_trace

That's brilliant, thanks! I'll give it a go.

One sec... the merge I have given is for merging smth else. Give me 5 and I will give you the one you need.

OK, cheers.

def merge_world_qsr_traces(world_qsr_traces, qsr_type=""):
    """
    Merge a list of traces into one world_qsr_trace. It offers no protection versus overwriting previously
    existing relation.
    :param world_qsr_traces: list of World_QSR_Trace objects
        :type world_qsr_traces: list or tuple
    :param qsr_type: the qsr_type of the returned merged World_QSR_Trace object
        :type qsr_type: str
    :return: a World_QSR_Trace that is the merge of all World_QSR_Trace objects in traces
        :rtype: World_QSR_Trace
    """
    ret_world_qsr_trace = World_QSR_Trace(qsr_type=qsr_type)
    for world_qsr_trace in world_qsr_traces:
        for t, s in world_qsr_trace.trace.items():
            for k, qsr_obj in s.qsrs.items():
                for qsr_k, qsr_v in qsr_obj.qsr.items():
                    try:
                        ret_world_qsr_trace.trace[t].qsrs[k].qsr[qsr_k] = qsr_v
                    except KeyError:
                        ret_world_qsr_trace.add_qsr(qsr_obj, t)
    return ret_world_qsr_trace

Test:

def test_merge_world_qsr_traces():
    which_qsrs = ("cone_direction_bounding_boxes_centroid_2d", "rcc3_rectangle_bounding_boxes_2d",
                  "moving_or_stationary", "qtc_b_simplified")
    traj = [Object_State(name="traj", timestamp=0, x=1., y=1., width=5., length=8.),
            Object_State(name="traj", timestamp=1, x=1., y=2., width=5., length=8.)]
    o1 = [Object_State(name="o1", timestamp=0, x=11., y=1., width=5., length=8.),
          Object_State(name="o1", timestamp=1, x=11., y=2., width=5., length=8.)]
    o2 = [Object_State(name="o2", timestamp=0, x=11., y=1., width=5., length=8.),
          Object_State(name="o2", timestamp=1, x=11., y=2., width=5., length=8.)]
    world_trace1 = World_Trace()
    world_trace1.add_object_state_series(traj)
    world_trace1.add_object_state_series(o1)

    qsrlib = QSRlib()

    world_qsr_traces = []
    for which_qsr in which_qsrs:
        request_message = QSRlib_Request_Message(which_qsr=which_qsr, input_data=world_trace1, future=True,
                                                 include_missing_data=True)
        world_qsr_traces.append(qsrlib.request_qsrs(request_message=request_message).qsrs)

    world_qsr_trace = merge_world_qsr_traces(world_qsr_traces, ",".join(which_qsrs))

    print("Response is:")
    for t in world_qsr_trace.get_sorted_timestamps():
        foo = str(t) + ": "
        for k, v in zip(world_qsr_trace.trace[t].qsrs.keys(), world_qsr_trace.trace[t].qsrs.values()):
            foo += str(k) + ":" + str(v.qsr) + "; "
        print(foo)

Bear in mind it works only with future and there is no check in the function itself as the check should be elsewhere.

I'll do my best ;)