  
  
def makeSelectDisplay(filereader,spectrum, selector_reals, selector_colors, line_width=2):
  #-- VisAD displays are awt.Canvas -> Canvas3D, so mixing heavyweight/lightweight 
  #-- components causes problems with the popup menus always rendered beneath the Canvas
  JPopupMenu.setDefaultLightWeightPopupEnabled(lightWeightPopupEnabled)


      
  global spectrumDisplay, obs_valid_range, line_width
    
  obs_valid_range = filereader.getObsValidRange()
  obsElementInstrument, obsLineInstrument, obsChannelIndexInstrument, observationChannelsInstrument, observationsInstrument = filereader.getRealTypes()
  spmps = makeMaps(observationChannelsInstrument,'x',observationsInstrument,'y')
  xmap = spmps[0]
  ymap = spmps[1]
  spmps[1].setRange(obs_valid_range[0], obs_valid_range[1])
  spectrumDisplay = makeDisplay(spmps)
  subs.setAspectRatio(spectrumDisplay,2)
  mode = spectrumDisplay.getGraphicsModeControl()
  mode.setPointSize(5)
  showAxesScales(spectrumDisplay,1)
  setBoxSize(spectrumDisplay,.6,clip=0)
  #dset = self.spectrum.getDomainSet()
  dset = filereader.observationDomain
  lo = dset.getLow()
  hi = dset.getHi()
  lens    = dset.getLengths()
  spmps[0].setRange(lo[0], hi[0])
  addData('b',spectrum,spectrumDisplay,makeLineStyleMap('solid',1),zlayer=-0.05) 
    
     
  class ChannelChangeCell(CellImpl):
    def __init__(self, init_val, selectRef, lineColor):
      self.selectRef = selectRef
      self.lineRef = spectrumDisplay.drawLine([[init_val,init_val], [obs_valid_range[0], obs_valid_range[1]]], color=lineColor, line_width=2)
        
    def doAction(self):
      val = self.selectRef.getData().getValue()
      self.spectrumDisplay.moveLine(self.lineRef, [[val, val], [obs_valid_range[0], obs_valid_range[1]]])
 
  num_selectors = len(selectors)
  selectorRefs  = []
  for kk in xrange(num_selectors):      
    selectRef = spectrumDisplay.addData("channelSelector", selector_reals[kk],
      constantMaps=[ConstantMap(-0.5, Display.YAxis)]+makeColorMap(selector_colors[kk]), renderer=OneDProbeRendererJ3D(dset))                    
    ccell = ChannelChangeCell(init_real, selectRef, selector_colors[kk])
    ccell.addReference(selectRef)
    selectorRefs.append(selectRef)


 
  zoomBoxRef = DataReferenceImpl("zoomBoxRef")
  zoomBoxRef.setData(Gridded2DSet(RealTupleType(observationChannelsInstrument, observationsInstrument), None, 1))
  spectrumDisplay.addReferences(RubberBandBoxRendererJ3D(observationChannelsInstrument, observationsInstrument,2,2), zoomBoxRef)

     
  class ZoomBox(CellImpl):
    def __init__(self, zoomBoxRef, xmap, xlohi, ymap, ylohi, display):
      self.first      = 1
      self.zoomBoxRef = zoomBoxRef
      self.xmap       = xmap
      self.ymap       = ymap
      self.disp       = display
      self.pcntrl     = display.getProjectionControl()
      self.init_mtrx  = self.pcntrl.getMatrix()
      self.xlohi      = xlohi
      self.ylohi      = ylohi
    
    
    def doAction(self):
      if self.first == 0:
        set = self.zoomBoxRef.getData()
        lo  = set.getLow()
        hi  = set.getHi()
        if ((lo[0] == hi[0]) or (lo[1] == hi[1])):
          self.unzoom()
        else:
          self.xmap.setRange(lo[0], hi[0])
          self.ymap.setRange(lo[1], hi[1])
      else:
        self.first = 0
               
     def unzoom(self):
       self.pcntrl.setMatrix(self.imtrx)
       self.xmap.setRange(self.xlohi[0], self.xlohi[1])
       self.ymap.setRange(self.ylohi[0], self.ylohi[1])
       
  zcell = ZoomBox(zoomBoxRef, spmps[0], [lo[0], hi[0]], spmps[1], [obs_valid_range[0], obs_valid_range[1]], spectrumDisplay)
  zcell.addReference(zoomBoxRef)

  return spectrumDisplay, selectorRefs