예제 #1
0
    if v.is_individual():
        children, siblings = set(), set()
        idx = term2id(v)

        title = v.name()[0].decode('utf8').encode(
            'ascii',
            'xmlcharrefreplace') + " " + v.name()[1].decode('utf8').encode(
                'ascii', 'xmlcharrefreplace')
        title = title.replace('"',
                              '').replace('[', '').replace(']', '').replace(
                                  '(', '').replace(')', '').strip()

        own_families = g.families(v, 'FAMS')
        for fam in own_families:
            children |= set(
                term2id(i) for i in g.get_family_members(fam, "CHIL"))

        parent_families = g.families(v, 'FAMC')
        if len(parent_families):
            for member in g.get_family_members(
                    parent_families[0], "CHIL"
            ):  # NB adoptive families i.e len(parent_families)>1 are not considered (TODO?)
                if member.pointer() == v.pointer():
                    continue
                siblings.add(term2id(member))

        if idx in individuals:
            children |= individuals[idx].get('children', set())
            siblings |= individuals[idx].get('siblings', set())
        individuals[idx] = {
            'sex': v.gender().lower(),
예제 #2
0
class GedcomFamilies:

    families: list = None
    single_individuals: list = None

    # gedcom file and object
    __gedcom: Gedcom = None
    __gedcom_file_path: str = None

    # all elements
    __individuals: list = None
    __families: list = None
    __files: list = None

    def __init__(self, gedcom_file_path, subtree_type=1):
        """
        @param gedcom_file_path path to the gedcom file
        @param subtree_type how to split tree into families:
               1 - split tree using father's surname
               2 - join related families into the same tree
        """

        # load gedcom object
        self.__gedcom_file_path = gedcom_file_path
        self.__gedcom = Gedcom(gedcom_file_path)

        # load GEDCOM elements
        self.__load_gedcom_elements()

        # split the whole free into families
        if subtree_type == 1:
            self.__generate_family_subtrees()
        if subtree_type == 2:
            self.__generate_subtrees()

    def __load_gedcom_elements(self):

        self.__individuals = []
        self.__families = []
        self.__files = []
        for element in self.__gedcom.get_root_child_elements():
            if element.is_individual():
                self.__individuals.append(element)
            if element.is_family():
                self.__families.append(element)
            if element.is_file():
                self.__files.append(element)

    def __generate_subtrees(self):

        self.families = []
        self.single_individuals = []

        # set all persons as unvisited
        for individual in self.__individuals:
            individual.visited = False

        self.__set_all_individuals_as_unvisited()

        # split them all
        for individual in self.__individuals:

            if individual.visited:
                continue

            new_family = []

            queue = []
            queue.append(individual)

            while len(queue) > 0:

                tmp_individual = queue.pop()
                if tmp_individual.visited:
                    continue

                tmp_individual.visited = True
                new_family.append(tmp_individual)

                tmp_families = self.__gedcom.get_families(
                    tmp_individual, 'FAMC')
                tmp_families = tmp_families + self.__gedcom.get_families(
                    tmp_individual, 'FAMS')

                for tmp_family in tmp_families:
                    for tmp_child in self.__gedcom.get_family_members(
                            tmp_family):
                        queue.append(tmp_child)

            if len(new_family) == 1:
                self.single_individuals.append(new_family[0])
            else:
                self.families.append(copy(new_family))

    def __generate_family_subtrees(self):

        self.families = []
        self.single_individuals = []

        self.__set_all_individuals_as_unvisited()

        # split them all
        for individual in self.__individuals:

            if individual.visited:
                continue

            new_family = []
            tmp_indivdual_list = []

            # let's find the oldest ancestor of this family
            individual_pointer = individual
            stop = False
            while not stop:

                families = self.__gedcom.get_families(individual_pointer,
                                                      'FAMC')
                if len(families) == 0:
                    break

                for family in families:
                    fathers = self.__gedcom.get_family_members(
                        family, GEDCOM_TAG_HUSBAND)
                    if len(fathers) > 0:
                        individual_pointer = fathers[0]
                    else:
                        stop = True
                    break

            # let's find all descendants
            tmp_indivdual_list.append(individual_pointer)
            while len(tmp_indivdual_list) > 0:
                individual2 = tmp_indivdual_list.pop()
                individual2.visited = True
                new_family.append(individual2)
                families = self.__gedcom.get_families(individual2, 'FAMS')
                for family in families:
                    fathers = self.__gedcom.get_family_members(
                        family, GEDCOM_TAG_HUSBAND)
                    if len(fathers) > 0 and fathers[0] == individual2:
                        for individual3 in self.__gedcom.get_family_members(
                                family, 'CHIL'):
                            tmp_indivdual_list.append(individual3)

            if len(new_family) == 1:
                self.single_individuals.append(individual_pointer)
            else:
                self.families.append(copy(new_family))
            """
            (firstname, lastname) = individual.get_name()
            if lastname:
                lastname_lower = lastname.lower()
                if lastname_lower not in self.families.keys():
                    self.families[lastname_lower] = []

                self.families[lastname_lower].append(individual)
            """

        #print(self.families)
        #print(len(self.families))
        #print('')
        #print(self.families.keys())

    def __set_all_individuals_as_unvisited(self):
        # set all persons as unvisited
        for individual in self.__individuals:
            individual.visited = False

    def get_dot_graph(self):
        data = ''
        data += GedcomFamilies.__get_dot_graph_header()

        # prepare subgraphs for families
        i = 0
        for family in self.families:
            if len(family) < 3:
                continue

            #if family_key == 'koperkiewicz':
            family_key = str(i)
            i = i + 1
            #if i == 3:
            data += self.__get_subgraph_for_family(family, family_key)

        data += GedcomFamilies.__get_dot_graph_footer()

        return data

    @staticmethod
    def __get_dot_graph_header():
        return """digraph G {
\tgraph [fontname="fixed"];
\tnode [fontname="fixed"];
\tedge [fontname="fixed"];
\tmincross = 2.0;splines=polyline;
\tratio = expand;\n"""

    @staticmethod
    def __get_dot_graph_footer():
        return """}\n"""

    def __get_subgraph_for_family(self, family, family_key):
        data = """subgraph cluster_%s {\n
label = "process %s";color=red;\n
""" % (family_key, family_key)

        # dict for people from family
        person_list_in_family = {}
        family_list_in_family = {}

        for person in family:
            if len(self.__gedcom.get_families(person)) > 0:
                data += u'\t_%s [shape=box, label="%s"];\n' % (
                    person.get_pointer().replace('@', ''),
                    (' '.join(person.get_name())).replace('"', '^'))
            person_list_in_family[person.get_pointer()] = person

        for person in family:
            for family in self.__gedcom.get_families(person):

                if family.get_pointer() in family_list_in_family.keys():
                    continue
                family_list_in_family[family.get_pointer()] = True

                data += u'\t_%s [label="M",height=.1,width=.1];' % family.get_pointer(
                ).replace('@', '')

                # data += u'\t_%s -> _%s [weight=1];\n' % (person.get_pointer().replace('@', ''), family.get_pointer().replace('@', ''))

                data += u'\t\tsubgraph cluster_family_%s {\ncolor=blue;\n' % family.get_pointer(
                ).replace('@', '')
                parents = self.__gedcom.get_family_members(family, 'PARENTS')
                children = self.__gedcom.get_family_members(family, 'CHIL')
                for parent in parents:
                    data += u'\t\t\t_%s -> _%s [weight=50];\n' % (
                        parent.get_pointer().replace(
                            '@', ''), family.get_pointer().replace('@', ''))
                    """
                    for child in children:
                        if len(self.__gedcom.get_families(child))==0:
                            data += u'\t_%s [shape=box, label="%s"];\n' % (
                                child.get_pointer().replace('@', ''),
                                (' '.join(child.get_name())).replace('"', '^')
                            )
                    """

                data += u'\t\t}\n'

                for child in children:
                    if len(self.__gedcom.get_families(child)) > 0:
                        #print(self.__gedcom.get_families(child))
                        data += u'\t_%s -> _%s [weight=1];\n' % (
                            family.get_pointer().replace(
                                '@', ''), child.get_pointer().replace('@', ''))

        data += "}\n\n"
        return data
예제 #3
0
g = Gedcom(workpath)
gedcom_dict = g.element_dict()
individuals, marriages = {}, {}

for k, v in gedcom_dict.iteritems():
    if v.is_individual():
        children, siblings = set(), set()
        idx = term2id(v)

        title = v.name()[0].decode('utf8').encode('ascii', 'xmlcharrefreplace') + " " + v.name()[1].decode('utf8').encode('ascii', 'xmlcharrefreplace')
        title = title.replace('"', '').replace('[', '').replace(']', '').replace('(', '').replace(')', '').strip()

        own_families = g.families(v, 'FAMS')
        for fam in own_families:
            children |= set(term2id(i) for i in g.get_family_members(fam, "CHIL"))

        parent_families = g.families(v, 'FAMC')
        if len(parent_families):
            for member in g.get_family_members(parent_families[0], "CHIL"): # NB adoptive families i.e len(parent_families)>1 are not considered (TODO?)
                if member.pointer() == v.pointer():
                    continue
                siblings.add(term2id(member))

        if idx in individuals:
            children |= individuals[idx].get('children', set())
            siblings |= individuals[idx].get('siblings', set())
        individuals[idx] = {'sex': v.gender().lower(), 'children': children, 'siblings': siblings, 'title': title}

    elif v.is_family():
        wife, husb, children = None, None, set()