Commit 216cebce authored by Piotr Gawron's avatar Piotr Gawron
Browse files

possibility to create submodel with explicitly defined list of elements

parent 2b022463
......@@ -6,14 +6,15 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import lcsb.mapviewer.model.map.layout.graphics.Layer;
import lcsb.mapviewer.model.map.layout.graphics.LayerText;
import lcsb.mapviewer.model.map.model.Model;
import lcsb.mapviewer.model.map.reaction.AbstractNode;
import lcsb.mapviewer.model.map.reaction.Reaction;
import lcsb.mapviewer.model.map.reaction.ReactionNode;
import lcsb.mapviewer.model.map.species.Element;
import lcsb.mapviewer.model.map.species.Complex;
import lcsb.mapviewer.model.map.species.Element;
import lcsb.mapviewer.model.map.species.Species;
/**
......@@ -24,118 +25,160 @@ import lcsb.mapviewer.model.map.species.Species;
*
*/
public class SubModelCommand extends NewModelCommand {
/**
* Polygon that limits the area for the new model.
*
*/
private Path2D polygon;
/**
* Default constructor.
*
* @param model
* original {@link NewModelCommand#model}
* @param polygon
* #polygon that limits the area for the new model
*/
public SubModelCommand(Model model, Path2D polygon) {
super(model);
this.polygon = polygon;
}
@Override
public Model execute() {
CopyCommand copy = new CopyCommand(getModel());
Model result = copy.execute();
Set<Element> aliasNotToRemove = new HashSet<Element>();
for (Element alias : result.getElements()) {
if (polygon.intersects(alias.getBorder())) {
aliasNotToRemove.add(alias);
}
}
boolean added = false;
do {
Set<Element> iterativeAliasNotToRemove = new HashSet<>();
for (Element alias : aliasNotToRemove) {
Element parent = alias.getCompartment();
if (parent != null) {
if (!aliasNotToRemove.contains(parent)) {
iterativeAliasNotToRemove.add(parent);
}
}
if (alias instanceof Species) {
parent = ((Species) alias).getComplex();
if (parent != null) {
if (!aliasNotToRemove.contains(parent)) {
iterativeAliasNotToRemove.add(parent);
}
}
}
}
added = iterativeAliasNotToRemove.size() != 0;
aliasNotToRemove.addAll(iterativeAliasNotToRemove);
} while (added);
List<Element> aliasToRemove = new ArrayList<Element>();
for (Element alias : result.getElements()) {
if (!(polygon.intersects(alias.getBorder()))) {
boolean remove = true;
if (alias instanceof Species) {
remove = ((Species) alias).getComplex() == null;
}
if (aliasNotToRemove.contains(alias)) {
remove = false;
}
if (remove) {
aliasToRemove.add(alias);
if (alias instanceof Complex) {
List<Species> aliases = ((Complex) alias).getAllChildren();
aliasToRemove.addAll(aliases);
}
}
}
}
for (Element alias : aliasToRemove) {
result.removeElement(alias);
}
List<Reaction> reactionsToRemove = new ArrayList<Reaction>();
for (Reaction reaction : result.getReactions()) {
boolean remove = false;
for (AbstractNode node : reaction.getNodes()) {
if (node instanceof ReactionNode) {
if (!result.getElements().contains(((ReactionNode) node).getElement())) {
remove = true;
break;
}
}
}
if (remove) {
reactionsToRemove.add(reaction);
}
}
for (Reaction reaction : reactionsToRemove) {
result.removeReaction(reaction);
}
for (Layer layer : result.getLayers()) {
List<LayerText> textToRemove = new ArrayList<LayerText>();
for (LayerText text : layer.getTexts()) {
if (!(polygon.intersects(text.getBorder()))) {
textToRemove.add(text);
}
}
for (LayerText text : textToRemove) {
layer.removeLayerText(text);
}
}
return result;
}
Logger logger = Logger.getLogger(SubModelCommand.class);
/**
* Polygon that limits the area for the new model.
*
*/
private Path2D polygon;
private Set<Integer> elementIds;
private Set<Integer> reactionIds;
/**
* Default constructor.
*
* @param model
* original {@link NewModelCommand#model}
* @param polygon
* #polygon that limits the area for the new model
*/
public SubModelCommand(Model model, Path2D polygon) {
this(model, polygon, new HashSet<>(), new HashSet<>());
}
/**
* Default constructor.
*
* @param model
* original {@link NewModelCommand#model}
* @param polygon
* #polygon that limits the area for the new model
*/
public SubModelCommand(Model model, Path2D polygon, Set<Integer> elementIds, Set<Integer> reactionIds) {
super(model);
this.polygon = polygon;
this.elementIds = elementIds;
this.reactionIds = reactionIds;
}
@Override
public Model execute() {
CopyCommand copy = new CopyCommand(getModel());
Model result = copy.execute();
Set<Element> inputElements = new HashSet<>();
if (elementIds.size() == 0) {
inputElements.addAll(result.getElements());
} else {
for (Element element : getModel().getElements()) {
if (elementIds.contains(element.getId())) {
inputElements.add(result.getElementByElementId(element.getElementId()));
}
}
}
Set<Element> aliasNotToRemove = new HashSet<>();
for (Element alias : result.getElements()) {
if (polygon.intersects(alias.getBorder())) {
aliasNotToRemove.add(alias);
}
}
aliasNotToRemove.retainAll(inputElements);
boolean added = false;
do {
Set<Element> iterativeAliasNotToRemove = new HashSet<>();
for (Element alias : aliasNotToRemove) {
Element parent = alias.getCompartment();
if (parent != null) {
if (!aliasNotToRemove.contains(parent)) {
iterativeAliasNotToRemove.add(parent);
}
}
if (alias instanceof Species) {
parent = ((Species) alias).getComplex();
if (parent != null) {
if (!aliasNotToRemove.contains(parent)) {
iterativeAliasNotToRemove.add(parent);
}
}
}
}
added = iterativeAliasNotToRemove.size() != 0;
aliasNotToRemove.addAll(iterativeAliasNotToRemove);
} while (added);
List<Element> aliasToRemove = new ArrayList<>();
for (Element element : result.getElements()) {
if (!(polygon.intersects(element.getBorder())) || !inputElements.contains(element)) {
boolean remove = true;
if (element instanceof Species) {
remove = ((Species) element).getComplex() == null;
}
if (aliasNotToRemove.contains(element)) {
remove = false;
}
if (remove) {
aliasToRemove.add(element);
if (element instanceof Complex) {
List<Species> aliases = ((Complex) element).getAllChildren();
aliasToRemove.addAll(aliases);
}
}
}
}
for (Element alias : aliasToRemove) {
result.removeElement(alias);
}
Set<String> reactionStringIds = new HashSet<>();
for (Reaction reaction : getModel().getReactions()) {
if (reactionIds.size() == 0 || reactionIds.contains(reaction.getId())) {
reactionStringIds.add(reaction.getElementId());
}
}
List<Reaction> reactionsToRemove = new ArrayList<>();
for (Reaction reaction : result.getReactions()) {
boolean remove = false;
if (!reactionStringIds.contains(reaction.getElementId())) {
remove = true;
} else {
for (ReactionNode node : reaction.getReactionNodes()) {
if (!result.getElements().contains(node.getElement())) {
remove = true;
break;
}
}
}
if (remove) {
reactionsToRemove.add(reaction);
}
}
for (Reaction reaction : reactionsToRemove) {
result.removeReaction(reaction);
}
for (Layer layer : result.getLayers()) {
List<LayerText> textToRemove = new ArrayList<>();
for (LayerText text : layer.getTexts()) {
if (!(polygon.intersects(text.getBorder()))) {
textToRemove.add(text);
}
}
for (LayerText text : textToRemove) {
layer.removeLayerText(text);
}
}
return result;
}
}
......@@ -2,167 +2,245 @@ package lcsb.mapviewer.commands;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.awt.geom.Path2D;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashSet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import lcsb.mapviewer.converter.ConverterParams;
import lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser;
import lcsb.mapviewer.model.map.model.Model;
import lcsb.mapviewer.model.map.model.ModelComparator;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class SubModelCommandTest extends CommandTestFunctions {
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testGetSubmodel1() throws Exception {
try {
Model model = getModelForFile("testFiles/spliting_test_Case.xml", true);
Path2D polygon = new Path2D.Double();
polygon.moveTo(0, 0);
polygon.lineTo(0, 100);
polygon.lineTo(100, 100);
polygon.lineTo(100, 0);
polygon.closePath();
Model copy = new SubModelCommand(model, polygon).execute();
assertEquals(2, copy.getElements().size());
assertEquals(0, copy.getReactions().size());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testGetSubmodel2() throws Exception {
try {
Model model = getModelForFile("testFiles/spliting_test_Case.xml", true);
Path2D polygon = new Path2D.Double();
polygon.moveTo(50, 50);
polygon.lineTo(350, 50);
polygon.lineTo(350, 200);
polygon.lineTo(50, 200);
polygon.closePath();
Model copy = new SubModelCommand(model, polygon).execute();
assertEquals(9, copy.getElements().size());
assertEquals(1, copy.getReactions().size());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testGetSubmodel3() throws Exception {
try {
Model model = getModelForFile("testFiles/spliting_test_Case.xml", true);
Path2D polygon = new Path2D.Double();
polygon.moveTo(0, 200);
polygon.lineTo(350, 200);
polygon.lineTo(350, 400);
polygon.lineTo(0, 400);
polygon.closePath();
Model copy = new SubModelCommand(model, polygon).execute();
double dx = 10;
double dy = -10;
new MoveCommand(copy, dx, dy).execute();
assertEquals(model.getElementByElementId("sa3").getCenterX(), copy.getElementByElementId("sa3").getCenterX() - dx, EPSILON);
assertEquals(model.getElementByElementId("sa3").getCenterY(), copy.getElementByElementId("sa3").getCenterY() - dy, EPSILON);
assertEquals(model.getReactionByReactionId("re3").getLines().get(0).getX2(), copy.getReactionByReactionId("re3").getLines().get(0).getX2() - dx, EPSILON);
assertEquals(model.getReactionByReactionId("re3").getLines().get(0).getY2(), copy.getReactionByReactionId("re3").getLines().get(0).getY2() - dy, EPSILON);
CellDesignerXmlParser parser = new CellDesignerXmlParser();
String xml = parser.toXml(copy);
InputStream stream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
Model copy2 = parser.createModel(new ConverterParams().inputStream(stream).sizeAutoAdjust(false));
ModelComparator comparator = new ModelComparator();
// check if after conversion to xml everything works
assertEquals(0, comparator.compare(copy, copy2));
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testGetSubmodelWithoutCompartments() throws Exception {
try {
Model model = getModelForFile("testFiles/compartments.xml", true);
Path2D polygon = new Path2D.Double();
polygon.moveTo(0, 10);
polygon.lineTo(10, 10);
polygon.lineTo(10, 0);
polygon.lineTo(0, 0);
polygon.closePath();
Model copy = new SubModelCommand(model, polygon).execute();
// we should cut off some of compartmets
assertFalse(model.getLayers().iterator().next().getTexts().size() == copy.getLayers().iterator().next().getTexts().size());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testGetSubmodelWithoutCompartments2() throws Exception {
try {
Model model = getModelForFile("testFiles/problematic/cutting_without_compartment.xml", true);
Path2D polygon = new Path2D.Double();
polygon.moveTo(0, 0);
polygon.lineTo(0, 500);
polygon.lineTo(300, 500);
polygon.lineTo(300, 0);
polygon.closePath();
Model copy = new SubModelCommand(model, polygon).execute();
CellDesignerXmlParser parser = new CellDesignerXmlParser();
String xmlString = parser.toXml(copy);
InputStream stream = new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8));
Model model2 = parser.createModel(new ConverterParams().inputStream(stream).sizeAutoAdjust(false));
ModelComparator mc = new ModelComparator();
assertEquals(0, mc.compare(copy, model2));
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testGetSubmodel1() throws Exception {
try {
Model model = getModelForFile("testFiles/spliting_test_Case.xml", true);
Path2D polygon = new Path2D.Double();
polygon.moveTo(0, 0);
polygon.lineTo(0, 100);
polygon.lineTo(100, 100);
polygon.lineTo(100, 0);
polygon.closePath();
Model copy = new SubModelCommand(model, polygon).execute();
assertEquals(2, copy.getElements().size());
assertEquals(0, copy.getReactions().size());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testGetSubmodel2() throws Exception {
try {
Model model = getModelForFile("testFiles/spliting_test_Case.xml", true);
Path2D polygon = new Path2D.Double();
polygon.moveTo(50, 50);
polygon.lineTo(350, 50);
polygon.lineTo(350, 200);
polygon.lineTo(50, 200);
polygon.closePath();
Model copy = new SubModelCommand(model, polygon).execute();
assertEquals(9, copy.getElements().size());
assertEquals(1, copy.getReactions().size());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testGetSubmodel3() throws Exception {
try {
Model model = getModelForFile("testFiles/spliting_test_Case.xml", true);
Path2D polygon = new Path2D.Double();
polygon.moveTo(0, 200);
polygon.lineTo(350, 200);
polygon.lineTo(350, 400);
polygon.lineTo(0, 400);
polygon.closePath();
Model copy = new SubModelCommand(model, polygon).execute();
double dx = 10;
double dy = -10;
new MoveCommand(copy, dx, dy).execute();
assertEquals(model.getElementByElementId("sa3").getCenterX(), copy.getElementByElementId("sa3").getCenterX() - dx,
EPSILON);
assertEquals(model.getElementByElementId("sa3").getCenterY(), copy.getElementByElementId("sa3").getCenterY() - dy,
EPSILON);
assertEquals(model.getReactionByReactionId("re3").getLines().get(0).getX2(),
copy.getReactionByReactionId("re3").getLines().get(0).getX2() - dx, EPSILON);
assertEquals(model.getReactionByReactionId("re3").getLines().get(0).getY2(),
copy.getReactionByReactionId("re3").getLines().get(0).getY2() - dy, EPSILON);
CellDesignerXmlParser parser = new CellDesignerXmlParser();
String xml = parser.toXml(copy);
InputStream stream = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
Model copy2 = parser.createModel(new ConverterParams().inputStream(stream).sizeAutoAdjust(false));
ModelComparator comparator = new ModelComparator();
// check if after conversion to xml everything works
assertEquals(0, comparator.compare(copy, copy2));
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
@Test
public void testGetSubmodelWithoutCompartments() throws Exception {
try {
Model model = getModelForFile("testFiles/compartments.xml", true);
Path2D polygon = new Path2D.Double();
polygon.moveTo(0, 10);
polygon.lineTo(10, 10);
polygon.lineTo(10, 0);
polygon.lineTo(0, 0);
polygon.closePath();
Model copy = new SubModelCommand(model, polygon).execute();