From 00735b52095a2928ea3cd54e554527e1a54ca4f8 Mon Sep 17 00:00:00 2001
From: Sebastian David <sebastian.david@uni-hamburg.de>
Date: Thu, 23 Dec 2021 09:49:50 +0100
Subject: [PATCH] added verarbeitung and output to main program

---
 .citation_parser_ui.py.swp | Bin 0 -> 20480 bytes
 assets/cn.js               | 548 +++++++++++++++++++++++++++++++++++++
 assets/index.html          | 107 ++++++++
 assets/json_text.json      |   1 +
 citation_parser_ui.py      |  25 +-
 5 files changed, 668 insertions(+), 13 deletions(-)
 create mode 100644 .citation_parser_ui.py.swp
 create mode 100644 assets/cn.js
 create mode 100644 assets/index.html
 create mode 100644 assets/json_text.json

diff --git a/.citation_parser_ui.py.swp b/.citation_parser_ui.py.swp
new file mode 100644
index 0000000000000000000000000000000000000000..38c0d61d4724d853b03e358ed4916b537560e72f
GIT binary patch
literal 20480
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
VnTM(ayB(2a&<E6UszMr22LK?O0b~FG

literal 0
HcmV?d00001

diff --git a/assets/cn.js b/assets/cn.js
new file mode 100644
index 0000000..309678b
--- /dev/null
+++ b/assets/cn.js
@@ -0,0 +1,548 @@
+/**
+* creates a new zoom behavior
+*/
+var zoom = d3.zoom().on("zoom", handle_zoom);
+
+/**
+* creates svg object and associated attributes
+* applies the zoom behavior to svg
+*/
+var svg = d3.select("svg.graph")
+    .call(zoom),
+width = svg.attr("width"),
+height = svg.attr("height"),
+perc;
+
+/**
+* scale functions that return y coordinate/color of node depending on group
+*/
+var color = d3.scaleOrdinal()
+    .domain(["height", "input", "depth"])
+    .range([' #01d7c0', ' #8b90fe ', '  #a15eb2 ']),
+y_scale = d3.scaleOrdinal()
+    .domain(["height", "input", "depth"])
+    .range([0, 200, 400]),
+to_remove;
+
+/**
+* creates node object and (default) radius
+*/
+var node,
+r = 10;
+
+/**
+* creates link object
+*/
+var link;
+
+/**
+* creates a background with a click functionality
+*/
+var rect = svg.append("rect")
+    .attr("x", 0)
+    .attr("y", 0)
+    .attr("height", height)
+    .attr("width", width)
+    .style("fill", 'white')
+    .on('click', click_rect);
+
+/**
+* creates svg object (legend) and associated attributes
+*/
+var svg_legend = d3.select("svg.legendsvg"),
+legend_position = [65,95,125],
+arrow_legend_position = [0,25],
+arrow_group_names = ["citation","self-citation"],
+group_names = ["cited by","input","reference"],
+line_type = d3.scaleOrdinal()
+    .domain(["line","dotted"])
+    .range([("8,0"),("8,8")]),
+text_info = '',
+text_abstract = '';
+    
+var legend = svg_legend.selectAll(".legend")
+    .data(legend_position)
+    .enter()
+    .append("g")
+    .attr("class","legend")
+    .attr("transform", function(d,i) {return "translate(0," + d  + ")"; });
+    
+legend.append("text")
+    .attr("x", 80)
+    .attr("y", 0)
+    .attr("dy", ".35em")
+    .style("text-anchor", "start")
+    .text(function(d,i) {return group_names[i]});
+    
+legend.append("circle")
+    .attr("r", r)
+    .attr("cx",30-r)
+    .style("fill", color);
+        
+var legend_arrow = svg_legend.selectAll(".legendarr")
+    .data(arrow_legend_position)
+    .enter()
+    .append("g")
+    .attr("class","legendarr")
+    .attr("transform", function(d) { return "translate(0," + d  + ")"; });
+    
+legend_arrow.append("line")
+    .attr("x1", 10)
+    .attr("x2", 50)
+    .attr("y1", 10)
+    .attr("y2", 10)
+    .style("stroke-dasharray",line_type)
+    .style("stroke", '#999')
+    .style("stroke-width", "1px")
+    .style('pointer-events', 'none')
+    .attr('marker-end',update_marker('#999',this));
+
+legend_arrow.append("text")
+    .attr("x", 80)
+    .attr("y", 10)
+    .attr("dy", ".35em")
+    .style("text-anchor", "start")
+    .text(function(d,i){return arrow_group_names[i]});
+
+/**
+* creates a new simulation
+* updates the positions of the links and nodes when the 
+  state of the layout has changed (simulation has advanced by a tick)
+*/
+var simulation = d3.forceSimulation()
+    .force("link", d3.forceLink().id(function(d) {return d.doi;}).distance(50).strength(function(d) {
+            if (d.group == "input") {return 0;}
+            else {return 5;}
+        }))
+        .force("collide", d3.forceCollide(function(d) {
+            if (d.group == "input") {return 100;}
+            else {return 65;}
+        }).strength(0.5))
+    .force("charge", d3.forceManyBody().strength(0.001))
+    .force("center", d3.forceCenter(width/2, height/2+20))
+    .force("yscale", d3.forceY().strength(function(d) {
+        if (d.group == "input") {return 1000;}
+        else {return 50;}
+    }).y(function(d) {return y_scale(d.group)}))
+    .alpha(0.005)
+    .on("end",  zoom_to);
+
+/**
+* creates group element
+*/
+var g = svg.append("g")
+    .attr("class", "everything")
+
+/**
+* loads JSON data and calls the update function
+*/
+d3.json("json_text.json").then(function(graph) {
+    update(graph.links, graph.nodes);
+})
+
+/**
+* calls update functions for links and nodes
+* adds the nodes, links and tick functionality to the simulation
+* @param {object} nodes - nodes
+* @param {object} links - links
+*/
+function update(links, nodes) {
+    update_links(links);
+    update_nodes(nodes);
+    
+    simulation
+        .nodes(nodes)
+        .on("tick", handle_tick);
+    simulation.force("link")
+        .links(links);
+    
+    link.attr('marker-end', function(d) {return update_marker("#999", d.target);})
+        .style("stroke-dasharray",function(d){return self_citation(d.source,d.target)? ("8,8"): ("1,0")});
+}
+
+/**
+* initializes and shows links
+* @param {object} links - links
+*/
+function update_links(links) {
+    link = g.append("g")
+        .selectAll(".link")
+        .data(links)
+        .enter()
+        .append("line")
+        .style("stroke-width", "1px")
+        .style("stroke", "#999")
+        .attr("class", "link");
+}
+
+/**
+* initializes and shows nodes with circles, texts and a click functionality
+* creates a new drag behavior and applies it to the circles
+* @param {object} nodes - nodes
+*/
+function update_nodes(nodes) {
+    node = g.selectAll(".node")
+        .data(nodes)
+        .enter()
+        .append("g")
+        .attr("class", "node")
+        .call(d3.drag()
+            .on("start", start_drag)
+            .on("drag", dragged)
+        );
+
+    node.append("circle")
+        .attr("class", "circle")
+        .attr("r", function(d) {return 1.5*r+d.citations*0.05})
+        .style("fill", function(d){ return color(d.group)})
+        .on('click', click_node);
+
+    node.append("text")
+        .attr("class", "text") 
+        .style("font-size", "15px")
+        .style('pointer-events', 'auto')
+        .text(function (d) {const first_author=d.author[0].split(" ")
+        return first_author[first_author.length-1];})
+        .on('click', click_node);
+}
+
+/**
+* creates arrowhead and returns its url
+* @param {string} color - color of arrowhead
+* @param {string} target - target node
+*/
+function update_marker(color, target) {
+    var radius = 1.5*r+target.citations*0.05;
+    svg.append('defs').append('marker')
+        .attr('id',color.replace("#", "")+radius)
+        .attr('viewBox','-0 -5 10 10')
+        .attr('refX',radius+9.5)
+        .attr('refY',0)
+        .attr('orient','auto')
+        .attr('markerWidth',10)
+        .attr('markerHeight',15)
+        .attr('xoverflow','visible')
+        .append('svg:path')
+        .attr('d', 'M 0,-5 L 10 ,0 L 0,5')
+        .attr('fill', color)
+        .style('stroke','none');
+    return "url(" + color + radius + ")";
+};
+
+/**
+* sets color of circle and its links to black and removes the previous highlights
+* displays overview info of node in textbox
+* @param {object} node - node
+*/
+function click_node(node) {
+    d3.select(this.parentNode).raise();
+    fix_nodes(node);
+    if(to_remove){
+        d3.select(to_remove).selectAll(".circle").style("stroke","none")
+    }
+    to_remove = this.parentNode;
+    d3.select(this.parentNode).selectAll(".circle").style("stroke","black")
+    mark_link(node)
+    textbox_content(node)
+    reset_button_highlight()
+    highlight_button("overview")
+}
+
+/**
+* removes the highlights of the circles and their links
+*/
+function click_rect() {
+    fix_nodes(node);
+    d3.selectAll(".circle").style("stroke", "none")
+    d3.selectAll(".link")
+        .style("stroke", "#999")
+        .attr('marker-end', function(d) {return update_marker('#999', d.target);})
+    text_abstract='';
+    text_info='';
+    reset_button_highlight()
+    document.getElementById('textbox').innerHTML = "Click node";
+}
+
+/**
+* returns true if journals have a common author (self-citation)
+* @param {object} source - node
+* @param {object} target - node
+*/
+function self_citation(source,target) {
+    return source.author.some(item=>target.author.includes(item))
+}
+
+/**
+* sets color of link (line and arrowhead) to black if it is directly connected to node
+* and to grey otherwise
+* @param {object} node - node
+*/
+function mark_link(node) {
+    d3.selectAll(".link")
+        .style("stroke", function(o) {
+            return is_link_for_node(node, o) ? "black" : "#999";})
+        .attr('marker-end', function(o) {
+            return is_link_for_node(node, o) ? update_marker('#000000', o.target) : update_marker('#999', o.target);})
+}
+
+/**
+* returns true if link is directly connected to node and false if it is not
+* @param {object} node - node
+* @param {object} link - link
+*/
+function is_link_for_node(node, link) {
+    return link.source.index == node.index || link.target.index == node.index;
+}
+
+/**
+* saves text for overview and abstract of node
+* outputs node info to textbox
+* @param {object} node - node
+*/
+function textbox_content(node) {
+    text_info = "Title:" + '</br>' + node.name +
+    '</br>' +'</br>'+"Author:"+ '</br>' +node.author+'</br>'+'</br>'+"Date:"+'</br>'
+    +node.year+'</br>'+'</br>'+"Journal:"+'</br>'+node.journal+'</br>'+'</br>'+"doi:"
+    +'</br>'+'<a href="'+node.doi+ '">'+node.doi+'</a>'+'</br>'+'</br>'+"Citations:"
+    +'</br>'+node.citations;
+    text_abstract = node.abstract;
+    document.getElementById('textbox').innerHTML = text_info;
+}
+
+/**
+* sets color of btn to dark gray
+* @param {object} btn - button
+*/
+function highlight_button(btn) {
+    reset_button_highlight();
+    document.getElementById(btn).style.background = "#CACACA";
+}
+
+/**
+* sets color of all buttons to default light gray
+*/
+function reset_button_highlight() {
+    document.getElementById("overview").style.background = '';
+    document.getElementById("abstract").style.background = '';
+}
+
+/**
+* displays abstract in textbox if a is true, overview text otherwise
+* @param {bool} a- bool
+*/
+function display_abstract(a) {
+    if (text_abstract == '' && text_info == '') {
+        document.getElementById('textbox').innerHTML="Click node";
+    }
+    else {
+        if (a == true) {
+            document.getElementById('textbox').innerHTML = text_abstract;
+        }
+        else {
+            document.getElementById('textbox').innerHTML = text_info;
+        }
+    }   
+}
+
+/**
+* updates the positions of the links and nodes
+*/
+function handle_tick() {
+    link.attr("x1", function (d) {return d.source.x;})
+        .attr("y1", function (d) {return d.source.y;})
+        .attr("x2", function (d) {return d.target.x;})
+        .attr("y2", function (d) {return d.target.y;});
+    node.attr("transform", function (d) {return "translate(" + d.x + ", " + d.y + ")";});
+}
+
+/**
+* initializes the dragging of the node
+* @param {object} node - node
+*/
+function start_drag(node) {
+    d3.select(this).raise();
+    if (!d3.event.active) 
+        simulation.alphaTarget(0.3).restart()
+    node.fx = node.x;
+    node.fy = node.y;
+    fix_nodes(node);
+}
+
+/**
+* applies the dragging to the node
+* @param {object} node - node
+*/
+function dragged(node) {
+    node.fx = d3.event.x;
+    node.fy = d3.event.y;
+    fix_nodes(node);
+}
+
+/**
+* fix positions of all nodes except for the current node
+* @param {object} this_node - node
+*/
+function fix_nodes(this_node) {
+    node.each(function(d) {
+      if (this_node != d) {
+        d.fx = d.x;
+        d.fy = d.y;
+      }
+    });
+}
+
+/**
+* applies the transformation (zooming or dragging) to the g element
+*/
+function handle_zoom() {
+    d3.select('g').attr("transform", d3.event.transform);
+}
+
+/**
+* transforms svg so that the zoom is adapted to the size of the graph
+*/
+function zoom_to() {
+    node_bounds = d3.selectAll("svg.graph").node().getBBox();
+    svg_bounds = d3.select("rect").node().getBBox();
+
+    perc_x = width/(node_bounds.width+100);
+    perc_y = height/(node_bounds.height+100);
+    perc = d3.min([perc_x, perc_y])
+    
+    d3.select('svg')
+		.call(zoom.scaleBy, perc);
+}
+
+/**
+* transforms svg so that the zoom and drag is reset
+*/
+function reset_view() {
+    d3.select('svg')
+        .call(zoom.scaleTo, 1)
+    d3.select('svg')
+        .call(zoom.translateTo, 0.5 * width, 0.5 * height);
+    d3.select('svg')
+		.call(zoom.scaleBy, perc);
+}
+
+/**
+* save svg as png
+*/
+function save_svg(){
+	var svgString = get_svg_string(svg.node());
+	svg_string_to_image(svgString, 2*width, 2*height, 'png', save); // passes Blob and filesize String to the callback
+
+	function save( dataBlob, filesize ){
+		saveAs(dataBlob, 'D3 vis exported to PNG.png'); // FileSaver.js function
+	}
+};
+
+/**
+* generate svgString
+* @param {object} svgNode - node
+*/
+function get_svg_string(svgNode) {
+	svgNode.setAttribute('xlink', 'http://www.w3.org/1999/xlink');
+	var cssStyleText = get_css_styles(svgNode);
+	append_css(cssStyleText, svgNode);
+
+	var serializer = new XMLSerializer();
+	var svgString = serializer.serializeToString(svgNode);
+	svgString = svgString.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink='); // Fix root xlink without namespace
+	svgString = svgString.replace(/NS\d+:href/g, 'xlink:href'); // Safari NS namespace fix
+
+	return svgString;
+
+	function get_css_styles(parentElement) {
+		var selectorTextArr = [];
+
+		// Add Parent element Id and Classes to the list
+		selectorTextArr.push('#' + parentElement.id);
+		for (var c = 0; c < parentElement.classList.length; c++)
+				if (!contains('.'+parentElement.classList[c], selectorTextArr))
+					selectorTextArr.push('.'+parentElement.classList[c]);
+
+		// Add Children element Ids and Classes to the list
+		var nodes = parentElement.getElementsByTagName("*");
+		for (var i = 0; i < nodes.length; i++) {
+			var id = nodes[i].id;
+			if (!contains('#'+id, selectorTextArr))
+				selectorTextArr.push('#' + id);
+
+			var classes = nodes[i].classList;
+			for (var c = 0; c < classes.length; c++)
+				if (!contains('.'+classes[c], selectorTextArr))
+					selectorTextArr.push('.'+classes[c]);
+		}
+
+		// Extract CSS Rules
+		var extractedCSSText = "";
+		for (var i = 0; i < document.styleSheets.length; i++) {
+			var s = document.styleSheets[i];
+			
+			try {
+			    if(!s.cssRules) continue;
+			} catch(e) {
+		    		if(e.name !== 'SecurityError') throw e; // for Firefox
+		    		continue;
+		    	}
+
+			var cssRules = s.cssRules;
+			for (var r = 0; r < cssRules.length; r++) {
+				if (contains(cssRules[r].selectorText, selectorTextArr))
+					extractedCSSText += cssRules[r].cssText;
+			}
+		}
+		
+
+		return extractedCSSText;
+
+		function contains(str,arr) {
+			return arr.indexOf(str) === -1 ? false : true;
+		}
+
+	}
+
+	function append_css(cssText, element) {
+		var styleElement = document.createElement("style");
+		styleElement.setAttribute("type","text/css"); 
+		styleElement.innerHTML = cssText;
+		var refNode = element.hasChildNodes() ? element.children[0] : null;
+		element.insertBefore(styleElement, refNode);
+	}
+}
+
+/**
+* convert svgString to image and export it
+* @param {object} svgString - svgString
+* @param {object} width - width of image
+* @param {object} height - height of image
+* @param {object} format - format to save image in 
+* @param {object} callback - callback function 
+*/
+function svg_string_to_image( svgString, width, height, format, callback ) {
+	var format = format ? format : 'png';
+
+	var imgsrc = 'data:image/svg+xml;base64,'+ btoa(unescape(encodeURIComponent(svgString))); // Convert SVG string to data URL
+
+	var canvas = document.createElement("canvas");
+	var context = canvas.getContext("2d");
+
+	canvas.width = width;
+	canvas.height = height;
+
+	var image = new Image();
+	image.onload = function() {
+		context.clearRect(0, 0, width, height);
+		context.drawImage(image, 0, 0, width, height);
+
+		canvas.toBlob(function(blob) {
+			var filesize = Math.round(blob.length/1024) + ' KB';
+			if (callback) callback(blob, filesize);
+		});
+		
+	};
+
+	image.src = imgsrc;
+}
+
diff --git a/assets/index.html b/assets/index.html
new file mode 100644
index 0000000..78560da
--- /dev/null
+++ b/assets/index.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    
+    <!-- style specifications for button and div elements -->
+    <style type="text/css">
+        button {
+            width: 100px;
+            height:20px;
+            display: flex;
+            justify-content: center;
+            position: absolute;
+            left: 455px;
+            top: 575px;
+            transition-duration: 0.4s;
+            border-radius:3px;
+            border:1px solid #909090;
+        }
+
+        .button:hover {
+            background-color: #CACACA;
+        }
+
+        button.resetZoom {
+            margin-left: 110px;
+        }
+
+        button.save {
+            margin-left: 220px;
+        }
+
+        button.abstract {
+            width:146px;
+            position:absolute;
+            top: 181px; 
+            left: 1114px;
+            border-radius:0;
+            border:1px solid #909090;
+        }
+
+        button.overview {
+            width:147px;
+            position:absolute;
+            display:inline-block;
+            top: 181px; 
+            left: 968px;
+            border-radius:0;
+            border:1px solid #909090;
+        }
+
+        div.legendbox {
+            width:270px;
+            height:170px; 
+            padding: 10px;
+            /*border: 1px solid #999;*/
+            position: absolute; 
+            top: 10px; 
+            left: 968px;
+            display: inline-block;
+            margin: 0;
+        }
+
+        div.textbox {
+            width:270px;
+            min-height:200px; 
+            max-height:370px;
+            padding: 10px;
+            border: 1px solid #999;
+            position: absolute; 
+            top: 200px; 
+            left: 968px;
+            display: inline-block;
+            overflow-y: scroll;
+            margin: 0;
+        }
+    </style>
+</head>
+
+<body>
+    <!-- graph -->
+    <svg class="graph" width="960" height="560"></svg>
+
+    <!-- legend -->
+    <div class="legendbox"> <svg class="legendsvg"></svg></div>
+
+    <!-- textbox -->
+    <div class="textbox" id = "textbox">Click node</div>
+    <button id="overview" class="overview" onclick='display_abstract(false), highlight_button("overview")'>Overview</button>
+    <button id="abstract" class="abstract" onclick='display_abstract(true), highlight_button("abstract")'>Abstract</button>
+
+    <!-- buttons -->
+    <button onclick="location.reload()">Reload Graph</button>
+    <button class="resetZoom" onclick="reset_view()">Reset View</button>
+    <button class="save" onclick="save_svg()">Save</button>
+ 
+    <!-- D3 (version 5) -->
+    <script src="https://d3js.org/d3.v5.min.js"></script>
+
+    <!-- scripts to save svg element as png -->
+    <script src="https://cdn.rawgit.com/eligrey/canvas-toBlob.js/f1a01896135ab378aa5c0118eadd81da55e698d8/canvas-toBlob.js"></script>
+	<script src="https://cdn.rawgit.com/eligrey/FileSaver.js/e9d941381475b5df8b7d7691013401e171014e89/FileSaver.min.js"></script>
+    
+    <!-- javascript for force-directed graph -->
+    <script type="text/javascript" id="cn" src="cn.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/assets/json_text.json b/assets/json_text.json
new file mode 100644
index 0000000..b2e4c5f
--- /dev/null
+++ b/assets/json_text.json
@@ -0,0 +1 @@
+{"nodes": [{"doi": "https://doi.org/10.1021/acs.jcim.6b00709", "name": "Matched Molecular Series: Measuring SAR Similarity", "author": ["Emanuel S. R. Ehmki", "Christian Kramer"], "year": "May 1, 2017", "journal": "Journal of Chemical Information and Modeling", "group": "Input", "depth": 0, "citations": 5}, {"doi": "https://doi.org/10.1021/acs.jcim.0c00269", "name": "Matched Molecular Series Analysis for ADME Property Prediction", "author": ["Mahendra Awale", "Sereina Riniker", "Christian Kramer"], "year": "May 5, 2020", "journal": "Journal of Chemical Information and Modeling", "group": "Citedby", "depth": 1, "citations": 6}, {"doi": "https://doi.org/10.1021/acs.jcim.0c00290", "name": "Identification of Bioisosteric Substituents by a Deep Neural Network", "author": ["Peter Ertl"], "year": "June 15, 2020", "journal": "Journal of Chemical Information and Modeling", "group": "Citedby", "depth": 2, "citations": 2}], "links": [{"source": "https://doi.org/10.1021/acs.jcim.0c00269", "target": "https://doi.org/10.1021/acs.jcim.6b00709"}, {"source": "https://doi.org/10.1021/acs.jcim.0c00290", "target": "https://doi.org/10.1021/acs.jcim.0c00269"}]}
\ No newline at end of file
diff --git a/citation_parser_ui.py b/citation_parser_ui.py
index 453ead9..7431a91 100644
--- a/citation_parser_ui.py
+++ b/citation_parser_ui.py
@@ -1,3 +1,4 @@
+import os
 import base64
 import re
 import dash
@@ -8,6 +9,7 @@ from dash.dependencies import Input, Output, State
 from dash.exceptions import PreventUpdate
 from input.interface import InputInterface
 import input.publication
+from verarbeitung.process_main import Processing
 
 app = dash.Dash(__name__)
 
@@ -76,7 +78,11 @@ app.layout = html.Div([
             value=[])
     ]),
     # Layer 4: For the Graph
-    html.Div([
+    html.Div(
+        [html.Iframe(
+            src="assets/index.html",
+            style={"height": "600px", "width": "100%"},
+        ),
         html.Div(id='test-output')
     ])
 ])
@@ -125,6 +131,7 @@ def update_input_checklist(input_value,btn1,btn2,filecontents,all_inputs,
 
     # if clear-all-button was pressed:
     if 'clear-all-button' in changed_id:
+        os.remove('assets/json_text.json')
         return list(),list(),'',''
     
     # if clear-selected-button was pressed:
@@ -147,7 +154,7 @@ def update_input_checklist(input_value,btn1,btn2,filecontents,all_inputs,
                     i = InputInterface()
                     pub = i.get_pub_light(input_value)
                 except Exception as err:
-                    return options,selected_inputs,'','{}'.format(err)
+                    return all_inputs,selected_inputs,'','{}'.format(err)
                 # Creates a more readable string to display in the checklist
                 rep_str = pub.contributors[0] + ',' + pub.journal + \
                         ',' + pub.publication_date
@@ -240,16 +247,8 @@ def generate_output(n_clicks,all_inputs,selected_inputs,
         raise PreventUpdate
     elif 'Update Automatically' in additional_options \
             or 'start-button' in changed_id: 
-        s = ''
-        for i in range(len(all_inputs)):
-            x = all_inputs[i]['value']
-            if x in selected_inputs:
-                s += x*(abs(int(forward_depth)-int(backward_depth)))
-            else:
-                s += x*(int(forward_depth)+int(backward_depth))
-        return s
-    else:
-        raise PreventUpdate
+        input_links = [x['value'] for x in all_inputs]
+        Processing(input_links,int(forward_depth),int(backward_depth),'assets/json_text.json')
 
 if __name__ == '__main__':
-    app.run_server(debug=True)
+    app.run_server(debug=False)
-- 
GitLab