Index: /XIOS/trunk/GENERIC_TESTCASE/context_atm.xml
===================================================================
--- /XIOS/trunk/GENERIC_TESTCASE/context_atm.xml	(revision 1703)
+++ /XIOS/trunk/GENERIC_TESTCASE/context_atm.xml	(revision 1704)
@@ -289,8 +289,8 @@
   
   <field_definition level="1" prec="8" operation="instant" freq_op="1ts" enabled=".true." default_value="1.e+20" detect_missing_value="true">
-    <field id="field2D" grid_ref="grid2D"/>
-    <field id="field3D" grid_ref="grid3D"  />
+    <field id="field2D" grid_ref="grid2D" />
+    <field id="field3D" grid_ref="grid3D" build_workflow_graph="true"  />
     <field id="pressure" grid_ref="grid3D"  />
-    <field id="field3D_recv" read_access="true" grid_ref="grid3D"  field_ref="field3D"/>
+    <field id="field3D_recv" read_access="true" grid_ref="grid3D"  field_ref="field3D" />
     <field id="field3D_resend" grid_ref="grid3D" />
 
@@ -363,5 +363,5 @@
   <file_definition  type="one_file" >
     
-    <file id="atm_output" output_freq="1ts" type="one_file" enabled="true">
+    <file id="atm_output" output_freq="4ts" type="one_file" enabled="true">
 <!--      <field field_ref="field3D" />
       <field field_ref="field2D" /> 
@@ -385,13 +385,13 @@
 
     <file id="atm_output_other" output_freq="1ts" type="one_file" enabled="true">
-       <field field_ref="other_field3D" enabled="false"/>
+       <field field_ref="other_field3D" enabled="true"/>
        <field field_ref="other_field2D" enabled="true"/> 
-       <field field_ref="other_field_X" enabled="false"/>
-       <field field_ref="other_field_Y" enabled="false"/>
-       <field field_ref="other_field_XY" enabled="false"/>
-       <field field_ref="other_field_Z" enabled="false"/>
-       <field field_ref="other_field_XYZ" enabled="false"/>
-       <field field_ref="other_field_XZ" enabled="false"/>
-       <field field_ref="other_field_YZ" enabled="false"/>
+       <field field_ref="other_field_X" enabled="true"/>
+       <field field_ref="other_field_Y" enabled="true"/>
+       <field field_ref="other_field_XY" enabled="true"/>
+       <field field_ref="other_field_Z" enabled="true"/>
+       <field field_ref="other_field_XYZ" enabled="true"/>
+       <field field_ref="other_field_XZ" enabled="true"/>
+       <field field_ref="other_field_YZ" enabled="true"/>
     </file>
 
@@ -407,4 +407,5 @@
        <field field_ref="field_YZW" enabled="true"/>
     </file>
+    
 
     <file id="atm_output_reorder" output_freq="1ts" enabled="false" >
Index: /XIOS/trunk/GENERIC_TESTCASE/iodef.xml
===================================================================
--- /XIOS/trunk/GENERIC_TESTCASE/iodef.xml	(revision 1703)
+++ /XIOS/trunk/GENERIC_TESTCASE/iodef.xml	(revision 1704)
@@ -6,5 +6,5 @@
 
       <variable id="timestep"> 1h </variable>
-      <variable id="domain"> gaussian </variable>
+      <variable id="domain"> lmdz </variable>
       <variable id="domain_mask"> true </variable>
       <variable id="axis_mask"> true </variable>
Index: /XIOS/trunk/bld.cfg
===================================================================
--- /XIOS/trunk/bld.cfg	(revision 1703)
+++ /XIOS/trunk/bld.cfg	(revision 1704)
@@ -46,10 +46,11 @@
 #bld::target test_remap.exe
 bld::target xios_server.exe 
+bld::target generic_testcase.exe 
 #bld::target test_regular.exe
 #bld::target test_xios2_cmip6.exe
 #bld::target test_new_features.exe test_unstruct_complete.exe 
-#bld::target test_remap.exe
-#bld::target test_complete.exe
-#bld::target test_client.exe
+bld::target test_remap.exe
+bld::target test_complete.exe
+bld::target test_client.exe
 #bld::target test_unstruct_complete.exe
 #bld::target test_unstructured.exe
Index: /XIOS/trunk/graph.html
===================================================================
--- /XIOS/trunk/graph.html	(revision 1704)
+++ /XIOS/trunk/graph.html	(revision 1704)
@@ -0,0 +1,1165 @@
+<html>
+
+<!--
+ ##########################################################################
+ Author: Patrick.Brockmann@cea.fr
+ ##########################################################################
+-->
+
+<head>
+
+    <meta charset="utf-8">
+
+    <style type="text/css">
+        body {
+            font-family: arial;
+            font-size: 12px;
+        }
+
+        .row {
+            margin-top: 10px;
+            margin-bottom: 20px;
+        }
+
+        #mynetwork {
+            width: 1000px;
+            height: 1000px;
+            border: 1px solid lightgray;
+        }
+
+        #mynetwork1 {
+            width: 200px;
+            height: 200px;
+            border: 1px solid lightgray;
+        }
+
+        input {
+            padding: 10px;
+        }
+
+        ul li {
+            display: inline;
+            border: 1px solid gray;
+            padding: 4px;
+            margin: 2px;
+            border-radius: 4px;
+        }
+
+        .btn {
+            margin-top: 5px;
+        }
+
+        /* /!\ Use border-top-color not border-color for firefox compatibility */
+    </style>
+
+</head>
+
+<body>
+    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
+
+    <script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+
+    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.js"></script>
+    <link href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet" type="text/css" />
+
+    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
+    <link href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css" rel="stylesheet" type="text/css" />
+
+    <link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet">
+    <script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
+
+    <script type="text/javascript">
+
+        //######################################################################################################
+        $(document).ready(function() {
+
+            var container = $('#mynetwork')[0];
+            var container1 = $('#mynetwork1')[0];
+
+            //===========================================================
+            $('#file').on('change', function() {
+                var file = $("#file").prop('files')[0];
+                handleFileSelect(file);
+            });
+
+            //===========================================================
+            $('#lastTemporal').on('click', function() {
+                var node = nodes.get(nodeSelected);
+
+                if (node.class == 5) //temporal filter
+                {
+                    // disable all parents
+                    node.hidden = true;
+                    console.log("node.id = ", node.id, "hidden = ", node.hidden);
+                    nodes.update(node);
+
+                    var connectedEdgeArray = edges.get(network.getConnectedEdges(node.id));
+                    for (j = 0; j < connectedEdgeArray.length; j++) {
+                        var edge = connectedEdgeArray[j];
+                        if (edge.to == node.id) {
+                            edge.hidden = true;
+                        }
+
+                    }
+                    edges.update(connectedEdgeArray);
+
+                    var allNode = nodes.get(allParentsNode);
+                    for (i = 0; i < allNode.length; i++) {
+                        var node = allNode[i];
+                        node.hidden = true;
+                    }
+                    nodes.update(allNode);
+
+                    for (i = 0; i < allNode.length; i++) {
+                        var node = allNode[i];
+
+                        var cNodes = nodes.get(network.getConnectedNodes(node.id, 'to'));
+                        for (j = 0; j < cNodes.length; j++) {
+                            var cnode = cNodes[j];
+
+                            if (cnode.hidden != true) {
+                                node.hidden = false;
+                                nodes.update(node);
+                                break;
+                            }
+                        }
+                    }
+                    nodes.update(allNode);
+
+                    node = nodes.get(nodeSelected);
+                    node.hidden = false;
+                    console.log("node.id = ", node.id, "hidden = ", node.hidden);
+                    nodes.update(node);
+
+                    allNode = nodes.get();
+                    nodes.update(allNode);
+
+
+
+                    // enable last input
+                    var inputnodes = network.getConnectedNodes(node.id, 'from');
+                    var repere = 0;
+                    for (i = 0; i < inputnodes.length; i++) {
+                        repere = Math.max(repere, nodes.get(inputnodes[i]).id);
+                    }
+                    var inputnode = nodes.get(repere);
+                    console.log("last inputnode id = ", inputnode.id);
+
+                    inputnode.hidden = false;
+                    nodes.update(inputnode);
+
+                    var edges_ofinputnode = edges.get(network.getConnectedEdges(inputnode.id));
+                    for (i = 0; i < edges_ofinputnode.length; i++) {
+                        var edge = edges_ofinputnode[i];
+                        if (edge.from == inputnode.id) {
+                            edge.hidden = false;
+                        }
+                    }
+                    edges.update(edges_ofinputnode);
+
+                    var allNode = nodes.get();
+                    nodes.update(allNode);
+
+                }
+
+
+            });
+
+
+            //===========================================================
+            $('#showGraph').on('click', function() {
+                //===== hide all except selected
+                var allNode = nodes.get();
+
+                for (i = 0; i < allNode.length; i++) {
+                    var node = allNode[i];
+
+                    if (node.hidden != true) {
+                        node.hidden = true;
+                    }
+                }
+
+                nodes.update(allNode);
+
+                var node = nodes.get(nodeSelected);
+                node.hidden = false;
+                nodes.update(node);
+
+                //===== enable all parents
+                console.log("showAllParents: allParentsNode = ", allParentsNode);
+                allNode = nodes.get(allParentsNode);
+
+                for (i = 0; i < allNode.length; i++) {
+                    node = allNode[i];
+                    node.font = {
+                        color: 'black'
+                    }
+                    node.hidden = false;
+                    if (node.filled == 1) {
+                        node.color = {
+                            background: redNode.background,
+                            border: redNode.border,
+                            hover: redNode.background,
+                            highlight: {
+                                background: redNode.background,
+                                border: 'blue'
+                            }
+                        }
+                    } else {
+                        node.color = {
+                            background: styleArr[node.class].background,
+                            border: styleArr[node.class].border,
+                            highlight: {
+                                background: styleArr[node.class].background,
+                                border: 'blue'
+                            }
+                        }
+                    }
+                }
+
+                nodes.update(allNode);
+
+                node = nodes.get(nodeSelected);
+                var connectedEdgeArray = edges.get(network.getConnectedEdges(node.id));
+                for (j = 0; j < connectedEdgeArray.length; j++) {
+                    var edge = connectedEdgeArray[j];
+                    if (edge.to == node.id) {
+                        edge.hidden = false;
+                    }
+
+                }
+                edges.update(connectedEdgeArray);
+
+                allNode = nodes.get();
+                nodes.update(allNode);
+
+                //===== enable all children
+                allNode = nodes.get(allChildNode);
+
+                for (i = 0; i < allNode.length; i++) {
+                    node = allNode[i];
+                    node.font = {
+                        color: 'black'
+                    }
+                    node.hidden = false;
+                    if (node.filled == 1) {
+                        node.color = {
+                            background: redNode.background,
+                            border: redNode.border,
+                            hover: redNode.background,
+                            highlight: {
+                                background: redNode.background,
+                                border: 'blue'
+                            }
+                        }
+                    } else {
+                        node.color = {
+                            background: styleArr[node.class].background,
+                            border: styleArr[node.class].border,
+                            highlight: {
+                                background: styleArr[node.class].background,
+                                border: 'blue'
+                            }
+                        }
+                    }
+                }
+
+                nodes.update(allNode);
+
+                node = nodes.get(nodeSelected);
+                connectedEdgeArray = edges.get(network.getConnectedEdges(node.id));
+                for (j = 0; j < connectedEdgeArray.length; j++) {
+                    var edge = connectedEdgeArray[j];
+                    if (edge.from == node.id) {
+                        edge.hidden = false;
+                    }
+
+                }
+                edges.update(connectedEdgeArray);
+
+                allNode = nodes.get();
+                nodes.update(allNode);
+
+
+                network1 = new vis.Network(container1, data);
+
+
+            });
+
+
+
+            //===========================================================
+            $('#disableAll').on('click', function() {
+                var allNode = nodes.get();
+
+                for (i = 0; i < allNode.length; i++) {
+                    var node = allNode[i];
+
+                    if (node.hidden != true) {
+                        node.hidden = true;
+                    }
+                }
+                nodes.update(allNode);
+            });
+
+
+            //===========================================================
+            $('#enableAll').on('click', function() {
+                var allNode = nodes.get();
+
+                for (i = 0; i < allNode.length; i++) {
+                    var node = allNode[i];
+
+                    if (node.hidden != false) {
+                        node.hidden = false;
+                    }
+                }
+                nodes.update(allNode);
+
+                var allEdge = edges.get();
+                for (i = 0; i < allEdge.length; i++) {
+                    var edge = allEdge[i];
+
+                    if (edge.hidden != false) {
+                        edge.hidden = false;
+                    }
+                }
+                edges.update(allEdge);
+
+            });
+
+
+
+            //===========================================================
+            $('#enableInput').on('click', function() {
+                var allNode = nodes.get();
+
+                for (i = 0; i < allNode.length; i++) {
+                    var node = allNode[i];
+
+                    if (node.class == 1) {
+                        node.hidden = false;
+                    }
+                }
+                nodes.update(allNode);
+            });
+
+
+
+            //===========================================================
+            $('#enableOutput').on('click', function() {
+                var allNode = nodes.get();
+
+                for (i = 0; i < allNode.length; i++) {
+                    var node = allNode[i];
+
+                    if (node.class >= 6 || node.filled == 1) {
+                        node.hidden = false;
+                    }
+                }
+                nodes.update(allNode);
+            });
+
+
+            //===========================================================
+            $('#hideNode').on('click', function() {
+                var node = nodes.get(nodeSelected);
+
+                node.color = {
+                    background: transparentNode.background,
+                    border: transparentNode.border,
+                    highlight: {
+                        background: transparentNode.border,
+                        border: 'blue'
+                    }
+                }
+                node.font = {
+                    color: transparentNode.background
+                }
+                nodes.update(node);
+
+                var connectedEdgeArray = edges.get(network.getConnectedEdges(node.id));
+                for (i = 0; i < connectedEdgeArray.length; i++) {
+                    var edge = connectedEdgeArray[i];
+
+                    edge.color = {
+                        color: transparentEdge.color,
+                        highlight: transparentEdge.color,
+                        hover: transparentEdge.color,
+                    }
+                    edge.font = {
+                        size: 0
+                    }
+
+                }
+                edges.update(connectedEdgeArray);
+
+            });
+
+
+            //===========================================================
+            $('#showNode').on('click', function() {
+                var node = nodes.get(nodeSelected);
+
+                node.font = {
+                    color: 'black'
+                }
+                if (node.filled == 1) {
+                    node.color = {
+                        background: redNode.background,
+                        border: redNode.border,
+                        hover: redNode.background,
+                        highlight: {
+                            background: redNode.background,
+                            border: 'blue'
+                        }
+                    }
+                } else {
+                    node.color = {
+                        background: styleArr[node.class].background,
+                        border: styleArr[node.class].border,
+                        highlight: {
+                            background: styleArr[node.class].background,
+                            border: 'blue'
+                        }
+                    }
+                }
+                nodes.update(node);
+
+                var connectedEdgeArray = edges.get(network.getConnectedEdges(node.id));
+                for (i = 0; i < connectedEdgeArray.length; i++) {
+
+                    var edge = connectedEdgeArray[i];
+
+                    edge.color = {
+                        color: 'black',
+                        highlight: 'black',
+                        hover: 'black',
+                    }
+                    edge.font = {
+                        size: 14,
+                    }
+                }
+                edges.update(connectedEdgeArray);
+            });
+
+
+            //===========================================================
+            $('#enableParents').on('click', function() {
+                console.log("enableParents: ", allParentsNode);
+
+                var node = nodes.get(nodeSelected);
+
+                var connectedParents = nodes.get(network.getConnectedNodes(node.id, "from"));
+                console.log("connectedParents = ", connectedParents);
+
+                for (i = 0; i < connectedParents.length; i++) {
+                    var node = connectedParents[i];
+                    node.font = {
+                        color: 'black'
+                    }
+                    node.hidden = false;
+                    if (node.filled == 1) {
+                        node.color = {
+                            background: redNode.background,
+                            border: redNode.border,
+                            hover: redNode.background,
+                            highlight: {
+                                background: redNode.background,
+                                border: 'blue'
+                            }
+                        }
+                    } else {
+                        node.color = {
+                            background: styleArr[node.class].background,
+                            border: styleArr[node.class].border,
+                            highlight: {
+                                background: styleArr[node.class].background,
+                                border: 'blue'
+                            }
+                        }
+                    }
+                }
+                nodes.update(connectedParents);
+            });
+
+
+
+            //===========================================================
+            $('#enableAllParents').on('click', function() {
+                console.log("showAllParents: allParentsNode = ", allParentsNode);
+                var allNode = nodes.get(allParentsNode);
+
+                for (i = 0; i < allNode.length; i++) {
+                    var node = allNode[i];
+                    node.font = {
+                        color: 'black'
+                    }
+                    node.hidden = false;
+                    if (node.filled == 1) {
+                        node.color = {
+                            background: redNode.background,
+                            border: redNode.border,
+                            hover: redNode.background,
+                            highlight: {
+                                background: redNode.background,
+                                border: 'blue'
+                            }
+                        }
+                    } else {
+                        node.color = {
+                            background: styleArr[node.class].background,
+                            border: styleArr[node.class].border,
+                            highlight: {
+                                background: styleArr[node.class].background,
+                                border: 'blue'
+                            }
+                        }
+                    }
+                }
+
+                nodes.update(allNode);
+
+                var node = nodes.get(nodeSelected);
+                var connectedEdgeArray = edges.get(network.getConnectedEdges(node.id));
+                for (j = 0; j < connectedEdgeArray.length; j++) {
+                    var edge = connectedEdgeArray[j];
+                    if (edge.to == node.id) {
+                        edge.hidden = false;
+                    }
+
+                }
+                edges.update(connectedEdgeArray);
+
+                allNode = nodes.get();
+                nodes.update(allNode);
+
+            });
+
+
+
+
+            //===========================================================
+            $('#disableAllParents').on('click', function() {
+                console.log("disableAllParents: ", allParentsNode);
+
+                var node = nodes.get(nodeSelected);
+                node.hidden = true;
+                console.log("node.id = ", node.id, "hidden = ", node.hidden);
+                nodes.update(node);
+
+                var connectedEdgeArray = edges.get(network.getConnectedEdges(node.id));
+                for (j = 0; j < connectedEdgeArray.length; j++) {
+                    var edge = connectedEdgeArray[j];
+                    if (edge.to == node.id) {
+                        edge.hidden = true;
+                    }
+
+                }
+                edges.update(connectedEdgeArray);
+
+                var allNode = nodes.get(allParentsNode);
+                for (i = 0; i < allNode.length; i++) {
+                    var node = allNode[i];
+                    node.hidden = true;
+                }
+                nodes.update(allNode);
+
+                for (i = 0; i < allNode.length; i++) {
+                    var node = allNode[i];
+
+                    var cNodes = nodes.get(network.getConnectedNodes(node.id, 'to'));
+                    for (j = 0; j < cNodes.length; j++) {
+                        var cnode = cNodes[j];
+
+                        if (cnode.hidden != true) {
+                            node.hidden = false;
+                            nodes.update(node);
+                            break;
+                        }
+                    }
+                }
+                nodes.update(allNode);
+
+                node = nodes.get(nodeSelected);
+                node.hidden = false;
+                console.log("node.id = ", node.id, "hidden = ", node.hidden);
+                nodes.update(node);
+
+                allNode = nodes.get();
+                nodes.update(allNode);
+            });
+
+
+            //===========================================================
+            $('#enableChild').on('click', function() {
+                console.log("enableChild: ", allChildNode);
+                var node = nodes.get(nodeSelected);
+
+                var connectedChild = nodes.get(network.getConnectedNodes(node.id, "to"));
+                console.log("connectedChild = ", connectedChild);
+
+                for (i = 0; i < connectedChild.length; i++) {
+                    var node = connectedChild[i];
+                    node.font = {
+                        color: 'black'
+                    }
+                    node.hidden = false;
+                    if (node.filled == 1) {
+                        node.color = {
+                            background: redNode.background,
+                            border: redNode.border,
+                            hover: redNode.background,
+                            highlight: {
+                                background: redNode.background,
+                                border: 'blue'
+                            }
+                        }
+                    } else {
+                        node.color = {
+                            background: styleArr[node.class].background,
+                            border: styleArr[node.class].border,
+                            highlight: {
+                                background: styleArr[node.class].background,
+                                border: 'blue'
+                            }
+                        }
+                    }
+                }
+                nodes.update(connectedChild);
+                var connectedEdgeArray = edges.get(network.getConnectedEdges(node.id));
+                for (j = 0; j < connectedEdgeArray.length; j++) {
+                    var edge = connectedEdgeArray[j];
+                    if (edge.from == node.id) {
+                        edge.hidden = false;
+                    }
+
+                }
+                edges.update(connectedEdgeArray);
+
+            });
+
+
+
+            //===========================================================
+            $('#enableAllChild').on('click', function() {
+                console.log("enableAllChild: ", allChildNode);
+
+                var node = nodes.get(nodeSelected);
+                node.hidden = false;
+                console.log("node.id = ", node.id, "hidden = ", node.hidden);
+                nodes.update(node);
+
+                var connectedEdgeArray = edges.get(network.getConnectedEdges(node.id));
+                for (j = 0; j < connectedEdgeArray.length; j++) {
+                    var edge = connectedEdgeArray[j];
+                    if (edge.from == node.id) {
+                        edge.hidden = false;
+                    }
+
+                }
+                edges.update(connectedEdgeArray);
+
+                var edgesforupdate = [];
+                var count=0;
+
+
+                var allNode = nodes.get(allChildNode);
+
+                for (i = 0; i < allNode.length; i++) {
+                    node = allNode[i];
+                    node.font = {
+                        color: 'black'
+                    }
+                    node.hidden = false;
+                    if (node.filled == 1) {
+                        node.color = {
+                            background: redNode.background,
+                            border: redNode.border,
+                            hover: redNode.background,
+                            highlight: {
+                                background: redNode.background,
+                                border: 'blue'
+                            }
+                        }
+                    } else {
+                        node.color = {
+                            background: styleArr[node.class].background,
+                            border: styleArr[node.class].border,
+                            highlight: {
+                                background: styleArr[node.class].background,
+                                border: 'blue'
+                            }
+                        }
+                    }
+                    var decendentEdges = edges.get(network.getConnectedEdges(node.id)); 
+                    for (j = 0; j < decendentEdges.length; j++) {
+                        if (decendentEdges[j].from == node.id) {
+                            edgesforupdate[count] = decendentEdges[j];
+
+                            edgesforupdate[count].hidden = false;
+                            count++;
+                        }
+                    }
+                }
+
+                nodes.update(allNode);
+                edges.update(edgesforupdate);
+
+                allNode = nodes.get();
+                nodes.update(allNode);
+
+                
+
+            });
+
+            //===========================================================
+            $('#disableAllChild').on('click', function() {
+                console.log("disableAllChind: ", allChildNode);
+                var node = nodes.get(nodeSelected);
+                node.hidden = true;
+                console.log("node.id = ", node.id, "hidden = ", node.hidden);
+                nodes.update(node);
+
+                var connectedEdgeArray = edges.get(network.getConnectedEdges(node.id));
+                for (j = 0; j < connectedEdgeArray.length; j++) {
+                    var edge = connectedEdgeArray[j];
+                    if (edge.from == node.id) {
+                        edge.hidden = true;
+                    }
+
+                }
+                edges.update(connectedEdgeArray);
+
+                var edgesforupdate = [];
+                var count=0;
+
+                var allNode = nodes.get(allChildNode);
+                for (i = 0; i < allNode.length; i++) {
+                    var node = allNode[i];
+                    node.hidden = true;
+                }
+                nodes.update(allNode);
+
+                for (i = 0; i < allNode.length; i++) {
+                    var node = allNode[i];
+
+                    var pNodes = nodes.get(network.getConnectedNodes(node.id, 'from'));
+                    for (j = 0; j < pNodes.length; j++) {
+                        var pnode = pNodes[j];
+
+                        if (pnode.hidden != true) {
+                            node.hidden = false;
+                            nodes.update(node);
+                            break;
+                        }
+                    }
+                    var decendentEdges = edges.get(network.getConnectedEdges(node.id)); 
+                    for (j = 0; j < decendentEdges.length; j++) {
+                        if (decendentEdges[j].from == node.id) {
+                            edgesforupdate[count] = decendentEdges[j];
+
+                            edgesforupdate[count].hidden = true;
+                            count++;
+                        }
+                    }
+                }
+                nodes.update(allNode);
+                edges.update(edgesforupdate);
+
+                node = nodes.get(nodeSelected);
+                node.hidden = false;
+                console.log("node.id = ", node.id, "hidden = ", node.hidden);
+                nodes.update(node);
+
+                allNode = nodes.get();
+                nodes.update(allNode);
+            });
+
+            //===========================================================
+            var shapeArr = [
+                'box',
+                'ellipse',
+                'ellipse',
+                'ellipse',
+                'box',
+                'ellipse'
+            ];
+
+            var styleArr = {
+                1: {
+                    background: 'LightSlateGray',
+                    border: 'SlateGray',
+                    shape: 'box'
+                },
+                2: {
+                    background: 'Khaki',
+                    border: 'DarkKhaki',
+                    shape: 'ellipse'
+                },
+                3: {
+                    background: 'Orchid',
+                    border: 'DarkOrchid',
+                    shape: 'ellipse'
+                },
+                4: {
+                    background: 'Orange',
+                    border: 'DarkOrange',
+                    shape: 'ellipse'
+                },
+                5: {
+                    background: 'YellowGreen',
+                    border: 'OliveDrab',
+                    shape: 'box'
+                },
+                6: {
+                    background: 'LightGray',
+                    border: 'Gray',
+                    shape: 'ellipse'
+                },
+                7: {
+                    background: 'LightBlue',
+                    border: 'Gray',
+                    shape: 'ellipse'
+                }
+            }
+
+            var transparentNode = {
+                background: 'white',
+                border: 'LightGray'
+            }
+
+            var redNode = {
+                background: 'Red',
+                border: 'DarkRed'
+            }
+
+            var transparentEdge = {
+                color: '#00000000',
+                font: 0
+            }
+
+            var nbClass = shapeArr.length;
+
+            //===========================================================
+            var node;
+            var nodes;
+            var edges;
+            var network;
+
+
+            //==================================================
+            var allParentsNode = [];
+            var allChildNode = [];
+
+            var allParentsEdge = [];
+            var allChildEdge = [];
+
+            //===========================================================
+            function handleFileSelect(file) {
+
+                if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
+                    alert('The File APIs are not fully supported in this browser.');
+                    return;
+                }
+
+
+                var reader = new FileReader();
+                var json;
+
+                reader.onload = (function(file) {
+                    return function(e) {
+                        //console.log('e readAsText = ', e);
+                        //console.log('e readAsText target = ', e.target);
+                        try {
+                            //==================================================
+                            json = JSON.parse(e.target.result);
+                            //alert('json global var has been set to parsed json of this file here it is unevaled = \n' + JSON.stringify(json));
+
+                            //==================================================
+                            json.nodes.forEach(function(node, index) {
+                                var classVal = node.class;
+                                var typeVal = node.type;
+                                var entryVal = node.entry;
+                                var attrVal = node.attributes;
+                                var inputsVal = node.inputs;
+                                var labelVal = node.label;
+                                var cidVal = node.cid;
+                                var distVal = node.distance;
+                                var nbinVal = node.nbin;
+                                var nboutVal = node.nbout;
+
+                                node.color = {
+                                    background: styleArr[classVal].background,
+                                    border: styleArr[classVal].border,
+                                    hover: styleArr[classVal].background,
+                                    highlight: {
+                                        background: styleArr[classVal].background,
+                                        border: 'blue'
+                                    }
+                                }
+
+                                node.shape = styleArr[classVal].shape;
+
+                                if (node.class == 1 || node.class >= 6)
+                                    node.title = "node id = " + node.id + "</br>" + labelVal + "</br>field attributes : </br>" + attrVal + "</br>filter entry nb = " + entryVal + "</br>cid = " + cidVal + "</br>distance = " + distVal;
+                                else if (node.class == 5)
+                                    node.title = "node id = " + node.id + "</br>" + labelVal + "</br>filter type = " + typeVal + "</br> entry nb = " + entryVal + "</br> inputs_complete = " + inputsVal + "</br>cid = " + cidVal + "</br>distance = " + distVal;
+                                else
+                                    node.title = "node id = " + node.id + "</br>" + labelVal + "</br>filter entry nb = " + entryVal + "</br>cid = " + cidVal + "</br>distance = " + distVal;
+
+                                if (node.filled == 1) {
+                                    node.title += "</br></br> filter has no child!!!</br>" + "</br>field attributes : </br>" + attrVal + "</br> entry nb = " + entryVal;
+                                    node.color = {
+                                        background: 'Red',
+                                        border: 'DarkRed',
+                                        hover: 'Red',
+                                        highlight: {
+                                            background: 'Red',
+                                            border: 'blue'
+                                        }
+                                    }
+                                }
+
+                                node.level = distVal;
+
+                                if (node.class >= 6 || node.filled == 1) node.hidden = true;
+                                else node.hidden = true;
+
+                            });
+
+                            //==================================================
+                            json.edges.forEach(function(node, index) {
+                                var dateVal = node.date;
+                                var fidVal = node.fid;
+                                var fnameVal = node.fname;
+                                var gidVal = node.gid;
+                                var attVal = node.attributes;
+                                var idVal = node.id
+
+                                node.title = "id = " + idVal + "</br>field attributes : </br>" + attVal + "</br> date = " + dateVal;
+
+                            });
+
+                            //==================================================
+                            nodes = new vis.DataSet();
+                            nodes.add(json.nodes);
+
+                            edges = new vis.DataSet();
+                            edges.add(json.edges);
+
+                            //==================================================
+                            var data = {
+                                nodes: nodes,
+                                edges: edges
+                            };
+
+                            //==================================================
+                            var options = {
+                                edges: {
+                                    smooth: false,
+                                    arrows: 'to',
+                                    font: {
+                                        align: 'middle',
+                                        size: 14,
+                                    },
+                                    color: {
+                                        color: 'black',
+                                        highlight: 'black',
+                                        hover: 'black',
+                                    }
+                                },
+                                physics: {
+                                    enabled: false
+                                },
+                                nodes: {
+                                    borderWidth: 2
+                                },
+                                interaction: {
+                                    hover: true
+                                },
+                                layout: {
+                                    hierarchical: {
+                                        enabled: true,
+                                        direction: "LR",
+                                        sortMethod: "directed",
+                                        levelSeparation: 300,
+                                        nodeSpacing: 80,
+                                        treeSpacing: 100,
+                                        blockShifting: true,
+                                        edgeMinimization: true
+                                    }
+                                },
+
+
+                            };
+
+                            //==================================================
+                            network = new vis.Network(container, data, options);
+                            //network1 = new vis.Network(container1, data, options);
+                            
+
+
+
+                            //==================================================
+                            Array.prototype.unique = function() {
+                                var a = this.concat();
+                                for (var i = 0; i < a.length; ++i) {
+                                    for (var j = i + 1; j < a.length; ++j) {
+                                        if (a[i] === a[j])
+                                            a.splice(j--, 1);
+                                    }
+                                }
+                                return a;
+                            };
+
+                            //==================================================
+                            function findAllParents(nodesArray) {
+                                if (nodesArray.length == 0) {
+                                    return 1;
+                                }
+                                var parentsArray = network.getConnectedNodes(nodesArray[0], 'from');
+                                //console.log('node ', nodesArray[0], 'has ', parentsArray);
+                                nodesArray = nodesArray.concat(parentsArray).unique();
+                                //console.log('---> ', nodesArray);
+                                allParentsNode = allParentsNode.concat(nodesArray[0]).unique();
+
+
+                                nodesArray.splice(0, 1);
+                                return findAllParents(nodesArray);
+                            }
+
+                            //==================================================
+                            function findAllChild(nodesArray) {
+                                if (nodesArray.length == 0) {
+                                    return 1;
+                                }
+                                var childArray = network.getConnectedNodes(nodesArray[0], 'to');
+                                //console.log('node ', nodesArray[0], 'has ', childArray);
+                                nodesArray = nodesArray.concat(childArray).unique();
+                                //console.log('---> ', nodesArray);
+                                allChildNode = allChildNode.concat(nodesArray[0]).unique();
+                                nodesArray.splice(0, 1);
+                                return findAllChild(nodesArray);
+                            }
+
+                            //==================================================
+                            function getEdgeConnections(node) {
+                                var connectedEdgeArray = network.getConnectedEdges(node);
+                            }
+
+                            //==================================================
+                            network.on("click", function(params) {
+                                params.event = "[original event]";
+                                console.log('__________________________');
+                                nodeSelected = this.getNodeAt(params.pointer.DOM);
+                                if (nodeSelected === undefined) return 0;
+
+                                var node = nodes.get(nodeSelected);
+
+                                var connectedChild = nodes.get(network.getConnectedNodes(node.id, "to"));
+                                console.log('------->', connectedChild.length);
+                                if (connectedChild.length == 0) {
+                                    $('#enableAllChild').attr("disabled", true);
+                                } else {
+                                    $('#enableAllChild').attr("disabled", false);
+                                }
+
+                                var connectedEdgeArray = getEdgeConnections(nodeSelected);
+
+                                //--------------------------
+                                var parentsArray = network.getConnectedNodes(nodeSelected, 'from');
+
+
+                                allParentsNode = [nodeSelected];
+                                findAllParents(parentsArray);
+                                // remove selected node
+                                var index = allParentsNode.indexOf(nodeSelected);
+                                if (index !== -1) allParentsNode.splice(index, 1);
+                                console.log('Final parents: ', allParentsNode);
+
+
+                                //--------------------------
+                                var node = this.getNodeAt(params.pointer.DOM);
+                                var childArray = network.getConnectedNodes(nodeSelected, 'to');
+
+
+                                allChildNode = [nodeSelected];
+                                findAllChild(childArray);
+                                // remove selected node
+                                var index = allChildNode.indexOf(nodeSelected);
+                                if (index !== -1) allChildNode.splice(index, 1);
+                                console.log('Final child: ', allChildNode);
+
+
+                                //--------------------------
+                            });
+
+                        } catch (ex) {
+                            alert('ex when trying to parse json = ' + ex);
+                        }
+                    }
+                })(file);
+
+                reader.readAsText(file);
+
+            }
+
+            //######################################################################################################
+        });
+    </script>
+
+    <div class="container">
+
+        <div class="row">
+            <label class="btn btn-primary" for="file">
+                <input type="file" id="file" style="display:none" onchange="$('#upload-file-info').html(this.files[0].name)">
+                Load a JSON XIOS file
+            </label>
+            <button type="button" class="btn btn-default disabled" id="upload-file-info">...</button>
+        </div>
+
+        <div class="row">
+
+            <div class="btn-group">
+                <button type="button" class="btn btn-success" id="showNode">Show node</button>
+                <button type="button" class="btn btn-success" id="hideNode">Hide node</button>
+            </div>
+
+            <div class="btn-group">
+                <button type="button" class="btn btn-success" id="enableAll">Enable all</button>
+                <button type="button" class="btn btn-success" id="disableAll">Disable all</button>
+            </div>
+
+            <div class="btn-group">
+                <button type="button" class="btn btn-success" id="enableParents">Enable parents</button>
+                <button type="button" class="btn btn-success" id="enableChild">Enable children</button>
+            </div>
+
+            <div class="btn-group">
+                <button type="button" class="btn btn-success" id="enableAllParents">Enable all parents</button>
+                <button type="button" class="btn btn-success" id="disableAllParents">Disable all parents</button>
+            </div>
+
+            <div class="btn-group">
+                <button type="button" class="btn btn-success" id="enableAllChild">Enable all children</button>
+                <button type="button" class="btn btn-success" id="disableAllChild">Disable all children</button>
+            </div>
+
+            <button type="button" class="btn btn-success" id="enableInput">Enable input</button>
+            <button type="button" class="btn btn-success" id="enableOutput">Enable output</button>
+
+            <button type="button" class="btn btn-success" id="lastTemporal">Enable last temporal input</button>
+            <button type="button" class="btn btn-success" id="showGraph">Show subgraph (and hide other)</button>            
+
+
+        </div>
+
+        <div class="row">
+            <div id="mynetwork"></div>
+            <div id="mynetwork1"></div>
+        </div>
+
+</body>
+
+</html>
Index: /XIOS/trunk/inputs/iodef.xml
===================================================================
--- /XIOS/trunk/inputs/iodef.xml	(revision 1703)
+++ /XIOS/trunk/inputs/iodef.xml	(revision 1704)
@@ -7,5 +7,7 @@
 
    <field_definition level="1" enabled=".TRUE.">
-     <field id="field_A"  operation="average" freq_op="3600s" grid_ref="grid_A"/>
+     <field id="field_A"  operation="average" freq_op="3600s" grid_ref="grid_A" />
+     <field id="field_B"  operation="average" freq_op="3600s" grid_ref="grid_A"/>
+     <field id="field_C"  operation="average" freq_op="3600s" grid_ref="grid_A" />
      <field id="field_Axis"  operation="average" freq_op="3600s" axis_ref="axis_A"/>
      <field id="field_Domain"  operation="average" freq_op="3600s" domain_ref="domain_A"/>
@@ -15,18 +17,29 @@
 
 
-   <file_definition type="one_file" par_access="collective" output_freq="1h" output_level="10" enabled=".FALSE.">
-      <file id="output" name="output" enabled=".TRUE.">
+   <file_definition type="one_file" par_access="collective" output_freq="1h" output_level="10" >
+      
+     <file id="output2" name="output2" output_freq="4h" enabled=".FALSE.">
+        <field id="field_G" field_ref="field_A" name="field_G_zoom" grid_ref="grid_A_zoom" build_workflow_graph=".TRUE." build_workflow_graph_start="1h" build_workflow_graph_end="8h" />        
+        <!-- <field field_ref="field_Scalar" name="field_A_scalar" build_workflow_graph=".TRUE."/>         -->
+     </file>
+
+
+     <file id="output1" name="output1" output_freq="24h" enabled=".TRUE.">
         <!-- <field field_ref="field_Domain" name="field_A" /> -->
-        <field field_ref="field_A" name="field_A" /> 
-        <field field_ref="field_A_zoom" name="field_B" />
+        <field id="field_F" field_ref="field_A" name="field_24h" grid_ref="grid_A" build_workflow_graph=".TRUE." build_workflow_graph_start="4h" build_workflow_graph_end="24h"  />        
+        
+     </file>  
+
+     <file id="output" name="output" enabled=".TRUE.">
+        <!-- <field field_ref="field_Domain" name="field_A" /> -->
+        <!-- <field field_ref="field_A" name="field_A_name"  build_workflow_graph=".FALSE." />  -->
+        <!-- <field field_ref="field_B" name="field_B_name"  build_workflow_graph=".FALSE."/>  -->
+        <!-- <field field_ref="field_C" name="field_C_name"  enabled=".TRUE." />  -->
+        <!-- <field id="field_D" field_ref="field_A" operation="instant" build_workflow_graph=".TRUE." name="field_D_name" build_workflow_graph_start="1h" build_workflow_graph_end="2h" > sqrt(field_A) </field> -->
+        <field id="field_E" field_ref="field_A" operation="instant" build_workflow_graph=".TRUE." name="field_E_name" build_workflow_graph_start="1h" build_workflow_graph_end="4h" > field_A + field_B + field_C</field>
+        <!-- <field field_ref="field_A_zoom" name="field_B" build_workflow_graph=".TRUE."/> -->
      </file>
-     <file id="output1" name="output1" enabled=".TRUE.">
-        <!-- <field field_ref="field_Domain" name="field_A" /> -->
-        <field field_ref="field_A" name="field_A" />        
-     </file> 
-     <file id="output2" name="output2" enabled=".TRUE.">
-        <!-- <field field_ref="field_Domain" name="field_A" /> -->
-        <field field_ref="field_Scalar" name="field_A" />        
-     </file>
+
+     
  <!--     <file id="output_s" name="output_s" mode="read" >
        <field id="field" name="field_A" grid_ref="grid_Scalar" operation="instant" />
@@ -79,5 +92,5 @@
         <variable_group id="parameters" >
           <variable id="using_server" type="bool">false</variable>
-          <variable id="info_level" type="int">50</variable>
+          <variable id="info_level" type="int">80</variable>
           <variable id="print_file" type="bool">true</variable>
         </variable_group>
Index: /XIOS/trunk/src/attribute.hpp
===================================================================
--- /XIOS/trunk/src/attribute.hpp	(revision 1703)
+++ /XIOS/trunk/src/attribute.hpp	(revision 1704)
@@ -42,4 +42,5 @@
             virtual void fromString(const StdString & str) = 0;
             virtual StdString dump(void) const = 0;
+            virtual StdString dump4graph(void) const = 0;
             virtual bool isEqual(const CAttribute& ) = 0;
 
Index: /XIOS/trunk/src/attribute_array.hpp
===================================================================
--- /XIOS/trunk/src/attribute_array.hpp	(revision 1703)
+++ /XIOS/trunk/src/attribute_array.hpp	(revision 1704)
@@ -56,4 +56,5 @@
             virtual bool fromBuffer(CBufferIn& buffer) { return _fromBuffer(buffer); }
             virtual string dump(void) const { return _dump();}
+            virtual string dump4graph(void) const { return _dump4graph();}
 
             virtual void generateCInterface(ostream& oss,const string& className) ;
@@ -71,4 +72,5 @@
           StdString _toString(void) const;
           StdString _dump(void) const;
+          StdString _dump4graph(void) const;
           void _fromString(const StdString & str);
           bool _toBuffer  (CBufferOut& buffer) const;
Index: /XIOS/trunk/src/attribute_array_impl.hpp
===================================================================
--- /XIOS/trunk/src/attribute_array_impl.hpp	(revision 1703)
+++ /XIOS/trunk/src/attribute_array_impl.hpp	(revision 1704)
@@ -138,4 +138,13 @@
     }
 
+    template <typename T_numtype, int N_rank>
+    StdString CAttributeArray<T_numtype,N_rank>::_dump4graph(void) const
+    {
+      StdOStringStream oss;
+      if (! isEmpty() && this->hasId() && (this->numElements()!=0))
+        oss << this->getName() << "=" << CArray<T_numtype, N_rank>::dump() << "";
+      return (oss.str());
+    }
+
 
       template <typename T_numtype, int N_rank>
Index: /XIOS/trunk/src/attribute_enum.hpp
===================================================================
--- /XIOS/trunk/src/attribute_enum.hpp	(revision 1703)
+++ /XIOS/trunk/src/attribute_enum.hpp	(revision 1704)
@@ -63,4 +63,5 @@
             virtual void fromString(const StdString & str) { if (str==resetInheritanceStr) { reset(); _canInherite=false ;}  else _fromString(str);}
             virtual StdString dump(void) const { return _toString();}
+            virtual StdString dump4graph(void) const { return _dump4graph();}
 
             virtual bool toBuffer  (CBufferOut& buffer) const { return _toBuffer(buffer);} 
@@ -79,4 +80,5 @@
           bool isEqual_(const CAttributeEnum& attr );
           StdString _toString(void) const;
+          StdString _dump4graph(void) const;
           void _fromString(const StdString & str);
           bool _toBuffer  (CBufferOut& buffer) const;
Index: /XIOS/trunk/src/attribute_enum_impl.hpp
===================================================================
--- /XIOS/trunk/src/attribute_enum_impl.hpp	(revision 1703)
+++ /XIOS/trunk/src/attribute_enum_impl.hpp	(revision 1704)
@@ -149,4 +149,13 @@
   }
 
+template <class T>
+  StdString CAttributeEnum<T>::_dump4graph(void) const
+  {
+     StdOStringStream oss;
+     if (!CEnum<T>::isEmpty() && this->hasId())
+        oss << this->getName() << "=" << CEnum<T>::toString() << "</br>";
+     return (oss.str());
+  }
+
   template <class T>
   void CAttributeEnum<T>::_fromString(const StdString & str)
Index: /XIOS/trunk/src/attribute_map.cpp
===================================================================
--- /XIOS/trunk/src/attribute_map.cpp	(revision 1703)
+++ /XIOS/trunk/src/attribute_map.cpp	(revision 1704)
@@ -48,4 +48,31 @@
             {
               str.append(att.second->dump());
+              str.append(" ");
+            }
+            else if (str.length() == maxNbChar)
+            {
+              str.append("...");
+            }
+          }
+        }
+        return str;
+      }
+
+
+
+      StdString CAttributeMap::record4graphXiosAttributes(void) const
+      {
+        int maxNbChar = 250;
+        StdString str;
+        typedef std::pair<StdString, CAttribute*> StdStrAttPair;
+        auto it = SuperClassMap::begin(), end = SuperClassMap::end();
+        for (; it != end; it++)
+        {
+          const StdStrAttPair& att = *it;
+          if (!att.second->isEmpty())
+          {
+            if (str.length() < maxNbChar)
+            {
+              str.append(att.second->dump4graph());
               str.append(" ");
             }
Index: /XIOS/trunk/src/attribute_map.hpp
===================================================================
--- /XIOS/trunk/src/attribute_map.hpp	(revision 1703)
+++ /XIOS/trunk/src/attribute_map.hpp	(revision 1704)
@@ -39,4 +39,5 @@
             void clearAllAttributes(void);
             StdString dumpXiosAttributes(void) const;
+            StdString record4graphXiosAttributes(void) const;
 
             void clearAttribute(const StdString& key);
Index: /XIOS/trunk/src/attribute_template.hpp
===================================================================
--- /XIOS/trunk/src/attribute_template.hpp	(revision 1703)
+++ /XIOS/trunk/src/attribute_template.hpp	(revision 1704)
@@ -75,4 +75,5 @@
 //            virtual void fromBinary(StdIStream & is);
             virtual StdString dump(void) const { return _dump();}
+            virtual StdString dump4graph(void) const { return _dump4graph();}
 
             virtual bool toBuffer  (CBufferOut& buffer) const { return _toBuffer(buffer);}
@@ -100,4 +101,5 @@
           StdString _toString(void) const;
           StdString _dump(void) const;
+          StdString _dump4graph(void) const;
           void _fromString(const StdString & str);
           bool _toBuffer  (CBufferOut& buffer) const;
Index: /XIOS/trunk/src/attribute_template_impl.hpp
===================================================================
--- /XIOS/trunk/src/attribute_template_impl.hpp	(revision 1703)
+++ /XIOS/trunk/src/attribute_template_impl.hpp	(revision 1704)
@@ -208,4 +208,13 @@
          if (!CType<T>::isEmpty() && this->hasId())
             oss << this->getName() << "=\"" << CType<T>::dump() << "\"";
+         return (oss.str());
+      }
+
+      template <class T>
+         StdString CAttributeTemplate<T>::_dump4graph(void) const
+      {
+         StdOStringStream oss;
+         if (!CType<T>::isEmpty() && this->hasId())
+            oss << this->getName() << "=" << CType<T>::dump() << "</br>";
          return (oss.str());
       }
Index: /XIOS/trunk/src/config/field_attribute.conf
===================================================================
--- /XIOS/trunk/src/config/field_attribute.conf	(revision 1703)
+++ /XIOS/trunk/src/config/field_attribute.conf	(revision 1704)
@@ -40,2 +40,7 @@
 DECLARE_ATTRIBUTE(StdString, cell_methods)
 DECLARE_ENUM4(cell_methods_mode,  overwrite, prefix, suffix, none)
+
+
+DECLARE_ATTRIBUTE(bool,      build_workflow_graph)
+DECLARE_ATTRIBUTE(CDuration, build_workflow_graph_start)
+DECLARE_ATTRIBUTE(CDuration, build_workflow_graph_end)
Index: /XIOS/trunk/src/cxios.cpp
===================================================================
--- /XIOS/trunk/src/cxios.cpp	(revision 1703)
+++ /XIOS/trunk/src/cxios.cpp	(revision 1704)
@@ -11,4 +11,6 @@
 #include "memtrack.hpp"
 #include "registry.hpp"
+
+#include "graphviz.hpp"
 
 namespace xios
@@ -135,4 +137,5 @@
        globalRegistry->toFile("xios_registry.bin") ;
        delete globalRegistry ;
+       CGraphviz::buildWorkflowGraphVisjs_with_info();
      }
 
Index: /XIOS/trunk/src/filter/binary_arithmetic_filter.cpp
===================================================================
--- /XIOS/trunk/src/filter/binary_arithmetic_filter.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/binary_arithmetic_filter.cpp	(revision 1704)
@@ -1,3 +1,7 @@
 #include "binary_arithmetic_filter.hpp"
+#include "workflow_graph.hpp"
+#include "yacc_var.hpp"
+#include "file.hpp"
+
 
 namespace xios
@@ -7,5 +11,67 @@
     , op(operatorExpr.getOpScalarField(op))
     , value(value)
-  { /* Nothing to do */ };
+  { 
+    expression.assign(*yacc_globalInputText_ptr, 0, yacc_globalInputText_ptr->size()-1);
+  };
+
+  std::tuple<int, int, int> CScalarFieldArithmeticFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+    // bool building_graph = true;
+    int unique_filter_id;
+    bool firstround;
+
+    if(building_graph)
+    {
+      CWorkflowGraph::allocNodeEdge();
+
+      size_t filterhash = std::hash<StdString>{}(expression+to_string(data[0]->timestamp)+this->field->getId());
+
+      // first round
+      if(CWorkflowGraph::mapHashFilterID_ptr->find(filterhash) == CWorkflowGraph::mapHashFilterID_ptr->end())
+      {
+        firstround = true;
+        this->filterID = InvalidableObject::filterIdGenerator++;
+        int edgeID = InvalidableObject::edgeIdGenerator++;
+
+        CWorkflowGraph::addNode(this->filterID, "Arithmetic Filter\\n("+expression+")", 3, 1, 0, data[0]);
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].filter_tag = this->tag;
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+        if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+      
+
+        if(CWorkflowGraph::build_begin)
+        {
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ;
+        }
+        else CWorkflowGraph::build_begin = true;
+
+        (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash] = this->filterID; 
+        unique_filter_id = this->filterID;
+      }
+      // not first round
+      else 
+      {
+        firstround=false;
+        unique_filter_id = (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash];
+        if(data[0]->src_filterID != unique_filter_id)
+        {
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[0]);  
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ; 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+      }  
+    }
+
+    return std::make_tuple(building_graph, firstround, unique_filter_id);
+  }
+
 
   CDataPacketPtr CScalarFieldArithmeticFilter::apply(std::vector<CDataPacketPtr> data)
@@ -16,4 +82,12 @@
     packet->status = data[0]->status;
 
+    std::tuple<int, int, int> graph = buildGraph(data);
+
+    if(std::get<0>(graph)) packet->src_filterID = std::get<2>(graph);
+    if(std::get<0>(graph) && std::get<1>(graph)) packet->distance = data[0]->distance+1;
+    if(std::get<0>(graph) && !std::get<1>(graph)) packet->distance = data[0]->distance;
+
+    packet->field = this->field;
+
     if (packet->status == CDataPacket::NO_ERROR)
       packet->data.reference(op(value, data[0]->data));
@@ -26,5 +100,66 @@
     , op(operatorExpr.getOpFieldScalar(op))
     , value(value)
-  { /* Nothing to do */ };
+  { 
+    expression.assign(*yacc_globalInputText_ptr, 0, yacc_globalInputText_ptr->size()-1);
+  };
+
+  std::tuple<int, int, int> CFieldScalarArithmeticFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+    // bool building_graph = true;
+    int unique_filter_id;
+    bool firstround;
+
+    if(building_graph)
+    {
+      CWorkflowGraph::allocNodeEdge();
+
+      size_t filterhash = std::hash<StdString>{}(expression+to_string(data[0]->timestamp)+this->field->getId());
+
+      // first round
+      if(CWorkflowGraph::mapHashFilterID_ptr->find(filterhash) == CWorkflowGraph::mapHashFilterID_ptr->end())
+      {
+        firstround = true;
+        this->filterID = InvalidableObject::filterIdGenerator++;
+        int edgeID = InvalidableObject::edgeIdGenerator++;
+
+        CWorkflowGraph::addNode(this->filterID, "Arithmetic Filter\\n("+expression+")", 3, 1, 0, data[0]);
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].filter_tag = this->tag;
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+        if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+      
+
+        if(CWorkflowGraph::build_begin)
+        {
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ;
+        }
+        else CWorkflowGraph::build_begin = true;
+
+        (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash] = this->filterID; 
+        unique_filter_id = this->filterID;
+      }
+      // not first round
+      else 
+      {
+        firstround=false;
+        unique_filter_id = (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash];
+        if(data[0]->src_filterID != unique_filter_id)
+        {
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[0]);  
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ; 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+      }  
+    }
+
+    return std::make_tuple(building_graph, firstround, unique_filter_id);
+  }
 
   CDataPacketPtr CFieldScalarArithmeticFilter::apply(std::vector<CDataPacketPtr> data)
@@ -35,4 +170,12 @@
     packet->status = data[0]->status;
 
+    std::tuple<int, int, int> graph = buildGraph(data);
+
+    if(std::get<0>(graph)) packet->src_filterID = std::get<2>(graph);
+    if(std::get<0>(graph) && std::get<1>(graph)) packet->distance = data[0]->distance+1;
+    if(std::get<0>(graph) && !std::get<1>(graph)) packet->distance = data[0]->distance;
+
+    packet->field = this->field;
+
     if (packet->status == CDataPacket::NO_ERROR)
       packet->data.reference(op(data[0]->data, value));
@@ -44,5 +187,83 @@
     : CFilter(gc, 2, this)
     , op(operatorExpr.getOpFieldField(op))
-  { /* Nothing to do */ };
+  { 
+    expression.assign(*yacc_globalInputText_ptr, 0, yacc_globalInputText_ptr->size()-1);
+  };
+
+  std::tuple<int, int, int> CFieldFieldArithmeticFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? ((data[0]->timestamp >= this->field->field_graph_start && data[0]->timestamp <= this->field->field_graph_end) && (data[0]->timestamp == data[1]->timestamp)) : false;
+
+    int unique_filter_id;
+
+    bool firstround;
+
+    if(building_graph)
+    {  
+      CWorkflowGraph::allocNodeEdge();
+
+      // std::cout<<"CFieldFieldArithmeticFilter::apply filter tag = "<<this->tag<<std::endl;
+
+      size_t filterhash = std::hash<StdString>{}(expression+to_string(data[0]->timestamp)+this->field->getId());
+
+      // first round
+      if(CWorkflowGraph::mapHashFilterID_ptr->find(filterhash) == CWorkflowGraph::mapHashFilterID_ptr->end())
+      {
+        firstround = true;
+        this->filterID = InvalidableObject::filterIdGenerator++;
+        int edgeID = InvalidableObject::edgeIdGenerator++;
+    
+        CWorkflowGraph::addNode(this->filterID, "Arithmetic Filter\\n("+expression+")", 3, 1, 0, data[0]);
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+        if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+    
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].filter_tag = this->tag;
+        if(CWorkflowGraph::build_begin)
+        {
+
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          edgeID = InvalidableObject::edgeIdGenerator++;
+
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[1]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[1]->src_filterID].filter_filled = 0 ;
+        }
+        CWorkflowGraph::build_begin = true;
+
+        (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash] = this->filterID; 
+        unique_filter_id = this->filterID;
+ 
+      }
+      // not first round
+      else 
+      {
+        firstround = false;
+        unique_filter_id = (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash];
+        if(data[0]->src_filterID != unique_filter_id)
+        {
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[0]); 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ; 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+        if(data[1]->src_filterID != unique_filter_id)
+        { 
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[1]);  
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[1]->src_filterID].filter_filled = 0 ;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+        
+      }  
+    }
+
+    return std::make_tuple(building_graph, firstround, unique_filter_id);
+  }
 
   CDataPacketPtr CFieldFieldArithmeticFilter::apply(std::vector<CDataPacketPtr> data)
@@ -51,4 +272,13 @@
     packet->date = data[0]->date;
     packet->timestamp = data[0]->timestamp;
+
+    std::tuple<int, int, int> graph = buildGraph(data);
+
+    if(std::get<0>(graph)) packet->src_filterID = std::get<2>(graph);
+    if(std::get<0>(graph) && std::get<1>(graph)) packet->distance = data[0]->distance+1;
+    if(std::get<0>(graph) && !std::get<1>(graph)) packet->distance = data[0]->distance;
+    
+    packet->field = this->field;
+    
 
     if (data[0]->status != CDataPacket::NO_ERROR)
@@ -64,3 +294,9 @@
     return packet;
   }
+
+  StdString CScalarFieldArithmeticFilter::GetName(void)    { return StdString("CScalarFieldArithmeticFilter"); }
+  StdString CFieldScalarArithmeticFilter::GetName(void)    { return StdString("CFieldScalarArithmeticFilter"); }
+  StdString CFieldFieldArithmeticFilter::GetName(void)     { return StdString("CFieldFieldArithmeticFilter"); }
+
+
 } // namespace xios
Index: /XIOS/trunk/src/filter/binary_arithmetic_filter.hpp
===================================================================
--- /XIOS/trunk/src/filter/binary_arithmetic_filter.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/binary_arithmetic_filter.hpp	(revision 1704)
@@ -6,4 +6,5 @@
 #include "operator_expr.hpp"
 #include <unordered_map>
+#include <tuple>
 
 namespace xios
@@ -23,4 +24,6 @@
        */
       CScalarFieldArithmeticFilter(CGarbageCollector& gc, const std::string& op, double value);
+      StdString virtual GetName(void);
+
 
     protected:
@@ -35,4 +38,7 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      std::tuple<int, int, int> virtual buildGraph(std::vector<CDataPacketPtr> data);
+      
+
   }; // class CScalarFieldArithmeticFilter
 
@@ -51,4 +57,6 @@
        */
       CFieldScalarArithmeticFilter(CGarbageCollector& gc, const std::string& op, double value);
+      StdString virtual GetName(void);
+
 
     protected:
@@ -63,4 +71,5 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      std::tuple<int, int, int> virtual buildGraph(std::vector<CDataPacketPtr> data);
   }; // class CFieldScalarArithmeticFilter
 
@@ -78,4 +87,6 @@
        */
       CFieldFieldArithmeticFilter(CGarbageCollector& gc, const std::string& op);
+      StdString virtual GetName(void);
+
 
     protected:
@@ -89,4 +100,5 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      std::tuple<int, int, int> virtual buildGraph(std::vector<CDataPacketPtr> data);
   }; // class CFieldFieldArithmeticFilter
 } // namespace xios
Index: /XIOS/trunk/src/filter/data_packet.hpp
===================================================================
--- /XIOS/trunk/src/filter/data_packet.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/data_packet.hpp	(revision 1704)
@@ -9,4 +9,5 @@
 namespace xios
 {
+  class CField;
   /*!
    * A packet corresponds to a timestamped array of data.
@@ -26,5 +27,9 @@
     Time timestamp;         //!< Timestamp of the data
     StatusCode status;      //!< Status of the packet
-
+    int src_filterID;
+    std::vector<int> filterIDoutputs;
+    CField *field;
+    int distance;
+    
     /*!
      * Creates a deep copy of the packet.
Index: /XIOS/trunk/src/filter/file_writer_filter.cpp
===================================================================
--- /XIOS/trunk/src/filter/file_writer_filter.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/file_writer_filter.cpp	(revision 1704)
@@ -3,4 +3,6 @@
 #include "field.hpp"
 #include "utils.hpp"
+#include "workflow_graph.hpp"
+#include "graphviz.hpp"
 
 namespace xios
@@ -15,6 +17,40 @@
   }
 
+  void CFileWriterFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph: false;
+    
+    if(building_graph)
+    {
+      this->filterID = InvalidableObject::filterIdGenerator++;
+      int edgeID = InvalidableObject::edgeIdGenerator++;
+
+      CWorkflowGraph::allocNodeEdge();
+      StdString namestring = to_string(this->field->name);
+      namestring.erase(0, 6);
+      namestring.erase(namestring.length()-1, 1);
+
+      CWorkflowGraph::addNode(this->filterID, namestring + "\\n("+this->field->file->getId()+".nc)", 6, 0, 1, data[0]);
+
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].clusterID =1;
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+      if(CXios::isClient && CWorkflowGraph::build_begin) 
+      {
+
+        CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ;
+      }
+      else CWorkflowGraph::build_begin=true;
+    }
+  }
+
   void CFileWriterFilter::onInputReady(std::vector<CDataPacketPtr> data)
   {
+    buildGraph(data);
+    
     const bool detectMissingValue = ( !field->default_value.isEmpty() &&
                                ( (!field->detect_missing_value.isEmpty() || field->detect_missing_value == true)
Index: /XIOS/trunk/src/filter/file_writer_filter.hpp
===================================================================
--- /XIOS/trunk/src/filter/file_writer_filter.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/file_writer_filter.hpp	(revision 1704)
@@ -3,4 +3,6 @@
 
 #include "input_pin.hpp"
+#include "file.hpp"
+#include "duration.hpp"
 
 namespace xios
@@ -14,4 +16,11 @@
   {
     public:
+      int tag;
+      Time start_graph;
+      Time end_graph;
+      CField* field; //<! The associated field
+      int filterID;
+      int distance;
+
       /*!
        * Constructs the filter (with one input slot) associated to the specified field
@@ -22,4 +31,7 @@
        */
       CFileWriterFilter(CGarbageCollector& gc, CField* field);
+
+      inline StdString GetName(void) {return "File writer filter";};
+
 
       /*!
@@ -44,7 +56,7 @@
        */
       void virtual onInputReady(std::vector<CDataPacketPtr> data);
+      void virtual buildGraph(std::vector<CDataPacketPtr> data);
 
     private:
-      CField* field; //<! The associated field
       std::map<Time, CDataPacketPtr> packets; //<! The stored packets
   }; // class CFileWriterFilter
Index: /XIOS/trunk/src/filter/filter.cpp
===================================================================
--- /XIOS/trunk/src/filter/filter.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/filter.cpp	(revision 1704)
@@ -5,8 +5,10 @@
   CFilter::CFilter(CGarbageCollector& gc, size_t inputSlotsCount, IFilterEngine* engine)
     : CInputPin(gc, inputSlotsCount)
-    , COutputPin(gc)
+    , COutputPin(gc, false)
     , engine(engine)
     , inputSlotCount(inputSlotCount)
   { /* Nothing to do */ }
+
+  StdString CFilter::GetName(void)    { return StdString("Filter"); }
 
   void CFilter::onInputReady(std::vector<CDataPacketPtr> data)
Index: /XIOS/trunk/src/filter/filter.hpp
===================================================================
--- /XIOS/trunk/src/filter/filter.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/filter.hpp	(revision 1704)
@@ -25,4 +25,6 @@
        */
       CFilter(CGarbageCollector& gc, size_t inputSlotsCount, IFilterEngine* engine);
+
+      StdString virtual GetName(void);
 
       /*!
@@ -62,4 +64,10 @@
       bool virtual isDataExpected(const CDate& date) const;
 
+      
+      
+
+      int filterID;
+      StdString expression;
+
     protected:
       IFilterEngine* engine; //!< The filter engine, might be the filter itself
Index: /XIOS/trunk/src/filter/garbage_collector.cpp
===================================================================
--- /XIOS/trunk/src/filter/garbage_collector.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/garbage_collector.cpp	(revision 1704)
@@ -3,4 +3,10 @@
 namespace xios
 {
+  int InvalidableObject::filterIdGenerator = 0;
+
+  int InvalidableObject::edgeIdGenerator = 0;
+
+  int InvalidableObject::clusterIdGenerator = 0;
+  
   void CGarbageCollector::registerObject(InvalidableObject* Object, Time timestamp)
   {
Index: /XIOS/trunk/src/filter/garbage_collector.hpp
===================================================================
--- /XIOS/trunk/src/filter/garbage_collector.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/garbage_collector.hpp	(revision 1704)
@@ -20,4 +20,15 @@
      */
     void virtual invalidate(Time timestamp) = 0;
+  
+    
+
+    static int filterIdGenerator;
+
+    static int edgeIdGenerator;
+
+    static int clusterIdGenerator;
+
+    
+    
   }; // struct InvalidableObject
 
Index: /XIOS/trunk/src/filter/input_pin.cpp
===================================================================
--- /XIOS/trunk/src/filter/input_pin.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/input_pin.cpp	(revision 1704)
@@ -3,4 +3,5 @@
 #include "garbage_collector.hpp"
 #include "exception.hpp"
+#include "workflow_graph.hpp"
 
 namespace xios
@@ -11,5 +12,10 @@
     , triggers(slotsCount)
     , hasTriggers(false)
-  { /* Nothing to do */ }
+  {  }
+
+  StdString CInputPin::GetName(void)
+  {
+    return StdString("Input pin");
+  }
 
   void CInputPin::setInput(size_t inputSlot, CDataPacketPtr packet)
Index: /XIOS/trunk/src/filter/input_pin.hpp
===================================================================
--- /XIOS/trunk/src/filter/input_pin.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/input_pin.hpp	(revision 1704)
@@ -26,4 +26,6 @@
        */
       CInputPin(CGarbageCollector& gc, size_t slotsCount);
+      
+      StdString virtual GetName(void);
 
       /*!
Index: /XIOS/trunk/src/filter/output_pin.cpp
===================================================================
--- /XIOS/trunk/src/filter/output_pin.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/output_pin.cpp	(revision 1704)
@@ -1,4 +1,5 @@
 #include "output_pin.hpp"
 #include "exception.hpp"
+#include "workflow_graph.hpp"
 
 namespace xios
@@ -7,5 +8,10 @@
     : gc(gc)
     , manualTrigger(manualTrigger)
-  { /* Nothing to do */ }
+  {  }
+
+  StdString COutputPin::GetName(void)
+  {
+    return StdString("Output pin");
+  }
 
   void COutputPin::connectOutput(std::shared_ptr<CInputPin> inputPin, size_t inputSlot)
@@ -101,3 +107,25 @@
     outputPackets.erase(outputPackets.begin(), outputPackets.lower_bound(timestamp));
   }
+
+  void COutputPin::setParentFiltersTag()
+  {
+    for(int i=0; i<parent_filters.size(); i++)
+    {
+
+      if(parent_filters[i]->start_graph<0) parent_filters[i]->start_graph = start_graph;
+      else parent_filters[i]->start_graph = min(parent_filters[i]->start_graph, start_graph);
+
+
+      if(parent_filters[i]->end_graph<0) parent_filters[i]->end_graph = end_graph;  
+      else parent_filters[i]->end_graph = max(parent_filters[i]->end_graph, end_graph);
+      
+      
+      parent_filters[i]->tag += tag;
+      parent_filters[i]->setParentFiltersTag();
+    }
+  }
+
+
+
+
 } // namespace xios
Index: /XIOS/trunk/src/filter/output_pin.hpp
===================================================================
--- /XIOS/trunk/src/filter/output_pin.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/output_pin.hpp	(revision 1704)
@@ -4,7 +4,12 @@
 #include "garbage_collector.hpp"
 #include "input_pin.hpp"
+#include "duration.hpp"
 
 namespace xios
 {
+  class CField;
+  class CInputPin;
+  class CFilter;
+  class CDuration;
   /*!
    * An output pin handles the connections with downstream filters.
@@ -13,4 +18,14 @@
   {
     public:
+      int tag;
+      Time start_graph;
+      Time end_graph;
+      CField *field;
+      int distance;
+
+
+
+      std::vector< std::shared_ptr<COutputPin> > parent_filters;
+
       /*!
        * Constructs an ouput pin with manual or automatic trigger
@@ -22,4 +37,6 @@
       COutputPin(CGarbageCollector& gc, bool manualTrigger = false);
 
+      StdString virtual GetName(void);
+      
       /*!
        * Connects to a specific slot of the input pin of a downstream filter.
@@ -66,4 +83,7 @@
       void virtual invalidate(Time timestamp);
 
+      void virtual setParentFiltersTag();
+
+
     protected:
       /*!
Index: /XIOS/trunk/src/filter/pass_through_filter.cpp
===================================================================
--- /XIOS/trunk/src/filter/pass_through_filter.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/pass_through_filter.cpp	(revision 1704)
@@ -1,3 +1,6 @@
 #include "pass_through_filter.hpp"
+#include "workflow_graph.hpp"
+#include "field.hpp"
+#include "file.hpp"
 
 namespace xios
@@ -5,8 +8,45 @@
   CPassThroughFilter::CPassThroughFilter(CGarbageCollector& gc)
     : CFilter(gc, 1, this)
-  { /* Nothing to do */ }
+  { 
+  }
+
+  void CPassThroughFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+    // bool building_graph = this->tag ? data[0]->timestamp >= this->field->field_graph_start && data[0]->timestamp <= this->field->field_graph_end : false;
+
+    if(building_graph)
+    {
+      // std::cout<<"CPassThroughFilter::apply field_id = "<<this->field->getId()<<" start = "<<start_graph<<" end = "<<end_graph<<std::endl;
+      this->filterID = InvalidableObject::filterIdGenerator++;
+      int edgeID = InvalidableObject::edgeIdGenerator++;
+
+      CWorkflowGraph::allocNodeEdge();
+
+      CWorkflowGraph::addNode(this->filterID, "Pass Through Filter\\n("+data[0]->field->getId()+")", 2, 1, 1, data[0]);
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+      if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+
+      
+      if(CWorkflowGraph::build_begin)
+      {
+        CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0;
+      }
+      else CWorkflowGraph::build_begin = true;
+      
+      data[0]->src_filterID=this->filterID;
+      data[0]->distance++;
+
+    }
+
+    data[0]->field = this->field;
+  }
 
   CDataPacketPtr CPassThroughFilter::apply(std::vector<CDataPacketPtr> data)
   {
+    if(CXios::isClient) buildGraph(data);
     return data[0];
   }
Index: /XIOS/trunk/src/filter/pass_through_filter.hpp
===================================================================
--- /XIOS/trunk/src/filter/pass_through_filter.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/pass_through_filter.hpp	(revision 1704)
@@ -20,4 +20,6 @@
       CPassThroughFilter(CGarbageCollector& gc);
 
+      inline StdString GetName(void) {return StdString("Pass through filter");};
+
     protected:
       /*!
@@ -28,4 +30,5 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      void virtual buildGraph(std::vector<CDataPacketPtr> data);
   }; // class CPassThroughFilter
 } // namespace xios
Index: /XIOS/trunk/src/filter/source_filter.cpp
===================================================================
--- /XIOS/trunk/src/filter/source_filter.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/source_filter.cpp	(revision 1704)
@@ -4,4 +4,5 @@
 #include "calendar_util.hpp"
 #include <limits> 
+#include "workflow_graph.hpp"
 
 namespace xios
@@ -23,4 +24,28 @@
             "Impossible to construct a source filter without providing a grid.");
   }
+
+  void CSourceFilter::buildGraph(CDataPacketPtr packet)
+  {
+    bool building_graph = this->tag ? packet->timestamp >= this->field->field_graph_start && packet->timestamp <= this->field->field_graph_end : false;
+    if(building_graph)
+    {
+      this->filterID = InvalidableObject::filterIdGenerator++;  
+      packet->src_filterID=this->filterID;
+      packet->field = this->field;
+      packet->distance = 1;
+      
+    
+      CWorkflowGraph::allocNodeEdge();
+
+      CWorkflowGraph::addNode(this->filterID, "Source Filter ", 1, 1, 0, packet);
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].field_id = this->field->getId();
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = 1;
+
+      CWorkflowGraph::build_begin = true;
+    }
+
+  }
+
 
   template <int N>
@@ -59,4 +84,8 @@
       }
     }
+
+    if(CXios::isClient) buildGraph(packet);
+    
+
 
     onOutputReady(packet);
Index: /XIOS/trunk/src/filter/source_filter.hpp
===================================================================
--- /XIOS/trunk/src/filter/source_filter.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/source_filter.hpp	(revision 1704)
@@ -35,4 +35,6 @@
                     double defaultValue = 0.0);
 
+      inline StdString GetName(void) {return StdString("Source filter");};
+
       /*!
        * Transforms the data received from the model into a packet and send it
@@ -45,4 +47,6 @@
       template <int N>
       void streamData(CDate date, const CArray<double, N>& data);
+
+      void virtual buildGraph(CDataPacketPtr packet);
 
       /*!
@@ -62,4 +66,5 @@
        */
       void signalEndOfStream(CDate date);
+      int filterID;
 
     private:
Index: /XIOS/trunk/src/filter/spatial_transform_filter.cpp
===================================================================
--- /XIOS/trunk/src/filter/spatial_transform_filter.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/spatial_transform_filter.cpp	(revision 1704)
@@ -4,4 +4,6 @@
 #include "context_client.hpp"
 #include "timer.hpp"
+#include "workflow_graph.hpp"
+#include "file.hpp"
 
 namespace xios
@@ -64,5 +66,5 @@
   {
     CSpatialTransformFilterEngine* spaceFilter = static_cast<CSpatialTransformFilterEngine*>(engine);
-    CDataPacketPtr outputPacket = spaceFilter->applyFilter(data, outputDefaultValue);
+    CDataPacketPtr outputPacket = spaceFilter->applyFilter(data, outputDefaultValue, this->tag, this->start_graph, this->end_graph, this->field);
     if (outputPacket)
       onOutputReady(outputPacket);
@@ -96,5 +98,5 @@
   {
     CSpatialTransformFilterEngine* spaceFilter = static_cast<CSpatialTransformFilterEngine*>(engine);
-    CDataPacketPtr outputPacket = spaceFilter->applyFilter(data, outputDefaultValue);
+    CDataPacketPtr outputPacket = spaceFilter->applyFilter(data, outputDefaultValue, this->tag, this->start_graph, this->end_graph, this->field);
 
     if (outputPacket)
@@ -121,4 +123,5 @@
         packet->data.resize(tmpData.numElements());
         packet->data = tmpData;
+        packet->field = this->field;
         onOutputReady(packet);
         tmpData.resize(0) ;
@@ -159,6 +162,37 @@
   }
 
-  CDataPacketPtr CSpatialTransformFilterEngine::applyFilter(std::vector<CDataPacketPtr> data, double defaultValue)
-  {
+  bool CSpatialTransformFilterEngine::buildGraph(std::vector<CDataPacketPtr> data, int tag, Time start_graph, Time end_graph, CField *field)
+  {
+    bool building_graph = tag ? data[0]->timestamp >= start_graph && data[0]->timestamp <= end_graph : false;
+    if(building_graph)
+    {
+      this->filterID = InvalidableObject::filterIdGenerator++;
+      int edgeID = InvalidableObject::edgeIdGenerator++;    
+
+      CWorkflowGraph::allocNodeEdge();
+
+      CWorkflowGraph::addNode(this->filterID, "Spatial Transform Filter", 4, 1, 1, data[0]);
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = field->record4graphXiosAttributes();
+      if(field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +field->file->record4graphXiosAttributes();
+
+
+      if(CWorkflowGraph::build_begin)
+      {
+        CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0;
+      }
+      else CWorkflowGraph::build_begin = true;
+    }
+
+    return building_graph;
+  }
+
+  CDataPacketPtr CSpatialTransformFilterEngine::applyFilter(std::vector<CDataPacketPtr> data, double defaultValue, int tag, Time start_graph, Time end_graph, CField *field)
+  {
+    
+    bool BG = buildGraph(data, tag, start_graph, end_graph, field);
+
     CDataPacketPtr packet(new CDataPacket);
     packet->date = data[0]->date;
@@ -177,11 +211,16 @@
       if (0 != packet->data.numElements())
         (packet->data)(0) = defaultValue;
-      apply(data[0]->data, packet->data);
-    }
+      if(BG) apply(data[0]->data, packet->data, this->filterID);
+      else apply(data[0]->data, packet->data);
+    }
+
+    if(BG) packet->src_filterID=this->filterID;
+    if(BG) packet->distance=data[0]->distance+1;
+    packet->field = field;
 
     return packet;
   }
 
-  void CSpatialTransformFilterEngine::apply(const CArray<double, 1>& dataSrc, CArray<double,1>& dataDest)
+  void CSpatialTransformFilterEngine::apply(const CArray<double, 1>& dataSrc, CArray<double,1>& dataDest, int filterID)
   {
     CTimer::get("CSpatialTransformFilterEngine::apply").resume(); 
@@ -296,4 +335,9 @@
         const std::vector<std::pair<int,double> >& localIndex_p = itRecv->second;
         int srcRank = itRecv->first;
+
+        if(filterID >=0) // building_graph
+        {
+           (*CWorkflowGraph::mapFilters_ptr_with_info)[filterID].filter_name = (*itAlgo)->getName();
+        } 
         if (srcRank != rank)
         {
Index: /XIOS/trunk/src/filter/spatial_transform_filter.hpp
===================================================================
--- /XIOS/trunk/src/filter/spatial_transform_filter.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/spatial_transform_filter.hpp	(revision 1704)
@@ -3,4 +3,5 @@
 
 #include "filter.hpp"
+#include "field.hpp"
 
 namespace xios
@@ -9,4 +10,6 @@
   class CGridTransformation;
   class CSpatialTransformFilterEngine;
+
+  class CField;
 
   /*!
@@ -24,5 +27,8 @@
        * \param [in] inputSlotsCount number of input, by default there is only one for field src
        */
-      CSpatialTransformFilter(CGarbageCollector& gc, CSpatialTransformFilterEngine* engine, double outputValue, size_t inputSlotsCount = 1);
+      CSpatialTransformFilter(CGarbageCollector& gc, CSpatialTransformFilterEngine* engine,
+                              double outputValue, size_t inputSlotsCount = 1);
+
+      inline StdString GetName(void) {return StdString("Spatial transform filter");};
 
       /*!
@@ -93,4 +99,8 @@
   {
     public:
+
+      int filterID;
+      int tag;
+      CField *field;
       /*!
        * Returns the engine wrapping the specified grid transformation.
@@ -109,5 +119,6 @@
        * \return the result of the grid transformation
        */
-      CDataPacketPtr applyFilter(std::vector<CDataPacketPtr> data, double defaultValue = 0);
+      CDataPacketPtr applyFilter(std::vector<CDataPacketPtr> data, double defaultValue = 0, int tag=0, Time start_graph=0, Time end_graph=-1, CField *field=0);
+      bool buildGraph(std::vector<CDataPacketPtr> data, int tag=0, Time start_graph=0, Time end_graph=-1, CField *field=0);
 
        /*!
@@ -136,5 +147,5 @@
        * \param dataDest the resulting transformed data
        */
-      void apply(const CArray<double, 1>& dataSrc, CArray<double,1>& dataDest);
+      void apply(const CArray<double, 1>& dataSrc, CArray<double,1>& dataDest, int filterID=-1);
 
       CGridTransformation* gridTransformation; //!< The grid transformation used by the engine
Index: /XIOS/trunk/src/filter/store_filter.cpp
===================================================================
--- /XIOS/trunk/src/filter/store_filter.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/store_filter.cpp	(revision 1704)
@@ -3,4 +3,5 @@
 #include "grid.hpp"
 #include "timer.hpp"
+#include "file.hpp"
 
 namespace xios
@@ -76,6 +77,34 @@
   template CDataPacket::StatusCode CStoreFilter::getData<7>(Time timestamp, CArray<double, 7>& data);
 
+  void CStoreFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+
+    if(building_graph)
+    {
+      this->filterID = InvalidableObject::filterIdGenerator++;
+      int edgeID = InvalidableObject::edgeIdGenerator++;
+
+      CWorkflowGraph::allocNodeEdge();
+ 
+      CWorkflowGraph::addNode(this->filterID, "Store Filter", 7, 0, 1, data[0]);
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = ++(data[0]->distance);
+      (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+      if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+
+      // if(CXios::isClient) std::cout<<"CStoreFilter::apply filter tag = "<<this->tag<<std::endl;
+
+      if(CXios::isClient && CWorkflowGraph::build_begin) 
+      {
+        CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);;
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0;
+      }
+      else CWorkflowGraph::build_begin = true;
+    }
+  }
+
   void CStoreFilter::onInputReady(std::vector<CDataPacketPtr> data)
   {
+    buildGraph(data);
 
     CDataPacketPtr packet;
Index: /XIOS/trunk/src/filter/store_filter.hpp
===================================================================
--- /XIOS/trunk/src/filter/store_filter.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/store_filter.hpp	(revision 1704)
@@ -3,4 +3,6 @@
 
 #include "input_pin.hpp"
+#include "workflow_graph.hpp"
+
 
 namespace xios
@@ -8,4 +10,5 @@
   class CContext;
   class CGrid;
+  class CField;
 
   /*!
@@ -73,4 +76,12 @@
       void virtual invalidate(Time timestamp);
 
+      int filterID;
+      int tag;
+      Time start_graph;
+      Time end_graph;
+      CField *field;
+      int distance;
+
+
     protected:
       /*!
@@ -80,4 +91,5 @@
        */
       void virtual onInputReady(std::vector<CDataPacketPtr> data);
+      void virtual buildGraph(std::vector<CDataPacketPtr> data);
 
     private:
Index: /XIOS/trunk/src/filter/temporal_filter.cpp
===================================================================
--- /XIOS/trunk/src/filter/temporal_filter.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/temporal_filter.cpp	(revision 1704)
@@ -2,4 +2,6 @@
 #include "functor_type.hpp"
 #include "calendar_util.hpp"
+#include "workflow_graph.hpp"
+#include "file.hpp"
 
 namespace xios
@@ -22,5 +24,4 @@
                         this->samplingOffset.second, this->samplingOffset.timestep)
     , initDate(initDate)
-//    , nextSamplingDate(initDate + (this->samplingOffset + initDate.getRelCalendar().getTimeStep()))
     , nextSamplingDate(initDate + offsetMonth + ( offsetAllButMonth + initDate.getRelCalendar().getTimeStep()))
     , nbOperationDates(1)
@@ -28,9 +29,60 @@
 //    , nextOperationDate(initDate + opFreq + this->samplingOffset)
     , isFirstOperation(true)
+    , temp_op(opId)
   {
   }
 
+  
+
+
+
+  bool CTemporalFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph=this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+   
+    if(building_graph)
+    {
+      if(this->filterIDoutputs.size()==0) this->filterID = InvalidableObject::filterIdGenerator++;
+      int edgeID = InvalidableObject::edgeIdGenerator++;
+      
+      // std::cout<<"CTemporalFilter::apply filter tag = "<<this->tag<<" start = "<<this->start_graph<<" end = "<<this->end_graph<<std::endl;
+
+      CWorkflowGraph::allocNodeEdge();
+
+      if(this->filterIDoutputs.size()==0)
+      {
+        CWorkflowGraph::addNode(this->filterID, "Temporal Filter\\n("+this->temp_op+")", 5, 1, 0, data[0]);   
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].transform_type = this->temp_op;   
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].inputs_complete = false ;
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].clusterID = 1 ;
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = (data[0]->distance);
+
+
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+        if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+      }
+
+      if(CWorkflowGraph::build_begin)
+      {
+
+        CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ;
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb += 1 ;
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = max(data[0]->distance+1, (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance);
+      }
+
+
+      this->filterIDoutputs.push_back(data[0]->src_filterID); 
+    }
+
+    return building_graph;
+  }
+
+
   CDataPacketPtr CTemporalFilter::apply(std::vector<CDataPacketPtr> data)
   {
+    bool BG = buildGraph(data);
+
     CDataPacketPtr packet;
 
@@ -43,5 +95,4 @@
       {
         usePacket = (data[0]->date >= nextSamplingDate);
-//        outputResult = (data[0]->date + samplingFreq > nextOperationDate);
         outputResult = (data[0]->date  > initDate + nbOperationDates*opFreq - samplingFreq + offsetMonth + offsetAllButMonth);
         copyLess = (isInstantOperation && usePacket && outputResult);
@@ -80,5 +131,15 @@
 
         isFirstOperation = false;
-//        nextOperationDate = initDate + samplingFreq + nbOperationDates*opFreq - samplingFreq + offsetMonth + offsetAllButMonth;
+        
+        packet->field = this->field;
+        
+        if(BG)
+        {
+          packet->src_filterID=this->filterID;
+          packet->distance = data[0]->distance+1;
+          this->filterIDoutputs.clear();
+          CWorkflowGraph::build_begin=true;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].inputs_complete = true ;
+        }
       }
     }
Index: /XIOS/trunk/src/filter/temporal_filter.hpp
===================================================================
--- /XIOS/trunk/src/filter/temporal_filter.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/temporal_filter.hpp	(revision 1704)
@@ -31,4 +31,6 @@
                       bool ignoreMissingValue = false);
 
+      inline StdString GetName(void) {return StdString("Temporal filter");};
+
       /*!
        * Applies the temporal operation to the input data and returns the result when it is ready.
@@ -38,4 +40,5 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      bool virtual buildGraph(std::vector<CDataPacketPtr> data);
 
       /*!
@@ -52,4 +55,8 @@
        */
       bool virtual isDataExpected(const CDate& date) const;
+      std::vector<int > filterIDoutputs;
+      std::vector<std::pair<int, int> > filterIDoutputs_pair;
+
+      StdString temp_op;
 
     private:
Index: /XIOS/trunk/src/filter/ternary_arithmetic_filter.cpp
===================================================================
--- /XIOS/trunk/src/filter/ternary_arithmetic_filter.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/ternary_arithmetic_filter.cpp	(revision 1704)
@@ -1,3 +1,6 @@
 #include "ternary_arithmetic_filter.hpp"
+#include "workflow_graph.hpp"
+#include "yacc_var.hpp"
+#include "file.hpp"
 
 namespace xios
@@ -8,5 +11,66 @@
     , value1(value1)
     , value2(value2)
-  { /* Nothing to do */ };
+  { 
+    expression.assign(*yacc_globalInputText_ptr, 0, yacc_globalInputText_ptr->size()-1);
+    /* Nothing to do */ 
+  };
+
+  std::tuple<int, int, int> CScalarScalarFieldArithmeticFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+    int unique_filter_id;
+    bool firstround;
+
+    if(building_graph)
+    {
+      CWorkflowGraph::allocNodeEdge();
+
+      size_t filterhash = std::hash<StdString>{}(expression+to_string(data[0]->timestamp)+this->field->getId());
+
+      // first round
+      if(CWorkflowGraph::mapHashFilterID_ptr->find(filterhash) == CWorkflowGraph::mapHashFilterID_ptr->end())
+      {
+        firstround = true;
+        this->filterID = InvalidableObject::filterIdGenerator++;
+        int edgeID = InvalidableObject::edgeIdGenerator++;
+
+        CWorkflowGraph::addNode(this->filterID, "Arithmetic Filter\\n("+expression+")", 3, 1, 0, data[0]);
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].filter_tag = this->tag;
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+        if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+      
+
+        if(CWorkflowGraph::build_begin)
+        {
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ;
+        }
+        else CWorkflowGraph::build_begin = true;
+
+        (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash] = this->filterID; 
+        unique_filter_id = this->filterID;
+      }
+      // not first round
+      else 
+      {
+        firstround=false;
+        unique_filter_id = (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash];
+        if(data[0]->src_filterID != unique_filter_id)
+        {
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[0]);  
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ; 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+      }  
+    }
+
+    return std::make_tuple(building_graph, firstround, unique_filter_id);
+  }
 
   CDataPacketPtr CScalarScalarFieldArithmeticFilter::apply(std::vector<CDataPacketPtr> data)
@@ -16,4 +80,12 @@
     packet->timestamp = data[0]->timestamp;
     packet->status = data[0]->status;
+    
+    std::tuple<int, int, int> graph = buildGraph(data);
+
+    if(std::get<0>(graph)) packet->src_filterID = std::get<2>(graph);
+    if(std::get<0>(graph) && std::get<1>(graph)) packet->distance = data[0]->distance+1;
+    if(std::get<0>(graph) && !std::get<1>(graph)) packet->distance = data[0]->distance;
+
+    packet->field = this->field;
 
     if (packet->status == CDataPacket::NO_ERROR)
@@ -28,5 +100,66 @@
     , value1(value1)
     , value2(value2)
-  { /* Nothing to do */ };
+  { 
+    expression.assign(*yacc_globalInputText_ptr, 0, yacc_globalInputText_ptr->size()-1);
+    /* Nothing to do */ 
+  };
+
+  std::tuple<int, int, int> CScalarFieldScalarArithmeticFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+    int unique_filter_id;
+    bool firstround;
+
+    if(building_graph)
+    {
+      CWorkflowGraph::allocNodeEdge();
+
+      size_t filterhash = std::hash<StdString>{}(expression+to_string(data[0]->timestamp)+this->field->getId());
+
+      // first round
+      if(CWorkflowGraph::mapHashFilterID_ptr->find(filterhash) == CWorkflowGraph::mapHashFilterID_ptr->end())
+      {
+        firstround = true;
+        this->filterID = InvalidableObject::filterIdGenerator++;
+        int edgeID = InvalidableObject::edgeIdGenerator++;
+
+        CWorkflowGraph::addNode(this->filterID, "Arithmetic Filter\\n("+expression+")", 3, 1, 0, data[0]);
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].filter_tag = this->tag;
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+        if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+      
+
+        if(CWorkflowGraph::build_begin)
+        {
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ;
+        }
+        else CWorkflowGraph::build_begin = true;
+
+        (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash] = this->filterID; 
+        unique_filter_id = this->filterID;
+      }
+      // not first round
+      else 
+      {
+        firstround=false;
+        unique_filter_id = (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash];
+        if(data[0]->src_filterID != unique_filter_id)
+        {
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[0]);  
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ; 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+      }  
+    }
+
+    return std::make_tuple(building_graph, firstround, unique_filter_id);
+  }
 
   CDataPacketPtr CScalarFieldScalarArithmeticFilter::apply(std::vector<CDataPacketPtr> data)
@@ -36,4 +169,12 @@
     packet->timestamp = data[0]->timestamp;
     packet->status = data[0]->status;
+    
+    std::tuple<int, int, int> graph = buildGraph(data);
+
+    if(std::get<0>(graph)) packet->src_filterID = std::get<2>(graph);
+    if(std::get<0>(graph) && std::get<1>(graph)) packet->distance = data[0]->distance+1;
+    if(std::get<0>(graph) && !std::get<1>(graph)) packet->distance = data[0]->distance;
+
+    packet->field = this->field;
 
     if (packet->status == CDataPacket::NO_ERROR)
@@ -47,5 +188,81 @@
     , op(operatorExpr.getOpScalarFieldField(op))
     , value(value)
-  { /* Nothing to do */ };
+  { 
+    expression.assign(*yacc_globalInputText_ptr, 0, yacc_globalInputText_ptr->size()-1);
+    /* Nothing to do */ 
+  };
+
+  std::tuple<int, int, int> CScalarFieldFieldArithmeticFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+    int unique_filter_id;
+
+    bool firstround;
+
+    if(building_graph)
+    {  
+      CWorkflowGraph::allocNodeEdge();
+
+      size_t filterhash = std::hash<StdString>{}(expression+to_string(data[0]->timestamp)+this->field->getId());
+
+      // first round
+      if(CWorkflowGraph::mapHashFilterID_ptr->find(filterhash) == CWorkflowGraph::mapHashFilterID_ptr->end())
+      {
+        firstround = true;
+        this->filterID = InvalidableObject::filterIdGenerator++;
+        int edgeID = InvalidableObject::edgeIdGenerator++;
+    
+        CWorkflowGraph::addNode(this->filterID, "Arithmetic Filter\\n("+expression+")", 3, 1, 0, data[0]);
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+        if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+    
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].filter_tag = this->tag;
+        if(CWorkflowGraph::build_begin)
+        {
+
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          edgeID = InvalidableObject::edgeIdGenerator++;
+
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[1]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[1]->src_filterID].filter_filled = 0 ;
+        }
+        CWorkflowGraph::build_begin = true;
+
+        (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash] = this->filterID; 
+        unique_filter_id = this->filterID;
+ 
+      }
+      // not first round
+      else 
+      {
+        firstround = false;
+        unique_filter_id = (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash];
+        if(data[0]->src_filterID != unique_filter_id)
+        {
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[0]); 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ; 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+        if(data[1]->src_filterID != unique_filter_id)
+        { 
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[1]);  
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[1]->src_filterID].filter_filled = 0 ;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+        
+      }  
+    }
+
+    return std::make_tuple(building_graph, firstround, unique_filter_id);
+  }
 
   CDataPacketPtr CScalarFieldFieldArithmeticFilter::apply(std::vector<CDataPacketPtr> data)
@@ -55,4 +272,12 @@
     packet->timestamp = data[0]->timestamp;
     packet->status = data[0]->status;
+    
+    std::tuple<int, int, int> graph = buildGraph(data);
+
+    if(std::get<0>(graph)) packet->src_filterID = std::get<2>(graph);
+    if(std::get<0>(graph) && std::get<1>(graph)) packet->distance = data[0]->distance+1;
+    if(std::get<0>(graph) && !std::get<1>(graph)) packet->distance = data[0]->distance;
+
+    packet->field = this->field;
 
     if (data[0]->status != CDataPacket::NO_ERROR)
@@ -75,5 +300,66 @@
     , value1(value1)
     , value2(value2)
-  { /* Nothing to do */ };
+  { 
+    expression.assign(*yacc_globalInputText_ptr, 0, yacc_globalInputText_ptr->size()-1);
+    /* Nothing to do */ 
+  };
+
+  std::tuple<int, int, int> CFieldScalarScalarArithmeticFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+    int unique_filter_id;
+    bool firstround;
+
+    if(building_graph)
+    {
+      CWorkflowGraph::allocNodeEdge();
+
+      size_t filterhash = std::hash<StdString>{}(expression+to_string(data[0]->timestamp)+this->field->getId());
+
+      // first round
+      if(CWorkflowGraph::mapHashFilterID_ptr->find(filterhash) == CWorkflowGraph::mapHashFilterID_ptr->end())
+      {
+        firstround = true;
+        this->filterID = InvalidableObject::filterIdGenerator++;
+        int edgeID = InvalidableObject::edgeIdGenerator++;
+
+        CWorkflowGraph::addNode(this->filterID, "Arithmetic Filter\\n("+expression+")", 3, 1, 0, data[0]);
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].filter_tag = this->tag;
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+        if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+      
+
+        if(CWorkflowGraph::build_begin)
+        {
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ;
+        }
+        else CWorkflowGraph::build_begin = true;
+
+        (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash] = this->filterID; 
+        unique_filter_id = this->filterID;
+      }
+      // not first round
+      else 
+      {
+        firstround=false;
+        unique_filter_id = (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash];
+        if(data[0]->src_filterID != unique_filter_id)
+        {
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[0]);  
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ; 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+      }  
+    }
+
+    return std::make_tuple(building_graph, firstround, unique_filter_id);
+  }
 
   CDataPacketPtr CFieldScalarScalarArithmeticFilter::apply(std::vector<CDataPacketPtr> data)
@@ -84,4 +370,12 @@
     packet->status = data[0]->status;
 
+    std::tuple<int, int, int> graph = buildGraph(data);
+
+    if(std::get<0>(graph)) packet->src_filterID = std::get<2>(graph);
+    if(std::get<0>(graph) && std::get<1>(graph)) packet->distance = data[0]->distance+1;
+    if(std::get<0>(graph) && !std::get<1>(graph)) packet->distance = data[0]->distance;
+
+    packet->field = this->field;
+
     if (packet->status == CDataPacket::NO_ERROR)
       packet->data.reference(op(data[0]->data, value1, value2));
@@ -95,5 +389,81 @@
     , op(operatorExpr.getOpFieldScalarField(op))
     , value(value)
-  { /* Nothing to do */ };
+  { 
+    expression.assign(*yacc_globalInputText_ptr, 0, yacc_globalInputText_ptr->size()-1);
+    /* Nothing to do */ 
+  };
+
+  std::tuple<int, int, int> CFieldScalarFieldArithmeticFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+    int unique_filter_id;
+
+    bool firstround;
+
+    if(building_graph)
+    {  
+      CWorkflowGraph::allocNodeEdge();
+
+      size_t filterhash = std::hash<StdString>{}(expression+to_string(data[0]->timestamp)+this->field->getId());
+
+      // first round
+      if(CWorkflowGraph::mapHashFilterID_ptr->find(filterhash) == CWorkflowGraph::mapHashFilterID_ptr->end())
+      {
+        firstround = true;
+        this->filterID = InvalidableObject::filterIdGenerator++;
+        int edgeID = InvalidableObject::edgeIdGenerator++;
+    
+        CWorkflowGraph::addNode(this->filterID, "Arithmetic Filter\\n("+expression+")", 3, 1, 0, data[0]);
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+        if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+    
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].filter_tag = this->tag;
+        if(CWorkflowGraph::build_begin)
+        {
+
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          edgeID = InvalidableObject::edgeIdGenerator++;
+
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[1]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[1]->src_filterID].filter_filled = 0 ;
+        }
+        CWorkflowGraph::build_begin = true;
+
+        (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash] = this->filterID; 
+        unique_filter_id = this->filterID;
+ 
+      }
+      // not first round
+      else 
+      {
+        firstround = false;
+        unique_filter_id = (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash];
+        if(data[0]->src_filterID != unique_filter_id)
+        {
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[0]); 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ; 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+        if(data[1]->src_filterID != unique_filter_id)
+        { 
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[1]);  
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[1]->src_filterID].filter_filled = 0 ;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+        
+      }  
+    }
+
+    return std::make_tuple(building_graph, firstround, unique_filter_id);
+  }
 
   CDataPacketPtr CFieldScalarFieldArithmeticFilter::apply(std::vector<CDataPacketPtr> data)
@@ -103,4 +473,12 @@
     packet->timestamp = data[0]->timestamp;
     packet->status = data[0]->status;
+    
+    std::tuple<int, int, int> graph = buildGraph(data);
+
+    if(std::get<0>(graph)) packet->src_filterID = std::get<2>(graph);
+    if(std::get<0>(graph) && std::get<1>(graph)) packet->distance = data[0]->distance+1;
+    if(std::get<0>(graph) && !std::get<1>(graph)) packet->distance = data[0]->distance;
+
+    packet->field = this->field;
 
     if (data[0]->status != CDataPacket::NO_ERROR)
@@ -120,5 +498,82 @@
     , op(operatorExpr.getOpFieldFieldScalar(op))
     , value(value)
-  { /* Nothing to do */ };
+  { 
+    expression.assign(*yacc_globalInputText_ptr, 0, yacc_globalInputText_ptr->size()-1);
+    std::cout<<"expression = "<<expression;
+    /* Nothing to do */ 
+  };
+
+  std::tuple<int, int, int> CFieldFieldScalarArithmeticFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+    int unique_filter_id;
+
+    bool firstround;
+
+    if(building_graph)
+    {  
+      CWorkflowGraph::allocNodeEdge();
+
+      size_t filterhash = std::hash<StdString>{}(expression+to_string(data[0]->timestamp)+this->field->getId());
+
+      // first round
+      if(CWorkflowGraph::mapHashFilterID_ptr->find(filterhash) == CWorkflowGraph::mapHashFilterID_ptr->end())
+      {
+        firstround = true;
+        this->filterID = InvalidableObject::filterIdGenerator++;
+        int edgeID = InvalidableObject::edgeIdGenerator++;
+    
+        CWorkflowGraph::addNode(this->filterID, "Arithmetic Filter\\n("+expression+")", 3, 1, 0, data[0]);
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+        if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+    
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].filter_tag = this->tag;
+        if(CWorkflowGraph::build_begin)
+        {
+
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          edgeID = InvalidableObject::edgeIdGenerator++;
+
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[1]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[1]->src_filterID].filter_filled = 0 ;
+        }
+        CWorkflowGraph::build_begin = true;
+
+        (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash] = this->filterID; 
+        unique_filter_id = this->filterID;
+ 
+      }
+      // not first round
+      else 
+      {
+        firstround = false;
+        unique_filter_id = (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash];
+        if(data[0]->src_filterID != unique_filter_id)
+        {
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[0]); 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ; 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+        if(data[1]->src_filterID != unique_filter_id)
+        { 
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[1]);  
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[1]->src_filterID].filter_filled = 0 ;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+        
+      }  
+    }
+
+    return std::make_tuple(building_graph, firstround, unique_filter_id);
+  }
 
   CDataPacketPtr CFieldFieldScalarArithmeticFilter::apply(std::vector<CDataPacketPtr> data)
@@ -128,4 +583,12 @@
     packet->timestamp = data[0]->timestamp;
     packet->status = data[0]->status;
+    
+    std::tuple<int, int, int> graph = buildGraph(data);
+
+    if(std::get<0>(graph)) packet->src_filterID = std::get<2>(graph);
+    if(std::get<0>(graph) && std::get<1>(graph)) packet->distance = data[0]->distance+1;
+    if(std::get<0>(graph) && !std::get<1>(graph)) packet->distance = data[0]->distance;
+
+    packet->field = this->field;
 
     if (data[0]->status != CDataPacket::NO_ERROR)
@@ -145,5 +608,94 @@
     : CFilter(gc, 3, this)
     , op(operatorExpr.getOpFieldFieldField(op))
-  { /* Nothing to do */ };
+  { 
+    expression.assign(*yacc_globalInputText_ptr, 0, yacc_globalInputText_ptr->size()-1);
+    /* Nothing to do */ 
+  };
+
+  std::tuple<int, int, int> CFieldFieldFieldArithmeticFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+    int unique_filter_id;
+
+    bool firstround;
+
+    if(building_graph)
+    {  
+      CWorkflowGraph::allocNodeEdge();
+
+      size_t filterhash = std::hash<StdString>{}(expression+to_string(data[0]->timestamp)+this->field->getId());
+
+      // first round
+      if(CWorkflowGraph::mapHashFilterID_ptr->find(filterhash) == CWorkflowGraph::mapHashFilterID_ptr->end())
+      {
+        firstround = true;
+        this->filterID = InvalidableObject::filterIdGenerator++;
+        int edgeID = InvalidableObject::edgeIdGenerator++;
+    
+        CWorkflowGraph::addNode(this->filterID, "Arithmetic Filter\\n("+expression+")", 3, 1, 0, data[0]);
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+        if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+    
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].filter_tag = this->tag;
+        if(CWorkflowGraph::build_begin)
+        {
+
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          edgeID = InvalidableObject::edgeIdGenerator++;
+
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[1]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          edgeID = InvalidableObject::edgeIdGenerator++;
+
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[2]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[1]->src_filterID].filter_filled = 0 ;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[2]->src_filterID].filter_filled = 0 ;
+        }
+        CWorkflowGraph::build_begin = true;
+
+        (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash] = this->filterID; 
+        unique_filter_id = this->filterID;
+ 
+      }
+      // not first round
+      else 
+      {
+        firstround = false;
+        unique_filter_id = (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash];
+        if(data[0]->src_filterID != unique_filter_id)
+        {
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[0]); 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ; 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+        if(data[1]->src_filterID != unique_filter_id)
+        { 
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[1]);  
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[1]->src_filterID].filter_filled = 0 ;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+        if(data[2]->src_filterID != unique_filter_id)
+        { 
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[2]);  
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[2]->src_filterID].filter_filled = 0 ;
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }
+        
+      }  
+    }
+
+    return std::make_tuple(building_graph, firstround, unique_filter_id);
+  }
 
   CDataPacketPtr CFieldFieldFieldArithmeticFilter::apply(std::vector<CDataPacketPtr> data)
@@ -153,4 +705,12 @@
     packet->timestamp = data[0]->timestamp;
     packet->status = data[0]->status;
+    
+    std::tuple<int, int, int> graph = buildGraph(data);
+
+    if(std::get<0>(graph)) packet->src_filterID = std::get<2>(graph);
+    if(std::get<0>(graph) && std::get<1>(graph)) packet->distance = data[0]->distance+1;
+    if(std::get<0>(graph) && !std::get<1>(graph)) packet->distance = data[0]->distance;
+
+    packet->field = this->field;
 
     if (data[0]->status != CDataPacket::NO_ERROR)
Index: /XIOS/trunk/src/filter/ternary_arithmetic_filter.hpp
===================================================================
--- /XIOS/trunk/src/filter/ternary_arithmetic_filter.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/ternary_arithmetic_filter.hpp	(revision 1704)
@@ -5,4 +5,5 @@
 #include <string>
 #include "operator_expr.hpp"
+#include <tuple>
 
 namespace xios
@@ -36,4 +37,5 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      std::tuple<int, int, int> virtual buildGraph(std::vector<CDataPacketPtr> data);
   }; // class CScalarScalarFieldArithmeticFilter
 
@@ -67,4 +69,5 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      std::tuple<int, int, int> virtual buildGraph(std::vector<CDataPacketPtr> data);
   }; // class CScalarScalarFieldArithmeticFilter
 
@@ -95,4 +98,5 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      std::tuple<int, int, int> virtual buildGraph(std::vector<CDataPacketPtr> data);
   }; // class CScalarScalarFieldArithmeticFilter
 
@@ -127,4 +131,5 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      std::tuple<int, int, int> virtual buildGraph(std::vector<CDataPacketPtr> data);
   }; // class CFieldScalarScalarArithmeticFilter
 
@@ -156,4 +161,5 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      std::tuple<int, int, int> virtual buildGraph(std::vector<CDataPacketPtr> data);
   }; // class CFieldScalarFieldArithmeticFilter
 
@@ -185,4 +191,5 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      std::tuple<int, int, int> virtual buildGraph(std::vector<CDataPacketPtr> data);
   }; // class CFieldFielScalardArithmeticFilter
 
@@ -212,4 +219,5 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      std::tuple<int, int, int> virtual buildGraph(std::vector<CDataPacketPtr> data);
   }; // class CFieldFielFieldArithmeticFilter
 
Index: /XIOS/trunk/src/filter/unary_arithmetic_filter.cpp
===================================================================
--- /XIOS/trunk/src/filter/unary_arithmetic_filter.cpp	(revision 1703)
+++ /XIOS/trunk/src/filter/unary_arithmetic_filter.cpp	(revision 1704)
@@ -1,3 +1,6 @@
 #include "unary_arithmetic_filter.hpp"
+#include "workflow_graph.hpp"
+#include "yacc_var.hpp"
+#include "file.hpp"
 
 namespace xios
@@ -6,5 +9,63 @@
     : CFilter(gc, 1, this)
     , op(operatorExpr.getOpField(op))
-  { /* Nothing to do */ };
+  { 
+    expression.assign(*yacc_globalInputText_ptr, 0, yacc_globalInputText_ptr->size()-1);
+  };
+
+  std::tuple<int, int, int> CUnaryArithmeticFilter::buildGraph(std::vector<CDataPacketPtr> data)
+  {
+    bool building_graph = this->tag ? data[0]->timestamp >= this->start_graph && data[0]->timestamp <= this->end_graph : false;
+    int unique_filter_id;
+    bool firstround;
+    
+    if(building_graph)
+    {
+      CWorkflowGraph::allocNodeEdge();
+      size_t filterhash = std::hash<StdString>{}(expression+to_string(data[0]->timestamp)+this->field->getId());
+
+      // first round
+      if(CWorkflowGraph::mapHashFilterID_ptr->find(filterhash) == CWorkflowGraph::mapHashFilterID_ptr->end())
+      {
+        firstround=true;
+        this->filterID = InvalidableObject::filterIdGenerator++;
+        int edgeID = InvalidableObject::edgeIdGenerator++;
+
+        CWorkflowGraph::addNode(this->filterID, "Arithmetic Filter\\n("+expression+")", 3, 1, 0, data[0]);
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].filter_tag = this->tag;
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].distance = data[0]->distance+1;
+
+        (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes = this->field->record4graphXiosAttributes();
+        if(this->field->file) (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].attributes += "</br>file attributes : </br>" +this->field->file->record4graphXiosAttributes();
+      
+        if(CWorkflowGraph::build_begin)
+        {
+
+          CWorkflowGraph::addEdge(edgeID, this->filterID, data[0]);
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[this->filterID].expected_entry_nb ++;
+
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ; 
+        }
+        else CWorkflowGraph::build_begin = true;
+
+        (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash] = this->filterID; 
+        unique_filter_id = this->filterID;
+      }
+      else 
+      {
+        firstround=false;
+        unique_filter_id = (*CWorkflowGraph::mapHashFilterID_ptr)[filterhash];
+        if(data[0]->src_filterID != unique_filter_id)
+        {
+          int edgeID = InvalidableObject::edgeIdGenerator++;
+          CWorkflowGraph::addEdge(edgeID, unique_filter_id, data[0]); 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[data[0]->src_filterID].filter_filled = 0 ; 
+          (*CWorkflowGraph::mapFilters_ptr_with_info)[unique_filter_id].expected_entry_nb ++;
+        }   
+      } 
+  
+    }
+
+    return std::make_tuple(building_graph, firstround, unique_filter_id);
+  }
 
   CDataPacketPtr CUnaryArithmeticFilter::apply(std::vector<CDataPacketPtr> data)
@@ -15,4 +76,12 @@
     packet->status = data[0]->status;
 
+    std::tuple<int, int, int> graph = buildGraph(data);
+
+    if(std::get<0>(graph)) packet->src_filterID = std::get<2>(graph);
+    if(std::get<0>(graph) && std::get<1>(graph)) packet->distance = data[0]->distance+1;
+    if(std::get<0>(graph) && !std::get<1>(graph)) packet->distance = data[0]->distance;
+
+    packet->field = this->field;
+
     if (packet->status == CDataPacket::NO_ERROR)
       packet->data.reference(op(data[0]->data));
Index: /XIOS/trunk/src/filter/unary_arithmetic_filter.hpp
===================================================================
--- /XIOS/trunk/src/filter/unary_arithmetic_filter.hpp	(revision 1703)
+++ /XIOS/trunk/src/filter/unary_arithmetic_filter.hpp	(revision 1704)
@@ -34,4 +34,5 @@
        */
       CDataPacketPtr virtual apply(std::vector<CDataPacketPtr> data);
+      std::tuple<int, int, int> virtual buildGraph(std::vector<CDataPacketPtr> data);
   }; // class CUnaryArithmeticFilter
 } // namespace xios
Index: /XIOS/trunk/src/graphviz.cpp
===================================================================
--- /XIOS/trunk/src/graphviz.cpp	(revision 1704)
+++ /XIOS/trunk/src/graphviz.cpp	(revision 1704)
@@ -0,0 +1,151 @@
+#include "graphviz.hpp"
+#include "workflow_graph.hpp"
+
+namespace xios
+{
+
+  CGraphviz::CGraphviz()
+  { }
+
+  /*!
+   *
+   */
+  void CGraphviz::buildWorkflowGraphDot()
+  TRY
+  {
+    if (CWorkflowGraph::mapFieldToFilters_ptr_with_info !=0 && !CWorkflowGraph::mapFieldToFilters_ptr_with_info->empty())
+    {
+      CWorkflowGraph::buildStaticWorkflow();
+    
+      typedef boost::property<boost::edge_name_t, std::string> EdgeProperty;
+      typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::no_property, EdgeProperty> Graph;
+
+      // Input 1: nodes (=filters)
+      vector<StdString>& nodes = CWorkflowGraph::filters;
+      const int nbNodes = nodes.size();
+
+      // Input 2: edges (=fields)
+      vector<StdString>& edges = CWorkflowGraph::fields;
+
+      // Input 3: nodes to edges connectivity
+      vector<pair<int, int> >& nodesToEdges = CWorkflowGraph::fieldsToFilters;
+      const int nbEdges = nodesToEdges.size();
+
+      // Declare a graph object, adding the edges and edge properties
+      Graph g(nbNodes);
+      for (int j = 0; j < nbEdges; ++j)
+      {
+        graph_traits<Graph>::edge_descriptor e;
+        bool inserted;
+        boost::tie(e, inserted) = boost::add_edge(nodesToEdges[j].first, nodesToEdges[j].second, edges[j], g);
+      }
+
+      std::for_each(vertices(g).first, vertices(g).second, exercise_vertex<Graph>(g));
+
+      std::map<std::string,std::string> graph_attr, vertex_attr, edge_attr;
+      graph_attr["size"] = "5,5";
+      graph_attr["rankdir"] = "LR";
+      graph_attr["ratio"] = "fill";
+      vertex_attr["shape"] = "record";
+      vertex_attr["width"] = "2.2";
+      vertex_attr["fontsize"] = "16";
+
+      const std::string filename = "graph.dot";
+      std::ofstream file (filename.c_str());
+
+      boost::write_graphviz(file, g,
+          boost::make_label_writer(&nodes[0]),
+          boost::make_label_writer(get(edge_name, g)),
+          boost::make_graph_attributes_writer(graph_attr, vertex_attr, edge_attr));
+         
+    }
+  }
+  CATCH
+
+
+
+
+  void CGraphviz::buildWorkflowGraphVisjs_with_info()
+  TRY
+  {
+    if (CWorkflowGraph::mapFilters_ptr_with_info !=0 && !CWorkflowGraph::mapFilters_ptr_with_info->empty())
+    {
+      CWorkflowGraph::buildStaticWorkflow_with_info();
+
+      StdString color_table[7] = {"black", "red", "blue", "green", "purple", "yellow", "gray"};
+    
+      std::ofstream fs_json;
+      fs_json.open ("graph_data.json", std::fstream::out);
+
+      fs_json << "{\"nodes\":["<<std::endl<<"      ";
+      static bool firstnode=true;
+      static bool firstedge=true;
+    
+      for (auto it=CWorkflowGraph::mapFilters_ptr_with_info->begin(); it != CWorkflowGraph::mapFilters_ptr_with_info->end(); it++)
+      {
+        if(firstnode) 
+        {
+          fs_json << "{\"id\": "<<it->first +1<<", "<<std::endl;
+          firstnode = false;
+        }
+        else
+        {
+          fs_json << ",{\"id\": "<<it->first +1<<", "<<std::endl;
+        }
+        if(it->second.filter_class == 1) // source filter
+          fs_json << "       \"label\": \""<<it->second.filter_name<<"\\n("<<it->second.field_id<<")\", "<<std::endl;
+        else
+          fs_json << "       \"label\": \""<<it->second.filter_name<<"\", "<<std::endl;
+        fs_json << "       \"class\": "<<it->second.filter_class<<", "<<std::endl;
+        fs_json << "       \"filled\": "<<it->second.filter_filled<<", "<<std::endl;
+        fs_json << "       \"type\": \""<<it->second.transform_type<<"\", "<<std::endl;
+        fs_json << "       \"entry\": "<<it->second.expected_entry_nb<<", "<<std::endl;
+        fs_json << "       \"inputs\": "<<it->second.inputs_complete<<", "<<std::endl;
+        fs_json << "       \"tag\": "<<it->second.filter_tag<<", "<<std::endl;
+        fs_json << "       \"cid\": "<<it->second.clusterID<<", "<<std::endl;
+        fs_json << "       \"distance\": "<<it->second.distance<<", "<<std::endl;
+        fs_json << "       \"attributes\": \""<<it->second.attributes<<"\"}"<<std::endl<<"      ";
+      }
+      fs_json << "    ],"<<std::endl;
+
+
+      fs_json << " \"edges\" : ["<<std::endl<<"      ";
+
+      for (auto it=CWorkflowGraph::mapFieldToFilters_ptr_with_info->begin(); it != CWorkflowGraph::mapFieldToFilters_ptr_with_info->end(); it++)
+      {
+        if(firstedge)
+        {
+          fs_json << "{\"id\": "<<it->first +1<<", "<<std::endl;
+          firstedge = false;
+        }
+        else
+        {
+          fs_json << ",{\"id\": "<<it->first +1<<", "<<std::endl;
+        }
+        fs_json << "       \"from\": "<<it->second.from+1<<", "<<std::endl;
+        fs_json << "       \"to\": "<<it->second.to+1<<", "<<std::endl;
+        fs_json << "       \"label\": \""<<it->second.field_id<<"\\n"<<it->second.date<<"\", "<<std::endl;
+        // fs_json << "       \"title\": \""<<"Show more information about this field"<<"\", "<<std::endl;
+        // fs_json << "       \"fid\": \""<<it->second.field_id<<"\", "<<std::endl;
+        // fs_json << "       \"fname\": \""<<it->second.field_name<<"\", "<<std::endl;
+        // fs_json << "       \"gid\": \""<<it->second.grid_id<<"\", "<<std::endl;
+        fs_json << "       \"date\": \""<<it->second.date<<"\", "<<std::endl;
+        fs_json << "       \"attributes\": \"id = "<<it->second.field_id<<"</br>"<<it->second.attributes<<"\"}"<<std::endl<<"      ";
+
+      }
+      fs_json << "    ]}"<<std::endl;
+
+      fs_json.close();
+    }
+  }
+  CATCH
+
+
+
+  void CGraphviz::showStaticWorkflowGraph()
+  TRY
+  {
+    CWorkflowGraph::showStaticWorkflow();
+  }
+  CATCH
+}
Index: /XIOS/trunk/src/graphviz.hpp
===================================================================
--- /XIOS/trunk/src/graphviz.hpp	(revision 1704)
+++ /XIOS/trunk/src/graphviz.hpp	(revision 1704)
@@ -0,0 +1,35 @@
+#ifndef __GRAPHVIZ_HPP__
+#define __GRAPHVIZ_HPP__
+
+#include <algorithm>
+#include <boost/utility.hpp>
+#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/graphviz.hpp>
+
+namespace xios
+{
+
+  class CGraphviz
+  {
+
+    public:
+
+      CGraphviz();
+      static void buildWorkflowGraphDot();
+      static void buildWorkflowGraphVisjs_with_info();
+      static void showStaticWorkflowGraph();
+
+    private:
+      template <class Graph> struct exercise_vertex;
+
+  }; // class CGraphviz
+
+  template <class Graph> struct CGraphviz::exercise_vertex {
+    exercise_vertex(Graph& g_) : g(g_) { }
+    typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
+    void operator()(const Vertex& v) const { } Graph& g;
+  };
+
+} // namespace xios
+
+#endif
Index: /XIOS/trunk/src/node/field.cpp
===================================================================
--- /XIOS/trunk/src/node/field.cpp	(revision 1703)
+++ /XIOS/trunk/src/node/field.cpp	(revision 1704)
@@ -24,4 +24,5 @@
 #include "spatial_transform_filter.hpp"
 #include "file_server_writer_filter.hpp"
+#include "workflow_graph.hpp"
 
 namespace xios{
@@ -45,5 +46,8 @@
       , mustAutoTrigger(false)
       , isEOF(false), nstepMaxRead(false)
-   { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); }
+   { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); 
+     field_graph_start = -2;
+     field_graph_end = -2;
+   }
 
    CField::CField(const StdString& id)
@@ -63,5 +67,9 @@
       , mustAutoTrigger(false)
       , isEOF(false), nstepMaxRead(false)
-   { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); }
+   { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); 
+     field_graph_start = -2;
+     field_graph_end = -2;
+   }
+
 
    CField::~CField(void)
@@ -1106,14 +1114,72 @@
     *                     read by the client or/and written to a file
     */
-   void CField::buildFilterGraph(CGarbageCollector& gc, bool enableOutput)
+   void CField::buildFilterGraph(CGarbageCollector& gc, bool enableOutput, Time start_graph, Time end_graph)
    TRY
    {     
-    if (!isReferenceSolvedAndTransformed) solveAllEnabledFieldsAndTransform();
-    if (!isGridChecked) checkGridOfEnabledFields();
+     if (!isReferenceSolvedAndTransformed) solveAllEnabledFieldsAndTransform();
+     if (!isGridChecked) checkGridOfEnabledFields();
 
      const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true);
+     
+     const bool buildWorkflowGraph = (!build_workflow_graph.isEmpty() && build_workflow_graph == true);
+
+     
      const double defaultValue  = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0);
 
      CContext* context = CContext::getCurrent();
+     
+     Time filter_start;
+     if(!build_workflow_graph_start.isEmpty() && buildWorkflowGraph) filter_start = context->calendar->getInitDate()+build_workflow_graph_start;
+     else if(build_workflow_graph_start.isEmpty() && buildWorkflowGraph) filter_start = 0;
+     else filter_start = -1;
+
+     Time filter_end;
+     if(!build_workflow_graph_end.isEmpty() && buildWorkflowGraph) filter_end = context->calendar->getInitDate()+build_workflow_graph_end;
+     else if(build_workflow_graph_end.isEmpty() && buildWorkflowGraph) filter_end = 9223372036854775807;
+     else filter_end = -1;
+
+     if(this->field_graph_start==-2) this->field_graph_start = filter_start;
+     if(this->field_graph_end==-2) this->field_graph_end = filter_end;         // init
+
+     // if(CXios::isClient) std::cout<<"****************** buildFilterGraph : field_id = "<<this->getId()<<" BEFORE: this->field_graph_start = "<<this->field_graph_start<<" this->field_graph_end = "<<this->field_graph_end<<std::endl;
+
+     if(start_graph == -1)
+     {
+       //nothing
+       // if(CXios::isClient) std::cout<<"buildFilterGraph field_id = "<<this->getId()<<" case1: this->field_graph_start = "<<this->field_graph_start<<std::endl;
+     }
+     else //if(start_graph != -1)
+     {
+       if(this->field_graph_start == -1) this->field_graph_start = start_graph;
+       else this->field_graph_start = min(this->field_graph_start, start_graph);
+
+       // if(CXios::isClient) std::cout<<"buildFilterGraph field_id = "<<this->getId()<<" case2: this->field_graph_start = "<<this->field_graph_start<<std::endl;
+     }
+
+
+     if(end_graph == -1)
+     {
+       //nothing
+       // if(CXios::isClient) std::cout<<"buildFilterGraph field_id = "<<this->getId()<<" case1: this->field_graph_end = "<<this->field_graph_end<<std::endl;
+     }
+     else
+     {
+       if(this->field_graph_end == -1) this->field_graph_end = end_graph;
+       else this->field_graph_end = max(this->field_graph_end, end_graph);
+
+       // if(CXios::isClient) std::cout<<"buildFilterGraph field_id = "<<this->getId()<<" case2: this->field_graph_end = "<<this->field_graph_end<<std::endl;
+     }
+    
+
+     filter_start = this->field_graph_start;
+     filter_end = this->field_graph_end;
+
+
+     // if(CXios::isClient) std::cout<<"****************** buildFilterGraph : field_id = "<<this->getId()<<" AFTER: this->field_graph_start = "<<this->field_graph_start<<" this->field_graph_end = "<<this->field_graph_end<<std::endl;
+     
+
+     
+     
+
      bool hasWriterServer = context->hasServer && !context->hasClient;
      bool hasIntermediateServer = context->hasServer && context->hasClient;
@@ -1159,5 +1225,5 @@
          {
            boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0'));
-           std::shared_ptr<COutputPin> filter = expr->reduce(gc, *this);
+           std::shared_ptr<COutputPin> filter = expr->reduce(gc, *this, filter_start, filter_end);
 
            // Check if a spatial transformation is needed
@@ -1168,5 +1234,5 @@
              if (grid && grid != gridRef && grid->hasTransform())
              {
-                 std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridRef, grid, detectMissingValues, defaultValue); 
+               std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridRef, grid, detectMissingValues, defaultValue);
 
                filter->connectOutput(filters.first, 0);
@@ -1176,8 +1242,23 @@
 
            instantDataFilter = filter;
+           instantDataFilter->field = this;
+           filter->tag = buildWorkflowGraph;
+           
+           filter->start_graph = filter_start;
+           filter->end_graph = filter_end;
+
+           for(int i=0; i<filter->parent_filters.size(); i++)
+           {
+             filter->tag = filter->tag || filter->parent_filters[i]->tag;
+           }
          }
          // Check if we have a reference on another field
          else if (!field_ref.isEmpty())
-           instantDataFilter = getFieldReference(gc);
+         {
+           instantDataFilter = getFieldReference(gc, filter_start, filter_end);
+           instantDataFilter->tag = buildWorkflowGraph;
+           instantDataFilter->start_graph = filter_start;
+           instantDataFilter->end_graph = filter_end;
+         }
          // Check if the data is to be read from a file
          else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read)
@@ -1186,4 +1267,9 @@
            instantDataFilter = serverSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, false, freq_offset, true,
                                                                                                        detectMissingValues, defaultValue));
+           instantDataFilter->tag = buildWorkflowGraph;
+           instantDataFilter->start_graph = filter_start;
+           instantDataFilter->end_graph = filter_end;
+           instantDataFilter->field = this;
+
          }
          else // The data might be passed from the model
@@ -1191,5 +1277,10 @@
             if (check_if_active.isEmpty()) check_if_active = false; 
             instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, false, true, NoneDu, false,
-                                                                                                        detectMissingValues, defaultValue));
+                                                                                                      detectMissingValues, defaultValue)); 
+            instantDataFilter->tag = buildWorkflowGraph;
+            instantDataFilter->start_graph = filter_start;
+            instantDataFilter->end_graph = filter_end;
+            instantDataFilter->field = this;
+            // if(CXios::isClient) std::cout<<"***********************buildFilterGraph init source filter : field_id = "<<this->getId()<<" sourcefilter->start_graph = "<<clientSourceFilter->start_graph<<" sourcefilter->end_graph = "<<clientSourceFilter->end_graph<<std::endl;
          }
        }
@@ -1203,4 +1294,14 @@
                                                                           detectMissingValues, defaultValue));
            instantDataFilter->connectOutput(storeFilter, 0);
+
+           storeFilter->tag = (instantDataFilter->tag || buildWorkflowGraph);
+           instantDataFilter->start_graph = filter_start;
+           instantDataFilter->end_graph = filter_end;
+
+           instantDataFilter->setParentFiltersTag();
+           storeFilter->start_graph = filter_start;
+           storeFilter->end_graph = filter_end;
+           storeFilter->field = this;
+           storeFilter->distance = instantDataFilter->distance+1;
          }
 
@@ -1209,4 +1310,16 @@
            fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this));
            getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0);
+           
+           fileWriterFilter->tag = (getTemporalDataFilter(gc, file->output_freq)->tag || buildWorkflowGraph);
+           getTemporalDataFilter(gc, file->output_freq)->start_graph = filter_start;
+           getTemporalDataFilter(gc, file->output_freq)->end_graph = filter_end;
+           getTemporalDataFilter(gc, file->output_freq)->tag = buildWorkflowGraph;
+           getTemporalDataFilter(gc, file->output_freq)->setParentFiltersTag();
+           fileWriterFilter->start_graph = filter_start;
+           fileWriterFilter->end_graph = filter_end;
+           fileWriterFilter->distance = getTemporalDataFilter(gc, file->output_freq)->distance+1;
+
+           // std::cout<<"CFileWriterFilter filter start = "<<filter_start<<" end = "<<filter_end<<" field = "<<this->getId()<<std::endl;
+
          }
        }
@@ -1222,5 +1335,5 @@
     * \return the output pin corresponding to the field reference
     */
-   std::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc)
+   std::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc, Time start_graph, Time end_graph)
    TRY
    {
@@ -1230,5 +1343,55 @@
 
      CField* fieldRef = CField::get(field_ref);
-     fieldRef->buildFilterGraph(gc, false);
+     fieldRef->buildFilterGraph(gc, false, start_graph, end_graph);
+     const bool buildWorkflowGraph = (!build_workflow_graph.isEmpty() && build_workflow_graph == true);
+
+     CContext* context = CContext::getCurrent();
+
+     Time filter_start;
+     if(!build_workflow_graph_start.isEmpty() && buildWorkflowGraph) filter_start = context->calendar->getInitDate()+build_workflow_graph_start;
+     else if(build_workflow_graph_start.isEmpty() && buildWorkflowGraph) filter_start = 0;
+     else filter_start = -1;
+
+     Time filter_end;
+     if(!build_workflow_graph_end.isEmpty() && buildWorkflowGraph) filter_end = context->calendar->getInitDate()+build_workflow_graph_end;
+     else if(build_workflow_graph_end.isEmpty() && buildWorkflowGraph) filter_end = 9223372036854775807;
+     else filter_end = -1;
+
+     if(this->field_graph_start==-2) this->field_graph_start = filter_start;
+     if(this->field_graph_end==-2) this->field_graph_end = filter_end;         // init
+
+     // if(CXios::isClient) std::cout<<"getFieldReference field_id = "<<this->getId()<<" BEFORE: this->field_graph_start = "<<this->field_graph_start<<" this->field_graph_end = "<<this->field_graph_end<<std::endl;
+
+     if(start_graph == -1)
+     {
+       //nothing
+       // if(CXios::isClient) std::cout<<"getFieldReference field_id = "<<this->getId()<<" case1: this->field_graph_start = "<<this->field_graph_start<<std::endl;
+     }
+     else //if(start_graph != -1)
+     {
+       if(this->field_graph_start == -1) this->field_graph_start = start_graph;
+       else this->field_graph_start = min(this->field_graph_start, start_graph);
+
+       // if(CXios::isClient) std::cout<<"getFieldReference field_id = "<<this->getId()<<" case2: this->field_graph_start = "<<this->field_graph_start<<std::endl;
+     }
+
+     if(end_graph == -1)
+     {
+       //nothing
+       // if(CXios::isClient) std::cout<<"getFieldReference field_id = "<<this->getId()<<" case1: this->field_graph_end = "<<this->field_graph_end<<std::endl;
+     }
+     else
+     {
+       if(this->field_graph_end == -1) this->field_graph_end = end_graph;
+       else this->field_graph_end = max(this->field_graph_end, end_graph);
+
+       // if(CXios::isClient) std::cout<<"getFieldReference field_id = "<<this->getId()<<" case2: this->field_graph_end = "<<this->field_graph_end<<std::endl;
+     }
+
+     filter_start = this->field_graph_start;
+     filter_end = this->field_graph_end;
+
+     // if(CXios::isClient) std::cout<<"getFieldReference field_id = "<<this->getId()<<" AFTER: this->field_graph_start = "<<this->field_graph_start<<" this->field_graph_end = "<<this->field_graph_end<<std::endl;
+
 
      std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters;
@@ -1239,9 +1402,36 @@
        double defaultValue  = hasMissingValue ? default_value : (!default_value.isEmpty() ? default_value : 0.0);                                
        filters = CSpatialTransformFilter::buildFilterGraph(gc, fieldRef->grid, grid, hasMissingValue, defaultValue);
+
+       fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0);
+
+     
+
+       filters.second->parent_filters.resize(1);
+       filters.second->parent_filters[0]= fieldRef->getInstantDataFilter();
+
+       filters.second->tag = (buildWorkflowGraph || filters.second->parent_filters[0]->tag);
+       
+       filters.second->start_graph = filter_start;
+       filters.second->end_graph = filter_end;
+       filters.second->field = this;
+       
      }
      else
+     {
        filters.first = filters.second = std::shared_ptr<CFilter>(new CPassThroughFilter(gc));
 
-     fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0);
+       fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0);
+     
+
+       filters.second->parent_filters.resize(1);
+       filters.second->parent_filters[0]= fieldRef->getInstantDataFilter();
+
+       filters.second->tag = (buildWorkflowGraph || filters.second->parent_filters[0]->tag);
+
+       filters.second->start_graph = filter_start;
+       filters.second->end_graph = filter_end;
+       filters.second->field = this;
+
+     }
 
      return filters.second;
@@ -1258,10 +1448,14 @@
     * \return the output pin corresponding to a self reference
     */
-   std::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc)
-   TRY
-   {
+   std::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc, Time start_graph, Time end_graph)
+   TRY
+   {
+     if(CXios::isClient) std::cout<<"getSelfReference field_id = "<<this->getId()<<" start_graph = "<<start_graph<<" end_graph = "<<end_graph<<std::endl;
+
      if (instantDataFilter || !hasExpression())
        ERROR("COutputPin* CField::getSelfReference(CGarbageCollector& gc)",
              "Impossible to add a self reference to a field which has already been parsed or which does not have an expression.");
+     
+     bool buildWorkflowGraph = (!build_workflow_graph.isEmpty() && build_workflow_graph == true);
 
      if (!selfReferenceFilter)
@@ -1300,4 +1494,6 @@
      }
 
+     selfReferenceFilter->tag = buildWorkflowGraph;
+     selfReferenceFilter->field = this;
      return selfReferenceFilter;
    }
@@ -1317,4 +1513,8 @@
    {
      std::map<CDuration, std::shared_ptr<COutputPin> >::iterator it = temporalDataFilters.find(outFreq);
+     const bool buildWorkflowGraph = (!build_workflow_graph.isEmpty() && build_workflow_graph == true);
+
+     CContext* context = CContext::getCurrent();
+
 
      if (it == temporalDataFilters.end())
@@ -1332,4 +1532,15 @@
 
        instantDataFilter->connectOutput(temporalFilter, 0);
+       // temporalFilter->tag = buildWorkflowGraph;
+       
+       temporalFilter->parent_filters.resize(1);
+       temporalFilter->parent_filters[0] = instantDataFilter;
+       
+
+       if(temporalFilter->parent_filters[0]->tag) temporalFilter->tag=true;
+
+       // temporalFilter->start_graph = filter_start;
+       // temporalFilter->end_graph = filter_end;
+       temporalFilter->field = this;
 
        it = temporalDataFilters.insert(std::make_pair(outFreq, temporalFilter)).first;
@@ -1367,9 +1578,13 @@
 
        const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true);
+       bool buildWorkflowGraph = (!build_workflow_graph.isEmpty() && build_workflow_graph == true);
        std::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation,
-                                                                             CContext::getCurrent()->getCalendar()->getInitDate(),
-                                                                             freq_op, freq_offset, outFreq, detectMissingValues));
+                                                                           CContext::getCurrent()->getCalendar()->getInitDate(),
+                                                                           freq_op, freq_offset, outFreq, detectMissingValues));
 
        selfReferenceFilter->connectOutput(temporalFilter, 0);
+       temporalFilter->tag = buildWorkflowGraph;
+       temporalFilter->field = this;
+
        return temporalFilter ;
      }
Index: /XIOS/trunk/src/node/field.hpp
===================================================================
--- /XIOS/trunk/src/node/field.hpp	(revision 1703)
+++ /XIOS/trunk/src/node/field.hpp	(revision 1704)
@@ -7,4 +7,5 @@
 #include "functor.hpp"
 #include "functor_type.hpp"
+#include "filter.hpp"
 #include "duration.hpp"
 #include "date.hpp"
@@ -139,10 +140,10 @@
          void checkTimeAttributes(CDuration* freqOp=NULL);
 
-         void buildFilterGraph(CGarbageCollector& gc, bool enableOutput);
+         void buildFilterGraph(CGarbageCollector& gc, bool enableOutput, Time start_graph=-1, Time end_graph=-1);
          size_t getGlobalWrittenSize(void) ;
          
          
-         std::shared_ptr<COutputPin> getFieldReference(CGarbageCollector& gc);
-         std::shared_ptr<COutputPin> getSelfReference(CGarbageCollector& gc);
+         std::shared_ptr<COutputPin> getFieldReference(CGarbageCollector& gc, Time start_graph=-1, Time end_graph=-1);
+         std::shared_ptr<COutputPin> getSelfReference(CGarbageCollector& gc, Time start_graph=-1, Time end_graph=-1);
          std::shared_ptr<COutputPin> getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq);
          std::shared_ptr<COutputPin> getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq);
@@ -243,4 +244,7 @@
          bool hasTimeCentered;
 
+         Time field_graph_start;
+         Time field_graph_end;
+
 
          DECLARE_REF_FUNC(Field,field)
Index: /XIOS/trunk/src/parse_expr/filter_expr_node.cpp
===================================================================
--- /XIOS/trunk/src/parse_expr/filter_expr_node.cpp	(revision 1703)
+++ /XIOS/trunk/src/parse_expr/filter_expr_node.cpp	(revision 1704)
@@ -12,5 +12,5 @@
 
   
-  std::shared_ptr<COutputPin> CFilterFieldExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
+  std::shared_ptr<COutputPin> CFilterFieldExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
   {
     std::shared_ptr<COutputPin> outputPin;
@@ -40,5 +40,6 @@
                 << "Use the keyword \"this\" if you want to reference the input data sent to this field.");
 
-        field->buildFilterGraph(gc, false);
+        // field->buildFilterGraph(gc, false);
+        field->buildFilterGraph(gc, false, start_graph, end_graph);
         outputPin = field->getInstantDataFilter();
       }
@@ -55,5 +56,5 @@
 
 
-  std::shared_ptr<COutputPin> CFilterTemporalFieldExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
+  std::shared_ptr<COutputPin> CFilterTemporalFieldExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
   {
     std::shared_ptr<COutputPin> outputPin;
@@ -104,8 +105,20 @@
   }
 
-  std::shared_ptr<COutputPin> CFilterUnaryOpExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
-  {
+  std::shared_ptr<COutputPin> CFilterUnaryOpExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
+  {
+    std::shared_ptr<COutputPin> ch = child->reduce(gc, thisField, start_graph, end_graph);
+
     std::shared_ptr<CUnaryArithmeticFilter> filter(new CUnaryArithmeticFilter(gc, opId));
-    child->reduce(gc, thisField)->connectOutput(filter, 0);
+    ch->connectOutput(filter, 0);
+
+    (filter->parent_filters).resize(1);
+    (filter->parent_filters)[0] = ch;
+
+    filter->tag = ch->tag;
+    filter->start_graph = ch->start_graph;
+    filter->end_graph = ch->end_graph;
+    filter->field = &thisField;
+
+
     return filter;
   }
@@ -121,8 +134,18 @@
   }
 
-  std::shared_ptr<COutputPin> CFilterScalarFieldOpExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
-  {
+  std::shared_ptr<COutputPin> CFilterScalarFieldOpExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
+  {
+    std::shared_ptr<COutputPin> ch2 = child2->reduce(gc, thisField, start_graph, end_graph);
     std::shared_ptr<CScalarFieldArithmeticFilter> filter(new CScalarFieldArithmeticFilter(gc, opId, child1->reduce()));
-    child2->reduce(gc, thisField)->connectOutput(filter, 0);
+    ch2->connectOutput(filter, 0);
+    
+    (filter->parent_filters).resize(1);
+    (filter->parent_filters)[0] = ch2;
+
+    filter->tag = ch2->tag;
+    filter->start_graph = ch2->start_graph;
+    filter->end_graph = ch2->end_graph;
+    filter->field = &thisField;
+
     return filter;
   }
@@ -138,8 +161,19 @@
   }
 
-  std::shared_ptr<COutputPin> CFilterFieldScalarOpExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
-  {
+  std::shared_ptr<COutputPin> CFilterFieldScalarOpExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
+  {
+    std::shared_ptr<COutputPin> ch1 = child1->reduce(gc, thisField, start_graph, end_graph);
+
     std::shared_ptr<CFieldScalarArithmeticFilter> filter(new CFieldScalarArithmeticFilter(gc, opId, child2->reduce()));
-    child1->reduce(gc, thisField)->connectOutput(filter, 0);
+    ch1->connectOutput(filter, 0);
+
+    (filter->parent_filters).resize(1);
+    (filter->parent_filters)[0] = ch1;
+
+    filter->tag = ch1->tag;
+    filter->start_graph = ch1->start_graph;
+    filter->end_graph = ch1->end_graph;
+    filter->field = &thisField;
+
     return filter;
   }
@@ -155,9 +189,24 @@
   }
 
-  std::shared_ptr<COutputPin> CFilterFieldFieldOpExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
-  {
+  std::shared_ptr<COutputPin> CFilterFieldFieldOpExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
+  {
+    std::shared_ptr<COutputPin> ch1 = child1->reduce(gc, thisField, start_graph, end_graph);
+    std::shared_ptr<COutputPin> ch2 = child2->reduce(gc, thisField, start_graph, end_graph);
+
     std::shared_ptr<CFieldFieldArithmeticFilter> filter(new CFieldFieldArithmeticFilter(gc, opId));
-    child1->reduce(gc, thisField)->connectOutput(filter, 0);
-    child2->reduce(gc, thisField)->connectOutput(filter, 1);
+    ch1->connectOutput(filter, 0);
+    ch2->connectOutput(filter, 1); 
+
+    (filter->parent_filters).resize(2);
+    (filter->parent_filters)[0] = ch1;
+    (filter->parent_filters)[1] = ch2;
+
+    filter->tag = (ch1->tag || ch2->tag);
+    filter->start_graph = ch1->tag? ch1->start_graph : (ch2->tag? ch2->start_graph: -1);
+    filter->end_graph = ch1->tag? ch1->end_graph : (ch2->tag? ch2->end_graph: -1);
+
+    filter->field = &thisField;
+
+
     return filter;
   }
@@ -177,8 +226,19 @@
   }
 
-  std::shared_ptr<COutputPin> CFilterScalarScalarFieldOpExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
-  {
+  std::shared_ptr<COutputPin> CFilterScalarScalarFieldOpExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
+  {
+    std::shared_ptr<COutputPin> ch3 = child3->reduce(gc, thisField, start_graph, end_graph);
+
     std::shared_ptr<CScalarScalarFieldArithmeticFilter> filter(new CScalarScalarFieldArithmeticFilter(gc, opId, child1->reduce(),child2->reduce()));
-    child3->reduce(gc, thisField)->connectOutput(filter, 0);
+    ch3->connectOutput(filter, 0);
+    
+    (filter->parent_filters).resize(1);
+    (filter->parent_filters)[0] = ch3;
+
+    filter->tag = ch3->tag;
+    filter->start_graph = ch3->start_graph;
+    filter->end_graph = ch3->end_graph;
+    filter->field = &thisField;
+
     return filter;
   }
@@ -196,8 +256,19 @@
   }
 
-  std::shared_ptr<COutputPin> CFilterScalarFieldScalarOpExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
-  {
+  std::shared_ptr<COutputPin> CFilterScalarFieldScalarOpExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
+  {
+    std::shared_ptr<COutputPin> ch2 = child2->reduce(gc, thisField, start_graph, end_graph);
+
     std::shared_ptr<CScalarFieldScalarArithmeticFilter> filter(new CScalarFieldScalarArithmeticFilter(gc, opId, child1->reduce(),child3->reduce()));
-    child2->reduce(gc, thisField)->connectOutput(filter, 0);
+    ch2->connectOutput(filter, 0);
+
+    (filter->parent_filters).resize(1);
+    (filter->parent_filters)[0] = ch2;
+
+    filter->tag = ch2->tag;
+    filter->start_graph = ch2->start_graph;
+    filter->end_graph = ch2->end_graph;
+    filter->field = &thisField;
+
     return filter;
   }
@@ -215,9 +286,22 @@
   }
 
-  std::shared_ptr<COutputPin> CFilterScalarFieldFieldOpExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
-  {
+  std::shared_ptr<COutputPin> CFilterScalarFieldFieldOpExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
+  {
+    std::shared_ptr<COutputPin> ch2 = child2->reduce(gc, thisField, start_graph, end_graph);
+    std::shared_ptr<COutputPin> ch3 = child3->reduce(gc, thisField, start_graph, end_graph);
+
     std::shared_ptr<CScalarFieldFieldArithmeticFilter> filter(new CScalarFieldFieldArithmeticFilter(gc, opId, child1->reduce()));
-    child2->reduce(gc, thisField)->connectOutput(filter, 0);
-    child3->reduce(gc, thisField)->connectOutput(filter, 1);
+    ch2->connectOutput(filter, 0);
+    ch3->connectOutput(filter, 1);
+
+    (filter->parent_filters).resize(2);
+    (filter->parent_filters)[0] = ch2;
+    (filter->parent_filters)[1] = ch3;
+
+    filter->tag = (ch3->tag || ch2->tag);
+    filter->start_graph = ch3->tag? ch3->start_graph : (ch2->tag? ch2->start_graph: -1);
+    filter->end_graph = ch3->tag? ch3->end_graph : (ch2->tag? ch2->end_graph: -1);
+    filter->field = &thisField;
+
     return filter;
   }
@@ -236,8 +320,19 @@
   }
 
-  std::shared_ptr<COutputPin> CFilterFieldScalarScalarOpExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
-  {
+  std::shared_ptr<COutputPin> CFilterFieldScalarScalarOpExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
+  {
+    std::shared_ptr<COutputPin> ch1 = child1->reduce(gc, thisField, start_graph, end_graph);
+
     std::shared_ptr<CFieldScalarScalarArithmeticFilter> filter(new CFieldScalarScalarArithmeticFilter(gc, opId, child2->reduce(),child3->reduce()));
-    child1->reduce(gc, thisField)->connectOutput(filter, 0);
+    ch1->connectOutput(filter, 0);
+
+    (filter->parent_filters).resize(1);
+    (filter->parent_filters)[0] = ch1;
+
+    filter->tag = ch1->tag;
+    filter->start_graph = ch1->start_graph;
+    filter->end_graph = ch1->end_graph;
+    filter->field = &thisField;
+
     return filter;
   }
@@ -256,9 +351,22 @@
   }
 
-  std::shared_ptr<COutputPin> CFilterFieldScalarFieldOpExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
-  {
+  std::shared_ptr<COutputPin> CFilterFieldScalarFieldOpExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
+  {
+    std::shared_ptr<COutputPin> ch1 = child1->reduce(gc, thisField, start_graph, end_graph);
+    std::shared_ptr<COutputPin> ch3 = child3->reduce(gc, thisField, start_graph, end_graph);
+
     std::shared_ptr<CFieldScalarFieldArithmeticFilter> filter(new CFieldScalarFieldArithmeticFilter(gc, opId, child2->reduce()));
-    child1->reduce(gc, thisField)->connectOutput(filter, 0);
-    child3->reduce(gc, thisField)->connectOutput(filter, 1);
+    ch1->connectOutput(filter, 0);
+    ch3->connectOutput(filter, 1);
+
+    (filter->parent_filters).resize(2);
+    (filter->parent_filters)[0] = ch1;
+    (filter->parent_filters)[1] = ch3;
+
+    filter->tag = (ch3->tag || ch1->tag);
+    filter->start_graph = ch3->tag? ch3->start_graph : (ch1->tag? ch1->start_graph: -1);
+    filter->end_graph = ch3->tag? ch3->end_graph : (ch1->tag? ch1->end_graph: -1);
+    filter->field = &thisField;
+
     return filter;
   }
@@ -277,9 +385,21 @@
   }
 
-  std::shared_ptr<COutputPin> CFilterFieldFieldScalarOpExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
-  {
+  std::shared_ptr<COutputPin> CFilterFieldFieldScalarOpExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
+  {
+    std::shared_ptr<COutputPin> ch1 = child1->reduce(gc, thisField, start_graph, end_graph);
+    std::shared_ptr<COutputPin> ch2 = child2->reduce(gc, thisField, start_graph, end_graph);
+
     std::shared_ptr<CFieldFieldScalarArithmeticFilter> filter(new CFieldFieldScalarArithmeticFilter(gc, opId, child3->reduce()));
-    child1->reduce(gc, thisField)->connectOutput(filter, 0);
-    child2->reduce(gc, thisField)->connectOutput(filter, 1);
+    ch1->connectOutput(filter, 0);
+    ch2->connectOutput(filter, 1);
+
+    (filter->parent_filters).resize(2);
+    (filter->parent_filters)[0] = ch1;
+    (filter->parent_filters)[1] = ch2;
+
+    filter->tag = (ch2->tag || ch1->tag);
+    filter->start_graph = ch2->tag? ch2->start_graph : (ch1->tag? ch1->start_graph: -1);
+    filter->end_graph = ch2->tag? ch2->end_graph : (ch1->tag? ch1->end_graph: -1);
+    filter->field = &thisField;
     return filter;
   }
@@ -297,10 +417,28 @@
   }
 
-  std::shared_ptr<COutputPin> CFilterFieldFieldFieldOpExprNode::reduce(CGarbageCollector& gc, CField& thisField) const
-  {
+  std::shared_ptr<COutputPin> CFilterFieldFieldFieldOpExprNode::reduce(CGarbageCollector& gc, CField& thisField, Time start_graph, Time end_graph) const
+  {
+    std::shared_ptr<COutputPin> ch1 = child1->reduce(gc, thisField, start_graph, end_graph);
+    std::shared_ptr<COutputPin> ch2 = child2->reduce(gc, thisField, start_graph, end_graph);
+    std::shared_ptr<COutputPin> ch3 = child3->reduce(gc, thisField, start_graph, end_graph);
+
     std::shared_ptr<CFieldFieldFieldArithmeticFilter> filter(new CFieldFieldFieldArithmeticFilter(gc, opId));
-    child1->reduce(gc, thisField)->connectOutput(filter, 0);
-    child2->reduce(gc, thisField)->connectOutput(filter, 1);
-    child3->reduce(gc, thisField)->connectOutput(filter, 2);
+    std::cout<<"std::shared_ptr<CFieldFieldFieldArithmeticFilter> filter(new CFieldFieldFieldArithmeticFilter(gc, opId))" <<std::endl;
+    ch1->connectOutput(filter, 0);
+    ch2->connectOutput(filter, 1);
+    ch3->connectOutput(filter, 2);
+
+    (filter->parent_filters).resize(3);
+    (filter->parent_filters)[0] = ch1;
+    (filter->parent_filters)[1] = ch2;
+    (filter->parent_filters)[2] = ch3;
+
+
+    filter->tag = (ch1->tag || ch1->tag || ch3->tag);
+    filter->start_graph = ch1->tag? ch1->start_graph : (ch2->tag? ch2->start_graph: (ch3->tag? ch3->start_graph: -1));
+    filter->end_graph = ch1->tag? ch1->end_graph : (ch2->tag? ch2->end_graph: (ch3->tag? ch3->end_graph: -1));
+    filter->field = &thisField;
+
+
     return filter;
   }
Index: /XIOS/trunk/src/parse_expr/filter_expr_node.hpp
===================================================================
--- /XIOS/trunk/src/parse_expr/filter_expr_node.hpp	(revision 1703)
+++ /XIOS/trunk/src/parse_expr/filter_expr_node.hpp	(revision 1704)
@@ -5,4 +5,6 @@
 #include <boost/smart_ptr/scoped_ptr.hpp>
 #include "scalar_expr_node.hpp"
+
+#include "duration.hpp"
 
 namespace xios
@@ -25,5 +27,5 @@
      * \return the output pin of the filter producing the result of the expression 
      */
-    virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const = 0;
+    virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const = 0;
   };
 
@@ -42,5 +44,5 @@
       CFilterFieldExprNode(const std::string& fieldId);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
@@ -63,5 +65,5 @@
       CFilterTemporalFieldExprNode(const std::string& fieldId);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
@@ -86,5 +88,5 @@
       CFilterUnaryOpExprNode(const std::string& opId, IFilterExprNode* child);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
@@ -111,5 +113,5 @@
       CFilterScalarFieldOpExprNode(IScalarExprNode* child1, const std::string& opId, IFilterExprNode* child2);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
@@ -137,5 +139,5 @@
       CFilterFieldScalarOpExprNode(IFilterExprNode* child1, const std::string& opId, IScalarExprNode* child2);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
@@ -162,5 +164,5 @@
       CFilterFieldFieldOpExprNode(IFilterExprNode* child1, const std::string& opId, IFilterExprNode* child2);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
@@ -190,5 +192,5 @@
       CFilterScalarScalarFieldOpExprNode(IScalarExprNode* child1, const std::string& opId, IScalarExprNode* child2, IFilterExprNode* child3);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
@@ -219,5 +221,5 @@
       CFilterScalarFieldScalarOpExprNode(IScalarExprNode* child1, const std::string& opId, IFilterExprNode* child2, IScalarExprNode* child3);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
@@ -248,5 +250,5 @@
       CFilterScalarFieldFieldOpExprNode(IScalarExprNode* child1, const std::string& opId, IFilterExprNode* child2, IFilterExprNode* child3);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
@@ -278,5 +280,5 @@
       CFilterFieldScalarScalarOpExprNode(IFilterExprNode* child1, const std::string& opId, IScalarExprNode* child2, IScalarExprNode* child3);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
@@ -307,5 +309,5 @@
       CFilterFieldScalarFieldOpExprNode(IFilterExprNode* child1, const std::string& opId, IScalarExprNode* child2, IFilterExprNode* child3);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
@@ -335,5 +337,5 @@
       CFilterFieldFieldScalarOpExprNode(IFilterExprNode* child1, const std::string& opId, IFilterExprNode* child2, IScalarExprNode* child3);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
@@ -364,5 +366,5 @@
       CFilterFieldFieldFieldOpExprNode(IFilterExprNode* child1, const std::string& opId, IFilterExprNode* child2, IFilterExprNode* child3);
 
-      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField) const;
+      virtual std::shared_ptr<COutputPin> reduce(CGarbageCollector& gc, CField& thisField, Time start_graph=-1, Time end_graph=-1) const;
 
     private:
Index: /XIOS/trunk/src/parse_expr/yacc_parser.cpp
===================================================================
--- /XIOS/trunk/src/parse_expr/yacc_parser.cpp	(revision 1703)
+++ /XIOS/trunk/src/parse_expr/yacc_parser.cpp	(revision 1704)
@@ -70,4 +70,6 @@
 #include "exception.hpp"
 
+#include "yacc_var.hpp"
+
 using namespace std;
 using namespace xios;
@@ -84,6 +86,13 @@
   size_t globalReadOffset = 0;
 
+  std::string *xios::yacc_globalInputText_ptr = 0;
+
   int readInputForLexer(char* buffer, size_t* numBytesRead, size_t maxBytesToRead)
   {
+    yacc_globalInputText_ptr = &globalInputText;
+    //*yacc_globalInputText_ptr = globalInputText;
+
+    std::cout<<"========= yacc_globalInputText_ptr = "<<*yacc_globalInputText_ptr<<std::endl;
+    
     size_t numBytesToRead = maxBytesToRead;
     size_t bytesRemaining = globalInputText.length()-globalReadOffset;
Index: /XIOS/trunk/src/parse_expr/yacc_var.hpp
===================================================================
--- /XIOS/trunk/src/parse_expr/yacc_var.hpp	(revision 1704)
+++ /XIOS/trunk/src/parse_expr/yacc_var.hpp	(revision 1704)
@@ -0,0 +1,10 @@
+#ifndef __YACC_VAR_HPP__
+#define __YACC_VAR_HPP__
+
+#include <string>
+namespace xios
+{
+  extern std::string *yacc_globalInputText_ptr;
+}
+
+#endif
Index: /XIOS/trunk/src/test/test_client.f90
===================================================================
--- /XIOS/trunk/src/test/test_client.f90	(revision 1703)
+++ /XIOS/trunk/src/test/test_client.f90	(revision 1704)
@@ -132,11 +132,13 @@
   PRINT*,"field field_A is active ? ",xios_field_is_active("field_A")
   ! CALL xios_recv_field("field", scalar)
-  DO ts=1,4
+  DO ts=1,24
     CALL xios_update_calendar(ts)
     CALL xios_send_field("field_A",field_A)
-    CALL xios_send_field("field_Axis",axisValue)
+    CALL xios_send_field("field_B",field_A)
+    CALL xios_send_field("field_C",field_A)
+    ! CALL xios_send_field("field_Axis",axisValue)
     ! CALL xios_send_field("field_Axis",lval)
-    CALL xios_send_field("field_Domain",field_domain)
-    CALL xios_send_field("field_Scalar",scalar)
+    ! CALL xios_send_field("field_Domain",field_domain)
+    ! CALL xios_send_field("field_Scalar",scalar)
     CALL wait_us(5000) ;
   ENDDO
Index: /XIOS/trunk/src/transformation/Functions/average_reduction.hpp
===================================================================
--- /XIOS/trunk/src/transformation/Functions/average_reduction.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/Functions/average_reduction.hpp	(revision 1704)
@@ -33,4 +33,6 @@
   virtual ~CAverageReductionAlgorithm() {}
 
+  virtual StdString getName() {return "Average reduction";}
+
 protected:
   CArray<double,1> weights_;
Index: /XIOS/trunk/src/transformation/Functions/extract.hpp
===================================================================
--- /XIOS/trunk/src/transformation/Functions/extract.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/Functions/extract.hpp	(revision 1704)
@@ -31,4 +31,6 @@
   virtual ~CExtractReductionAlgorithm() {}
 
+  virtual StdString getName() {return "Extract reduction";}
+
 public:
   static bool registerTrans();
Index: /XIOS/trunk/src/transformation/Functions/max_reduction.hpp
===================================================================
--- /XIOS/trunk/src/transformation/Functions/max_reduction.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/Functions/max_reduction.hpp	(revision 1704)
@@ -31,4 +31,6 @@
   virtual ~CMaxReductionAlgorithm() {}
 
+  virtual StdString getName() {return "Max reduction";}
+
 public:
   static bool registerTrans();
Index: /XIOS/trunk/src/transformation/Functions/min_reduction.hpp
===================================================================
--- /XIOS/trunk/src/transformation/Functions/min_reduction.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/Functions/min_reduction.hpp	(revision 1704)
@@ -31,4 +31,6 @@
   virtual ~CMinReductionAlgorithm() {}
 
+  virtual StdString getName() {return "Min reduction";}
+
 public:
   static bool registerTrans();
Index: /XIOS/trunk/src/transformation/Functions/reduction.hpp
===================================================================
--- /XIOS/trunk/src/transformation/Functions/reduction.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/Functions/reduction.hpp	(revision 1704)
@@ -57,4 +57,6 @@
   virtual ~CReductionAlgorithm() {}
 
+  virtual StdString getName() {return "Reduction";}
+
 protected:
   typedef CReductionAlgorithm* (*CreateOperationCallBack)();
Index: /XIOS/trunk/src/transformation/Functions/sum_reduction.hpp
===================================================================
--- /XIOS/trunk/src/transformation/Functions/sum_reduction.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/Functions/sum_reduction.hpp	(revision 1704)
@@ -31,4 +31,6 @@
   virtual ~CSumReductionAlgorithm() {}
 
+  virtual StdString getName() {return "Sum reduction";}
+
 public:
   static bool registerTrans();
Index: /XIOS/trunk/src/transformation/axis_algorithm_duplicate_scalar.hpp
===================================================================
--- /XIOS/trunk/src/transformation/axis_algorithm_duplicate_scalar.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/axis_algorithm_duplicate_scalar.hpp	(revision 1704)
@@ -33,4 +33,6 @@
   static bool registerTrans();
 
+  virtual StdString getName() {return "Axis Trans. Filter \\n Duplicate Scalar";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/axis_algorithm_extract.hpp
===================================================================
--- /XIOS/trunk/src/transformation/axis_algorithm_extract.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/axis_algorithm_extract.hpp	(revision 1704)
@@ -27,4 +27,7 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Axis Trans. Filter \\n Extract";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/axis_algorithm_extract_domain.hpp
===================================================================
--- /XIOS/trunk/src/transformation/axis_algorithm_extract_domain.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/axis_algorithm_extract_domain.hpp	(revision 1704)
@@ -39,4 +39,7 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Axis Trans. Filter \\n Extract Domain";}
+
 protected:
   enum ExtractDirection {
Index: /XIOS/trunk/src/transformation/axis_algorithm_interpolate.hpp
===================================================================
--- /XIOS/trunk/src/transformation/axis_algorithm_interpolate.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/axis_algorithm_interpolate.hpp	(revision 1704)
@@ -32,4 +32,7 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Axis Trans. Filter \\n Interpolation";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/axis_algorithm_inverse.hpp
===================================================================
--- /XIOS/trunk/src/transformation/axis_algorithm_inverse.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/axis_algorithm_inverse.hpp	(revision 1704)
@@ -31,4 +31,6 @@
   static bool registerTrans();
 
+  virtual StdString getName() {return "Axis Trans. Filter \\n Inverse";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/axis_algorithm_reduce_axis.hpp
===================================================================
--- /XIOS/trunk/src/transformation/axis_algorithm_reduce_axis.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/axis_algorithm_reduce_axis.hpp	(revision 1704)
@@ -39,4 +39,6 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Axis Trans. Filter \\n Reduce Axis";}
 protected:
   
Index: /XIOS/trunk/src/transformation/axis_algorithm_reduce_domain.hpp
===================================================================
--- /XIOS/trunk/src/transformation/axis_algorithm_reduce_domain.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/axis_algorithm_reduce_domain.hpp	(revision 1704)
@@ -40,4 +40,7 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Axis Trans. Filter \\n Reduce Domain";}
+
 protected:
   enum ReduceDirection {
Index: /XIOS/trunk/src/transformation/axis_algorithm_temporal_splitting.hpp
===================================================================
--- /XIOS/trunk/src/transformation/axis_algorithm_temporal_splitting.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/axis_algorithm_temporal_splitting.hpp	(revision 1704)
@@ -34,4 +34,6 @@
   static bool registerTrans();
 
+  virtual StdString getName() {return "Axis Trans. Filter \\n Temporal Splitting";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/axis_algorithm_transformation.hpp
===================================================================
--- /XIOS/trunk/src/transformation/axis_algorithm_transformation.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/axis_algorithm_transformation.hpp	(revision 1704)
@@ -31,4 +31,6 @@
   virtual ~CAxisAlgorithmTransformation();
 
+  virtual StdString getName() {return "Axis Trans. Filter \\n Transformation";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/axis_algorithm_zoom.hpp
===================================================================
--- /XIOS/trunk/src/transformation/axis_algorithm_zoom.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/axis_algorithm_zoom.hpp	(revision 1704)
@@ -27,4 +27,7 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Axis Trans. Filter \\n Zoom";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/domain_algorithm_compute_connectivity.hpp
===================================================================
--- /XIOS/trunk/src/transformation/domain_algorithm_compute_connectivity.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/domain_algorithm_compute_connectivity.hpp	(revision 1704)
@@ -28,4 +28,7 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Domain Trans. Filter \\n Compute Connectivity";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/domain_algorithm_expand.hpp
===================================================================
--- /XIOS/trunk/src/transformation/domain_algorithm_expand.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/domain_algorithm_expand.hpp	(revision 1704)
@@ -28,4 +28,6 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Domain Trans. Filter \\n Expand";}
 
 protected:
Index: /XIOS/trunk/src/transformation/domain_algorithm_extract.hpp
===================================================================
--- /XIOS/trunk/src/transformation/domain_algorithm_extract.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/domain_algorithm_extract.hpp	(revision 1704)
@@ -23,4 +23,6 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Domain Trans. Filter \\n Extract";}
 protected:
   void updateDomainAttributes();
Index: /XIOS/trunk/src/transformation/domain_algorithm_generate_rectilinear.hpp
===================================================================
--- /XIOS/trunk/src/transformation/domain_algorithm_generate_rectilinear.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/domain_algorithm_generate_rectilinear.hpp	(revision 1704)
@@ -33,4 +33,6 @@
   virtual ~CDomainAlgorithmGenerateRectilinear() {}
 
+  virtual StdString getName() {return "Domain Trans. Filter \\n Generate Rectilinear";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/domain_algorithm_interpolate.hpp
===================================================================
--- /XIOS/trunk/src/transformation/domain_algorithm_interpolate.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/domain_algorithm_interpolate.hpp	(revision 1704)
@@ -39,4 +39,7 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Domain Trans. Filter \\n Interpolation";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/domain_algorithm_reorder.hpp
===================================================================
--- /XIOS/trunk/src/transformation/domain_algorithm_reorder.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/domain_algorithm_reorder.hpp	(revision 1704)
@@ -26,4 +26,6 @@
   static bool registerTrans();
 
+  virtual StdString getName() {return "Domain Trans. Filter \\n Reorder";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/domain_algorithm_transformation.hpp
===================================================================
--- /XIOS/trunk/src/transformation/domain_algorithm_transformation.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/domain_algorithm_transformation.hpp	(revision 1704)
@@ -27,4 +27,6 @@
   virtual ~CDomainAlgorithmTransformation();
 
+  virtual StdString getName() {return "Domain Trans. Filter \\n Transformation";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >&);
Index: /XIOS/trunk/src/transformation/domain_algorithm_zoom.hpp
===================================================================
--- /XIOS/trunk/src/transformation/domain_algorithm_zoom.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/domain_algorithm_zoom.hpp	(revision 1704)
@@ -23,4 +23,6 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Domain Trans. Filter \\n Zoom";}
 protected:
   void updateDomainAttributes();
Index: /XIOS/trunk/src/transformation/generic_algorithm_transformation.hpp
===================================================================
--- /XIOS/trunk/src/transformation/generic_algorithm_transformation.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/generic_algorithm_transformation.hpp	(revision 1704)
@@ -73,4 +73,6 @@
                      std::vector<bool>& flagInitial,                     
                      bool ignoreMissingValue, bool firstPass);
+
+  virtual StdString getName() {return "Generic Trans. Filter";}
 
   /*!
Index: /XIOS/trunk/src/transformation/scalar_algorithm_extract_axis.hpp
===================================================================
--- /XIOS/trunk/src/transformation/scalar_algorithm_extract_axis.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/scalar_algorithm_extract_axis.hpp	(revision 1704)
@@ -39,4 +39,6 @@
   static bool registerTrans();
 
+  virtual StdString getName() {return "Scalar Trans. Filter \\n Extract Axis";}
+
 protected:
   int pos_;
Index: /XIOS/trunk/src/transformation/scalar_algorithm_reduce_axis.cpp
===================================================================
--- /XIOS/trunk/src/transformation/scalar_algorithm_reduce_axis.cpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/scalar_algorithm_reduce_axis.cpp	(revision 1704)
@@ -13,5 +13,4 @@
 #include "grid.hpp"
 #include "grid_transformation_factory_impl.hpp"
-#include "reduction.hpp"
 
 #include "reduction.hpp"
Index: /XIOS/trunk/src/transformation/scalar_algorithm_reduce_axis.hpp
===================================================================
--- /XIOS/trunk/src/transformation/scalar_algorithm_reduce_axis.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/scalar_algorithm_reduce_axis.hpp	(revision 1704)
@@ -40,4 +40,7 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Scalar Trans. Filter \\n Reduce Axis";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/scalar_algorithm_reduce_domain.hpp
===================================================================
--- /XIOS/trunk/src/transformation/scalar_algorithm_reduce_domain.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/scalar_algorithm_reduce_domain.hpp	(revision 1704)
@@ -40,4 +40,7 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Scalar Trans. Filter \\n Reduce Domain";}
+
 protected:
   bool local ;
Index: /XIOS/trunk/src/transformation/scalar_algorithm_reduce_scalar.hpp
===================================================================
--- /XIOS/trunk/src/transformation/scalar_algorithm_reduce_scalar.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/scalar_algorithm_reduce_scalar.hpp	(revision 1704)
@@ -35,4 +35,7 @@
 
   static bool registerTrans();
+
+  virtual StdString getName() {return "Scalar Trans. Filter \\n Reduce Scalar";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/transformation/scalar_algorithm_transformation.hpp
===================================================================
--- /XIOS/trunk/src/transformation/scalar_algorithm_transformation.hpp	(revision 1703)
+++ /XIOS/trunk/src/transformation/scalar_algorithm_transformation.hpp	(revision 1704)
@@ -31,4 +31,6 @@
   virtual ~CScalarAlgorithmTransformation();
 
+  virtual StdString getName() {return "Scalar Trans. Filter \\n Transformation";}
+
 protected:
   void computeIndexSourceMapping_(const std::vector<CArray<double,1>* >& dataAuxInputs);
Index: /XIOS/trunk/src/workflow_graph.cpp
===================================================================
--- /XIOS/trunk/src/workflow_graph.cpp	(revision 1704)
+++ /XIOS/trunk/src/workflow_graph.cpp	(revision 1704)
@@ -0,0 +1,163 @@
+#include "workflow_graph.hpp"
+
+namespace xios
+{
+
+  std::unordered_map <int, graph_info_box_node> *CWorkflowGraph::mapFilters_ptr_with_info = 0;
+
+  std::unordered_map <int, graph_info_box_edge > *CWorkflowGraph::mapFieldToFilters_ptr_with_info = 0;
+
+  std::unordered_map <size_t, int> *CWorkflowGraph::mapHashFilterID_ptr = 0;
+
+
+  vector <StdString> CWorkflowGraph::filters;
+  vector <StdString> CWorkflowGraph::fields;
+  vector <pair<int, int> > CWorkflowGraph::fieldsToFilters;
+
+  bool CWorkflowGraph::build_begin = false;
+
+  CWorkflowGraph::CWorkflowGraph()
+  { }
+
+  /*!
+   * Reorganize information collected by XIOS for visualization.
+   */
+  void CWorkflowGraph::buildStaticWorkflow()
+  TRY
+  {
+    
+    if(mapFilters_ptr_with_info==0 || mapFieldToFilters_ptr_with_info==0) 
+      std::cout<<"No graph information provided"<<std::endl;
+
+    else // Create a list of filters (graph nodes)
+    {
+      size_t filterIdx = 0;
+      filters.resize(mapFilters_ptr_with_info->size());
+      fieldsToFilters.clear();
+      fields.clear();
+      for (auto it=mapFilters_ptr_with_info->begin(); it != mapFilters_ptr_with_info->end(); it++)
+      {
+        filters[it->first]=it->second.filter_name;
+      }
+
+      // Create a list of fields and their filter connectivity (graph edges and edge-to-node connectivity)
+      for (auto it=mapFieldToFilters_ptr_with_info->begin(); it != mapFieldToFilters_ptr_with_info->end(); it++)
+      {
+        fieldsToFilters.push_back(make_pair(it->second.from,it->second.to));
+        fields.push_back(it->second.field_id + " "+it->second.date.toString());
+      }
+    }
+  }
+  CATCH
+
+
+
+
+/*!
+   * Reorganize information collected by XIOS for visualization.
+   */
+  void CWorkflowGraph::buildStaticWorkflow_with_info()
+  TRY
+  {
+    // showStaticWorkflow();
+    
+    if(mapFilters_ptr_with_info==0 || mapFieldToFilters_ptr_with_info==0) 
+      std::cout<<"No graph information provided"<<std::endl;
+
+    else // Create a list of filters (graph nodes)
+    {
+      size_t filterIdx = 0;
+      filters.resize(mapFilters_ptr_with_info->size());
+      fieldsToFilters.clear();
+      fields.clear();
+      for (auto it=mapFilters_ptr_with_info->begin(); it != mapFilters_ptr_with_info->end(); it++)
+      {
+        // std::cout<<"it->first = "<<it->first<<std::endl;
+        filters[it->first]=it->second.filter_name;
+      }
+
+      // Create a list of fields and their filter connectivity (graph edges and edge-to-node connectivity)
+      for (auto it=mapFieldToFilters_ptr_with_info->begin(); it != mapFieldToFilters_ptr_with_info->end(); it++)
+      {
+        fieldsToFilters.push_back(make_pair(it->second.from,it->second.to));
+        fields.push_back(it->second.field_id + " "+it->second.date.toString());
+      }
+    }
+  }
+  CATCH
+
+
+
+  void CWorkflowGraph::showStaticWorkflow()
+  TRY
+  {
+    if(mapFilters_ptr_with_info!=0 && !mapFilters_ptr_with_info->empty())
+    for (auto it=mapFilters_ptr_with_info->begin(); it != mapFilters_ptr_with_info->end(); it++)
+    {
+      std::cout<<"mapFilters_ptr_with_info["<<it->first<<"].filter_name="<<it->second.filter_name<<std::endl;
+      std::cout<<"mapFilters_ptr_with_info["<<it->first<<"].filter_class="<<it->second.filter_class<<std::endl;
+      std::cout<<"mapFilters_ptr_with_info["<<it->first<<"].filter_fillled="<<it->second.filter_filled<<std::endl;
+      std::cout<<"mapFilters_ptr_with_info["<<it->first<<"].expected_entry_nb="<<it->second.expected_entry_nb<<std::endl;
+      std::cout<<"mapFilters_ptr_with_info["<<it->first<<"].date="<<it->second.date<<std::endl;
+      std::cout<<"mapFilters_ptr_with_info["<<it->first<<"].timestamp="<<it->second.timestamp<<std::endl;
+      std::cout<<"mapFilters_ptr_with_info["<<it->first<<"].transform_type="<<it->second.transform_type<<std::endl;
+    }
+    else std::cout<<"mapFilters_ptr_with_info empty"<<std::endl;
+
+    if(mapFieldToFilters_ptr_with_info!=0 && !mapFieldToFilters_ptr_with_info->empty())
+    for (auto it=mapFieldToFilters_ptr_with_info->begin(); it != mapFieldToFilters_ptr_with_info->end(); it++)
+    {
+      std::cout<<"mapFieldToFilters_ptr_with_info["<<it->first<<"].from = "<<it->second.from<<std::endl;
+      std::cout<<"mapFieldToFilters_ptr_with_info["<<it->first<<"].to = "<<it->second.to<<std::endl;
+      std::cout<<"mapFieldToFilters_ptr_with_info["<<it->first<<"].field_id = "<<it->second.field_id<<std::endl;
+      std::cout<<"mapFieldToFilters_ptr_with_info["<<it->first<<"].field_name = "<<it->second.field_name<<std::endl;
+      std::cout<<"mapFieldToFilters_ptr_with_info["<<it->first<<"].date = "<<it->second.date<<std::endl;
+      
+    }
+    else std::cout<<"mapFieldToFilters_ptr_with_info empty"<<std::endl;
+
+
+  }
+  CATCH
+
+
+  void CWorkflowGraph::addNode(int nodeID, StdString filterName, int filterClass, bool filterFilled, int entry_nb, CDataPacketPtr packet)
+  TRY
+  {
+    (*mapFilters_ptr_with_info)[nodeID].filter_name = filterName;
+    (*mapFilters_ptr_with_info)[nodeID].filter_class = filterClass;
+    (*mapFilters_ptr_with_info)[nodeID].filter_filled = filterFilled;
+    (*mapFilters_ptr_with_info)[nodeID].expected_entry_nb = entry_nb;
+    (*mapFilters_ptr_with_info)[nodeID].date = packet->date;
+    (*mapFilters_ptr_with_info)[nodeID].timestamp = packet->timestamp;
+  }
+  CATCH
+
+
+
+  void CWorkflowGraph::addEdge(int edgeID, int toID, CDataPacketPtr packet)
+  TRY
+  {
+    (*mapFieldToFilters_ptr_with_info)[edgeID].from = packet->src_filterID;
+    (*mapFieldToFilters_ptr_with_info)[edgeID].to = toID;
+    (*mapFieldToFilters_ptr_with_info)[edgeID].field_id = packet->field->getId();
+    (*mapFieldToFilters_ptr_with_info)[edgeID].field_name = packet->field->name;
+    (*mapFieldToFilters_ptr_with_info)[edgeID].grid_id = packet->field->grid->getId();
+    (*mapFieldToFilters_ptr_with_info)[edgeID].date = packet->date;
+    (*mapFieldToFilters_ptr_with_info)[edgeID].timestamp = packet->timestamp;
+    (*mapFieldToFilters_ptr_with_info)[edgeID].field = packet->field;
+    (*mapFieldToFilters_ptr_with_info)[edgeID].attributes = packet->field->record4graphXiosAttributes();
+  }
+  CATCH
+
+
+  void CWorkflowGraph::allocNodeEdge()
+  TRY
+  {
+    if(mapFilters_ptr_with_info==0) mapFilters_ptr_with_info = new std::unordered_map <int, graph_info_box_node>;
+    if(mapFieldToFilters_ptr_with_info==0) mapFieldToFilters_ptr_with_info = new std::unordered_map <int, graph_info_box_edge >;
+    if(mapHashFilterID_ptr==0) mapHashFilterID_ptr = new std::unordered_map <size_t, int >;
+  }
+  CATCH
+
+}
Index: /XIOS/trunk/src/workflow_graph.hpp
===================================================================
--- /XIOS/trunk/src/workflow_graph.hpp	(revision 1704)
+++ /XIOS/trunk/src/workflow_graph.hpp	(revision 1704)
@@ -0,0 +1,99 @@
+#ifndef __WORKFLOW_GRAPH_HPP__
+#define __WORKFLOW_GRAPH_HPP__
+
+#include "xios_spl.hpp"
+#include "field.hpp"
+#include "grid.hpp"
+#include "garbage_collector.hpp"
+#include "date.hpp"
+#include "duration.hpp"
+
+
+namespace xios
+{
+  class CField;
+
+  struct graph_info_box_node
+  {
+
+    StdString filter_name;
+    int filter_class;
+    bool filter_filled;
+    int expected_entry_nb;
+    CDate date;
+    Time timestamp;
+    StdString transform_type;
+    StdString attributes;
+    StdString field_id;
+    bool inputs_complete;
+    int filter_tag;
+    int clusterID;
+    int distance;
+  };
+
+  struct graph_info_box_edge
+  {
+    int from;
+    int to;
+    StdString field_id;
+    StdString field_name;
+    StdString grid_id;
+    CDate date;
+    Time timestamp;
+    CField *field;
+    StdString attributes;
+    
+  };
+
+  class CWorkflowGraph
+  {
+
+    friend class CGraphviz;
+
+    public:
+
+      CWorkflowGraph();
+
+      /*! Map between fields identified by its id and their filters identified by an integer.
+       * It is filled up during reconstruction of a workflow (in function CField::buildFilterGraph()).
+      */
+      // static std::unordered_map <StdString, vector <int> > *mapFieldToFilters_ptr;
+      // #pragma omp threadprivate(mapFieldToFilters_ptr)
+
+
+
+      static std::unordered_map <int, graph_info_box_node> *mapFilters_ptr_with_info;
+
+      static std::unordered_map <int, graph_info_box_edge> *mapFieldToFilters_ptr_with_info;
+
+      static std::unordered_map <size_t, int> *mapHashFilterID_ptr;
+
+
+      static bool build_begin;
+
+      static void addNode(int nodeID, StdString filterName, int filter_class, bool filter_filled, int entry_nb, CDataPacketPtr packet);
+      static void addEdge(int edgeID, int toID, CDataPacketPtr packet);
+      static void allocNodeEdge();
+
+    private:
+
+      //! List of fields marked for visualizing of their workflow
+      static vector <StdString> fields;
+
+      //! List of connected filters for fields for visualizing of their workflow
+      static vector <StdString> filters;
+
+      //! Fields to filters connectivity
+      static vector <pair<int, int> > fieldsToFilters;
+
+      static void buildStaticWorkflow();
+      static void buildStaticWorkflow_with_info();
+      static void showStaticWorkflow();
+
+      
+
+
+  };
+}
+
+#endif
