BenPortner / js_family_tree

An interactive family tree visualization using d3-dag
GNU General Public License v3.0
70 stars 29 forks source link

advice for dynamic data #3

Open bidplayrepeat opened 3 years ago

bidplayrepeat commented 3 years ago

IS there a way for changing the basic data variables dynamically (persons, links, unions) and the DAG automatically adjusts itself to new info. - for example if I add a person with the correct links in the appropriate [data.persons, data.unions, data.links] new information should be auto updated in the dag. If not auto updated at least a refresh function to take care of new data.

Thanks for any help.

BenPortner commented 3 years ago

Hi @bidplayrepeat,

Sorry for getting back to you so late! Adding and removing nodes dynamically is a very cool idea, thanks for bringing it up! Unfortunately, realizing this with the current code structure is rather hard. Apart from the things you already mentioned, here are some more points that would need attention:

1) All nodes (i.e. persons and unions) keep track of their surrounding nodes (parents, children and siblings) via the neighbors property. Thus, when dynamically inserting a node, the new node must list all neighboring nodes AND all neighboring nodes must list the new node in their respective neighbors properties. Luckily, there is a helper function getNeighbors, which should make this easier to realize.

2) All nodes remember, which neighboring nodes and links they inserted (i.e. made visible) via the inserted_nodes and inserted_connections properties. This is what makes collapsing/expanding the graph work. Updating this information can get tricky if the newly added node is not a leaf node, see attached diagram. Untitled Diagram When adding node D, you will have to make sure that:

3) Extra work is needed when inserting root nodes. Root nodes are nodes, which do not have a visible parent. All root nodes need to be listed in dag.children in order for the d3-dag dependency to work correctly. Furthermore, when inserting a root node, you would have to pick one of it's child nodes and add the root node to the child's inserted_roots property. This makes sure that dag.children is correctly updated when the user clicks on the child node.

These changes are necessary for sure - and there might be more that I missed 😅 In any case, dynamically adding nodes is a really nice feature but it will require substantial work. Currently, I do not have time to implement this but I'll be glad to help if someone picks it up!

Cheers, Ben

bidplayrepeat commented 2 years ago

Hi Ben.

Thanks for replying. Let me see how I can modify the script. Thanks for your help. Anyway thanks for the directions

bidplayrepeat commented 2 years ago

One more thing, instead of drawing a complete tree, would it be possible to draw a partial tree. say only max 2 up and max 2 down given a starting node. or alternatively given a starting node extract only [n] connected entities and then draw the DAG

Thanks for help

BenPortner commented 2 years ago

Hi @bidplayrepeat,

I am not sure I understand. Per default, when opening the familytree.html, only one node should be visible - the one defined by the start property in data.js. Only after clicking the start node, it's immediate neighbors should become visible, too. And when clicking on these neighbors, even more nodes should show up. This way, the graph can be explored one by one.

If you want more than one node to be visible from the start, one option would be to call uncollapse(root) before update(root) in the familytree.html. This will make the start node as well as it's immediate neighbors visible when opening the file.

Does this answer your question?

Cheers. Ben

bidplayrepeat commented 2 years ago

Hey BenPortner/js_family_tree

Thanks for getting back to me. I just want to explore a scenario with you. regarding the family_tree

Assuming the tree is drawn as you have shown - the code on github.

I have opened up the tree. Clicked on one of the nodes - a popup asks (you want to add mother & father, spouse or a child

Only 1 relation at a single click (not all three) For arguments sake. Lets say He clicks he wants to add a child

He enters the name of the child. I am able to join the child to the parent (in backend and frontend) but I have to redraw the DAG (going back to the first selected person)

Is there a way to refresh the DAG once the data is pushed inside. Basically all three arrays/objects (persons, links & unions) do get updated properly. since when I refresh all show/redraw correctly at the proper place. (even spouses and parents also when added 1-by-1)

So any inputs on this. ?

Its become an interesting project in these COVID times.

Thanks & Regards

On Thu, Jul 29, 2021 at 4:13 AM Benjamin W. Portner < @.***> wrote:

Hi @bidplayrepeat https://github.com/bidplayrepeat,

Sorry for getting back to you so late! Adding and removing nodes dynamically is a very cool idea, thanks for bringing it up! Unfortunately, realizing this with the current code structure is rather hard. Apart from the things you already mentioned, here are some more points that would need attention:

1.

All nodes (i.e. persons and unions) keep track of their surrounding nodes (parents, children and siblings) via the neighbors property. Thus, when dynamically inserting a node, the new node must list all neighboring nodes AND all neighboring nodes must list the new node in their respective neighbors properties. Luckily, there is a helper function getNeighbors, which should make this easier to realize. 2.

All nodes remember, which neighboring nodes and links they inserted (i.e. made visible) via the inserted_nodes and inserted_connections properties. This is what makes collapsing/expanding the graph work. Updating this information can get tricky if the newly added node is not a leaf node, see attached diagram. [image: Untitled Diagram] https://user-images.githubusercontent.com/52913510/127403578-2822cb29-7ba4-4b13-885c-5aa781ba3d7c.png When adding node D, you will have to make sure that:

  • B.inserted_connections keeps 2, adds 4 and drops 3
  • B.inserted_nodes keeps C, adds D and drops E
  • D.inserted_connections = [5] and D.inserted_nodes =[E]

    1. Extra work is needed when inserting root nodes. Root nodes are nodes, which do not have a visible parent. All root nodes need to be listed in dag.children in order for the d3-dag dependency to work correctly. Furthermore, when inserting a root node, you would have to pick one of it's child nodes and add the root node to the child's inserted_roots property. This makes sure that dag.children is correctly updated when the user clicks on the child node.

These changes are necessary for sure - and there might be more that I missed 😅 In any case, dynamically adding nodes is a really nice feature but it will require substantial work. Currently, I do not have time to implement this but I'll be glad to help if someone picks it up!

Cheers, Ben

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/BenPortner/js_family_tree/issues/3#issuecomment-888667507, or unsubscribe https://github.com/notifications/unsubscribe-auth/AT3NPFQL73HS5RD5I5Z53ADT2CBYVANCNFSM47NIL2KA .

BenPortner commented 2 years ago

Hi @bidplayrepeat,

Sorry that it took me so long to get back to you. I decided to do a major code restructuring to make tasks like the one you describe easier. This should now be possible with the new version of js_family_tree. Please note that the code has changed a lot so make sure you download the new version and familiarize yourself with it.

Regarding your question, I added new functionality to facilitate adding new nodes programmatically. The following code snippet demonstrates how to use the new functions:


        // insert svg object to hold the family tree
        const svg = d3.select("body").append("svg")
            .attr("width", document.body.offsetWidth)
            .attr("height", document.documentElement.clientHeight);

        // make family tree object
        FT = new FamilyTree(data, svg);

        // add an empty union to the root node
        const own_union = FT.root.add_own_union({});

       // add a child to the union
        own_union.add_child({
            "name": "Dan's first child",
            "birthyear": 1950
        });

        // add a partner to the union
        own_union.add_parent({
            "name": "Dan's wife",
            "birthyear": 1930,
        })

        // add a parent union to the root node
        const parent_union = FT.root.add_parent_union({});

       // add parents to the new union
        parent_union.add_parent({
            "name": "Dan's Father",
            "birthyear": 1900,
            "deathyear": 1990,
        });
        parent_union.add_parent({
            "name": "Dan's Mother",
            "birthyear": 1902,
            "deathyear": 2000,
        });

        // add a sibling
        parent_union.add_child({
            "name": "Dan's brother",
            "birthyear": 1928,
        });

        // draw the family tree
        FT.draw();

This example demonstrates how to add new nodes to the graph and how to re-draw the graph after. The only thing left to implement to get the behavior you describe is the user interface, i.e. the popups that ask you which kind of relation you want to insert and also input prompts that lets you enter names and other basic information. This shouldn't be too hard with d3 and/or jQuery. However, I leave this up to you, as I do not plan to make js_family_tree a tool for family tree creation. Instead, the focus shall remain on displaying existing family trees in a visually pleasing, interactive fashion. Hence, the preferred way to use js_family_tree is to enter all relevant data in the data/data.js before opening familytree.html. Nevertheless, I am curious to see your progress on this task! Keep me updated :)

Thanks for using js_family_tree. Let me know if you have any more questions. Ben

bidplayrepeat commented 2 years ago

BenPortner/js_family_tree

Hi. Thanks Will have a look. And get back to you

Sorry about replying so late

On Wed, Mar 2, 2022 at 8:54 PM Benjamin W. Portner @.***> wrote:

Hi @bidplayrepeat https://github.com/bidplayrepeat,

Sorry that it took me so long to get back to you. I decided to do a major code restructuring to make tasks like the one you describe easier. This should now be possible with the new version of js_family_tree. Please note that the code has changed a lot so make sure you download the new version and familiarize yourself with it.

Regarding your question, I added new functionality to facilitate adding new nodes programmatically. The following code snippet demonstrates how to use the new functions:

    // insert svg object to hold the family tree
    const svg = d3.select("body").append("svg")
        .attr("width", document.body.offsetWidth)
        .attr("height", document.documentElement.clientHeight);

    // make family tree object
    FT = new FamilyTree(data, svg);

    // add an empty union to the root node
    const own_union = FT.root.add_own_union({});

   // add a child to the union
    own_union.add_child({
        "name": "Dan's first child",
        "birthyear": 1950
    });

    // add a partner to the union
    own_union.add_parent({
        "name": "Dan's wife",
        "birthyear": 1930,
    })

    // add a parent union to the root node
    const parent_union = FT.root.add_parent_union({});

   // add parents to the new union
    parent_union.add_parent({
        "name": "Dan's Father",
        "birthyear": 1900,
        "deathyear": 1990,
    });
    parent_union.add_parent({
        "name": "Dan's Mother",
        "birthyear": 1902,
        "deathyear": 2000,
    });

    // add a sibling
    parent_union.add_child({
        "name": "Dan's brother",
        "birthyear": 1928,
    });

    // draw the family tree
    FT.draw();

This example demonstrates how to add new nodes to the graph and how to re-draw the graph after. The only thing left to implement to get the behavior you describe is the user interface, i.e. the popups that ask you which kind of relation you want to insert and also input prompts that lets you enter names and other basic information. This shouldn't be too hard with d3 and/or jQuery. However, I leave this up to you, as I do not plan to make js_family_tree a tool for family tree creation. Instead, the focus shall remain on displaying existing family trees in a visually pleasing, interactive fashion. Hence, the preferred way to use js_family_tree is to enter all relevant data in the data/data.js before opening familytree.html. Nevertheless, I am curious to see your progress on this task! Keep me updated :)

Thanks for using js_family_tree. Let me know if you have any more questions. Ben

— Reply to this email directly, view it on GitHub https://github.com/BenPortner/js_family_tree/issues/3#issuecomment-1057053547, or unsubscribe https://github.com/notifications/unsubscribe-auth/AT3NPFRWKVL4J3UNSIDNERLU56BZVANCNFSM47NIL2KA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you were mentioned.Message ID: @.***>