content: import numpy as np
  
  # from matplotlib import pyplot as plt
  
  from PyQt5.QtWidgets import *
  from PyQt5.QtCore import *
  from PyQt5.QtGui import *
  
  class RVLoadHistogram(QGraphicsView):
      '''A histogram for the maximum load across the reachable area'''
      def __init__(self, ik):
          width = 330
          height = 120
          self.scene = QGraphicsScene(0,-15,width,height-15)
          super(RVLoadHistogram, self).__init__(self.scene)
          self.setBackgroundBrush(QBrush(Qt.white))
          self.setRenderHints(QPainter.Antialiasing)
          self.setFrameStyle(0)
          self.setAlignment(Qt.AlignCenter)
          self.setFixedSize(width, height)
          self.setSceneRect(0, 0, width, height)
          self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
          self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
          self.scale(1, -1)
  
          self.subscribers = {
          'mouseEnter' : [],
          'mouseLeave' : [],
          'mouseMove' : []
          }
  
          self.lines = []
          self.hist = []
          self.edges = []
          self.config = ik.config
          self.update(ik)
  
          self.setMouseTracking(True)
  
      def update(self, ik=None):
          if ik is not None:
              self.ik = ik
              self.min_load = self.config['min_load'].value
  
          for line in self.lines:
              self.scene.removeItem(line)
          self.lines = []
  
          width = self.width()
          height = self.height()
  
          loads = np.ma.masked_invalid(self.ik.loads*self.ik.partial_ok)
          loads = np.ma.masked_where(loads == 0, loads).compressed()
          self.hist, self.edges = np.histogram(loads, bins='auto')
  
          buckets = len(self.hist)
          self.screen_step = width/np.max(self.edges)
          max_count = np.max(self.hist)
  
          # Display histogram
          for i in range(buckets):
              x = self.edges[i] * self.screen_step
              w = max(1, (self.edges[i+1] - self.edges[i]) * self.screen_step)
              l = (self.edges[i] + self.edges[i + 1]) / 2
              count = self.hist[i]
              if l < self.min_load:
                  color = QColor(100,100,100)
              else:
                  color = QColor(200, 180, 100)
              # print(count)
              line = self.scene.addLine(x, 5, x, 5 + (height-5) * count/max_count, QPen(color, w))
              self.lines.append(line)
          # Setpoint shows the configuration's minimum load
          setpoint = self.config['min_load'].value * self.screen_step
          line = self.scene.addLine(setpoint, 0, setpoint, height, QPen(QColor(150, 150, 255), 2))
          self.lines.append(line)
  
      def setMinimumLoad(self, val):
          self.min_load = val
          self.update()
  
      def subscribe(self, event, function):
          self.subscribers[event].append(function)
  
      def enterEvent(self, event):
          for func in self.subscribers['mouseEnter']:
              func(event)
  
      def leaveEvent(self, event):
          self.setMinimumLoad(self.config['min_load'].value)
          for func in self.subscribers['mouseLeave']:
              func(event)
  
      def mouseMoveEvent(self, event):
          if event.buttons() == Qt.LeftButton:
              self.click(event.pos())
          else:
              pt = self.mapToScene(event.pos())
              self.setMinimumLoad(pt.x()/self.screen_step)
          for func in self.subscribers['mouseMove']:
              func(event)
  
      def mousePressEvent(self, event):
          if event.button() == Qt.LeftButton:
              self.click(event.pos())
  
      def click(self, pos):
          pt = self.mapToScene(pos)
          self.config['min_load'].value = pt.x()/self.screen_step
          self.config.notifyChange()
  