From 0bcff139b22bf1edac291a87bd1e601a907f110d Mon Sep 17 00:00:00 2001 From: unknown <david.hoksza@gmail.com> Date: Thu, 31 Oct 2019 09:34:39 +0100 Subject: [PATCH] when laying connecting species on a line consider their position to the closest copied species --- talent/layout.py | 64 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/talent/layout.py b/talent/layout.py index ebbfd15..8c62b72 100644 --- a/talent/layout.py +++ b/talent/layout.py @@ -165,7 +165,7 @@ def layout_on_line(s_ids: List[str], center: np.ndarray, dir: np.ndarray, forbid return rv -def layout_on_perp_line(s_ids, center, dir, forbidden: List[gr.Rectangle]=[]) -> Dict[str, np.ndarray]: +def layout_on_perp_line(g, s_ids, center, dir, forbidden: List[gr.Rectangle]=[]) -> Dict[str, np.ndarray]: """ Get center of positions for the input species. The positions will be on a line perependicular to the line defined by center and direction vector (which is normalized). The purpose is to lay out @@ -187,9 +187,43 @@ def layout_on_perp_line(s_ids, center, dir, forbidden: List[gr.Rectangle]=[]) -> return {} pos = center + dir * settings.render.optimal_species_reaction_dist - dir_ortho = gr.utils.orthogonal(dir) - return layout_on_line(s_ids, pos, dir_ortho, forbidden) + dir_ortho1 = gr.utils.orthogonal(dir) + dir_ortho2 = - dir_ortho1 + + # Connsider both possible directions of orthogonal line. This might be important if we are laying out + # a connecting species between existing reaction and an inserted reaction while the connecting species is + # inserted as well. In such a case we need the connecting species to be positioned between the two reaction. + # However, it could happen that if we chose the wrong direction it would be positioned on the outside of the + # space between the two reactions. + # S1 ------r1-----> S2 + # \ + # \ + # X + # / + # / + # S3 ------r2-----> S4 + + poss1 = layout_on_line(s_ids, pos, dir_ortho1, forbidden) + poss2 = layout_on_line(s_ids, pos, dir_ortho2, forbidden) + + # For each species we consider all the distances of its tentative position to all the species which has been + # copied from template and pick position with lowest sum of the distances. + + poss = {} + for s_id in s_ids: + pos1 = poss1[s_id] + pos2 = poss2[s_id] + pos_nbs = [gu.get_predicted_layout(g, id).get_center() for id in gu.get_neibhbors_in_distance(g, s_id, 2) if gu.get_predicted_layout(g, id).is_copied()] + + sum_dist1 = sum([gr.utils.dist(pos1, pos_nb) for pos_nb in pos_nbs]) + sum_dist2 = sum([gr.utils.dist(pos2, pos_nb) for pos_nb in pos_nbs]) + if len(pos_nbs) == 0 or sum_dist1 < sum_dist2: + poss[s_id] = pos1 + else: + poss[s_id] = pos2 + + return poss def impute_dirs(dir_reactants: np.ndarray, dir_products: np.ndarray, dir_modifiers: np.ndarray) -> List[np.ndarray]: @@ -273,10 +307,11 @@ def get_pos_for_species(g: nx.MultiGraph, r_id: str, s_ids: Collection[str], r_k rv[id] = [] rv[id].append(d[id]) - add_dict(layout_on_perp_line(list(s_id_products), r_center, dir_products)) - add_dict(layout_on_perp_line(list(s_id_reactans), r_center, dir_reactants)) - add_dict(layout_on_perp_line(list(s_id_modifiers), r_center, dir_modifiers)) - add_dict(layout_on_perp_line(list(s_id_modifiers), r_center, -dir_modifiers)) + forbidden: List[gr.Rectangle] = [gu.get_predicted_layout(g, s_id).get_bb().get() for s_id in known_cs_and_copied] + add_dict(layout_on_perp_line(g, list(s_id_products), r_center, dir_products, forbidden)) + add_dict(layout_on_perp_line(g, list(s_id_reactans), r_center, dir_reactants, forbidden)) + add_dict(layout_on_perp_line(g, list(s_id_modifiers), r_center, dir_modifiers, forbidden)) + add_dict(layout_on_perp_line(g, list(s_id_modifiers), r_center, -dir_modifiers, forbidden)) return rv @@ -333,9 +368,16 @@ def lay_out_reaction_center(g: nx.MultiGraph, r_id: str, known_connecting_s_ids: def get_correctly_laid_connecting_species(g:nx.MultiGraph, rg: nx.MultiGraph, r_id:str, not_laid_r_ids:List[str]) -> List[str]: css = set() for r_id1 in rg[r_id]: + # cn_ids = [] + # for cn_id in gu.get_connecting_nodes(g, r_id1, r_id): + # if r_id1 not in not_laid_r_ids or gu.get_predicted_layout(g, cn_id).is_copied(): + # cn_ids.append(cn_id) + # + # css = css.union(cn_ids) if r_id1 in not_laid_r_ids: continue css = css.union(gu.get_connecting_nodes(g, r_id1, r_id)) + return list(css) def aux_lay_out_reaction_center(g, rg, r_id, not_laid_r_ids): @@ -859,11 +901,11 @@ def layout_ods_for_inserted_reaction(g: nx.MultiGraph, r_id) -> List[Dict[str, n not_laid_modifiers_ids = list(set(r_s_ids.modifierIds).difference(laid_out_s_ids)) #TODO when a group of species is laid out the taken_bb should be extended to encompass also the bbs of the new species - s_id_pos = {**layout_on_perp_line(not_laid_reactant_ids, r_center, dir_reactants, taken_bb)} - s_id_pos = {**s_id_pos, **layout_on_perp_line(not_laid_products_ids, r_center, dir_products, taken_bb)} + s_id_pos = {**layout_on_perp_line(g, not_laid_reactant_ids, r_center, dir_reactants, taken_bb)} + s_id_pos = {**s_id_pos, **layout_on_perp_line(g, not_laid_products_ids, r_center, dir_products, taken_bb)} if len(not_laid_modifiers_ids) > 0: - s_id_pos_mod1 = {**s_id_pos, **layout_on_perp_line(not_laid_modifiers_ids, r_center, dir_modifiers, taken_bb)} - s_id_pos_mod2 = {**s_id_pos, **layout_on_perp_line(not_laid_modifiers_ids, r_center, -dir_modifiers, taken_bb)} + s_id_pos_mod1 = {**s_id_pos, **layout_on_perp_line(g, not_laid_modifiers_ids, r_center, dir_modifiers, taken_bb)} + s_id_pos_mod2 = {**s_id_pos, **layout_on_perp_line(g, not_laid_modifiers_ids, r_center, -dir_modifiers, taken_bb)} return [s_id_pos_mod1, s_id_pos_mod2] else: return [s_id_pos] -- GitLab