def from_family(family: Family, add_missing_members=True): family_connections = FamilyConnections.from_family( family, add_missing_members=add_missing_members ) if not family_connections: return [Layout._handle_broken_family_connections(family)] if family_connections.is_connected(): logger.debug( f"building layout for connected family: {family.family_id}") return [Layout._build_family_layout(family, family_connections)] layouts = [] for component in family_connections.connected_components(): members = [ m for m in family.full_members if m.person_id in component ] fam = Family.from_persons(members) fc = FamilyConnections.from_family(fam) # assert fc.is_connected(), fam.family_id layouts.append(Layout._build_family_layout(fam, fc)) x_offset = 0.0 for layout in layouts: layout.translate(x_offset, 0.0) bbox = layout.get_bbox() x_offset = bbox.max_x + IndividualWithCoordinates.SIZE + 4.0 return layouts
def test_family3_connections(family3): assert len(family3.full_members) == 1 FamilyConnections.add_missing_members(family3) assert len(family3.full_members) == 3 ids = [member.person_id for member in family3.full_members] assert len(ids) == 3 assert sorted(ids) == sorted(["id3", "mom3", "mom3.father"])
def test_family2_connections(family2): assert len(family2.full_members) == 3 FamilyConnections.add_missing_members(family2) assert len(family2.full_members) == 3 ids = [member.person_id for member in family2.full_members] assert len(ids) == 3 assert sorted(ids) == sorted(["id2", "mom2", "dad2"])
def test_family_connections_invalid(individual4, individual5, individual6): id_to_mating_unit = [ { "mom2,dad2": MatingUnit(Individual(), individual6, SibshipUnit(individual4)) }, { "mom2,dad2": MatingUnit(individual5, Individual(), SibshipUnit(individual4)) }, { "mom2,dad2": MatingUnit(individual5, individual6, SibshipUnit([Individual()])) }, ] assert FamilyConnections.is_valid_family(id_to_mating_unit[0]) is False assert FamilyConnections.is_valid_family(id_to_mating_unit[1]) is False assert FamilyConnections.is_valid_family(id_to_mating_unit[2]) is False
def from_family_layout(family): if any([p.layout is None for p in family.full_members]): print( f"family {family.family_id} has member without layout", file=sys.stderr, ) return None family_connections = FamilyConnections.from_family( family, add_missing_members=False ) if family_connections is None: print( f"can't build family connections for family " f"{family.family_id}", file=sys.stderr, ) return None layout_positions = defaultdict(list) for person in family_connections.members: position = layout_parser(person.layout) if position is None: print( f"can't parse layout for person {person}: {person.layout}", file=sys.stderr, ) return None individual = family_connections.get_individual(person.person_id) assert isinstance(position["rank"], int), ( person, person.layout, position, ) layout_positions[position["rank"]].append( IndividualWithCoordinates( individual, position["x"], position["y"] ) ) individual_positions = [[]] * len(layout_positions) for level, iwc in layout_positions.items(): individual_positions[level - 1] = iwc individual_positions = [ sorted(level, key=lambda x: x.x) for level in individual_positions ] layout = Layout() layout.positions = individual_positions layout._create_lines() return layout
def _build_family_layout( family: Family, family_connections: FamilyConnections): if family_connections is None: logger.warning( f"missing family connections for family: {family.family_id}") return Layout._handle_broken_family_connections(family) assert family_connections.is_connected() sandwich_instance = family_connections.create_sandwich_instance() intervals = SandwichSolver.solve(sandwich_instance) if intervals is None: logger.warning(f"no intervals for family: {family.family_id}") return Layout._handle_broken_family_connections(family) individuals_intervals = [ interval for interval in intervals if interval.vertex.is_individual() ] return Layout(individuals_intervals)
def test_family_connections_from_family_simple(family2): family_connections = FamilyConnections.from_family(family2) assert family_connections is not None assert len(family_connections.members) == 3 sandwich_instance = family_connections.create_sandwich_instance() assert len(sandwich_instance.vertices) == 5 assert len(sandwich_instance.required_graph) == 5 assert len(sandwich_instance.forbidden_graph) == 5 individuals_with_rank = family_connections.get_individuals_with_rank(1) assert len(individuals_with_rank) == 1 assert "id2" in [el.member.person_id for el in individuals_with_rank]
def test_not_connected_aunts_roles(families_loader): families = families_loader("test_not_connected_aunts.csv") assert families is not None fam = families["fam1"] assert len(fam) == 7 assert len(fam.full_members) == 7 fc = FamilyConnections.from_family(fam) fam1 = fc.family assert len(fam) == 7 assert len(fam1.full_members) == 9 print(fam1.full_members) aunt = fam1.get_member("aunt1") assert aunt.role == Role.unknown aunt_mating = fam.get_member("aunt1.father") assert aunt_mating.role == Role.unknown
def test_not_connected_aunts(families_loader): families = families_loader("test_not_connected_aunts.csv") assert families is not None fam = families["fam1"] assert fam is not None family_connections = FamilyConnections.from_family(fam) assert family_connections is not None print(family_connections.get_mating_units()) print(family_connections.get_sibship_units()) g = family_connections.get_graph() print(g) assert not family_connections.is_connected() for comp in family_connections.connected_components(): print(comp, type(comp))
def test_family_connections_from_family_add_members(family2): family2._members_in_order = list( filter(lambda member: member.person_id != "mom2", family2.members_in_order)) prb = list( filter(lambda member: member.person_id == "id2", family2.members_in_order)) assert len(prb) == 1 prb[0].mother = "0" family_connections = FamilyConnections.from_family( family2, add_missing_members=True) assert family_connections is not None assert len(family_connections.members) == 3 sandwich_instance = family_connections.create_sandwich_instance() assert len(sandwich_instance.vertices) == 5 assert len(sandwich_instance.required_graph) == 5 assert len(sandwich_instance.forbidden_graph) == 5 individuals_with_rank = family_connections.get_individuals_with_rank(1) assert len(individuals_with_rank) == 1 assert "id2" in [el.member.person_id for el in individuals_with_rank]
def fam1_family_connections(fam1): return FamilyConnections.from_family(fam1)
def family_connections_from_family2(family2): return FamilyConnections.from_family(family2)
def test_family_connections_valid(mating_unit2): id_to_mating_unit = {"mom2,dad2": mating_unit2} assert FamilyConnections.is_valid_family(id_to_mating_unit) is True
def test_family_connections_from_family_do_not_add_members(family3): assert (FamilyConnections.from_family(family3, add_missing_members=False) is None)
def test_family_connections_from_family1_simple(family1): family_connections = FamilyConnections.from_family(family1) assert family_connections is not None