class_docstr: The PlateViewer class lets the user view the files associated with plates
  
  The idea here is that the PlateViewer is given a list of image files
  with plate, well and site metadata. The plate viewer organizes the
  files and lets the user browse individual plates.
class_docstr_tok: ["The","PlateViewer","class","lets","the","user","view","the","files","associated","with","plates","The","idea","here","is","that","the","PlateViewer","is","given","a","list","of","image","files","with","plate",",","well","and","site","metadata",".","The","plate","viewer","organizes","the","files","and","lets","the","user","browse","individual","plates","."]
code: def __init__(self, frame, data):
      self.data = data
      self.palette = matplotlib.cm.get_cmap("jet")
      data.register_for_updates(self.on_update)
      self.frame = frame
      self.plate_bitmap = None
      self.frame.Sizer = wx.BoxSizer(wx.VERTICAL)
      self.splitter = wx.SplitterWindow(self.frame)
      try:
          self.splitter.Bind(
              wx.EVT_SPLITTER_DOUBLECLICKED, self.on_splitter_dclick
          )
      except:
          pass
      self.frame.Sizer.Add(self.splitter, 1, wx.EXPAND)
      self.sr_panel = wx.Panel(self.splitter)
      self.sr_panel.SetInitialSize((120, -1))
      self.sr_panel.Sizer = wx.BoxSizer(wx.VERTICAL)
      self.plate_choice = wx.Choice(self.sr_panel)
      self.sr_panel.Sizer.Add(
          self.plate_choice, 0, wx.LEFT | wx.ALL | wx.EXPAND, 4
      )
      self.plate_panel = wx.Panel(self.sr_panel)
      self.sr_panel.Sizer.Add(self.plate_panel, 1, wx.EXPAND)
      rows, cols = data.plate_layout
      w, h, _, _ = self.plate_panel.GetFullTextExtent(
          "".join(["00"] * cols)
      )
      h *= rows
      self.plate_panel.SetInitialSize((w, h))
      self.canvas_panel = wx.Panel(self.splitter)
      self.canvas_panel.Sizer = wx.BoxSizer(wx.VERTICAL)
      control_sizer = wx.BoxSizer(wx.HORIZONTAL)
      self.canvas_panel.Sizer.Add(
          control_sizer, 0, wx.EXPAND | wx.ALL, 2
      )
      self.site_grid = wx.grid.Grid(self.canvas_panel)
      self.site_grid.SetDefaultRenderer(wx.grid.GridCellFloatRenderer())
      self.site_grid.SetDefaultEditor(wx.grid.GridCellFloatEditor())
      self.site_grid.CreateGrid(1, 2)
      self.site_grid.SetColLabelValue(0, "X")
      self.site_grid.SetColLabelValue(1, "Y")
      control_sizer.Add(
          self.site_grid,
          0,
          wx.ALIGN_LEFT | wx.ALIGN_TOP | wx.ALL | wx.EXPAND,
          5,
      )
  
      self.channel_grid = wx.grid.Grid(self.canvas_panel)
      self.channel_grid.CreateGrid(1, 4)
      self.channel_grid.SetColLabelValue(0, "Red")
      self.channel_grid.SetColLabelValue(1, "Green")
      self.channel_grid.SetColLabelValue(2, "Blue")
      self.channel_grid.SetColLabelValue(3, "Alpha")
      self.channel_grid.SetDefaultEditor(wx.grid.GridCellNumberEditor())
      self.channel_grid.SetDefaultRenderer(
          wx.grid.GridCellNumberRenderer()
      )
      control_sizer.Add(
          self.channel_grid, 0, wx.ALIGN_TOP | wx.ALL | wx.EXPAND, 5
      )
      self.figure = matplotlib.figure.Figure()
      self.axes = self.figure.add_axes((0.05, 0.05, 0.9, 0.9))
      self.subcanvaspanel = wx.Panel(self.canvas_panel)
      self.canvas = matplotlib.backends.backend_wxagg.FigureCanvasWxAgg(
          self.subcanvaspanel, -1, self.figure
      )
      self.canvas_panel.Sizer.Add(self.subcanvaspanel, 1, wx.EXPAND)
      #
      # The following is largely taken from the matplotlib examples:
      # http://matplotlib.sourceforge.net/examples/user_interfaces/embedding_in_wx2.html
      #
      self.navtoolbar = (
          matplotlib.backends.backend_wx.NavigationToolbar2Wx(
              self.canvas
          )
      )
      self.navtoolbar.Realize()
      if wx.Platform == "__WXMAC__":
          # Mac platform (OSX 10.3, MacPython) does not seem to cope with
          # having a toolbar in a sizer. This work-around gets the buttons
          # back, but at the expense of having the toolbar at the top
          self.frame.SetToolBar(self.navtoolbar)
      # update the axes menu on the toolbar
      self.navtoolbar.update()
      self.image_dict = None
      self.image_dict_lock = multiprocessing.RLock()
      self.image_dict_generation = 0
      self.splitter.SplitVertically(self.sr_panel, self.canvas_panel)
      self.plate_panel.Bind(wx.EVT_PAINT, self.on_paint_plate)
      self.plate_panel.Bind(
          wx.EVT_ERASE_BACKGROUND, self.on_erase_background
      )
      self.plate_panel.Bind(wx.EVT_SIZE, self.on_plate_size)
      self.plate_panel.Bind(wx.EVT_MOTION, self.on_plate_motion)
      self.plate_panel.Bind(wx.EVT_LEFT_DOWN, self.on_plate_click)
      self.plate_choice.Bind(wx.EVT_CHOICE, self.on_plate_choice_evt)
      self.site_grid.Bind(
          wx.grid.EVT_GRID_CELL_CHANGED,
          lambda event: self.update_figure(),
      )
      self.channel_grid.Bind(
          wx.grid.EVT_GRID_CELL_CHANGED,
          lambda event: self.update_figure(),
      )
      self.frame.Bind(wx.EVT_CLOSE, self.on_close)
      self.subcanvaspanel.Bind(wx.EVT_SIZE, self.on_subcanvaspanel_size)
      self.on_update()
      self.frame.Layout()
  
imports: import multiprocessing
  import threading
  import traceback
  import matplotlib
  import matplotlib.backends.backend_wx
  import matplotlib.backends.backend_wxagg
  import matplotlib.cm
  import matplotlib.figure
  import numpy
  import wx
  import wx.grid
  import scyjava
label_desc: Use image node_id 1 to create a new PlateViewer object from inherited base classes: object with example: obj = PlateViewer(frame, data)