feat(import): merge animals with different DOBs if their parent names match
This commit is contained in:
@@ -612,6 +612,49 @@ def dedup(animals):
|
||||
"files": sorted(set(f for a in grp for f in a["sourceFiles"])),
|
||||
})
|
||||
|
||||
# 2. Merge groups that have different DOBs but same call-name (and Zucht) and matching parents
|
||||
def get_parent_keys(a):
|
||||
parent_refs = a.get("parentRefs", [])
|
||||
f_name = next((p["name"] for p in parent_refs if p.get("roleGuess") == "father"), "")
|
||||
m_name = next((p["name"] for p in parent_refs if p.get("roleGuess") == "mother"), "")
|
||||
return norm_name(f_name), norm_name(m_name)
|
||||
|
||||
def groups_parents_match(g1, g2):
|
||||
for a1 in g1:
|
||||
for a2 in g2:
|
||||
f1, m1 = get_parent_keys(a1)
|
||||
f2, m2 = get_parent_keys(a2)
|
||||
if f1 and f2 and f1 == f2 and m1 and m2 and m1 == m2:
|
||||
return True
|
||||
return False
|
||||
|
||||
i = 0
|
||||
while i < len(final_groups):
|
||||
g1 = final_groups[i]
|
||||
call1, _ = split_name_zucht(g1[0]["name"])
|
||||
n_call1 = norm_name(call1)
|
||||
zucht1 = g1[0].get("_zucht", "")
|
||||
|
||||
j = i + 1
|
||||
merged_any = False
|
||||
while j < len(final_groups):
|
||||
g2 = final_groups[j]
|
||||
call2, _ = split_name_zucht(g2[0]["name"])
|
||||
n_call2 = norm_name(call2)
|
||||
zucht2 = g2[0].get("_zucht", "")
|
||||
|
||||
if n_call1 == n_call2:
|
||||
if zucht1 == zucht2 or not zucht1 or not zucht2:
|
||||
if groups_parents_match(g1, g2):
|
||||
g1.extend(g2)
|
||||
final_groups.pop(j)
|
||||
merged_any = True
|
||||
continue
|
||||
j += 1
|
||||
if merged_any:
|
||||
continue
|
||||
i += 1
|
||||
|
||||
merged = []
|
||||
conflicts = []
|
||||
for grp in final_groups:
|
||||
@@ -652,11 +695,25 @@ def dedup(animals):
|
||||
return sum(1 for pair in gd["mapped8locus"].values() for a in pair if a != "?")
|
||||
best = max((a["genotype"] for a in grp),
|
||||
key=lambda gd: (len(gd["mapped8locus"]), _specificity(gd), len(gd["rawGenotype"])))
|
||||
|
||||
# Find best DOB (proband first)
|
||||
best_dob = ""
|
||||
for a in grp:
|
||||
if a.get("_gen") == 0 and a.get("dob"):
|
||||
best_dob = a["dob"]
|
||||
break
|
||||
if not best_dob:
|
||||
for a in grp:
|
||||
if a.get("dob"):
|
||||
best_dob = a["dob"]
|
||||
break
|
||||
chosen_dob = norm_dob(best_dob or base["dob"])
|
||||
|
||||
out = {
|
||||
"id": slug(base["name"], base["dob"]),
|
||||
"id": slug(base["name"], chosen_dob),
|
||||
"name": base["name"],
|
||||
"nameVariants": sorted(v for v in variants if v),
|
||||
"dob": norm_dob(base["dob"]),
|
||||
"dob": chosen_dob,
|
||||
"death": sorted(deaths)[0] if deaths else "",
|
||||
# box-colour sex (blue=male, white=female): majority across mentions, else None.
|
||||
"gender": Counter(genders).most_common(1)[0][0] if genders else None,
|
||||
|
||||
Reference in New Issue
Block a user