          """ Set the color map and line width for each group """
          logger.trace("Setting lines style")
          groups = int(len(lines) / groupsize)
          colours = self.lines_create_colors(groupsize, groups)
          for idx, item in enumerate(lines):
              linewidth = widths[idx // groupsize]
              item.extend((linewidth, colours[idx]))
          return lines
 
</s> remove             linewidth = ceil((idx + 1) / groupsize)
 </s> add             linewidth = widths[idx // groupsize] </s> remove             iterations = range(len(timestamps) - 1)
            rate.extend([(batchsize * 2) / (timestamps[i + 1] - timestamps[i])
                         for i in iterations])
        logger.debug("Calculated totals rate: Item_count: %s", len(rate))
        return rate

    @staticmethod
    def flatten_outliers(data):
        """ Remove the outliers from a provided list """
        logger.debug("Flattening outliers")
        retdata = list()
        samples = len(data)
        mean = (sum(data) / samples)
        limit = sqrt(sum([(item - mean)**2 for item in data]) / samples)
        logger.debug("samples: %s, mean: %s, limit: %s", samples, mean, limit)

        for idx, item in enumerate(data):
            if (mean - limit) <= item <= (mean + limit):
                retdata.append(item)
            else:
                logger.trace("Item idx: %s, value: %s flattened to %s", idx, item, mean)
                retdata.append(mean)
        logger.debug("Flattened outliers")
        return retdata
 </s> add             rate.extend((batchsize * 2) / np.diff(timestamps))
        retval = np.array(rate)
        logger.debug("Calculated totals rate: Item_count: %s", len(retval))
        return retval </s> remove             graph.calcs.args["smooth_amount"] = smooth_amount
 </s> add             graph.calcs.set_smooth_amount(smooth_amount)

    def _iteration_limit_callback(self, *args):
        """ Limit the amount of data displayed in the live graph on a iteration slider
        variable change. """
        try:
            limit = self.vars["display_iterations"].get()
        except tk.TclError:
            # Don't update when there is no value in the variable
            return
        logger.debug("Updating graph iteration limit: (new_value: %s, args: %s)",
                     limit, args)
        for graph in self.subnotebook.children.values():
            graph.calcs.set_iterations_limit(limit)

    def _display_data_callback(self, line, variable):
        """ Update the displayed graph lines based on option check button selection.

        Parameters
        ----------
        line: str
            The line to hide or display
        variable: :class:`tkinter.BooleanVar`
            The tkinter variable containing the ``True`` or ``False`` data for this display item
        """
        var = variable.get()
        logger.debug("Updating display %s to %s", line, var)
        for graph in self.subnotebook.children.values():
            graph.calcs.update_selections(line, var) </s> remove     @staticmethod
    def init_training_session(cliopt):
        """ Set the session stats for disable logging, model folder and model name """
        session = get_config().session
        if cliopt[0] == "-t":
            session.modelname = cliopt[1].lower().replace("-", "_")
            logger.debug("modelname: '%s'", session.modelname)
        if cliopt[0] == "-m":
            session.modeldir = cliopt[1]
            logger.debug("modeldir: '%s'", session.modeldir)
 </s> add     def _get_training_session_info(self, cli_option):
        """ Set the model folder and model name to :`attr:_training_session_location` so the global
        session picks them up for logging to the graph and analysis tab.

        Parameters
        ----------
        cli_option: list
            The command line option to be checked for model folder or name
        """
        if cli_option[0] == "-t":
            self._training_session_location["model_name"] = cli_option[1].lower().replace("-", "_")
            logger.debug("model_name: '%s'", self._training_session_location["model_name"])
        if cli_option[0] == "-m":
            self._training_session_location["model_folder"] = cli_option[1]
            logger.debug("model_folder: '%s'", self._training_session_location["model_folder"]) </s> remove         for item in data:
            dataset = list(filter(lambda x: x is not None, item))
            if not dataset:
                continue
            ymin.append(min(dataset) * 1000)
            ymax.append(max(dataset) * 1000)
 </s> add         for item in data:  # TODO Handle as array not loop
            ymin.append(np.nanmin(item) * 1000)
            ymax.append(np.nanmax(item) * 1000)
        widths = list(range(1, groups + 1))
          """ Set the color map and line width for each group """
          logger.trace("Setting lines style")
          groups = int(len(lines) / groupsize)
          colours = self.lines_create_colors(groupsize, groups)
        widths = list(range(1, groups + 1))
          for idx, item in enumerate(lines):
              linewidth = widths[idx // groupsize]
              item.extend((linewidth, colours[idx]))
          return lines
keep keep keep add keep keep keep keep
 GUI - Stats optimization (#1067)

* Faster stat loading + caching

* Compress data in cache

* Optimize some calculations

* Vectorize smoothing

* stats.Calculations optimized

* Load latest training data from live iterator

* Add options to training graph 
lib/gui/display_graph.py