              NB: For totals, gaps between sessions can be large
              so time difference has to be reset for each session's
              rate calculation """
          logger.debug("Calculating totals rate")
          batchsizes = self.session.total_batchsize
          total_timestamps = self.session.total_timestamps
          rate = list()
          for sess_id in sorted(total_timestamps.keys()):
              batchsize = batchsizes[sess_id]
              timestamps = total_timestamps[sess_id]
              iterations = range(len(timestamps) - 1)
 
</s> remove         batchsize = self.session.batchsize
        timestamps = self.session.timestamps
        iterations = range(len(timestamps) - 1)
        rate = [(batchsize * 2) / (timestamps[i + 1] - timestamps[i]) for i in iterations]
        logger.debug("Calculated rate: Item_count: %s", len(rate))
        return rate

    def calc_rate_total(self):
        """ Calculate rate per iteration
            NB: For totals, gaps between sessions can be large
            so time difference has to be reset for each session's
            rate calculation """
 </s> add         retval = (Session.batch_sizes[self._session_id] * 2) / np.diff(Session.get_timestamps(
            self._session_id))
        logger.debug("Calculated rate: Item_count: %s", len(retval))
        return retval

    @classmethod
    def _calc_rate_total(cls):
        """ Calculate rate per iteration for all sessions.

        Returns
        -------
        :class:`numpy.ndarray`
            The training rate for each iteration in all sessions

        Notes
        -----
        For totals, gaps between sessions can be large so the time difference has to be reset for
        each session's rate calculation.
        """ </s> remove     def calc_rate(self):
        """ Calculate rate per iteration """
 </s> add     def _calc_rate(self):
        """ Calculate rate per iteration.

        Returns
        -------
        :class:`numpy.ndarray`
            The training rate for each iteration of the selected session
        """ </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     @property
    def sessions_stats(self):
        """ Return compiled stats """
        compiled = list()
        for sess_idx, ts_data in self.time_stats.items():
            logger.debug("Compiling session ID: %s", sess_idx)
            if self.session.state is None:
                logger.debug("Session state dict doesn't exist. Most likely task has been "
                             "terminated during compilation")
                return None
            iterations = self.session.get_iterations_for_session(sess_idx)
            elapsed = ts_data["end_time"] - ts_data["start_time"]
            batchsize = self.session.total_batchsize.get(sess_idx, 0)
            compiled.append(
                {"session": sess_idx,
                 "start": ts_data["start_time"],
                 "end": ts_data["end_time"],
                 "elapsed": elapsed,
                 "rate": ((batchsize * 2) * iterations) / elapsed if elapsed != 0 else 0,
                 "batch": batchsize,
                 "iterations": iterations})
        compiled = sorted(compiled, key=lambda k: k["session"])
        return compiled

    def compile_stats(self):
        """ Compile sessions stats with totals, format and return """
        logger.debug("Compiling sessions summary data")
        compiled_stats = self.sessions_stats
        if not compiled_stats:
            return compiled_stats
        logger.debug("sessions_stats: %s", compiled_stats)
        total_stats = self.total_stats(compiled_stats)
        compiled_stats.append(total_stats)
        compiled_stats = self.format_stats(compiled_stats)
        logger.debug("Final stats: %s", compiled_stats)
        return compiled_stats

    @staticmethod
    def total_stats(sessions_stats):
        """ Return total stats """
 </s> add     def _total_stats(self):
        """ Compile the Totals stats.
        Totals are fully calculated each time as they will change on the basis of the training
        session.

        Returns
        -------
        dict:
            The Session name, start time, end time, elapsed time, rate, batch size and number of
            iterations for all session ids within the loaded data.
        """ </s> remove     @property
    def time_stats(self):
        """ Return session time stats """
        ts_data = self.session.tb_logs.get_timestamps()
        time_stats = {sess_id: {"start_time": min(timestamps) if timestamps else 0,
                                "end_time": max(timestamps) if timestamps else 0,
                                "datapoints": len(timestamps) if timestamps else 0}
                      for sess_id, timestamps in ts_data.items()}
        return time_stats
 </s> add         Returns
        -------
        dict
            The collated session summary statistics
        """
        timestamps = self._time_stats[session_id]
        elapsed = int(timestamps["end_time"] - timestamps["start_time"])
        batchsize = self._session.batch_sizes.get(session_id, 0)
        retval = dict(
            session=session_id,
            start=timestamps["start_time"],
            end=timestamps["end_time"],
            elapsed=elapsed,
            rate=(((batchsize * 2) * timestamps["iterations"]) / elapsed if elapsed != 0 else 0),
            batch=batchsize,
            iterations=timestamps["iterations"])
        logger.debug(retval)
        return retval
        batchsizes = Session.batch_sizes
        total_timestamps = Session.get_timestamps(None)
              NB: For totals, gaps between sessions can be large
              so time difference has to be reset for each session's
              rate calculation """
          logger.debug("Calculating totals rate")
        batchsizes = Session.batch_sizes
        total_timestamps = Session.get_timestamps(None)
        batchsizes = Session.batch_sizes
        total_timestamps = Session.get_timestamps(None)
          rate = list()
          for sess_id in sorted(total_timestamps.keys()):
              batchsize = batchsizes[sess_id]
              timestamps = total_timestamps[sess_id]
              iterations = range(len(timestamps) - 1)
keep keep keep keep replace replace keep 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/stats.py