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 on_update(self):
      self.error = False
      try:
          if tuple(sorted(self.plate_choice.GetItems())) != tuple(
              sorted(self.data.get_plate_names())
          ):
              plate_names = self.data.get_plate_names()
              self.plate_choice.SetItems(plate_names)
              if len(plate_names) > 0:
                  self.plate_choice.SetSelection(0)
  
          self.plate_name = self.plate_choice.GetStringSelection()
          if self.plate_name in self.data.get_plate_names():
              self.plate_data = self.data.get_plate(self.plate_name)
          elif (
              len(self.data.get_plate_names()) == 0
              and None in self.data.plate_well_site
          ):
              self.plate_data = self.data.get_plate(None)
          else:
              self.plate_data = None
      except:
          # Metadata was invalid.
          wx.MessageBox(
              "Failed to open plate viewer.\n"
              "Plate metadata was invalid.\n"
              "'Well' metadata must be in the format [Column][Row], e.g. 'A01'\n"
              "Please see 'Help-->Using Your Output-->Plate Viewer' for guidance.",
              caption="Plate Metadata Error",
          )
          self.plate_data = None
          self.error = True
          return
      self.draw_plate()
      #
      # Set up the site grid size
      #
      if self.plate_data is not None:
          site_names = set()
          channel_names = set()
          for well in self.plate_data.flatten():
              if well is not None:
                  site_names.update(list(well.keys()))
                  for sd in list(well.values()):
                      channel_names.update(
                          [
                              fd[PlateData.D_CHANNEL]
                              if PlateData.D_CHANNEL in fd
                              else str(i + 1)
                              for i, fd in enumerate(sd)
                          ]
                      )
          if len(site_names) > 1 or None not in site_names:
              self.site_grid.Show(True)
              self.use_site_grid = True
              update_values = self.site_grid.GetNumberRows() != len(
                  site_names
              )
              if self.site_grid.GetNumberRows() < len(site_names):
                  self.site_grid.AppendRows(
                      len(site_names) - self.site_grid.GetNumberRows()
                  )
              elif self.site_grid.GetNumberRows() > len(site_names):
                  self.site_grid.DeleteRows(
                      numRows=self.site_grid.GetNumberRows()
                      - len(site_names)
                  )
              side = int(numpy.ceil(numpy.sqrt(float(len(site_names)))))
              for i, site_name in enumerate(sorted(site_names)):
                  self.site_grid.SetRowLabelValue(i, site_name)
                  if update_values:
                      self.site_grid.SetCellValue(
                          i, 0, str((i % side) + 1)
                      )
                      self.site_grid.SetCellValue(
                          i, 1, str(int(i / side) + 1)
                      )
          else:
              self.site_grid.Show(False)
              self.use_site_grid = False
          update_values = self.channel_grid.GetNumberRows() != len(
              channel_names
          )
          if self.channel_grid.GetNumberRows() < len(channel_names):
              self.channel_grid.AppendRows(
                  len(channel_names) - self.channel_grid.GetNumberRows()
              )
          elif self.channel_grid.GetNumberRows() > len(channel_names):
              self.channel_grid.DeleteRows(
                  numRows=self.channel_grid.GetNumberRows()
                  - len(channel_names)
              )
          for i, channel_name in enumerate(sorted(channel_names)):
              self.channel_grid.SetRowLabelValue(i, channel_name)
              for j in range(4):
                  if (
                      update_values
                      or not self.channel_grid.GetCellValue(
                          i, j
                      ).isdigit()
                  ):
                      self.channel_grid.SetCellValue(
                          i, j, str(255 if j == 3 or i == j else 0)
                      )
  
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 11 for calling the PlateViewer obj's underlying member method code with example usage: obj.on_update() without return types