/// <summary> /// Populates the edges list based on the SBML Qual model content. /// </summary> /// <param name="model">The target binary model to populate</param> /// <param name="sbmlModel">The input SBML Qual model</param> private void PopulateEdges(BinaryModel model, Model sbmlModel) { var modelQualPlugin = (QualModelPlugin)sbmlModel.getPlugin("qual"); var numTransitions = modelQualPlugin.getNumTransitions(); for (var i = 0; i < numTransitions; i++) { var transition = modelQualPlugin.getTransition(i); var numInputs = transition.getNumInputs(); var numOutputs = transition.getNumOutputs(); for (var j = 0; j < numInputs; j++) { var input = transition.getInput(j); for (var k = 0; k < numOutputs; k++) { var output = transition.getOutput(k); var edge = new BinaryEdge(model, transition.getId(), input.getSign() == libsbml.INPUT_SIGN_NEGATIVE ? EdgeType.Negative : EdgeType.Positive) { Input = model.Nodes.FirstOrDefault(n => n.Id.Equals(input.getQualitativeSpecies())), Output = model.Nodes.FirstOrDefault(n => n.Id.Equals(output.getQualitativeSpecies())) }; model.Edges.Add(edge); } } } }
/// <summary> /// Returns the edge type of a new edge merging two edges. /// </summary> /// <param name="inputEdge">The input edge</param> /// <param name="outputEdge">The output edge</param> /// <returns>The new edge type of the merged edge</returns> private EdgeType GetMergedEdgeType(BinaryEdge inputEdge, BinaryEdge outputEdge) { switch (inputEdge.Type) { case EdgeType.Positive: return(outputEdge.Type); case EdgeType.Negative: return(outputEdge.IsPositive() ? EdgeType.Negative : EdgeType.Positive); default: return(EdgeType.Positive); } }
/// <summary> /// In a target model, finds the drugs that could have the desired effect on the target node. /// </summary> /// <param name="model">The target model</param> /// <param name="nodeId">The Id of the target node</param> /// <param name="drugEffect">The desired effect</param> /// <param name="drugsList">The list of available drugs</param> /// <param name="drugNodes">The new nodes added for the drugs</param> /// <param name="drugsEdges">The new edges added for the drugs</param> public void FindDrugs(BinaryModel model, string nodeId, DrugEffect drugEffect, List <DrugDescription> drugsList, out List <BinaryNode> drugNodes, out List <BinaryEdge> drugsEdges) { drugNodes = new List <BinaryNode>(); drugsEdges = new List <BinaryEdge>(); var node = model.GetNode(nodeId); if (node.State != State.Unset) { return; } node.State = drugEffect == DrugEffect.Activation ? State.Active : State.Inactive; var targetDrug = drugsList.FirstOrDefault(d => d.TargetId.Equals(nodeId) && d.Effect == drugEffect); if (targetDrug != null) { var drugNode = new BinaryNode(model, targetDrug.Id); drugNode.State = State.Active; drugNodes.Add(drugNode); var drugEdge = new BinaryEdge(model, string.Concat(targetDrug.Id, node.Id), targetDrug.Effect == DrugEffect.Activation ? EdgeType.Positive : EdgeType.Negative); drugEdge.Input = drugNode; drugEdge.Output = node; drugsEdges.Add(drugEdge); } foreach (var edge in model.Edges.Where(e => e.Output == node)) { var modelClone = model.Clone(); var inputEffect = DrugEffect.Activation; switch (edge.Type) { case EdgeType.Positive: inputEffect = drugEffect; break; case EdgeType.Negative: inputEffect = drugEffect == DrugEffect.Activation ? DrugEffect.Inhibition : DrugEffect.Activation; break; } FindDrugs(modelClone, edge.Input.Id, inputEffect, drugsList, out var newDrugNodes, out var newDrugEdges); drugNodes.AddRange(newDrugNodes); drugsEdges.AddRange(newDrugEdges); } }
/// <summary> /// Adds new entities to the target model /// </summary> /// <param name="model">The target model</param> /// <param name="newNodes">The nodes to add</param> /// <param name="newEdges">The edges to add</param> /// <param name="protectNodes">If set to<c>true</c>, new nodes and nodes related to the added edges will be protected</param> public void AddEntitiesToModel(BinaryModel model, List <BinaryNode> newNodes, List <BinaryEdge> newEdges, bool protectNodes) { // Add them to the model without duplicates foreach (var drugNode in newNodes) { drugNode.Model = model; drugNode.Protected = protectNodes; } model.Nodes.AddRange(newNodes); foreach (var fullDrugEdge in newEdges) { var newEdge = new BinaryEdge(model, fullDrugEdge.Id, fullDrugEdge.Type) { Input = model.Nodes.First(n => n.Id.Equals(fullDrugEdge.Input.Id)), Output = model.Nodes.First(n => n.Id.Equals(fullDrugEdge.Output.Id)) }; newEdge.Input.Protected = protectNodes; newEdge.Output.Protected = protectNodes; model.Edges.Add(newEdge); } }
/// <summary> /// Removes non protected nodes with only one input and one output and merges the appropriate edges. /// Loop nodes and nodes with no input and/or output are also removed. /// </summary> /// <param name="model">The binary model</param> /// <returns>The number of nodes removed</returns> public int CleanupNodes(BinaryModel model) { int entitiesRemoved = 0; var nodes = model.Nodes.ToList(); foreach (var node in nodes) { if (node.Protected) { continue; } var canRemoveNode = true; var edges = model.Edges.ToList(); var inputs = edges.Where(e => e.Output == node).ToList(); var outputs = edges.Where(e => e.Input == node).ToList(); // If a node has no imput nor output or is a loop, remove it if (inputs.Count == 0 || outputs.Count == 0) { model.Nodes.Remove(node); model.Edges.RemoveAll(e => inputs.Contains(e) || outputs.Contains(e)); entitiesRemoved++; } // Remove self regulations model.Edges.RemoveAll(e => e.Input == e.Output); var outputsToKeep = new List <BinaryEdge>(); var inputsToKeep = new List <BinaryEdge>(); var newEdgesToAdd = new List <BinaryEdge>(); foreach (var inputEdge in inputs) { foreach (var outputEdge in outputs) { var newEdge = new BinaryEdge(model, string.Concat(inputEdge.Id, outputEdge.Id), GetMergedEdgeType(inputEdge, outputEdge)) { Input = inputEdge.Input, Output = outputEdge.Output }; if (HasOpositeEdge(model, newEdge.Input, newEdge.Output, newEdge.Type)) { canRemoveNode = false; inputsToKeep.Add(inputEdge); outputsToKeep.Add(outputEdge); continue; } if (newEdge.Input != newEdge.Output && !HasSameEdge(model, newEdge.Input, newEdge.Output, newEdge.Type)) { newEdgesToAdd.Add(newEdge); } } } // Compute edges to remove var edgesToRemove = (model.Edges.Where(e => e.Input == node && !outputsToKeep.Contains(e) || e.Output == node && !inputsToKeep.Contains(e))).ToList(); // Compare edges to add count with edges to remove var delta = newEdgesToAdd.Count - edgesToRemove.Count; if (delta <= 0) { entitiesRemoved += model.Edges.RemoveAll(e => edgesToRemove.Contains(e)); model.Edges.AddRange(newEdgesToAdd); if (!canRemoveNode) { continue; } model.Nodes.Remove(node); entitiesRemoved++; } } return(entitiesRemoved); }