diff --git a/vipra-backend/src/main/java/de/vipra/rest/resource/ArticleResource.java b/vipra-backend/src/main/java/de/vipra/rest/resource/ArticleResource.java
index 74c809ec4d09adc853939ab6cfaa6b8b02a5da08..09991c62335e81fc930c42bdbb78d2818771a158 100644
--- a/vipra-backend/src/main/java/de/vipra/rest/resource/ArticleResource.java
+++ b/vipra-backend/src/main/java/de/vipra/rest/resource/ArticleResource.java
@@ -1,19 +1,12 @@
 package de.vipra.rest.resource;
 
 import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
 import java.util.List;
 
 import javax.servlet.ServletContext;
 import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
@@ -32,7 +25,6 @@ import de.vipra.util.Config;
 import de.vipra.util.MongoUtils;
 import de.vipra.util.StringUtils;
 import de.vipra.util.ex.ConfigException;
-import de.vipra.util.ex.DatabaseException;
 import de.vipra.util.model.ArticleFull;
 import de.vipra.util.model.TopicModel;
 import de.vipra.util.service.MongoService;
@@ -115,64 +107,4 @@ public class ArticleResource {
 		}
 	}
 
-	@POST
-	@Consumes(MediaType.APPLICATION_JSON)
-	@Produces(MediaType.APPLICATION_JSON)
-	public Response createArticle(ArticleFull article) {
-		final ResponseWrapper<ArticleFull> res = new ResponseWrapper<>();
-		try {
-			article = dbArticles.createSingle(article);
-			final URI newUri = new URL(uri.getAbsolutePath().toURL(), article.getId().toString()).toURI();
-			return res.created(article, newUri);
-		} catch (DatabaseException | MalformedURLException | URISyntaxException e) {
-			e.printStackTrace();
-			res.addError(new APIError(Response.Status.INTERNAL_SERVER_ERROR, "item could not be created",
-					"item could not be created due to an internal server error"));
-			return res.serverError();
-		}
-	}
-
-	@DELETE
-	@Path("{id}")
-	public Response deleteArticle(@PathParam("id") final String id) {
-		final ResponseWrapper<ArticleFull> res = new ResponseWrapper<>();
-		long deleted;
-		try {
-			deleted = dbArticles.deleteSingle(MongoUtils.objectId(id));
-		} catch (final DatabaseException e) {
-			e.printStackTrace();
-			res.addError(new APIError(Response.Status.INTERNAL_SERVER_ERROR, "item could not be deleted",
-					"item could not be created due to an internal server error"));
-			return res.serverError();
-		}
-		final int del = deleted > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) deleted;
-		switch (del) {
-			case 0:
-				res.addError(new APIError(Response.Status.NOT_FOUND, "Article not found", String.format(Messages.NOT_FOUND, "article", id)));
-				return res.notFound();
-			case 1:
-				return res.noContent();
-			default:
-				return res.serverError();
-		}
-	}
-
-	@PUT
-	@Consumes(MediaType.APPLICATION_JSON)
-	@Produces(MediaType.APPLICATION_JSON)
-	@Path("{id}")
-	public Response replaceArticle(@PathParam("id") final String id, final ArticleFull article) {
-		final ResponseWrapper<ArticleFull> res = new ResponseWrapper<>();
-
-		try {
-			dbArticles.replaceSingle(article);
-			return res.ok(article);
-		} catch (final DatabaseException e) {
-			e.printStackTrace();
-			res.addError(new APIError(Response.Status.INTERNAL_SERVER_ERROR, "item could not be updated",
-					"item could not be updated due to an internal server error"));
-			return res.serverError();
-		}
-	}
-
 }
diff --git a/vipra-backend/src/main/java/de/vipra/rest/resource/TopicResource.java b/vipra-backend/src/main/java/de/vipra/rest/resource/TopicResource.java
index 3f422d62145b3f43ae7132a7b67032ce5572789c..2d977f74e85508505224c1d1d30c83ff6f6aa886 100644
--- a/vipra-backend/src/main/java/de/vipra/rest/resource/TopicResource.java
+++ b/vipra-backend/src/main/java/de/vipra/rest/resource/TopicResource.java
@@ -138,11 +138,11 @@ public class TopicResource {
 	@Consumes(MediaType.APPLICATION_JSON)
 	@Produces(MediaType.APPLICATION_JSON)
 	@Path("{id}")
-	public Response replaceTopic(@PathParam("id") final String id, final TopicFull topic) {
+	public Response renameTopic(@PathParam("id") final String id, final TopicFull topic) {
 		final ResponseWrapper<TopicFull> res = new ResponseWrapper<>();
 
 		try {
-			dbTopics.replaceSingle(topic);
+			dbTopics.updateSingle(topic, "name");
 			return res.ok(topic);
 		} catch (final DatabaseException e) {
 			e.printStackTrace();
diff --git a/vipra-backend/src/main/java/de/vipra/rest/resource/WindowResource.java b/vipra-backend/src/main/java/de/vipra/rest/resource/WindowResource.java
index 6b3bed96c32a2e41efc086673d1716593f98c1cb..7d1555c7c75a1d05aaf8772da2bc46c91037644e 100644
--- a/vipra-backend/src/main/java/de/vipra/rest/resource/WindowResource.java
+++ b/vipra-backend/src/main/java/de/vipra/rest/resource/WindowResource.java
@@ -19,18 +19,18 @@ import de.vipra.util.Config;
 import de.vipra.util.StringUtils;
 import de.vipra.util.ex.ConfigException;
 import de.vipra.util.model.TopicModel;
-import de.vipra.util.model.Window;
+import de.vipra.util.model.WindowFull;
 import de.vipra.util.service.MongoService;
 import de.vipra.util.service.Service.QueryBuilder;
 
 @Path("windows")
 public class WindowResource {
 
-	final MongoService<Window, Integer> dbWindows;
+	final MongoService<WindowFull, Integer> dbWindows;
 
 	public WindowResource(@Context final ServletContext servletContext) throws ConfigException, IOException {
 		final Config config = Config.getConfig();
-		dbWindows = MongoService.getDatabaseService(config, Window.class);
+		dbWindows = MongoService.getDatabaseService(config, WindowFull.class);
 	}
 
 	@GET
@@ -38,7 +38,7 @@ public class WindowResource {
 	public Response getWindows(@QueryParam("topicModel") final String topicModel, @QueryParam("skip") final Integer skip,
 			@QueryParam("limit") final Integer limit, @QueryParam("sort") @DefaultValue("startDate") final String sortBy,
 			@QueryParam("fields") final String fields) {
-		final ResponseWrapper<List<Window>> res = new ResponseWrapper<>();
+		final ResponseWrapper<List<WindowFull>> res = new ResponseWrapper<>();
 
 		if (res.hasErrors())
 			return Response.status(Response.Status.BAD_REQUEST).entity(res).build();
@@ -51,7 +51,7 @@ public class WindowResource {
 			if (topicModel != null && !topicModel.isEmpty())
 				query.criteria("topicModel", new TopicModel(topicModel));
 
-			final List<Window> windows = dbWindows.getMultiple(query);
+			final List<WindowFull> windows = dbWindows.getMultiple(query);
 
 			if ((skip != null && skip > 0) || (limit != null && limit > 0))
 				res.addHeader("total", dbWindows.count(null));
@@ -65,4 +65,5 @@ public class WindowResource {
 			return Response.status(Response.Status.BAD_REQUEST).entity(res).build();
 		}
 	}
+
 }
\ No newline at end of file
diff --git a/vipra-backend/src/main/java/de/vipra/ws/State.java b/vipra-backend/src/main/java/de/vipra/ws/State.java
deleted file mode 100644
index cf5731a2a7687dd6ee09809f58bc12f0d559a46f..0000000000000000000000000000000000000000
--- a/vipra-backend/src/main/java/de/vipra/ws/State.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package de.vipra.ws;
-
-public enum State {
-	INDEX("index"),
-	ABOUT("about"),
-	NETWORK("network"),
-	ARTICLES("articles"),
-	TOPICS("topics"),
-	WORDS("words"),
-	ID(null);
-
-	private final String state;
-
-	State(final String state) {
-		this.state = state;
-	}
-
-	public String getState() {
-		return state;
-	}
-
-	public static State find(final String str) {
-		for (final State state : State.values())
-			if (state.state.equalsIgnoreCase(str))
-				return state;
-		return ID;
-	}
-
-}
diff --git a/vipra-backend/src/main/java/de/vipra/ws/StateSession.java b/vipra-backend/src/main/java/de/vipra/ws/StateSession.java
deleted file mode 100644
index be6ba8e4d9d22b9873b7b8e0a5ed86ac0e792694..0000000000000000000000000000000000000000
--- a/vipra-backend/src/main/java/de/vipra/ws/StateSession.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package de.vipra.ws;
-
-import javax.websocket.Session;
-
-public class StateSession {
-
-	private final Session session;
-	private State state;
-
-	public StateSession(final Session session) {
-		if (session == null)
-			throw new NullPointerException("session cannot be null");
-		this.session = session;
-	}
-
-	public State getState() {
-		return state;
-	}
-
-	public void setState(final State state) {
-		this.state = state;
-	}
-
-	public void setState(final String state) {
-		this.state = State.find(state);
-	}
-
-	public Session getSession() {
-		return session;
-	}
-
-	@Override
-	public boolean equals(Object o) {
-		if (o == null)
-			return false;
-
-		if (o instanceof StateSession)
-			o = ((StateSession) o).getSession();
-
-		if (o instanceof Session)
-			return o.equals(session);
-
-		return false;
-	}
-
-	@Override
-	public int hashCode() {
-		return session.hashCode();
-	}
-
-}
diff --git a/vipra-backend/src/main/java/de/vipra/ws/StateSessionMap.java b/vipra-backend/src/main/java/de/vipra/ws/StateSessionMap.java
deleted file mode 100644
index 02c47730ad4c92eb442d891ba65e6d30dbf40e6f..0000000000000000000000000000000000000000
--- a/vipra-backend/src/main/java/de/vipra/ws/StateSessionMap.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package de.vipra.ws;
-
-import java.util.HashMap;
-import java.util.stream.Stream;
-
-import javax.websocket.Session;
-
-public class StateSessionMap extends HashMap<StateSession, StateSession> {
-
-	private static final long serialVersionUID = 1L;
-
-	public Stream<Session> stream(final State state) {
-		return entrySet().stream().filter(s -> s.getKey().getState() == state).map(s -> s.getKey().getSession());
-	}
-
-	public void add(final StateSession session) {
-		put(session, session);
-	}
-
-}
diff --git a/vipra-backend/src/main/java/de/vipra/ws/WebSocket.java b/vipra-backend/src/main/java/de/vipra/ws/WebSocket.java
deleted file mode 100644
index 5cfd37f8f617f20c07ddd0b9a0222acb6417e3c9..0000000000000000000000000000000000000000
--- a/vipra-backend/src/main/java/de/vipra/ws/WebSocket.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package de.vipra.ws;
-
-import java.io.IOException;
-
-import javax.websocket.OnClose;
-import javax.websocket.OnError;
-import javax.websocket.OnMessage;
-import javax.websocket.OnOpen;
-import javax.websocket.Session;
-import javax.websocket.server.ServerEndpoint;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import de.vipra.ws.msg.InitMessage;
-import de.vipra.ws.msg.WebSocketMessage;
-
-@ServerEndpoint("/ws")
-public class WebSocket {
-
-	public static final Logger log = LogManager.getLogger(WebSocket.class);
-
-	public static final ObjectMapper mapper = new ObjectMapper();
-	public static final StateSessionMap sessions = new StateSessionMap();
-
-	@OnOpen
-	public void open(final Session session) {
-		log.debug("connect");
-		sessions.add(new StateSession(session));
-	}
-
-	@OnClose
-	public void close(final Session session) {
-		log.debug("disconnect");
-		sessions.remove(session);
-	}
-
-	@OnError
-	public void onError(final Throwable error) {
-		log.error(error);
-	}
-
-	@OnMessage
-	public void handleMessage(final String input, final Session session) throws JsonParseException, JsonMappingException, IOException {
-		log.trace("message received");
-		try {
-			final WebSocketMessage msg = mapper.readValue(input, WebSocketMessage.class);
-			switch (msg.getType()) {
-				case 1:
-					handleInitMessage(mapper.readValue(msg.getData(), InitMessage.class), session);
-					break;
-			}
-		} catch (final IOException e) {
-			log.error(e);
-		}
-	}
-
-	public void handleInitMessage(final InitMessage message, final Session session) {
-		log.debug("init message received. state = " + message.getState());
-		sessions.get(session).setState(message.getState());
-	}
-
-	public static void sendToState(final State state, final Object message) {
-		String json;
-		try {
-			json = mapper.writeValueAsString(message);
-		} catch (final JsonProcessingException e) {
-			log.error(e);
-			return;
-		}
-		sessions.stream(state).forEach(s -> s.getAsyncRemote().sendText(json));
-	}
-
-}
diff --git a/vipra-backend/src/main/java/de/vipra/ws/msg/InitMessage.java b/vipra-backend/src/main/java/de/vipra/ws/msg/InitMessage.java
deleted file mode 100644
index 93769d7da4637c69e1990c8375c91b379c540e8d..0000000000000000000000000000000000000000
--- a/vipra-backend/src/main/java/de/vipra/ws/msg/InitMessage.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package de.vipra.ws.msg;
-
-public class InitMessage extends WebSocketMessage {
-
-	private String state;
-
-	public String getState() {
-		return state;
-	}
-
-	public void setState(final String state) {
-		this.state = state;
-	}
-
-}
diff --git a/vipra-backend/src/main/java/de/vipra/ws/msg/WebSocketMessage.java b/vipra-backend/src/main/java/de/vipra/ws/msg/WebSocketMessage.java
deleted file mode 100644
index ac769465dddb9a759f91388575b36a25caf6d737..0000000000000000000000000000000000000000
--- a/vipra-backend/src/main/java/de/vipra/ws/msg/WebSocketMessage.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package de.vipra.ws.msg;
-
-public class WebSocketMessage {
-
-	private int type;
-
-	private String data;
-
-	public int getType() {
-		return type;
-	}
-
-	public void setType(final int type) {
-		this.type = type;
-	}
-
-	public String getData() {
-		return data;
-	}
-
-	public void setData(final String data) {
-		this.data = data;
-	}
-
-}
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/lda/Analyzer.java b/vipra-cmd/src/main/java/de/vipra/cmd/lda/Analyzer.java
index 458af103a1f6110847cd9274cdc7deb34c646d3c..365fc9a44d8c1cb06b4a1aa8fffa3c683fb1a3e4 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/lda/Analyzer.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/lda/Analyzer.java
@@ -39,6 +39,7 @@ import de.vipra.util.model.TopicModelFull;
 import de.vipra.util.model.TopicShare;
 import de.vipra.util.model.TopicWord;
 import de.vipra.util.model.Window;
+import de.vipra.util.model.WindowFull;
 import de.vipra.util.service.MongoService;
 import de.vipra.util.service.Service.QueryBuilder;
 
@@ -50,7 +51,7 @@ public class Analyzer {
 	private final MongoService<ArticleFull, ObjectId> dbArticles;
 	private final MongoService<TopicFull, ObjectId> dbTopics;
 	private final MongoService<SequenceFull, ObjectId> dbSequences;
-	private final MongoService<Window, Integer> dbWindows;
+	private final MongoService<WindowFull, Integer> dbWindows;
 	private final MongoService<TopicModelFull, String> dbTopicModels;
 
 	public Analyzer() throws AnalyzerException, ConfigException {
@@ -59,7 +60,7 @@ public class Analyzer {
 		dbArticles = MongoService.getDatabaseService(config, ArticleFull.class);
 		dbTopics = MongoService.getDatabaseService(config, TopicFull.class);
 		dbSequences = MongoService.getDatabaseService(config, SequenceFull.class);
-		dbWindows = MongoService.getDatabaseService(config, Window.class);
+		dbWindows = MongoService.getDatabaseService(config, WindowFull.class);
 		dbTopicModels = MongoService.getDatabaseService(config, TopicModelFull.class);
 
 		// check for binary
@@ -165,7 +166,7 @@ public class Analyzer {
 		// read topic definition files and create topics
 
 		final TopicModelFull topicModel = new TopicModelFull(modelConfig.getName(), modelConfig);
-		final List<Window> newWindows = new ArrayList<>(sequencesCount);
+		final List<WindowFull> newWindows = new ArrayList<>(sequencesCount);
 		final List<SequenceFull> newSequences = new ArrayList<>(topicCount * sequencesCount);
 		final List<TopicFull> newTopics = new ArrayList<>(topicCount);
 
@@ -177,7 +178,7 @@ public class Analyzer {
 
 		// create sequence windows
 		for (int idxSeq = 0; idxSeq < sequencesCount; idxSeq++) {
-			final Window newWindow = new Window();
+			final WindowFull newWindow = new WindowFull();
 			newWindow.setId(idxSeq);
 			newWindow.setStartDate(windowIndex.startDate(idxSeq));
 			newWindow.setEndDate(windowIndex.endDate(idxSeq));
@@ -259,7 +260,7 @@ public class Analyzer {
 
 				// create sequence
 				final SequenceFull newSequenceFull = new SequenceFull();
-				newSequenceFull.setWindow(newWindows.get(idxSeq));
+				newSequenceFull.setWindow(new Window(newWindows.get(idxSeq)));
 				newSequenceFull.setWords(newSeqTopicWords);
 				newSequenceFull.setRelevance(relevance);
 				newSequenceFull.setRelevanceChange(relevance - prevRelevance);
diff --git a/vipra-cmd/src/main/java/de/vipra/cmd/option/ListModelsCommand.java b/vipra-cmd/src/main/java/de/vipra/cmd/option/ListModelsCommand.java
index 54e4df82ee3865afcd9b8bd12376e248c19c4fb4..d6f1f4b694f22d2d00f42cb6924a89cb538b0970 100644
--- a/vipra-cmd/src/main/java/de/vipra/cmd/option/ListModelsCommand.java
+++ b/vipra-cmd/src/main/java/de/vipra/cmd/option/ListModelsCommand.java
@@ -19,9 +19,8 @@ public class ListModelsCommand implements Command {
 		for (final Entry<String, TopicModelConfig> entry : config.getTopicModelConfigs().entrySet())
 			longestModelName = Math.max(longestModelName, entry.getValue().getName().length());
 		for (final Entry<String, TopicModelConfig> entry : config.getTopicModelConfigs().entrySet())
-			ConsoleUtils
-					.info(" " + Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a(StringUtils.pad(entry.getValue().getName(), longestModelName)).reset()
-							+ " " + entry.getValue().toString());
+			ConsoleUtils.info(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a(StringUtils.pad(entry.getValue().getName(), longestModelName)).reset()
+					+ " " + entry.getValue().toString());
 	}
 
 }
diff --git a/vipra-ui/app/html/about.html b/vipra-ui/app/html/about.html
index a7343ea7476ff0db09d1c04401f2f969d820c168..9ba7c44e9c124de2d79e564032aae5fc8f59e4b7 100644
--- a/vipra-ui/app/html/about.html
+++ b/vipra-ui/app/html/about.html
@@ -74,23 +74,11 @@
             <th># of topics</th>
             <td ng-bind-template="{{::info.db.topics}}"></td>
           </tr>
-          <tr>
-            <th># of words</th>
-            <td ng-bind-template="{{::info.db.words}}"></td>
-          </tr>
         </tbody>
       </table>
       <h3>Constants</h3>
       <table class="table table-bordered table-fixed">
         <tbody>
-          <tr>
-            <th style="width:33%">Analyzer</th>
-            <td ng-bind-template="{{::info.const.analyzer}}"></td>
-          </tr>
-          <tr>
-            <th>Processor</th>
-            <td ng-bind-template="{{::info.const.processor}}"></td>
-          </tr>
           <tr>
             <th>Window resolution</th>
             <td ng-bind-template="{{::info.const.windowres}}"></td>
diff --git a/vipra-ui/app/html/articles/index.html b/vipra-ui/app/html/articles/index.html
index e284dcbe4c74ec2bd7f1279289092c602777eea7..ab26863ecfcdcf564862ef3434f326f8259bbb52 100644
--- a/vipra-ui/app/html/articles/index.html
+++ b/vipra-ui/app/html/articles/index.html
@@ -1,7 +1,7 @@
-<div class="container" ng-cloak ng-hide="$state.current.name !== 'articles'">
+<div class="container" ng-cloak ng-hide="!rootModels.topicModel || $state.current.name !== 'articles'">
   <div class="row">
     <div class="col-md-12">
-      <pagination total="articlesTotal" page="page" limit="limit" />
+      <pagination total="articlesTotal" page="articlesIndexModels.page" limit="articlesIndexModels.limit" />
     </div>
   </div>
   <div class="row">
@@ -12,12 +12,12 @@
           <ng-pluralize count="articlesTotal||0" when="{0:'no articles',1:'1 article',other:'{} articles'}"></ng-pluralize> in the database.
           <span ng-show="articlesTotal">
           Sort by
-          <ol class="nya-bs-select nya-bs-condensed" ng-model="opts.sortkey">
+          <ol class="nya-bs-select nya-bs-condensed" ng-model="articlesIndexModels.sortkey">
             <li value="title" class="nya-bs-option"><a>Title</a></li>
             <li value="date" class="nya-bs-option"><a>Date</a></li>
             <li value="created" class="nya-bs-option"><a>Added</a></li>
           </ol>
-          <sort-dir ng-model="opts.sortdir" />
+          <sort-dir ng-model="articlesIndexModels.sortdir" />
         </span>
         </div>
         <table class="table table-hover table-condensed">
@@ -30,14 +30,14 @@
           </tbody>
         </table>
         <div class="panel-footer">
-          Page <span ng-bind="page||1"></span> of <span ng-bind="maxPage||1"></span>
+          Page <span ng-bind="articlesIndexModels.page||1"></span> of <span ng-bind="maxPage||1"></span>
         </div>
       </div>
     </div>
   </div>
   <div class="row">
     <div class="col-md-12">
-      <pagination total="articlesTotal" page="page" limit="limit" />
+      <pagination total="articlesTotal" page="articlesIndexModels.page" limit="articlesIndexModels.limit" />
     </div>
   </div>
 </div>
diff --git a/vipra-ui/app/html/articles/show.html b/vipra-ui/app/html/articles/show.html
index 398eb46434a5f4da6f0254fa7b6a963118597dc5..1963a78b23bb0a3a2ca3a2131caf771f297bf729 100644
--- a/vipra-ui/app/html/articles/show.html
+++ b/vipra-ui/app/html/articles/show.html
@@ -1,4 +1,4 @@
-<div class="container" ng-cloak ng-hide="$state.current.name !== 'articles.show'">
+<div class="container" ng-cloak ng-hide="!rootModels.topicModel || $state.current.name !== 'articles.show'">
   <div class="row">
     <div class="col-md-12">
       <div class="page-header">
@@ -74,7 +74,6 @@
           <tr ng-repeat="topic in article.topics | orderBy:topicSort:topicSortRev">
             <td>
               <topic-link topic="topic.topic" />
-              <span class="colorbox" style="background:{{::topic.color}}"></span>
             </td>
             <td class="text-right" ng-bind-template="{{(topic.share*100).toFixed(1)}}%"></td>
           </tr>
diff --git a/vipra-ui/app/html/directives/topic-link.html b/vipra-ui/app/html/directives/topic-link.html
index 49ccb9e20545839284bb76e6f15aa5240fc6d337..7ad606fe8f90791a1f8b4db0f4d908b77ad73b0b 100644
--- a/vipra-ui/app/html/directives/topic-link.html
+++ b/vipra-ui/app/html/directives/topic-link.html
@@ -1,7 +1,7 @@
 <span>
+  <topic-menu topic="topic" right="true" />
   <a class="topic-link" ui-sref="topics.show({id:topic.id})">
     <span ng-bind="topic.name"></span>
     <ng-transclude/>
   </a>
-  <topic-menu topic="topic" right="true" />
 </span>
diff --git a/vipra-ui/app/html/explorer.html b/vipra-ui/app/html/explorer.html
index f6d7e25a2e284c75d982789798e6e5cbd256fa96..f925a7219bd3628b355028ab5a53309ef56677ee 100644
--- a/vipra-ui/app/html/explorer.html
+++ b/vipra-ui/app/html/explorer.html
@@ -1,4 +1,4 @@
-<div class="fullsize navpadding explorer" ng-cloak ng-hide="$state.current.name !== 'explorer'">
+<div class="fullsize navpadding explorer" ng-cloak ng-hide="!rootModels.topicModel || $state.current.name !== 'explorer'">
   <div class="sidebar">
     <div class="btn-group btn-group-justified" role="group" aria-label="...">
       <a class="btn btn-sm btn-default" ng-click="checkTopics(true)" title="Select all topics">All</a>
@@ -6,14 +6,14 @@
       <a class="btn btn-sm btn-default" ng-click="checkTopics()" title="Toggle all topics">Toggle</a>
     </div>
     <div class="btn-group btn-group-justified">
-      <a class="btn btn-sm btn-default" ng-model="opts.sorttopics" bs-radio="'name'" title="Sort by name">&#945;</a>
-      <a class="btn btn-sm btn-default" ng-model="opts.sorttopics" bs-radio="'avgRelevance'" title="Sort by average relevance">&#956;</a>
-      <a class="btn btn-sm btn-default" ng-model="opts.sorttopics" bs-radio="'varRelevance'" title="Sort by variance in relevance">&#963;</a>
-      <a class="btn btn-sm btn-default" ng-model="opts.sorttopics" bs-radio="'fallingRelevance'" title="Sort by falling relevance">&#8600;</a>
-      <a class="btn btn-sm btn-default" ng-model="opts.sorttopics" bs-radio="'risingRelevance'" title="Sort by rising relevance">&#8599;</a>
-      <a class="btn btn-sm btn-default" ng-model="opts.sorttopics" bs-radio="'risingDecayRelevance'" title="Sort by rising relevance with decay">&#8605;</a>
-      <a class="btn btn-sm btn-link btn-plain" ng-click="opts.sortdir=!opts.sortdir">
-        <sort-dir ng-model="opts.sortdir" />
+      <a class="btn btn-sm btn-default" ng-model="explorerModels.sorttopics" bs-radio="'name'" title="Sort by name">&#945;</a>
+      <a class="btn btn-sm btn-default" ng-model="explorerModels.sorttopics" bs-radio="'avgRelevance'" title="Sort by average relevance">&#956;</a>
+      <a class="btn btn-sm btn-default" ng-model="explorerModels.sorttopics" bs-radio="'varRelevance'" title="Sort by variance in relevance">&#963;</a>
+      <a class="btn btn-sm btn-default" ng-model="explorerModels.sorttopics" bs-radio="'fallingRelevance'" title="Sort by falling relevance">&#8600;</a>
+      <a class="btn btn-sm btn-default" ng-model="explorerModels.sorttopics" bs-radio="'risingRelevance'" title="Sort by rising relevance">&#8599;</a>
+      <a class="btn btn-sm btn-default" ng-model="explorerModels.sorttopics" bs-radio="'risingDecayRelevance'" title="Sort by rising relevance with decay">&#8605;</a>
+      <a class="btn btn-sm btn-link btn-plain" ng-click="explorerModels.sortdir=!explorerModels.sortdir">
+        <sort-dir ng-model="explorerModels.sortdir" />
       </a>
     </div>
     <div class="btn-group btn-group-justified">
@@ -21,9 +21,9 @@
       <span class="glyphicon glyphicon-remove-circle searchclear" ng-click="search=''"></span>
     </div>
     <ul class="list-unstyled topic-choice">
-      <li ng-repeat="topic in topics | orderBy:opts.sorttopics:opts.sortdir | filter:search">
+      <li ng-repeat="topic in topics | orderBy:explorerModels.sorttopics:explorerModels.sortdir | filter:search">
         <div class="checkbox checkbox-condensed" ng-class="{selected:topic.selected}">
-          <span class="valuebar" ng-style="{width:topicCurrValue(topic)}"></span>
+          <span class="valuebar" ng-style="{width:topic.topicCurrValue}"></span>
           <input type="checkbox" ng-model="topic.selected" ng-attr-id="{{::topic.id}}" ng-change="redrawGraph()">
           <label class="check" ng-attr-for="{{::topic.id}}">
             <topic-menu topic="topic" />
@@ -41,21 +41,21 @@
       <div class="topbar">
         <small>Values:</small>
         <div class="btn-group">
-          <a class="btn btn-sm btn-default" ng-model="opts.seqstyle" bs-radio="'absolute'">Absolute</a>
-          <a class="btn btn-sm btn-default" ng-model="opts.seqstyle" bs-radio="'relative'">Relative</a>
+          <a class="btn btn-sm btn-default" ng-model="explorerModels.seqstyle" bs-radio="'absolute'">Absolute</a>
+          <a class="btn btn-sm btn-default" ng-model="explorerModels.seqstyle" bs-radio="'relative'">Relative</a>
         </div>
         &nbsp;
         <small>Chart:</small>
         <div class="btn-group">
-          <a class="btn btn-sm btn-default" ng-model="opts.chartstyle" bs-radio="'areaspline'">Area</a>
-          <a class="btn btn-sm btn-default" ng-model="opts.chartstyle" bs-radio="'spline'">Line</a>
+          <a class="btn btn-sm btn-default" ng-model="explorerModels.chartstyle" bs-radio="'areaspline'">Area</a>
+          <a class="btn btn-sm btn-default" ng-model="explorerModels.chartstyle" bs-radio="'spline'">Line</a>
         </div>
         &nbsp;
         <small>Stacking:</small>
         <div class="btn-group">
-          <a class="btn btn-sm btn-default" ng-model="opts.chartstack" bs-radio="'none'">None</a>
-          <a class="btn btn-sm btn-default" ng-model="opts.chartstack" bs-radio="'normal'">Value</a>
-          <a class="btn btn-sm btn-default" ng-model="opts.chartstack" bs-radio="'percent'">Percent</a>
+          <a class="btn btn-sm btn-default" ng-model="explorerModels.chartstack" bs-radio="'none'">None</a>
+          <a class="btn btn-sm btn-default" ng-model="explorerModels.chartstack" bs-radio="'normal'">Value</a>
+          <a class="btn btn-sm btn-default" ng-model="explorerModels.chartstack" bs-radio="'percent'">Percent</a>
         </div>
       </div>
       <div class="chart" highcharts="topicSeq"></div>
diff --git a/vipra-ui/app/html/index.html b/vipra-ui/app/html/index.html
index d27f4c3d76b9edc4ffecaca272b574f4c56198af..e396195075a7cf9ebd660fcdf76133c4a029d9e6 100644
--- a/vipra-ui/app/html/index.html
+++ b/vipra-ui/app/html/index.html
@@ -1,4 +1,4 @@
-<div class="container" ng-cloak ng-hide="$state.current.name !== 'index'">
+<div class="container" ng-cloak ng-hide="!rootModels.topicModel || $state.current.name !== 'index'">
   <div class="row" ng-hide="search">
     <div class="col-md-12 text-center">
       <svg class="logo hover heading" viewBox="0 0 200 120">
diff --git a/vipra-ui/app/html/network.html b/vipra-ui/app/html/network.html
index 8f75e4951ecc3977b1620c5316665058d31ec3a5..445a5473d25fb081b5dac52b3d5b0fe1006cbb43 100644
--- a/vipra-ui/app/html/network.html
+++ b/vipra-ui/app/html/network.html
@@ -1,4 +1,4 @@
-<div ng-cloak ng-hide="$state.current.name !== 'network'">
+<div ng-cloak ng-hide="!rootModels.topicModel || $state.current.name !== 'network'">
   <div class="fullsize navpadding">
     <div class="graph-legend overlay">
       <div class="checkbox">
diff --git a/vipra-ui/app/html/partials/topic-popover.html b/vipra-ui/app/html/partials/topic-popover.html
index a1708a91869d7242cd1ef896fa40bd81b0b48746..e1b09ea5fbb01e5b7d44a95618bf3c740e8fed03 100644
--- a/vipra-ui/app/html/partials/topic-popover.html
+++ b/vipra-ui/app/html/partials/topic-popover.html
@@ -8,11 +8,11 @@
       <th class="text-center">&#8605;</th>
     </tr>
     <tr>
-      <td class="text-center" ng-bind-template="{{::topic.avgRelevance.toFixed(2)}}" ng-class="{'active text-primary':opts.sorttopics==='avgRelevance'}"></td>
-      <td class="text-center" ng-bind-template="{{::topic.varRelevance.toFixed(2)}}" ng-class="{'active text-primary':opts.sorttopics==='varRelevance'}"></td>
-      <td class="text-center" ng-bind-template="{{::topic.fallingRelevance.toFixed(2)}}" ng-class="{'active text-primary':opts.sorttopics==='fallingRelevance'}"></td>
-      <td class="text-center" ng-bind-template="{{::topic.risingRelevance.toFixed(2)}}" ng-class="{'active text-primary':opts.sorttopics==='risingRelevance'}"></td>
-      <td class="text-center" ng-bind-template="{{::topic.risingDecayRelevance.toFixed(2)}}" ng-class="{'active text-primary':opts.sorttopics==='risingDecayRelevance'}"></td>
+      <td class="text-center" ng-bind-template="{{::topic.avgRelevance.toFixed(2)}}" ng-class="{'active text-primary':explorerModels.sorttopics==='avgRelevance'}"></td>
+      <td class="text-center" ng-bind-template="{{::topic.varRelevance.toFixed(2)}}" ng-class="{'active text-primary':explorerModels.sorttopics==='varRelevance'}"></td>
+      <td class="text-center" ng-bind-template="{{::topic.fallingRelevance.toFixed(2)}}" ng-class="{'active text-primary':explorerModels.sorttopics==='fallingRelevance'}"></td>
+      <td class="text-center" ng-bind-template="{{::topic.risingRelevance.toFixed(2)}}" ng-class="{'active text-primary':explorerModels.sorttopics==='risingRelevance'}"></td>
+      <td class="text-center" ng-bind-template="{{::topic.risingDecayRelevance.toFixed(2)}}" ng-class="{'active text-primary':explorerModels.sorttopics==='risingDecayRelevance'}"></td>
     </tr>
   </tbody>
 </table>
diff --git a/vipra-ui/app/html/sequences/index.html b/vipra-ui/app/html/sequences/index.html
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/vipra-ui/app/html/sequences/show.html b/vipra-ui/app/html/sequences/show.html
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/vipra-ui/app/html/topics/articles.html b/vipra-ui/app/html/topics/articles.html
index c7ecd073bd87f7782a620bbee998451e4b7a95ae..a95e384887f6579839cfe7af9414a6fa70796ec0 100644
--- a/vipra-ui/app/html/topics/articles.html
+++ b/vipra-ui/app/html/topics/articles.html
@@ -1,4 +1,4 @@
-<div class="container" ng-cloak ng-hide="$state.current.name !== 'topics.show.articles'">
+<div class="container" ng-cloak ng-hide="!rootModels.topicModel || $state.current.name !== 'topics.show.articles'">
   <div class="row">
     <div class="col-md-12">
       <div class="page-header">
@@ -15,7 +15,7 @@
   </div>
   <div class="row">
     <div class="col-md-12">
-      <pagination total="articlesTotal" page="page" limit="limit" change="changePage" />
+      <pagination total="articlesTotal" page="topicsArticlesModels.page" limit="topicsArticlesModels.limit" change="changePage" />
     </div>
   </div>
   <div class="row">
@@ -26,12 +26,12 @@
           <ng-pluralize count="articlesTotal||0" when="{0:'no articles',1:'1 article',other:'{} articles'}"></ng-pluralize> in the database.
           <span ng-show="articlesTotal">
           Sort by
-          <ol class="nya-bs-select nya-bs-condensed" ng-model="opts.sortkey">
+          <ol class="nya-bs-select nya-bs-condensed" ng-model="topicsArticlesModels.sortkey">
             <li value="title" class="nya-bs-option"><a>Title</a></li>
             <li value="date" class="nya-bs-option"><a>Date</a></li>
             <li value="created" class="nya-bs-option"><a>Added</a></li>
           </ol>
-          <sort-dir ng-model="opts.sortdir" />
+          <sort-dir ng-model="topicsArticlesModels.sortdir" />
         </span>
         </div>
         <table class="table table-hover table-condensed">
@@ -44,14 +44,14 @@
           </tbody>
         </table>
         <div class="panel-footer">
-          Page <span ng-bind="page||1"></span> of <span ng-bind="maxPage||1"></span>
+          Page <span ng-bind="topicsArticlesModels.page||1"></span> of <span ng-bind="maxPage||1"></span>
         </div>
       </div>
     </div>
   </div>
   <div class="row">
     <div class="col-md-12">
-      <pagination total="articlesTotal" page="page" limit="limit" change="changePage" />
+      <pagination total="articlesTotal" page="topicsArticlesModels.page" limit="topicsArticlesModels.limit" change="changePage" />
     </div>
   </div>
 </div>
diff --git a/vipra-ui/app/html/topics/index.html b/vipra-ui/app/html/topics/index.html
index 3a8babc5d093749827f395fb55930e6bbf233f0c..b58dd69069addb80201369f2376c70c7f7012fe1 100644
--- a/vipra-ui/app/html/topics/index.html
+++ b/vipra-ui/app/html/topics/index.html
@@ -1,7 +1,7 @@
-<div class="container" ng-cloak ng-hide="$state.current.name !== 'topics'">
+<div class="container" ng-cloak ng-hide="!rootModels.topicModel || $state.current.name !== 'topics'">
   <div class="row">
     <div class="col-md-12">
-      <pagination total="topicsTotal" page="page" limit="limit" />
+      <pagination total="topicsTotal" page="topicsIndexModels.page" limit="topicsIndexModels.limit" />
     </div>
   </div>
   <div class="row">
@@ -12,11 +12,11 @@
           <ng-pluralize count="topicsTotal||0" when="{0:'no topics',1:'1 topic',other:'{} topics'}"></ng-pluralize> in the database.
           <span ng-show="topicsTotal">
           Sort by
-          <ol class="nya-bs-select nya-bs-condensed" ng-model="opts.sortkey">
+          <ol class="nya-bs-select nya-bs-condensed" ng-model="topicsIndexModels.sortkey">
             <li value="name" class="nya-bs-option"><a>Name</a></li>
             <li value="created" class="nya-bs-option"><a>Added</a></li>
           </ol>
-          <sort-dir ng-model="opts.sortdir" />
+          <sort-dir ng-model="topicsIndexModels.sortdir" />
         </span>
         </div>
         <table class="table table-hover table-condensed">
@@ -29,14 +29,14 @@
           </tbody>
         </table>
         <div class="panel-footer">
-          Page <span ng-bind="page||1"></span> of <span ng-bind="maxPage||1"></span>
+          Page <span ng-bind="topicsIndexModels.page||1"></span> of <span ng-bind="maxPage||1"></span>
         </div>
       </div>
     </div>
   </div>
   <div class="row">
     <div class="col-md-12">
-      <pagination total="topicsTotal" page="page" limit="limit" />
+      <pagination total="topicsTotal" page="topicsIndexModels.page" limit="topicsIndexModels.limit" />
     </div>
   </div>
 </div>
diff --git a/vipra-ui/app/html/topics/show.html b/vipra-ui/app/html/topics/show.html
index e04ddc66714301e6b531db7a3c9a55d8fc89b1eb..afd55ae723f13ba8ef2e0d5902b5c869155882d3 100644
--- a/vipra-ui/app/html/topics/show.html
+++ b/vipra-ui/app/html/topics/show.html
@@ -1,4 +1,4 @@
-<div class="container" ng-cloak ng-hide="$state.current.name !== 'topics.show'">
+<div class="container" ng-cloak ng-hide="!rootModels.topicModel || $state.current.name !== 'topics.show'">
   <div class="row">
     <div class="col-md-12">
       <div class="page-header">
@@ -60,14 +60,14 @@
         <div class="panel-heading">
           <small>Values:</small>
           <div class="btn-group">
-            <a class="btn btn-sm btn-default" ng-model="opts.seqstyle" bs-radio="'absolute'">Absolute</a>
-            <a class="btn btn-sm btn-default" ng-model="opts.seqstyle" bs-radio="'relative'">Relative</a>
+            <a class="btn btn-sm btn-default" ng-model="topicsShowModels.seqstyle" bs-radio="'absolute'">Absolute</a>
+            <a class="btn btn-sm btn-default" ng-model="topicsShowModels.seqstyle" bs-radio="'relative'">Relative</a>
           </div>
           &nbsp;
           <small>Chart:</small>
           <div class="btn-group">
-            <a class="btn btn-sm btn-default" ng-model="opts.chartstyle" bs-radio="'areaspline'">Area</a>
-            <a class="btn btn-sm btn-default" ng-model="opts.chartstyle" bs-radio="'spline'">Line</a>
+            <a class="btn btn-sm btn-default" ng-model="topicsShowModels.chartstyle" bs-radio="'areaspline'">Area</a>
+            <a class="btn btn-sm btn-default" ng-model="topicsShowModels.chartstyle" bs-radio="'spline'">Line</a>
           </div>
         </div>
         <div class="panel-body">
@@ -87,12 +87,12 @@
         <table class="table table-condensed table-bordered table-hover" ng-show="sequence">
           <thead>
             <tr>
-              <th ng-model="opts.sortwords" sort-by="id">Word</th>
-              <th ng-model="opts.sortwords" sort-by="likeliness">Likeliness</th>
+              <th ng-model="topicsShowModels.sortwords" sort-by="id">Word</th>
+              <th ng-model="topicsShowModels.sortwords" sort-by="likeliness">Likeliness</th>
             </tr>
           </thead>
           <tbody>
-            <tr ng-repeat="word in sequence.words | orderBy:opts.sortwords">
+            <tr ng-repeat="word in sequence.words | orderBy:topicsShowModels.sortwords">
               <td ng-bind="word.id"></td>
               <td ng-bind="word.likeliness.toFixed(4)"></td>
             </tr>
diff --git a/vipra-ui/app/index.html b/vipra-ui/app/index.html
index 49d4af3a0e4da3f0feb0647ebdc98e337dc89189..c39c42bec7338c08efb1ab66f3ffd92f441efb57 100644
--- a/vipra-ui/app/index.html
+++ b/vipra-ui/app/index.html
@@ -65,9 +65,6 @@
           <li ui-sref-active="active">
             <a ui-sref="topics">Topics</a>
           </li>
-          <li ui-sref-active="active">
-            <a ui-sref="sequences">Sequences</a>
-          </li>
         </ul>
         <ul class="nav navbar-nav navbar-right">
           <li>
@@ -86,20 +83,20 @@
     </div>
     <!-- /.container-fluid -->
   </nav>
-  <div class="main" ui-view ng-cloak ng-show="topicModel"></div>
+  <div class="main" ui-view ng-cloak></div>
 
-  <div id="topicModelModal" class="modal fade" tabindex="-1" role="dialog" data-backdrop="static" data-keyboard="false" bs-modal>
+  <div id="topicModelModal" class="modal fade" tabindex="-1" role="dialog" data-backdrop="static" data-keyboard="false">
     <div class="modal-dialog modal-lg">
       <div class="modal-content">
         <div class="modal-header">
-          <button type="button" class="close" data-dismiss="modal" aria-label="Close" ng-show="topicModel"><span aria-hidden="true">&times;</span></button>
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close" ng-show="rootModels.topicModel"><span aria-hidden="true">&times;</span></button>
           <h4 class="modal-title">Topic Models</h4>
         </div>
         <div class="modal-body">
           <ul class="list-group" ng-show="topicModels.length">
-            <button type="button" class="list-group-item" ng-repeat="model in topicModels" ng-click="changeTopicModel(model)" ng-class="{active:topicModel.id===model.id}">
-              <span class="badge" ng-bind="model.modelConfig.kTopics"></span>
-              <span ng-bind="model.id"></span>
+            <button type="button" class="list-group-item" ng-repeat="topicModel in topicModels" ng-click="changeTopicModel(topicModel)" ng-class="{active:rootModels.topicModel.id===topicModel.id}">
+              <span class="badge" ng-bind="topicModel.modelConfig.kTopics"></span>
+              <span ng-bind="topicModel.id"></span>
             </button>
           </ul>
           <p class="text-center" ng-show="loading.any">
diff --git a/vipra-ui/app/js/app.js b/vipra-ui/app/js/app.js
index aa9d621acba83a58a94ab468a0133cd36b512947..9b0ad989a68b0419c619ac412378a22b7fc56960 100644
--- a/vipra-ui/app/js/app.js
+++ b/vipra-ui/app/js/app.js
@@ -82,20 +82,6 @@
       controller: 'TopicsArticlesController'
     });
 
-    // states: sequences
-
-    $stateProvider.state('sequences', {
-      url: '/sequences',
-      templateUrl: 'html/sequences/index.html',
-      controller: 'SequencesIndexController'
-    });
-
-    $stateProvider.state('sequences.show', {
-      url: '/:id',
-      templateUrl: 'html/sequences/show.html',
-      controller: 'SequencesShowController'
-    });
-
   }]);
 
   app.config(['$httpProvider', function($httpProvider) {
diff --git a/vipra-ui/app/js/controllers.js b/vipra-ui/app/js/controllers.js
index 5fb343e0e046eb6dd4de525f10677eb780f0dea4..4be0f3afa730721f61cf00eac93c2a1f0106271c 100644
--- a/vipra-ui/app/js/controllers.js
+++ b/vipra-ui/app/js/controllers.js
@@ -16,6 +16,20 @@
     function($scope, $state, TopicModelFactory) {
 
       $scope.$state = $state;
+      $scope.rootModels = {
+        topicModel: null
+      };
+
+      if(localStorage.topicModel) {
+        try {
+          var topicModel = JSON.parse(localStorage.topicModel);
+          TopicModelFactory.get({
+            id: topicModel.id
+          }, function(data) {
+            $scope.rootModels.topicModel = data; 
+          });
+        } catch(e) {}
+      }
 
       TopicModelFactory.query({
         fields: 'modelConfig'
@@ -25,8 +39,13 @@
         $scope.errors = err;
       });
 
+      $scope.chooseTopicModel = function() {
+        $('#topicModelModal').modal();
+      };
+
       $scope.changeTopicModel = function(topicModel) {
-        $scope.topicModel = topicModel;
+        $scope.rootModels.topicModel = topicModel;
+        localStorage.topicModel = JSON.stringify(topicModel);
         $('#topicModelModal').modal('hide');
       };
 
@@ -39,13 +58,17 @@
   app.controller('IndexController', ['$scope', '$location', 'ArticleFactory', 'TopicFactory', 'SearchFactory',
     function($scope, $location, ArticleFactory, TopicFactory, SearchFactory) {
 
+      // page was reloaded, choose topic model
+      if(!$scope.rootModels.topicModel)
+        $scope.chooseTopicModel();
+
       $scope.search = $location.search().query;
 
-      $scope.$watch('topicModel', function(topicModel) {
-        if(!topicModel) return;
+      $scope.$watch('rootModels.topicModel', function() {
+        if(!$scope.rootModels.topicModel) return;
         
         ArticleFactory.query({
-          topicModel: topicModel.id,
+          topicModel: $scope.rootModels.topicModel.id,
           limit: 3,
           sort: '-created'
         }, function(data) {
@@ -55,7 +78,7 @@
         });
 
         TopicFactory.query({
-          topicModel: topicModel.id,
+          topicModel: $scope.rootModels.topicModel.id,
           limit: 3,
           sort: '-created'
         }, function(data) {
@@ -65,13 +88,13 @@
         });
       });
 
-      $scope.$watchGroup(['search', 'topicModel'], function() {
-        if ($scope.search && $scope.topicModel) {
+      $scope.$watchGroup(['search', 'rootModels.topicModel'], function() {
+        if ($scope.search && $scope.rootModels.topicModel) {
           $location.search('query', $scope.search);
           $scope.searching = true;
 
           SearchFactory.query({
-            topicModel: $scope.topicModel.id,
+            topicModel: $scope.rootModels.topicModel.id,
             limit: 10,
             query: $scope.search
           }, function(data) {
@@ -162,8 +185,17 @@
         return;
       }
 
+      // if the topic model is not set, the page was refreshed
+      // set to true, id of current node decides topic model
+      if(!$scope.rootModels.topicModel)
+        $scope.rootModels.topicModel = true;
+
       // get root node
-      factory.get({ id: $stateParams.id }, function(data) {
+      factory.get({
+        id: $stateParams.id
+      }, function(data) {
+        $scope.rootNode = data;
+
         // add root node
         if ($stateParams.type === 'articles')
           $scope.nodes.add([articleNode(data)]);
@@ -176,6 +208,12 @@
         $scope.graph = new vis.Network(container, $scope.data, $scope.options);
         $scope.graph.on('selectNode', $scope.select);
         $scope.graph.on('doubleClick', $scope.open);
+
+        // take topic model from node
+        if(!angular.isObject($scope.rootModels.topicModel))
+          $scope.rootModels.topicModel = data.topicModel;
+      }, function(err) {
+        $scope.errors = err;
       });
 
       var newNode = function(title, type, show, dbid, color, shape) {
@@ -290,11 +328,19 @@
         $state.transitionTo(node.show, { id: node.dbid });
       };
 
+      $scope.$watch('rootModels.topicModel', function(newVal) {
+        if($scope.rootNode && $scope.rootNode.topicModel.id !== newVal.id)
+          $state.transitionTo('index');
+      });
     }
   ]);
 
-  app.controller('ExplorerController', ['$scope', '$templateCache', '$compile', 'TopicFactory',
-    function($scope, $templateCache, $compile, TopicFactory) {
+  app.controller('ExplorerController', ['$scope', '$templateCache', '$timeout', 'TopicFactory',
+    function($scope, $templateCache, $timeout, TopicFactory) {
+
+      // page was reloaded, choose topic model
+      if(!$scope.rootModels.topicModel)
+        $scope.chooseTopicModel();
 
       var avgMax = 0,
         varMax = 0,
@@ -303,7 +349,7 @@
         risingDecayMax = 0,
         risingDecayMin = 0;
 
-      $scope.opts = {
+      $scope.explorerModels = {
         sorttopics: 'name',
         sortdir: false,
         seqstyle: 'absolute',
@@ -311,25 +357,30 @@
         chartstack: 'none'
       };
 
-      TopicFactory.query({
-        fields: 'name,sequences,avgRelevance,varRelevance,risingRelevance,fallingRelevance,risingDecayRelevance'
-      }, function(data) {
-        $scope.topics = data;
-        var colors = randomColor({ count: $scope.topics.length, seed: 1 });
-        for (var i = 0, t; i < $scope.topics.length; i++) {
-          t = $scope.topics[i];
-          t.color = colors[i];
-          avgMax = Math.max(t.avgRelevance, avgMax);
-          varMax = Math.max(t.varRelevance, varMax);
-          fallingMax = Math.max(t.fallingRelevance, fallingMax);
-          risingMax = Math.max(t.risingRelevance, risingMax);
-          risingDecayMax = Math.max(t.risingDecayRelevance, risingDecayMax);
-          risingDecayMin = Math.max(t.risingDecayRelevance, risingDecayMin);
-        }
-        risingDecayMin = Math.abs(risingDecayMin);
-        risingDecayMax = risingDecayMin + Math.abs(risingDecayMax);
-      }, function(err) {
-        $scope.errors = err;
+      $scope.$watch('rootModels.topicModel', function() {
+        if(!$scope.rootModels.topicModel) return;
+
+        TopicFactory.query({
+          fields: 'name,sequences,avgRelevance,varRelevance,risingRelevance,fallingRelevance,risingDecayRelevance',
+          topicModel: $scope.rootModels.topicModel.id
+        }, function(data) {
+          $scope.topics = data;
+          var colors = randomColor({ count: $scope.topics.length, seed: 1 });
+          for (var i = 0, t; i < $scope.topics.length; i++) {
+            t = $scope.topics[i];
+            t.color = colors[i];
+            avgMax = Math.max(t.avgRelevance, avgMax);
+            varMax = Math.max(t.varRelevance, varMax);
+            fallingMax = Math.max(t.fallingRelevance, fallingMax);
+            risingMax = Math.max(t.risingRelevance, risingMax);
+            risingDecayMax = Math.max(t.risingDecayRelevance, risingDecayMax);
+            risingDecayMin = Math.max(t.risingDecayRelevance, risingDecayMin);
+          }
+          risingDecayMin = Math.abs(risingDecayMin);
+          risingDecayMax = risingDecayMin + Math.abs(risingDecayMax);
+        }, function(err) {
+          $scope.errors = err;
+        });
       });
 
       $scope.checkTopics = function(to) {
@@ -354,7 +405,7 @@
             // data array with relevances and min/max
             for (var j = 0, sequence, relevance; j < topic.sequences.length; j++) {
               sequence = topic.sequences[j];
-              relevance = $scope.opts.seqstyle === 'relative' ? sequence.relevanceChange : sequence.relevance;
+              relevance = $scope.explorerModels.seqstyle === 'relative' ? sequence.relevanceChange : sequence.relevance;
               relevances.push({
                 x: new Date(sequence.window.startDate).getTime(),
                 y: relevance,
@@ -372,20 +423,14 @@
         }
 
         // highcharts configuration
-        $scope.topicSeq = areaRelevanceChart(series, $scope.selectNode, $scope.opts.chartstyle,
-          $scope.opts.chartstack);
+        $scope.topicSeq = areaRelevanceChart(series, $scope.explorerModels.chartstyle,
+          $scope.explorerModels.chartstack);
         $scope.topicsSelected = series.length;
       };
 
-      $scope.selectNode = function(node) {
-        $scope.$apply(function() {
-
-        });
-      };
-
       $scope.topicCurrValue = function(topic) {
         var percent = 0;
-        switch ($scope.opts.sorttopics) {
+        switch ($scope.explorerModels.sorttopics) {
           case 'avgRelevance':
             percent = topic.avgRelevance / avgMax;
             break;
@@ -405,7 +450,16 @@
         return (percent * 100) + '%';
       };
 
-      $scope.$watchGroup(['opts.seqstyle', 'opts.chartstyle', 'opts.chartstack'], $scope.redrawGraph);
+      $scope.$watchGroup(['explorerModels.seqstyle', 'explorerModels.chartstyle', 'explorerModels.chartstack'], $scope.redrawGraph);
+
+      $scope.$watch('explorerModels.sorttopics', function() {
+        if(!$scope.topics) return;
+
+        $timeout(function() {
+          for(var i = 0; i < $scope.topics.length; i++)
+            $scope.topics[i].topicCurrValue = $scope.topicCurrValue($scope.topics[i]);
+        }, 100);
+      });
     }
   ]);
 
@@ -419,23 +473,29 @@
   app.controller('ArticlesIndexController', ['$scope', '$state', '$location', 'ArticleFactory',
     function($scope, $state, $location, ArticleFactory) {
 
-      $scope.opts = {
+      // page was reloaded, choose topic model
+      if(!$scope.rootModels.topicModel && $state.current.name === 'articles')
+        $scope.chooseTopicModel();
+
+      $scope.articlesIndexModels = {
         sortkey: 'date',
-        sortdir: true
+        sortdir: true,
+        page: Math.max($location.search().page || 1, 1),
+        limit: 100
       };
 
-      $scope.page = Math.max($location.search().page || 1, 1);
-      $scope.limit = 100;
+      $scope.$watchGroup(['articlesIndexModels.page', 'articlesIndexModels.sortkey', 'articlesIndexModels.sortdir', 'rootModels.topicModel'], function() {
+        if(!$scope.rootModels.topicModel) return;
 
-      $scope.$watchGroup(['page', 'opts.sortkey', 'opts.sortdir'], function() {
         ArticleFactory.query({
-          skip: ($scope.page - 1) * $scope.limit,
-          limit: $scope.limit,
-          sort: ($scope.opts.sortdir ? '' : '-') + $scope.opts.sortkey
+          skip: ($scope.articlesIndexModels.page - 1) * $scope.articlesIndexModels.limit,
+          limit: $scope.articlesIndexModels.limit,
+          sort: ($scope.articlesIndexModels.sortdir ? '' : '-') + $scope.articlesIndexModels.sortkey,
+          topicModel: $scope.rootModels.topicModel.id
         }, function(data, headers) {
           $scope.articles = data;
           $scope.articlesTotal = headers("V-Total");
-          $scope.maxPage = Math.ceil($scope.articlesTotal / $scope.limit);
+          $scope.maxPage = Math.ceil($scope.articlesTotal / $scope.articlesIndexModels.limit);
         }, function(err) {
           $scope.errors = err;
         });
@@ -447,8 +507,8 @@
   /**
    * Article Show route
    */
-  app.controller('ArticlesShowController', ['$scope', '$stateParams', 'ArticleFactory',
-    function($scope, $stateParams, ArticleFactory) {
+  app.controller('ArticlesShowController', ['$scope', '$state', '$stateParams', '$timeout', 'ArticleFactory',
+    function($scope, $state, $stateParams, $timeout, ArticleFactory) {
 
       $scope.topicSort = $scope.topicSort || 'share';
       $scope.topicSortRev = typeof $scope.topicSortRev === 'undefined' ? true : $scope.topicSortRev;
@@ -462,6 +522,10 @@
         $scope.articleCreated = Vipra.formatDateTime($scope.article.created);
         $scope.articleModified = Vipra.formatDateTime($scope.article.modified);
 
+        // take topic model from article
+        if(!angular.isObject($scope.rootModels.topicModel))
+          $scope.rootModels.topicModel = data.topicModel;
+
         // calculate percentage share
         if ($scope.article.topics) {
           var topicShareSeries = [],
@@ -485,26 +549,23 @@
           // preselect biggest value
           maximum.selected = maximum.sliced = true;
 
-          // highcharts data
-          $scope.topicShare = topicShareChart([{
-            name: 'Topic Share',
-            colorByPoint: true,
-            data: topicShareSeries
-          }]);
+          $timeout(function() {
+            // highcharts data
+            $scope.topicShare = topicShareChart([{
+              name: 'Topic Share',
+              colorByPoint: true,
+              data: topicShareSeries
+            }]);
+          }, 0);
         }
       }, function(err) {
         $scope.errors = err;
       });
 
-    }
-  ]);
-
-  /**
-   * Article Similar route
-   */
-  app.controller('ArticlesSimilarController', [
-    function() {
-
+      $scope.$watch('rootModels.topicModel', function(newVal) {
+        if($scope.article && $scope.article.topicModel.id !== newVal.id)
+          $state.transitionTo('index');
+      });
     }
   ]);
 
@@ -515,29 +576,32 @@
   /**
    * Topic Index route
    */
-  app.controller('TopicsIndexController', ['$scope', '$location', 'TopicFactory',
-    function($scope, $location, TopicFactory) {
+  app.controller('TopicsIndexController', ['$scope', '$state', '$location', 'TopicFactory',
+    function($scope, $state, $location, TopicFactory) {
 
-      $scope.opts = {
+      // page was reloaded, choose topic model
+      if(!$scope.rootModels.topicModel && $state.current.name === 'topics')
+        $scope.chooseTopicModel();
+
+      $scope.topicsIndexModels = {
         sortkey: 'name',
-        sortdir: true
+        sortdir: true,
+        page: Math.max($location.search().page || 1, 1),
+        limit: 100
       };
 
-      $scope.page = Math.max($location.search().page || 1, 1);
-      $scope.limit = 100;
-
-      $scope.$watchGroup(['page', 'opts.sortkey', 'opts.sortdir', 'topicModel'], function() {
-        if(!$scope.topicModel) return;
+      $scope.$watchGroup(['topicsIndexModels.page', 'topicsIndexModels.sortkey', 'topicsIndexModels.sortdir', 'rootModels.topicModel'], function() {
+        if(!$scope.rootModels.topicModel) return;
 
         TopicFactory.query({
-          topicModel: $scope.topicModel.id,
-          skip: ($scope.page - 1) * $scope.limit,
-          limit: $scope.limit,
-          sort: ($scope.opts.sortdir ? '' : '-') + $scope.opts.sortkey
+          topicModel: $scope.rootModels.topicModel.id,
+          skip: ($scope.topicsIndexModels.page - 1) * $scope.topicsIndexModels.limit,
+          limit: $scope.topicsIndexModels.limit,
+          sort: ($scope.topicsIndexModels.sortdir ? '' : '-') + $scope.topicsIndexModels.sortkey
         }, function(data, headers) {
           $scope.topics = data;
           $scope.topicsTotal = headers("V-Total");
-          $scope.maxPage = Math.ceil($scope.topicsTotal / $scope.limit);
+          $scope.maxPage = Math.ceil($scope.topicsTotal / $scope.topicsIndexModels.limit);
         }, function(err) {
           $scope.errors = err;
         });
@@ -549,45 +613,46 @@
   /**
    * Topic Show route
    */
-  app.controller('TopicsShowController', ['$scope', '$stateParams', '$timeout', 'TopicFactory', 'SequenceFactory',
-    function($scope, $stateParams, $timeout, TopicFactory, SequenceFactory) {
+  app.controller('TopicsShowController', ['$scope', '$state', '$stateParams', '$timeout', 'TopicFactory', 'SequenceFactory',
+    function($scope, $state, $stateParams, $timeout, TopicFactory, SequenceFactory) {
 
-      $scope.opts = {
+      $scope.topicsShowModels = {
         seqstyle: 'absolute',
         chartstyle: 'areaspline',
         sortwords: '-likeliness'
       };
 
-      $scope.$watch('topicModel', function() {
-        if(!$scope.topicModel) return;
+      TopicFactory.get({
+        id: $stateParams.id
+      }, function(data) {
+        $scope.topic = data;
+        $scope.topicCreated = Vipra.formatDateTime($scope.topic.created);
+        $scope.topicModified = Vipra.formatDateTime($scope.topic.modified);
+
+        // take topic model from topic
+        if(!angular.isObject($scope.rootModels.topicModel))
+          $scope.rootModels.topicModel = data.topicModel;
 
-        TopicFactory.get({
-          id: $stateParams.id,
-          topicModel: $scope.topicModel.id
-        }, function(data) {
-          $scope.topic = data;
-          $scope.topicCreated = Vipra.formatDateTime($scope.topic.created);
-          $scope.topicModified = Vipra.formatDateTime($scope.topic.modified);
+        $timeout(function() {
           $scope.redrawGraph();
-        }, function(err) {
-          $scope.errors = err;
-        });
+        }, 0);
+      }, function(err) {
+        $scope.errors = err;
       });
 
       $scope.redrawGraph = function() {
         if (!$scope.topic || !$scope.topic.sequences) return;
-        console.log('redraw relevance chart');
         var relevances = [];
 
         // create series
         for (var i = 0, sequence, relevance; i < $scope.topic.sequences.length; i++) {
           sequence = $scope.topic.sequences[i];
-          relevance = $scope.opts.seqstyle === 'relative' ? sequence.relevanceChange : sequence.relevance;
+          relevance = $scope.topicsShowModels.seqstyle === 'relative' ? sequence.relevanceChange : sequence.relevance;
           relevances.push([new Date(sequence.window.startDate).getTime(), relevance]);
         }
 
         // highcharts configuration
-        $scope.topicSeq = areaRelevanceChart([{ name: $scope.topic.name, data: relevances }], null, $scope.opts.chartstyle);
+        $scope.topicSeq = areaRelevanceChart([{ name: $scope.topic.name, data: relevances }], $scope.topicsShowModels.chartstyle);
       };
 
       $scope.startRename = function() {
@@ -622,15 +687,14 @@
         }
       };
 
-      $scope.$watch('opts.seqstyle', $scope.redrawGraph);
-      $scope.$watch('opts.chartstyle', $scope.redrawGraph);
+      $scope.$watch('topicsShowModels.seqstyle', $scope.redrawGraph);
+      $scope.$watch('topicsShowModels.chartstyle', $scope.redrawGraph);
 
-      $scope.$watchGroup(['sequenceId', 'topicModel'], function() {
-        if(!$scope.sequenceId || !$scope.topicModel) return;
+      $scope.$watchGroup(['sequenceId'], function() {
+        if(!$scope.sequenceId) return;
 
         SequenceFactory.get({
           id: $scope.sequenceId,
-          topicModel: $scope.topicModel.id,
           topWords: 20
         }, function(data) {
           $scope.sequence = data;
@@ -638,6 +702,11 @@
           $scope.errors = err;
         });
       });
+
+      $scope.$watch('rootModels.topicModel', function(newVal) {
+        if($scope.topic && $scope.topic.topicModel.id !== newVal.id)
+          $state.transitionTo('index');
+      });
     }
   ]);
 
@@ -647,27 +716,23 @@
   app.controller('TopicsArticlesController', ['$scope', '$stateParams', '$location', 'TopicFactory',
     function($scope, $stateParams, $location, TopicFactory) {
 
-      $scope.opts = {
+      $scope.topicsArticlesModels = {
         sortkey: 'title',
-        sortdir: true
+        sortdir: true,
+        page: Math.max($location.search().page || 1, 1),
+        limit: 100
       };
 
-      $scope.page = Math.max($location.search().page || 1, 1);
-      $scope.limit = 100;
-
-      $scope.$watchGroup(['page', 'opts.sortkey', 'opts.sortdir', 'topicModel'], function() {
-        if(!$scope.topicModel) return;
-
+      $scope.$watchGroup(['topicsArticlesModels.page', 'topicsArticlesModels.sortkey', 'topicsArticlesModels.sortdir'], function() {
         TopicFactory.articles({
           id: $stateParams.id,
-          topicModel: $scope.topicModel.id,
-          skip: ($scope.page - 1) * $scope.limit,
-          limit: $scope.limit,
-          sort: ($scope.opts.sortdir ? '' : '-') + $scope.opts.sortkey
+          skip: ($scope.topicsArticlesModels.page - 1) * $scope.topicsArticlesModels.limit,
+          limit: $scope.topicsArticlesModels.limit,
+          sort: ($scope.topicsArticlesModels.sortdir ? '' : '-') + $scope.topicsArticlesModels.sortkey
         }, function(data, headers) {
           $scope.articles = data;
           $scope.articlesTotal = headers("V-Total");
-          $scope.maxPage = Math.ceil($scope.articlesTotal / $scope.limit);
+          $scope.maxPage = Math.ceil($scope.articlesTotal / $scope.topicsArticlesModels.limit);
         }, function(err) {
           $scope.errors = err;
         });
@@ -727,7 +792,7 @@
    * Shared Highcharts configurations
    ****************************************************************************/
 
-  function areaRelevanceChart(series, clickCallback, chartType, chartStack) {
+  function areaRelevanceChart(series, chartType, chartStack) {
     return {
       chart: {
         type: (chartType || 'areaspline'),
@@ -768,13 +833,6 @@
           animation: false,
           cursor: 'pointer',
           allowPointSelect: true,
-          point: {
-            events: {
-              click: function(e) {
-                clickCallback(e.point);
-              }
-            }
-          },
           states: {
             hover: {
               halo: {
diff --git a/vipra-ui/app/js/directives.js b/vipra-ui/app/js/directives.js
index 82900e4e00ac815addbd75d718f2ed7f70541cb8..ad6d4f1bca527a4d236cdc2023e8bb8114da285d 100644
--- a/vipra-ui/app/js/directives.js
+++ b/vipra-ui/app/js/directives.js
@@ -11,7 +11,7 @@
     'ui.router'
   ]);
 
-  app.directive('topicLink', function() {
+  app.directive('topicLink', [function() {
     return {
       scope: {
         topic: '='
@@ -21,9 +21,9 @@
       transclude: true,
       templateUrl: 'html/directives/topic-link.html'
     };
-  });
+  }]);
 
-  app.directive('articleLink', function() {
+  app.directive('articleLink', [function() {
     return {
       scope: {
         article: '='
@@ -33,9 +33,9 @@
       transclude: true,
       templateUrl: 'html/directives/article-link.html'
     };
-  });
+  }]);
 
-  app.directive('pagination', function() {
+  app.directive('pagination', [function() {
     return {
       restrict: 'E',
       replace: true,
@@ -48,9 +48,9 @@
       controller: 'PaginationController',
       templateUrl: 'html/directives/pagination.html'
     };
-  });
+  }]);
 
-  app.directive('highcharts', function() {
+  app.directive('highcharts', [function() {
     return {
       scope: {
         highcharts: '='
@@ -63,38 +63,9 @@
         });
       }
     };
-  });
-
-  app.directive('ngModelStore', ['Store', function(Store) {
-    return {
-      restrict: 'A',
-      require: 'ngModel',
-      link: function($scope, $elem, $attrs, $ctrl) {
-        if (!$attrs.ngModel) {
-          console.log('no model given');
-          return;
-        }
-        if (typeof $attrs.ngModelStore === 'undefined') {
-          console.log('no store key given');
-          return;
-        }
-        var key = $attrs.ngModelStore || $attrs.ngModel;
-        var value = Store(key);
-        if (value !== null) {
-          $ctrl.$setViewValue(value);
-          $ctrl.$render();
-        } else if ($attrs.ngModelDefault) {
-          $ctrl.$setViewValue($scope.$eval($attrs.ngModelDefault));
-          $ctrl.$render();
-        }
-        $scope.$watch($attrs.ngModel, function() {
-          Store(key, typeof $ctrl.$viewValue === 'undefined' ? null : $ctrl.$viewValue);
-        });
-      }
-    };
   }]);
 
-  app.directive('bsRadio', function() {
+  app.directive('bsRadio', [function() {
     return {
       scope: {
         bsRadio: '=',
@@ -118,7 +89,7 @@
         });
       }
     };
-  });
+  }]);
 
   app.directive('bsPopover', ['$templateCache', '$compile',
     function($templateCache, $compile) {
@@ -146,14 +117,6 @@
     }
   ]);
 
-  app.directive('bsModal', [function() {
-    return {
-      link: function($scope, $elem) {
-        $elem.modal();
-      }
-    };
-  }]);
-
   app.directive('sequenceDropdown', [function() {
     return {
       scope: {
@@ -174,7 +137,7 @@
     };
   }]);
 
-  app.directive('sortBy', function() {
+  app.directive('sortBy', [function() {
     return {
       restrict: 'A',
       scope: {
@@ -183,32 +146,28 @@
       },
       link: function($scope, $elem) {
         $elem.click(function() {
-          $scope.$apply($scope.check);
+          $scope.$apply(function() {
+            $scope.reverse = false;
+            if ($scope.ngModel === $scope.sortBy) {
+              $scope.ngModel = '-' + $scope.sortBy;
+              $scope.reverse = true;
+            } else {
+              $scope.ngModel = $scope.sortBy;
+              $scope.reverse = false;
+            }
+          });
         });
 
         $scope.showCaret = function() {
           return $scope.ngModel === $scope.sortBy || $scope.ngModel === '-' + $scope.sortBy;
         };
-
-        $scope.check = function() {
-          $scope.reverse = false;
-          if ($scope.ngModel === $scope.sortBy) {
-            $scope.ngModel = '-' + $scope.sortBy;
-            $scope.reverse = true;
-          } else {
-            $scope.ngModel = $scope.sortBy;
-            $scope.reverse = false;
-          }
-        };
-
-        $scope.check();
       },
       transclude: true,
       template: '<span ng-transclude></span> <i class="fa" ng-class="{\'fa-caret-down\':!reverse, \'fa-caret-up\':reverse}" ng-show="showCaret()"></i>'
     };
-  });
+  }]);
 
-  app.directive('topicMenu', function() {
+  app.directive('topicMenu', ['TopicFactory', function(TopicFactory) {
     return {
       scope: {
         topic: '=',
@@ -224,16 +183,27 @@
             value: $scope.topic.name,
             callback: function(name) {
               if (name && name.length && name !== $scope.topic.name) {
-
+                var oldName = $scope.topic.name;
+                $scope.topic.name = name;
+                $scope.$apply(function() {
+                  TopicFactory.update({
+                    id: $scope.topic.id
+                  }, $scope.topic, function(data) {
+                    $scope.topic = data;
+                  }, function(err) {
+                    $scope.topic.name = oldName;
+                    $scope.errors = err;
+                  });
+                });
               }
             }
           });
         };
       }
     };
-  });
+  }]);
 
-  app.directive('sortDir', function() {
+  app.directive('sortDir', [function() {
     return {
       scope: {
         ngModel: '='
@@ -241,7 +211,7 @@
       restrict: 'E',
       replace: true,
       templateUrl: 'html/directives/sort-dir.html'
-    }
-  });
+    };
+  }]);
 
 })();
diff --git a/vipra-ui/app/js/factories.js b/vipra-ui/app/js/factories.js
index f5ff9043fdcb454be0d5120b7613136bc98e1b6d..978878623f3e5cb714610bf1d890e6a706952f76 100644
--- a/vipra-ui/app/js/factories.js
+++ b/vipra-ui/app/js/factories.js
@@ -35,76 +35,7 @@
   }]);
 
   app.factory('TopicModelFactory', ['$resource', function($resource) {
-    return $resource(Vipra.config.restUrl + '/topicmodels');
-  }]);
-
-  // https://gist.github.com/Fluidbyte/4718380
-  app.factory('Store', ['$state', function($state) {
-    return function(key, value) {
-      key += '-' + $state.current.name;
-      var lsSupport = false;
-
-      // Check for native support
-      if (localStorage)
-        lsSupport = true;
-
-      // If value is detected, set new or modify store
-      if (typeof value !== "undefined" && value !== null) {
-        // Convert object values to JSON
-        if (typeof value === 'object')
-          value = JSON.stringify(value);
-        // Set the store
-        if (lsSupport)
-          localStorage.setItem(key, value);
-        else
-          createCookie(key, value, 30);
-      }
-
-      // No value supplied, return value
-      if (typeof value === "undefined") {
-        var data;
-        if (lsSupport)
-          data = localStorage.getItem(key);
-        else
-          data = readCookie(key);
-
-        try {
-          data = JSON.parse(data);
-        } catch (e) {
-          data = data;
-        }
-
-        return data;
-      }
-
-      // Null specified, remove store
-      if (value === null) {
-        if (lsSupport)
-          localStorage.removeItem(key);
-        else
-          createCookie(key, '', -1);
-      }
-
-      // Creates new cookie or removes cookie with negative expiration
-      function createCookie(key, value, exp) {
-        var date = new Date();
-        date.setTime(date.getTime() + (exp * 24 * 60 * 60 * 1000));
-        var expires = "; expires=" + date.toGMTString();
-        document.cookie = key + "=" + value + expires + "; path=/";
-      }
-
-      // Returns contents of cookie
-      function readCookie(key) {
-        var nameEQ = key + "=";
-        var ca = document.cookie.split(';');
-        for (var i = 0, max = ca.length; i < max; i++) {
-          var c = ca[i];
-          while (c.charAt(0) === ' ') c = c.substring(1, c.length);
-          if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);
-        }
-        return null;
-      }
-    };
+    return $resource(Vipra.config.restUrl + '/topicmodels/:id');
   }]);
 
 })();
diff --git a/vipra-ui/app/less/app.less b/vipra-ui/app/less/app.less
index d3e6ef59a2c32c076afa40709a24ab6029583c29..ed9d71d393994c08869c7a7d71b507696f706d72 100644
--- a/vipra-ui/app/less/app.less
+++ b/vipra-ui/app/less/app.less
@@ -125,7 +125,7 @@ a:hover {
 }
 
 .overlay {
-  z-index: 9999;
+  z-index: 1040;
 }
 
 .item-actions {
@@ -204,7 +204,7 @@ a:hover {
 .colorbox {
   display: inline-block;
   width: 10px;
-  height: 100%;
+  height: 20px;
   vertical-align: middle;
   float: right;
   border-radius: 3px;
@@ -217,7 +217,10 @@ a:hover {
   top: 0;
   left: 0;
   height: 100%;
+  width: 0px;
   background: @valuebg;
+  transition: width .5s linear;
+  transition-delay: .2s;
   *:hover > & {
     background: darken(@valuebg, 5%);
   }
diff --git a/vipra-util/src/main/java/de/vipra/util/model/Article.java b/vipra-util/src/main/java/de/vipra/util/model/Article.java
index 40635289dfc27df38e24f7b4517e778235000583..374606845067f7c2a3b7b8dd22744ff2bd9a126f 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/Article.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/Article.java
@@ -8,6 +8,9 @@ import org.mongodb.morphia.annotations.Id;
 import org.mongodb.morphia.annotations.Index;
 import org.mongodb.morphia.annotations.Indexes;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Entity(value = "articles", noClassnameStored = true)
 @Indexes({ @Index("title"), @Index("date"), @Index("-created") })
diff --git a/vipra-util/src/main/java/de/vipra/util/model/ArticleFull.java b/vipra-util/src/main/java/de/vipra/util/model/ArticleFull.java
index 179af17216756cc1ee5768784a54da5669cdea4f..692ca2ed5d8abefce8176423a32297e9f80ca4e9 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/ArticleFull.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/ArticleFull.java
@@ -20,6 +20,8 @@ import org.mongodb.morphia.annotations.Transient;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
 import de.vipra.util.Constants;
 import de.vipra.util.MongoUtils;
 import de.vipra.util.NestedMap;
@@ -27,6 +29,7 @@ import de.vipra.util.StringUtils;
 import de.vipra.util.an.ElasticIndex;
 import de.vipra.util.an.QueryIgnore;
 
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Entity(value = "articles", noClassnameStored = true)
 @Indexes({ @Index("title"), @Index("date"), @Index("-created") })
diff --git a/vipra-util/src/main/java/de/vipra/util/model/ArticleStats.java b/vipra-util/src/main/java/de/vipra/util/model/ArticleStats.java
index 64c13b17e18ded2617252c7c15d43093e7eb9844..4c012be26281bc08894641f5e001488dac278c8f 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/ArticleStats.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/ArticleStats.java
@@ -4,6 +4,9 @@ import java.io.Serializable;
 
 import org.mongodb.morphia.annotations.Embedded;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
 @Embedded
 public class ArticleStats implements Serializable {
 
diff --git a/vipra-util/src/main/java/de/vipra/util/model/ArticleWord.java b/vipra-util/src/main/java/de/vipra/util/model/ArticleWord.java
index fe043792dec3887e0cafeec6a102441286b1b7ba..f0fc0cab9160b32f79601e622d08e5566b01d253 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/ArticleWord.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/ArticleWord.java
@@ -4,6 +4,9 @@ import java.io.Serializable;
 
 import org.mongodb.morphia.annotations.Embedded;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Embedded
 public class ArticleWord implements Comparable<ArticleWord>, Serializable {
diff --git a/vipra-util/src/main/java/de/vipra/util/model/Sequence.java b/vipra-util/src/main/java/de/vipra/util/model/Sequence.java
index 35752e9ea4d18601f0f7f4df092277998f8ed2a3..3d59fdcdc659efb1c9ce7d24a6eb79876a5d6caa 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/Sequence.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/Sequence.java
@@ -6,10 +6,10 @@ import org.bson.types.ObjectId;
 import org.mongodb.morphia.annotations.Embedded;
 import org.mongodb.morphia.annotations.Entity;
 import org.mongodb.morphia.annotations.Id;
-import org.mongodb.morphia.annotations.Reference;
 
-import de.vipra.util.an.QueryIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Entity(value = "sequences", noClassnameStored = true)
 public class Sequence implements Model<ObjectId>, Comparable<Sequence>, Serializable {
@@ -17,10 +17,6 @@ public class Sequence implements Model<ObjectId>, Comparable<Sequence>, Serializ
 	@Id
 	private ObjectId id = new ObjectId();
 
-	@Reference
-	@QueryIgnore(multi = true)
-	private TopicModel topicModel;
-
 	@Embedded
 	private Window window;
 
@@ -44,14 +40,6 @@ public class Sequence implements Model<ObjectId>, Comparable<Sequence>, Serializ
 		this.id = id;
 	}
 
-	public TopicModel getTopicModel() {
-		return topicModel;
-	}
-
-	public void setTopicModel(final TopicModel topicModel) {
-		this.topicModel = topicModel;
-	}
-
 	public Window getWindow() {
 		return window;
 	}
diff --git a/vipra-util/src/main/java/de/vipra/util/model/SequenceFull.java b/vipra-util/src/main/java/de/vipra/util/model/SequenceFull.java
index 8efdbb74e5a892ad83bcac83a5a3b0be13209faa..a2124b5975f528f92cd0becaf7fb6ef6d7588af4 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/SequenceFull.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/SequenceFull.java
@@ -9,8 +9,11 @@ import org.mongodb.morphia.annotations.Entity;
 import org.mongodb.morphia.annotations.Id;
 import org.mongodb.morphia.annotations.Reference;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
 import de.vipra.util.an.QueryIgnore;
 
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Entity(value = "sequences", noClassnameStored = true)
 public class SequenceFull implements Model<ObjectId>, Comparable<SequenceFull>, Serializable {
diff --git a/vipra-util/src/main/java/de/vipra/util/model/SimilarArticle.java b/vipra-util/src/main/java/de/vipra/util/model/SimilarArticle.java
index 3f975ff81c1b33ced97bcc756734aa1b07a16330..4dab98473b321d3b93c7655e3a7a4d94b27fd37f 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/SimilarArticle.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/SimilarArticle.java
@@ -5,6 +5,9 @@ import java.io.Serializable;
 import org.mongodb.morphia.annotations.Embedded;
 import org.mongodb.morphia.annotations.Reference;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Embedded
 public class SimilarArticle implements Comparable<SimilarArticle>, Serializable {
diff --git a/vipra-util/src/main/java/de/vipra/util/model/TextEntity.java b/vipra-util/src/main/java/de/vipra/util/model/TextEntity.java
index d0bba63fee5917c2a5db59047c972a126594108d..49dfe53d03506e67024f3bcc5b75cb92a92b3f73 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/TextEntity.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/TextEntity.java
@@ -4,6 +4,9 @@ import java.io.Serializable;
 
 import org.mongodb.morphia.annotations.Embedded;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Embedded
 public class TextEntity implements Serializable {
diff --git a/vipra-util/src/main/java/de/vipra/util/model/Topic.java b/vipra-util/src/main/java/de/vipra/util/model/Topic.java
index b2291995bfb0aec6dd291334021b1618bdfa36ad..644520c842f505a3515de6f85605a19f408df7cc 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/Topic.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/Topic.java
@@ -8,8 +8,11 @@ import org.mongodb.morphia.annotations.Id;
 import org.mongodb.morphia.annotations.Index;
 import org.mongodb.morphia.annotations.Indexes;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
 import de.vipra.util.MongoUtils;
 
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Entity(value = "topics", noClassnameStored = true)
 @Indexes({ @Index("name"), @Index("-created") })
diff --git a/vipra-util/src/main/java/de/vipra/util/model/TopicFull.java b/vipra-util/src/main/java/de/vipra/util/model/TopicFull.java
index f875db28a1e88ae195f5acbbdb130c97a3349eb0..d8538861ee0bb10606984f81569f6589ec73e796 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/TopicFull.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/TopicFull.java
@@ -8,15 +8,21 @@ import java.util.List;
 import org.bson.types.ObjectId;
 import org.mongodb.morphia.annotations.Entity;
 import org.mongodb.morphia.annotations.Id;
+import org.mongodb.morphia.annotations.Index;
+import org.mongodb.morphia.annotations.Indexes;
 import org.mongodb.morphia.annotations.PrePersist;
 import org.mongodb.morphia.annotations.Reference;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
 import de.vipra.util.MongoUtils;
 import de.vipra.util.StringUtils;
 import de.vipra.util.an.QueryIgnore;
 
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Entity(value = "topics", noClassnameStored = true)
+@Indexes({ @Index("name"), @Index("-created") })
 public class TopicFull implements Model<ObjectId>, Serializable {
 
 	@Id
diff --git a/vipra-util/src/main/java/de/vipra/util/model/TopicModel.java b/vipra-util/src/main/java/de/vipra/util/model/TopicModel.java
index e205a16b7dcf0c73d06b431284be5389f2f55274..781924d8f384a12086bed38b42e5b0c7df31bf32 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/TopicModel.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/TopicModel.java
@@ -5,6 +5,9 @@ import java.io.Serializable;
 import org.mongodb.morphia.annotations.Entity;
 import org.mongodb.morphia.annotations.Id;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Entity(value = "topicmodels", noClassnameStored = true)
 public class TopicModel implements Model<String>, Comparable<TopicModel>, Serializable {
diff --git a/vipra-util/src/main/java/de/vipra/util/model/TopicModelConfig.java b/vipra-util/src/main/java/de/vipra/util/model/TopicModelConfig.java
index b916ea46d704f8606c01484076c7a8fa5ce1a152..366972d664942ec0d96507e6b5b66c89e9ae3fd1 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/TopicModelConfig.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/TopicModelConfig.java
@@ -5,10 +5,13 @@ import java.io.Serializable;
 
 import org.mongodb.morphia.annotations.Embedded;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
 import de.vipra.util.Constants;
 import de.vipra.util.Constants.ProcessorMode;
 import de.vipra.util.Constants.WindowResolution;
 
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Embedded
 public class TopicModelConfig implements Serializable {
diff --git a/vipra-util/src/main/java/de/vipra/util/model/TopicModelFull.java b/vipra-util/src/main/java/de/vipra/util/model/TopicModelFull.java
index 13a0a138faf8c6430beaa85591f5f8bfb8997b92..ad5572ab112f3f7aa426e76a86e8f8593419d936 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/TopicModelFull.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/TopicModelFull.java
@@ -6,8 +6,11 @@ import org.mongodb.morphia.annotations.Embedded;
 import org.mongodb.morphia.annotations.Entity;
 import org.mongodb.morphia.annotations.Id;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
 import de.vipra.util.an.QueryIgnore;
 
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Entity(value = "topicmodels", noClassnameStored = true)
 public class TopicModelFull implements Model<String>, Comparable<TopicModelFull>, Serializable {
diff --git a/vipra-util/src/main/java/de/vipra/util/model/TopicShare.java b/vipra-util/src/main/java/de/vipra/util/model/TopicShare.java
index 5f604cf9ef373c25a7552ddf24d5256cdb66a3ca..6d065bbf0aae693c97ff288c3e28321433da1919 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/TopicShare.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/TopicShare.java
@@ -5,6 +5,9 @@ import java.io.Serializable;
 import org.mongodb.morphia.annotations.Embedded;
 import org.mongodb.morphia.annotations.Reference;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Embedded
 public class TopicShare implements Comparable<TopicShare>, Serializable {
diff --git a/vipra-util/src/main/java/de/vipra/util/model/TopicWord.java b/vipra-util/src/main/java/de/vipra/util/model/TopicWord.java
index dad8de098b861f4941c90b517a69a6691a985935..4355d78abecb2aca05c93516cbb4f810278ea4b3 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/TopicWord.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/TopicWord.java
@@ -6,8 +6,10 @@ import org.mongodb.morphia.annotations.Embedded;
 
 import com.fasterxml.jackson.annotation.JsonGetter;
 import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonSetter;
 
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Embedded
 public class TopicWord implements Comparable<TopicWord>, Serializable {
diff --git a/vipra-util/src/main/java/de/vipra/util/model/Window.java b/vipra-util/src/main/java/de/vipra/util/model/Window.java
index da4e4f5c9ebe41165b417946bf7fcd646cb7291a..3039ca0358f909be9c26e767c4498364846cdcc9 100644
--- a/vipra-util/src/main/java/de/vipra/util/model/Window.java
+++ b/vipra-util/src/main/java/de/vipra/util/model/Window.java
@@ -5,11 +5,12 @@ import java.util.Date;
 
 import org.mongodb.morphia.annotations.Entity;
 import org.mongodb.morphia.annotations.Id;
-import org.mongodb.morphia.annotations.Reference;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 
 import de.vipra.util.Constants.WindowResolution;
-import de.vipra.util.an.QueryIgnore;
 
+@JsonIgnoreProperties(ignoreUnknown = true)
 @SuppressWarnings("serial")
 @Entity(value = "windows", noClassnameStored = true)
 public class Window implements Model<Integer>, Serializable, Comparable<Window> {
@@ -17,16 +18,25 @@ public class Window implements Model<Integer>, Serializable, Comparable<Window>
 	@Id
 	private Integer id;
 
-	@Reference
-	@QueryIgnore(multi = true)
-	private TopicModel topicModel;
-
 	private Date startDate;
 
 	private Date endDate;
 
 	private WindowResolution windowResolution;
 
+	public Window() {}
+
+	public Window(Integer id) {
+		this.id = id;
+	}
+
+	public Window(WindowFull window) {
+		this.id = window.getId();
+		this.startDate = window.getStartDate();
+		this.endDate = window.getEndDate();
+		this.windowResolution = window.getWindowResolution();
+	}
+
 	@Override
 	public Integer getId() {
 		return id;
@@ -37,14 +47,6 @@ public class Window implements Model<Integer>, Serializable, Comparable<Window>
 		this.id = id;
 	}
 
-	public TopicModel getTopicModel() {
-		return topicModel;
-	}
-
-	public void setTopicModel(final TopicModel model) {
-		topicModel = model;
-	}
-
 	public Date getStartDate() {
 		return startDate;
 	}
diff --git a/vipra-util/src/main/java/de/vipra/util/model/WindowFull.java b/vipra-util/src/main/java/de/vipra/util/model/WindowFull.java
new file mode 100644
index 0000000000000000000000000000000000000000..c34086ad1da48c2f1b2a76e46e6593e970a9ad0d
--- /dev/null
+++ b/vipra-util/src/main/java/de/vipra/util/model/WindowFull.java
@@ -0,0 +1,80 @@
+package de.vipra.util.model;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.mongodb.morphia.annotations.Entity;
+import org.mongodb.morphia.annotations.Id;
+import org.mongodb.morphia.annotations.Reference;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+import de.vipra.util.Constants.WindowResolution;
+import de.vipra.util.an.QueryIgnore;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@SuppressWarnings("serial")
+@Entity(value = "windows", noClassnameStored = true)
+public class WindowFull implements Model<Integer>, Comparable<WindowFull>, Serializable {
+
+	@Id
+	private Integer id;
+
+	@Reference
+	@QueryIgnore(multi = true)
+	private TopicModel topicModel;
+
+	private Date startDate;
+
+	private Date endDate;
+
+	private WindowResolution windowResolution;
+
+	@Override
+	public Integer getId() {
+		return id;
+	}
+
+	@Override
+	public void setId(final Integer id) {
+		this.id = id;
+	}
+
+	public TopicModel getTopicModel() {
+		return topicModel;
+	}
+
+	public void setTopicModel(final TopicModel model) {
+		topicModel = model;
+	}
+
+	public Date getStartDate() {
+		return startDate;
+	}
+
+	public void setStartDate(final Date startDate) {
+		this.startDate = startDate;
+	}
+
+	public Date getEndDate() {
+		return endDate;
+	}
+
+	public void setEndDate(final Date endDate) {
+		this.endDate = endDate;
+	}
+
+	public WindowResolution getWindowResolution() {
+		return windowResolution;
+	}
+
+	public void setWindowResolution(final WindowResolution windowResolution) {
+		this.windowResolution = windowResolution;
+	}
+
+	@Override
+	public int compareTo(final WindowFull o) {
+		return id - o.getId();
+	}
+
+}