# (c) MIT License Copyright 2014 <NAME>
# Please reuse, modify or distribute freely.

from collections import OrderedDict
import tkinter as tk

class StripChart( tk.Frame ):
   def __init__( self, parent, scale, historySize, trackColors, *args, **opts ):
      # Initialize
      super().__init__( parent, *args, **opts )
      self._trackHist   = OrderedDict() # Map: TrackName -> list of canvas objID 
      self._trackColor  = trackColors   # Map: Track Name -> color
      
      self._chartHeight = scale + 1
      self._chartLength = historySize * 2  # Stretch for readability

      self._canvas = tk.Canvas( self, height=self._chartHeight + 17,
                                width=self._chartLength, background='black' )
      self._canvas.grid( sticky=tk.N+tk.S+tk.E+tk.W )
      
      # Draw horizontal to divide plot from tick labels
      x,  y  = 0, self._chartHeight + 2
      x2, y2 = self._chartLength, y
      self._baseLine = self._canvas.create_line( x, y, x2, y2, fill='white' )
      
      # Init track def and histories lists
      self._trackColor.update( { 'tick':'white', 'tickline':'white',
                                 'ticklabel':'white' } )
      for trackName in self._trackColor.keys():
         self._trackHist[ trackName ] = [ None for x in range(historySize) ]

   def plotValues( self, **vals ):
      for trackName, trackHistory in self._trackHist.items():
         # Scroll left-wards
         self._canvas.delete( trackHistory.pop(0) )
              # Remove left-most canvas objs
         self._canvas.move( trackName, -2, 0 )
              # Scroll canvas objs 2 pixels left
         
         # Plot the new values
         try:
            val = vals[ trackName ]
            x = self._chartLength
            y = self._chartHeight - val
            color = self._trackColor[ trackName ]
            
            objId = self._canvas.create_line( x, y, x+1, y, fill=color,
                                              width=3, tags=trackName )
            trackHistory.append( objId )
         except:
            trackHistory.append( None )

   def drawTick( self, text=None, **lineOpts ):
      # draw vertical tick line
      x = self._chartLength
      y = 1
      x2 = x
      y2 = self._chartHeight
      color = self._trackColor[ 'tickline' ]
      
      objId = self._canvas.create_line( x, y, x2, y2, fill=color,
                                        tags='tick', **lineOpts )
      self._trackHist[ 'tickline' ].append( objId )
      
      # draw tick label
      if text is not None:
         x = self._chartLength
         y = self._chartHeight + 10
         color = self._trackColor[ 'ticklabel' ]
         
         objId = self._canvas.create_text( x, y, text=text,
                                           fill=color, tags='tick' )
         self._trackHist[ 'ticklabel' ].append( objId )

   def configTrackColors( self, **trackColors ):
      # Change plotted data color
      for trackName, colorName in trackColors.items( ):
         self._canvas.itemconfigure( trackName, fill=colorName )
      
      # Change settings so future data has the new color
      self._trackColor.update( trackColors )


if __name__ == '__main__':
   top = tk.Tk( )
   graph = StripChart( top, 100, 300, { 'A':'blue', 'B':'green', 'C':'red' } )
   graph.grid( )
   
   val_A = 0
   val_B = 0
   val_C = 0
   delta = [ -3, -2, -1, 0, 1, 2, 3 ]  # randomly vary the values by one of these
   tickCount = 0
   
   def nextVal( current, lowerBound, upperBound ):
      from random import choice
      
      current += choice( delta )
      if current < lowerBound:
         return lowerBound
      elif current > upperBound:
         return upperBound
      else:
         return current
   
   def plotNextVals( ):
      global val_A, val_B, val_C, tickCount
   
      if tickCount % 50 == 0:
         graph.drawTick( text=str(tickCount), dash=(1,4) )
      tickCount += 1
      
      val_A = nextVal( val_A, 0, 99 )
      val_B = nextVal( val_B, 0, 99 )
      val_C = nextVal( val_C, 0, 99 )
      graph.plotValues( A=val_A, B=val_B, C=val_C )
      
      #changeColor = { 800: 'black',
        #1200: 'yellow',
        #1600: 'orange',
        #2000: 'white',
        #2400: 'brown',
        #2800: 'blue' }
      #if tickCount in changeColor:
         #graph.configTrackColors( A=changeColor[tickCount] )
      
      top.after( 1, plotNextVals )
   
   top.after( 1, plotNextVals )
   
   top.mainloop( )

# (c) MIT License Copyright 2014 <NAME>
# Please reuse, modify or distribute freely.

from collections import OrderedDict
import tkinter as tk

class StripChart( tk.Frame ):
   def __init__( self, parent, scale, historySize, trackColors, *args, **opts ):
      # Initialize
      super().__init__( parent, *args, **opts )
      self._trackHist   = OrderedDict() # Map: TrackName -> list of canvas objID 
      self._trackColor  = trackColors   # Map: Track Name -> color
      
      self._chartHeight = scale + 1
      self._chartLength = historySize * 2  # Stretch for readability

      self._canvas = tk.Canvas( self, height=self._chartHeight + 17,
                                width=self._chartLength, background='black' )
      self._canvas.grid( sticky=tk.N+tk.S+tk.E+tk.W )
      
      # Draw horizontal to divide plot from tick labels
      x,  y  = 0, self._chartHeight + 2
      x2, y2 = self._chartLength, y
      self._baseLine = self._canvas.create_line( x, y, x2, y2, fill='white' )
      
      # Init track def and histories lists
      self._trackColor.update( { 'tick':'white', 'tickline':'white',
                                 'ticklabel':'white' } )
      for trackName in self._trackColor.keys():
         self._trackHist[ trackName ] = [ None for x in range(historySize) ]

   def plotValues( self, **vals ):
      for trackName, trackHistory in self._trackHist.items():
         # Scroll left-wards
         self._canvas.delete( trackHistory.pop(0) )
              # Remove left-most canvas objs
         self._canvas.move( trackName, -2, 0 )
              # Scroll canvas objs 2 pixels left
         
         # Plot the new values
         try:
            val = vals[ trackName ]
            x = self._chartLength
            y = self._chartHeight - val
            color = self._trackColor[ trackName ]
            
            objId = self._canvas.create_line( x, y, x+1, y, fill=color,
                                              width=3, tags=trackName )
            trackHistory.append( objId )
         except:
            trackHistory.append( None )

   def drawTick( self, text=None, **lineOpts ):
      # draw vertical tick line
      x = self._chartLength
      y = 1
      x2 = x
      y2 = self._chartHeight
      color = self._trackColor[ 'tickline' ]
      
      objId = self._canvas.create_line( x, y, x2, y2, fill=color,
                                        tags='tick', **lineOpts )
      self._trackHist[ 'tickline' ].append( objId )
      
      # draw tick label
      if text is not None:
         x = self._chartLength
         y = self._chartHeight + 10
         color = self._trackColor[ 'ticklabel' ]
         
         objId = self._canvas.create_text( x, y, text=text,
                                           fill=color, tags='tick' )
         self._trackHist[ 'ticklabel' ].append( objId )

   def configTrackColors( self, **trackColors ):
      # Change plotted data color
      for trackName, colorName in trackColors.items( ):
         self._canvas.itemconfigure( trackName, fill=colorName )
      
      # Change settings so future data has the new color
      self._trackColor.update( trackColors )


if __name__ == '__main__':
   top = tk.Tk( )
   graph = StripChart( top, 100, 300, { 'A':'blue', 'B':'green', 'C':'red' } )
   graph.grid( )
   
   val_A = 0
   val_B = 0
   val_C = 0
   delta = [ -3, -2, -1, 0, 1, 2, 3 ]  # randomly vary the values by one of these
   tickCount = 0
   
   def nextVal( current, lowerBound, upperBound ):
      from random import choice
      
      current += choice( delta )
      if current < lowerBound:
         return lowerBound
      elif current > upperBound:
         return upperBound
      else:
         return current
   
   def plotNextVals( ):
      global val_A, val_B, val_C, tickCount
   
      if tickCount % 50 == 0:
         graph.drawTick( text=str(tickCount), dash=(1,4) )
      tickCount += 1
      
      val_A = nextVal( val_A, 0, 99 )
      val_B = nextVal( val_B, 0, 99 )
      val_C = nextVal( val_C, 0, 99 )
      graph.plotValues( A=val_A, B=val_B, C=val_C )
      
      #changeColor = { 800: 'black',
        #1200: 'yellow',
        #1600: 'orange',
        #2000: 'white',
        #2400: 'brown',
        #2800: 'blue' }
      #if tickCount in changeColor:
         #graph.configTrackColors( A=changeColor[tickCount] )
      
      top.after( 1, plotNextVals )
   
   top.after( 1, plotNextVals )
   
   top.mainloop( )

# (c) MIT License Copyright 2014 <NAME> # Please reuse, modify or distribute freely. # Initialize # Map: TrackName -> list of canvas objID # Map: Track Name -> color # Stretch for readability # Draw horizontal to divide plot from tick labels # Init track def and histories lists # Scroll left-wards # Remove left-most canvas objs # Scroll canvas objs 2 pixels left # Plot the new values # draw vertical tick line # draw tick label # Change plotted data color # Change settings so future data has the new color # randomly vary the values by one of these #changeColor = { 800: 'black', #1200: 'yellow', #1600: 'orange', #2000: 'white', #2400: 'brown', #2800: 'blue' } #if tickCount in changeColor: #graph.configTrackColors( A=changeColor[tickCount] )