diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/SubModelCommand.java b/model-command/src/main/java/lcsb/mapviewer/commands/SubModelCommand.java
index 0ab7ea8d342d85d8b1df2ed67da5d0511292b20a..b1e301093a37e90c7e003adfb607acfadd20ca73 100644
--- a/model-command/src/main/java/lcsb/mapviewer/commands/SubModelCommand.java
+++ b/model-command/src/main/java/lcsb/mapviewer/commands/SubModelCommand.java
@@ -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;
+  }
 
 }
diff --git a/model-command/src/test/java/lcsb/mapviewer/commands/SubModelCommandTest.java b/model-command/src/test/java/lcsb/mapviewer/commands/SubModelCommandTest.java
index ccfb0bb1adb1959a048126a8de13f1522eabff26..d4e7f30e6ed84db9ffad7a6caa4a5ebdacddf562 100644
--- a/model-command/src/test/java/lcsb/mapviewer/commands/SubModelCommandTest.java
+++ b/model-command/src/test/java/lcsb/mapviewer/commands/SubModelCommandTest.java
@@ -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();
+
+      // 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;
+    }
+  }
+
+  @Test
+  public void testGetSubmodelWithElementIds() throws Exception {
+    try {
+      Model model = getModelForFile("testFiles/spliting_test_Case.xml", false);
+
+      Path2D polygon = new Path2D.Double();
+      polygon.moveTo(0, 0);
+      polygon.lineTo(0, 1000);
+      polygon.lineTo(1000, 1000);
+      polygon.lineTo(1000, 0);
+      polygon.closePath();
+      model.getElementByElementId("sa2").setId(-2);
+
+      Model copy = new SubModelCommand(model, polygon, new HashSet<>(Arrays.asList(-2)), new HashSet<>()).execute();
+
+      assertEquals(1, copy.getElements().size());
+      assertEquals(0, copy.getReactions().size());
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testGetSubmodelWithEmptyElementIds() throws Exception {
+    try {
+      Model model = getModelForFile("testFiles/spliting_test_Case.xml", true);
+
+      Path2D polygon = new Path2D.Double();
+      polygon.moveTo(0, 0);
+      polygon.lineTo(0, 1000);
+      polygon.lineTo(1000, 1000);
+      polygon.lineTo(1000, 0);
+      polygon.closePath();
+
+      Model copy = new SubModelCommand(model, polygon, new HashSet<>(), new HashSet<>()).execute();
+
+      assertEquals(12, copy.getElements().size());
+      assertEquals(3, copy.getReactions().size());
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+
+  @Test
+  public void testGetSubmodelWithReactionIds() throws Exception {
+    try {
+      Model model = getModelForFile("testFiles/spliting_test_Case.xml", false);
+
+      Path2D polygon = new Path2D.Double();
+      polygon.moveTo(0, 0);
+      polygon.lineTo(0, 1000);
+      polygon.lineTo(1000, 1000);
+      polygon.lineTo(1000, 0);
+      polygon.closePath();
+      model.getReactions().iterator().next().setId(-2);
+
+      Model copy = new SubModelCommand(model, polygon, new HashSet<>(), new HashSet<>(Arrays.asList(-2))).execute();
+
+      assertEquals(1, copy.getReactions().size());
+
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
 
 }
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/ModelController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/ModelController.java
index d350d59b6131c28a72bc47bb2f8ba281a0018a74..c72604753660d2bfb4462e08e3271b41e277a4a7 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/ModelController.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/ModelController.java
@@ -93,8 +93,8 @@ public class ModelController extends BaseController {
         .body(file.getFileContent());
   }
 
-  @RequestMapping(value = "/projects/{projectId}/models/{modelId}:downloadModel", method = {
-      RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON_VALUE })
+  @RequestMapping(value = "/projects/{projectId}/models/{modelId}:downloadModel", method = { RequestMethod.GET,
+      RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
   public ResponseEntity<byte[]> getModelAsModelFile(//
       @CookieValue(value = Configuration.AUTH_TOKEN) String token, //
       @PathVariable(value = "projectId") String projectId, //
@@ -103,12 +103,14 @@ public class ModelController extends BaseController {
       @RequestParam(value = "backgroundOverlayId", defaultValue = "") String backgroundOverlayId, //
       @RequestParam(value = "overlayIds", defaultValue = "") String overlayIds, //
       @RequestParam(value = "zoomLevel", defaultValue = "") String zoomLevel, //
-      @RequestParam(value = "polygonString", defaultValue = "") String polygonString//
+      @RequestParam(value = "polygonString", defaultValue = "") String polygonString, //
+      @RequestParam(value = "elementIds", defaultValue = "") String elementIds, //
+      @RequestParam(value = "reactionIds", defaultValue = "") String reactionIds //
   ) throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException,
       ConverterException, InconsistentModelException {
 
     FileEntry file = modelController.getModelAsModelFile(token, projectId, modelId, handlerClass, backgroundOverlayId,
-        overlayIds, zoomLevel, polygonString);
+        overlayIds, zoomLevel, polygonString, elementIds, reactionIds);
     MediaType type = MediaType.APPLICATION_OCTET_STREAM;
     return ResponseEntity.ok().contentLength(file.getFileContent().length).contentType(type)
         .header("Content-Disposition", "attachment; filename=" + file.getOriginalFileName())
diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/ModelRestImpl.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/ModelRestImpl.java
index f735bb5937aa81e1c578ebfb0d15a1142caa8d6e..bf5adaf6922b73d6f059e71c5b02f80309e6466d 100644
--- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/ModelRestImpl.java
+++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/ModelRestImpl.java
@@ -10,6 +10,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -58,8 +59,6 @@ import lcsb.mapviewer.services.utils.data.BuildInLayout;
 @Transactional(value = "txManager")
 public class ModelRestImpl extends BaseRestImpl {
 
-
-
   /**
    * Constant defining size of the array returned by
    * {@link PathIterator#currentSegment(double[])} method. More information can be
@@ -180,7 +179,6 @@ public class ModelRestImpl extends BaseRestImpl {
     } else {
       throw new InvalidArgumentException();
     }
-
   }
 
   private Double parseDouble(Object value) throws QueryException {
@@ -206,37 +204,25 @@ public class ModelRestImpl extends BaseRestImpl {
   }
 
   public FileEntry getModelAsModelFile(String token, String projectId, String modelId, String handlerClass,
-      String backgroundOverlayId, String overlayIds, String zoomLevel, String polygonString)
-      throws SecurityException, QueryException, IOException, InvalidColorSchemaException, CommandExecutionException,
-      ConverterException, InconsistentModelException {
+      String backgroundOverlayId, String overlayIds, String zoomLevel, String polygonString, String elementIds,
+      String reactionIds) throws SecurityException, QueryException, IOException, InvalidColorSchemaException,
+      CommandExecutionException, ConverterException, InconsistentModelException {
     User user = getUserService().getUserByToken(token);
-    Model topModel = getModelService().getLastModelByProjectId(projectId, token);
-    if (topModel == null) {
-      throw new ObjectNotFoundException("Project with given id doesn't exist");
-    }
-
-    Model originalModel = topModel.getSubmodelById(modelId);
-
-    if (originalModel == null) {
-      throw new ObjectNotFoundException("Model with given id doesn't exist");
-    }
+    Model originalModel = getModelByModelId(token, projectId, modelId);
 
     Path2D polygon = stringToPolygon(polygonString, originalModel);
 
+    Set<Integer> elementIdsList = stringListToIntegerSet(elementIds);
+    Set<Integer> reactionIdsList = stringListToIntegerSet(reactionIds);
+
     // create model bounded by the polygon
-    SubModelCommand subModelCommand = new SubModelCommand(originalModel, polygon);
+    SubModelCommand subModelCommand = new SubModelCommand(originalModel, polygon, elementIdsList, reactionIdsList);
     Model part = subModelCommand.execute();
 
     // Get list of overlay ids
-    String[] overlayIdsList;
-    if (overlayIds == null || overlayIds.trim().isEmpty()) {
-      overlayIdsList = new String[0];
-    } else {
-      overlayIdsList = overlayIds.split(",");
-    }
+    String[] overlayIdsList = stringListToArray(overlayIds);
     // Remove all colors
     if (overlayIdsList.length > 0) {
-
       for (Element element : part.getElements()) {
         element.setColor(Color.WHITE);
       }
@@ -264,6 +250,43 @@ public class ModelRestImpl extends BaseRestImpl {
 
   }
 
+  protected Set<Integer> stringListToIntegerSet(String elementIds) {
+    Set<Integer> result = new HashSet<>();
+    if (elementIds != null) {
+      String[] stringIds = elementIds.split(",");
+      for (String string : stringIds) {
+        if (!string.trim().isEmpty()) {
+          result.add(Integer.valueOf(string));
+        }
+      }
+    }
+    return result;
+  }
+
+  private Model getModelByModelId(String token, String projectId, String modelId)
+      throws SecurityException, ObjectNotFoundException {
+    Model topModel = getModelService().getLastModelByProjectId(projectId, token);
+    if (topModel == null) {
+      throw new ObjectNotFoundException("Project with given id doesn't exist");
+    }
+
+    Model originalModel = topModel.getSubmodelById(modelId);
+
+    if (originalModel == null) {
+      throw new ObjectNotFoundException("Model with given id doesn't exist");
+    }
+    return originalModel;
+  }
+
+  private String[] stringListToArray(String overlayIds) {
+    String[] overlayIdsList;
+    if (overlayIds == null || overlayIds.trim().isEmpty()) {
+      overlayIdsList = new String[0];
+    } else {
+      overlayIdsList = overlayIds.split(",");
+    }
+    return overlayIdsList;
+  }
 
   public FileEntry getModelAsImage(String token, String projectId, String modelId, String handlerClass,
       String backgroundOverlayId, String overlayIds, String zoomLevel, String polygonString) throws SecurityException,
@@ -424,5 +447,4 @@ public class ModelRestImpl extends BaseRestImpl {
     return result;
   }
 
-
 }
diff --git a/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/ModelRestImplTest.java b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/ModelRestImplTest.java
index 75e4f09a45a7bffdb355311eaf3b0e8891a6f6e1..80fe6f15bc32b675e78678324bae8452893aef32 100644
--- a/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/ModelRestImplTest.java
+++ b/rest-api/src/test/java/lcsb/mapviewer/api/projects/models/ModelRestImplTest.java
@@ -9,6 +9,7 @@ import static org.mockito.ArgumentMatchers.refEq;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.junit.After;
 import org.junit.Before;
@@ -117,8 +118,8 @@ public class ModelRestImplTest extends RestTestFunctions {
   public void testGetModelAsImage() throws Exception {
     try {
       ModelRestImpl modelRest = createMockProjectRest("testFiles/model/sample.xml");
-      FileEntry result = modelRest.getModelAsImage(token, "sample", "0", PdfImageGenerator.class.getCanonicalName(),
-          "", "", "", "");
+      FileEntry result = modelRest.getModelAsImage(token, "sample", "0", PdfImageGenerator.class.getCanonicalName(), "",
+          "", "", "");
       assertNotNull(result);
     } catch (Exception e) {
       e.printStackTrace();
@@ -141,7 +142,7 @@ public class ModelRestImplTest extends RestTestFunctions {
   public void testGetModelAsFileModel() throws Exception {
     try {
       ModelRestImpl modelRest = createMockProjectRest("testFiles/model/sample.xml");
-      modelRest.getModelAsModelFile(token, "sample", "0", "", "", "", "", "");
+      modelRest.getModelAsModelFile(token, "sample", "0", "", "", "", "", "", null, null);
       fail("Exception expected");
     } catch (QueryException e) {
     } catch (Exception e) {
@@ -155,7 +156,7 @@ public class ModelRestImplTest extends RestTestFunctions {
     try {
       ModelRestImpl modelRest = createMockProjectRest("testFiles/model/sample.xml");
       modelRest.getModelAsModelFile(token, "sample", "0", CellDesignerXmlParser.class.getCanonicalName(), "", "", "",
-          "0,0;90,0;90,90;90,0");
+          "0,0;90,0;90,90;90,0", null, null);
     } catch (Exception e) {
       e.printStackTrace();
       throw e;
@@ -166,7 +167,7 @@ public class ModelRestImplTest extends RestTestFunctions {
   public void testGetModelAsFileModel3() throws Exception {
     try {
       ModelRestImpl modelRest = createMockProjectRest("testFiles/model/sample.xml");
-      modelRest.getModelAsModelFile(token, "sample", "0", "", "", "", "", "0,0;90,0;90,90;90,0");
+      modelRest.getModelAsModelFile(token, "sample", "0", "", "", "", "", "0,0;90,0;90,90;90,0", null, null);
       fail("Exception expected");
     } catch (QueryException e) {
     } catch (Exception e) {
@@ -175,5 +176,26 @@ public class ModelRestImplTest extends RestTestFunctions {
     }
   }
 
-
+  @Test
+  public void testEmptyStringListToIntegerList() throws Exception {
+    try {
+      Set<Integer> ids = _modelRestImpl.stringListToIntegerSet("");
+      assertNotNull(ids);
+      assertEquals(0, ids.size());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
+  @Test
+  public void testStringListToIntegerArray() throws Exception {
+    try {
+      Set<Integer> ids = _modelRestImpl.stringListToIntegerSet("12,3");
+      assertNotNull(ids);
+      assertEquals(2, ids.size());
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw e;
+    }
+  }
 }