Пример #1
0
  /** Gets called when this tab gets focus. Uses the ActionListeners of the UI components */
  @Override
  public void gotSelected() {
    posUpdater_.pauseUpdates(true);
    joystickPanel_.gotSelected();
    cameraPanel_.gotSelected();
    beamPanel_.gotSelected();
    props_.callListeners();

    // moves illumination piezo to home
    if (illumPiezoHomeEnable_.isSelected()
        && devices_.isValidMMDevice(piezoIlluminationDeviceKey_)) {
      props_.setPropValue(
          piezoIlluminationDeviceKey_, Properties.Keys.MOVE_TO_HOME, Properties.Values.DO_IT);
    }

    // set scan waveform to be triangle
    // SPIM use can change, but for alignment avoid sharp edges
    props_.setPropValue(
        micromirrorDeviceKey_, Properties.Keys.SA_PATTERN_X, Properties.Values.SAM_TRIANGLE, true);

    // move piezo and scanner to "center" position
    centerPiezoAndGalvo();

    posUpdater_.pauseUpdates(false);
  }
Пример #2
0
 private void checkPropertyValueEquals(
     Devices.Keys devKey, Properties.Keys propKey, Properties.Values expectedValue) {
   if (!(props_.getPropValueString(devKey, propKey).equals(expectedValue.toString()))) {
     if (MyDialogUtils.getConfirmDialogResult(
         "This plugin may not work if property \""
             + propKey.toString()
             + "\" of device \""
             + devices_.getMMDevice(devKey)
             + "\" is not set to \""
             + expectedValue.toString()
             + "\".  Set it now?",
         JOptionPane.YES_NO_OPTION)) {
       props_.setPropValue(devKey, propKey, expectedValue);
     }
   }
 }
Пример #3
0
 /**
  * checks firmware versions and gives any necessary warnings to user
  *
  * @param key
  */
 private void checkFirmwareVersion(Devices.Keys key) {
   // firmware version check only for ASI devices
   if (!devices_.isTigerDevice(key)) {
     return;
   }
   float firmwareVersion = props_.getPropValueFloat(key, Properties.Keys.FIRMWARE_VERSION);
   switch (key) {
     case PIEZOA:
     case PIEZOB:
       if (firmwareVersion == 0f) {
         // firmware version property wasn't found, maybe device hasn't been selected
       } else if (firmwareVersion < (float) 2.829) {
         MyDialogUtils.showError(
             "Device "
                 + devices_.getMMDevice(key)
                 + ": Piezo firmware is old; piezo may not move correctly in sync with sheet."
                 + " Contact ASI for updated firmware.");
       }
       break;
     case GALVOA:
     case GALVOB:
       if (firmwareVersion == 0f) {
         // firmware version property wasn't found, maybe device hasn't been selected
       } else if (firmwareVersion < (float) 2.809) {
         MyDialogUtils.showError(
             "Device "
                 + devices_.getMMDevice(key)
                 + ": Micromirror firmware is old; wheel control of some scanner axes may not work."
                 + " Contact ASI for updated firmware.");
       } else if (firmwareVersion < (float) 2.829) {
         MyDialogUtils.showError(
             "Device "
                 + devices_.getMMDevice(key)
                 + ": Micromirror firmware is old; imaging piezo not set correctly the first stack."
                 + " Contact ASI for updated firmware.");
       } else if (firmwareVersion < (float) 2.859) {
         MyDialogUtils.showError(
             "Device "
                 + devices_.getMMDevice(key)
                 + ": Micromirror firmware is old; not all timing parameters are supported."
                 + " Contact ASI for updated firmware.");
       }
       break;
     case PLOGIC:
       if (firmwareVersion < 3.069) {
         MyDialogUtils.showError(
             "Device "
                 + devices_.getMMDevice(key)
                 + ": PLogic firmware is old; some features may not work."
                 + " Contact ASI for updated firmware.");
       }
       break;
     default:
       break;
   }
 }
  /**
   * Creates the ASIdiSPIM plugin frame
   *
   * @param gui - Micro-Manager script interface
   * @throws ASIdiSPIMException
   */
  public ASIdiSPIMFrame(ScriptInterface gui) throws ASIdiSPIMException {

    // create interface objects used by panels
    gui_ = gui;
    prefs_ = new Prefs(Preferences.userNodeForPackage(this.getClass()));
    devices_ = new Devices(gui_, prefs_);
    props_ = new Properties(gui_, devices_, prefs_);
    positions_ = new Positions(gui_, devices_);
    joystick_ = new Joystick(devices_, props_);
    cameras_ = new Cameras(gui_, devices_, props_, prefs_);
    controller_ = new ControllerUtils(gui_, props_, prefs_, devices_, positions_);

    // make sure Live mode is turned off (panels assume it can manipulate
    //   cameras which requires live mode to be turned off)
    boolean liveModeOriginally = gui_.isLiveModeOn();
    String cameraOriginal = gui_.getMMCore().getCameraDevice();
    if (liveModeOriginally) {
      gui_.enableLiveMode(false);
    }

    // create the panels themselves
    // in some cases dependencies create required ordering
    devicesPanel_ = new DevicesPanel(gui_, devices_, props_);
    stagePosUpdater_ =
        new StagePositionUpdater(positions_, props_); // needed for setup and navigation

    autofocus_ =
        new AutofocusUtils(
            gui_, devices_, props_, prefs_, cameras_, stagePosUpdater_, positions_, controller_);

    acquisitionPanel_ =
        new AcquisitionPanel(
            gui_,
            devices_,
            props_,
            cameras_,
            prefs_,
            stagePosUpdater_,
            positions_,
            controller_,
            autofocus_);
    setupPanelA_ =
        new SetupPanel(
            gui_,
            devices_,
            props_,
            joystick_,
            Devices.Sides.A,
            positions_,
            cameras_,
            prefs_,
            stagePosUpdater_,
            autofocus_);
    if (!ASIdiSPIM.oSPIM) {
      setupPanelB_ =
          new SetupPanel(
              gui_,
              devices_,
              props_,
              joystick_,
              Devices.Sides.B,
              positions_,
              cameras_,
              prefs_,
              stagePosUpdater_,
              autofocus_);
    } else {
      setupPanelB_ = null;
    }
    navigationPanel_ =
        new NavigationPanel(
            gui_, devices_, props_, joystick_, positions_, prefs_, cameras_, stagePosUpdater_);

    dataAnalysisPanel_ = new DataAnalysisPanel(gui_, prefs_);
    autofocusPanel_ = new AutofocusPanel(gui_, devices_, props_, prefs_, autofocus_);
    settingsPanel_ = new SettingsPanel(gui_, devices_, props_, prefs_, stagePosUpdater_);
    stagePosUpdater_.oneTimeUpdate(); // needed for NavigationPanel
    helpPanel_ = new HelpPanel();
    statusSubPanel_ = new StatusSubPanel(devices_, props_, positions_, stagePosUpdater_);

    // now add tabs to GUI
    // all added tabs must be of type ListeningJPanel
    // only use addLTab, not addTab to guarantee this
    tabbedPane_ = new ListeningJTabbedPane();
    if (isMac()) {
      tabbedPane_.setTabPlacement(JTabbedPane.TOP);
    } else {
      tabbedPane_.setTabPlacement(JTabbedPane.LEFT);
    }
    tabbedPane_.addLTab(navigationPanel_); // tabIndex = 0
    tabbedPane_.addLTab(setupPanelA_); // tabIndex = 1
    if (!ASIdiSPIM.oSPIM) {
      tabbedPane_.addLTab(setupPanelB_); // tabIndex = 2
    }
    tabbedPane_.addLTab(acquisitionPanel_); // tabIndex = 3
    tabbedPane_.addLTab(dataAnalysisPanel_); // tabIndex = 4
    tabbedPane_.addLTab(devicesPanel_); // tabIndex = 5
    final int deviceTabIndex = tabbedPane_.getTabCount() - 1;
    tabbedPane_.addLTab(autofocusPanel_); // tabIndex = 6
    tabbedPane_.addLTab(settingsPanel_); // tabIndex = 7
    tabbedPane_.addLTab(helpPanel_); // tabIndex = 8
    final int helpTabIndex = tabbedPane_.getTabCount() - 1;

    // make taller tabs for easier navigation between them
    // we create own labels instead of having JTabbedPane do it from titles
    final Border paddingBorder = BorderFactory.createEmptyBorder(4, 0, 4, 0);
    for (int i = 0; i < tabbedPane_.getTabCount(); i++) {
      JLabel lab = new JLabel(((ListeningJPanel) tabbedPane_.getComponentAt(i)).getPanelName());
      lab.setBorder(paddingBorder);
      tabbedPane_.setTabComponentAt(i, lab);
    }

    // add the testing panel explicitly by uncommenting following lines
    // intended to only be done in short term for testing
    // TestingPanel testingPanel = new TestingPanel();
    // tabbedPane_.addLTab(testingPanel);

    // attach position updaters
    stagePosUpdater_.addPanel(setupPanelA_);
    if (!ASIdiSPIM.oSPIM) {
      stagePosUpdater_.addPanel(setupPanelB_);
    }
    stagePosUpdater_.addPanel(navigationPanel_);
    stagePosUpdater_.addPanel(statusSubPanel_);

    piezoSleepPreventer_ = new PiezoSleepPreventer(gui_, devices_, props_);

    // attach live mode listeners
    MMStudio.getInstance()
        .getSnapLiveManager()
        .addLiveModeListener((LiveModeListener) setupPanelA_);
    if (!ASIdiSPIM.oSPIM) {
      MMStudio.getInstance()
          .getSnapLiveManager()
          .addLiveModeListener((LiveModeListener) setupPanelB_);
    }
    MMStudio.getInstance()
        .getSnapLiveManager()
        .addLiveModeListener((LiveModeListener) navigationPanel_);
    MMStudio.getInstance()
        .getSnapLiveManager()
        .addLiveModeListener(
            new LiveModeListener() {
              // make sure to "wake up" any piezos with autosleep enabled before we start imaging
              @Override
              public void liveModeEnabled(boolean enabled) {
                if (enabled) {
                  piezoSleepPreventer_.start();
                } else {
                  piezoSleepPreventer_.stop();
                }
              }
            });

    // set scan for live mode to be triangle (now live mode setting not affected by SPIM setting)
    props_.setPropValue(
        new Devices.Keys[] {Devices.Keys.GALVOA, Devices.Keys.GALVOB},
        Properties.Keys.SA_PATTERN_X,
        Properties.Values.SAM_TRIANGLE,
        true);

    // make sure gotDeSelected() and gotSelected() get called whenever we switch tabs
    tabbedPane_.addChangeListener(
        new ChangeListener() {
          int lastSelectedIndex_ = tabbedPane_.getSelectedIndex();

          @Override
          public void stateChanged(ChangeEvent e) {
            ((ListeningJPanel) tabbedPane_.getComponentAt(lastSelectedIndex_)).gotDeSelected();
            ((ListeningJPanel) tabbedPane_.getSelectedComponent()).gotSelected();
            lastSelectedIndex_ = tabbedPane_.getSelectedIndex();
          }
        });

    // put frame back where it was last time
    this.loadAndRestorePosition(100, 100);

    // clear any previous joystick settings
    joystick_.unsetAllJoysticks();

    // gotSelected will be called because we put this after adding the ChangeListener
    tabbedPane_.setSelectedIndex(
        helpTabIndex); // setSelectedIndex(0) just after initialization doesn't fire ChangeListener,
                       // so switch to help panel first
    tabbedPane_.setSelectedIndex(
        prefs_.getInt(
            MAIN_PREF_NODE,
            Prefs.Keys.TAB_INDEX,
            deviceTabIndex)); // default to devicesPanel_ on first run

    // set up the window
    add(tabbedPane_); // add the pane to the GUI window
    setTitle(ASIdiSPIM.menuName + " Control");
    pack(); // shrinks the window as much as it can
    setResizable(false);

    // take care of shutdown tasks when window is closed
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    // add status panel as an overlay that is visible from all tabs
    Container glassPane = (Container) getGlassPane();
    glassPane.setVisible(true);
    glassPane.setLayout(
        new MigLayout("", "[" + this.getWidth() + "]", "[" + this.getHeight() + "]"));
    glassPane.add(statusSubPanel_, "dock south");

    // restore live mode and camera
    if (liveModeOriginally) {
      gui_.enableLiveMode(true);
    }
    try {
      gui_.getMMCore().setCameraDevice(cameraOriginal);
    } catch (Exception ex) {
      // do nothing
    }
  }
Пример #5
0
 /**
  * checks that the device has correct library, properties that we need, and correct values set as
  * needed
  *
  * @param key
  */
 private void checkDeviceLibrary(Devices.Keys key) {
   Devices.Libraries deviceLibrary = devices_.getMMDeviceLibrary(key);
   if (deviceLibrary == Devices.Libraries.NODEVICE) {
     return;
   }
   switch (key) {
     case CAMERAA:
     case CAMERAB:
       switch (deviceLibrary) {
         case HAMCAM:
           checkPropertyExists(key, Properties.Keys.TRIGGER_SOURCE);
           checkPropertyValueEquals(
               key, Properties.Keys.TRIGGER_POLARITY, Properties.Values.POSITIVE);
           break;
         case PCOCAM:
           // trigger polarity not accessible in Micro-Manager, so we have to trust it is correct
           checkPropertyExists(key, Properties.Keys.TRIGGER_MODE_PCO);
           break;
         case ANDORCAM:
           // TODO check trigger polarity
           checkPropertyExists(key, Properties.Keys.TRIGGER_MODE);
           break;
         case DEMOCAM:
           checkPropertyValueEquals(key, Properties.Keys.PIXEL_TYPE, Properties.Values.SIXTEENBIT);
           break;
         default:
           MyDialogUtils.showError(
               "Plugin doesn't support your camera for SPIM yet;"
                   + " contact the authors for support (camera must have hardware trigger)");
       } // CamA/B case
       break;
     case GALVOA:
     case GALVOB:
       if (deviceLibrary == Devices.Libraries.ASITIGER) {
         checkPropertyValueEquals(
             key, Properties.Keys.INPUT_MODE, Properties.Values.INTERNAL_INPUT);
         // PLogic use in the plugin assumes "laser + side" output mode
         if (devices_.isValidMMDevice(Devices.Keys.PLOGIC)) {
           checkPropertyValueEquals(
               key, Properties.Keys.LASER_OUTPUT_MODE, Properties.Values.LASER_SHUTTER_SIDE);
         }
       } else {
         MyDialogUtils.showError("Plugin doesn't support galvo devices other than ASITiger");
       }
       break;
     case PIEZOA:
     case PIEZOB:
       if (deviceLibrary == Devices.Libraries.ASITIGER) {
         checkPropertyValueEquals(
             key, Properties.Keys.PIEZO_MODE, Properties.Values.INTERNAL_CLOSEDLOOP_INPUT);
       } else {
         MyDialogUtils.showError("Plugin doesn't support piezo devices other than ASITiger");
       }
       break;
     case PLOGIC:
       if (deviceLibrary == Devices.Libraries.ASITIGER) {
         // would like to do below line but we need to change pre-init value and reload config
         // checkPropertyValueEquals(key, Properties.Keys.PLOGIC_MODE,
         // Properties.Values.DISPIM_SHUTTER);
         if (!props_
             .getPropValueString(key, Properties.Keys.PLOGIC_MODE)
             .equals(Properties.Values.DISPIM_SHUTTER.toString())) {
           MyDialogUtils.showError(
               "Device "
                   + devices_.getMMDevice(key)
                   + ": need to set pre-initialization property PLogicMode to "
                   + "diSPIM Shutter (use Hardware Config Wizard, then edit device "
                   + devices_.getMMDevice(key)
                   + " on Step 2). Then reload the "
                   + " changed configuration and restart the diSPIM plugin.");
         }
         checkPropertyValueEquals(
             key, Properties.Keys.PLOGIC_TRIGGER_SOURCE, Properties.Values.PLOGIC_TRIGGER_MMIRROR);
         // PLogic use in the plugin assumes "laser + side" output mode
         for (Devices.Keys galvoKey : Devices.GALVOS) {
           if (devices_.isValidMMDevice(galvoKey)) {
             checkPropertyValueEquals(
                 galvoKey,
                 Properties.Keys.LASER_OUTPUT_MODE,
                 Properties.Values.LASER_SHUTTER_SIDE);
           }
         }
       } else {
         MyDialogUtils.showError("Plugin doesn't support shutter devices other than ASITiger");
       }
       break;
     default:
       break;
   }
 }
Пример #6
0
  public SetupPanel(
      ScriptInterface gui,
      Devices devices,
      Properties props,
      Joystick joystick,
      final Devices.Sides side,
      Positions positions,
      Cameras cameras,
      Prefs prefs,
      StagePositionUpdater posUpdater,
      AutofocusUtils autofocus) {
    super(
        MyStrings.PanelNames.SETUP.toString() + side.toString(),
        new MigLayout("", "[center]8[center]", "[]16[]16[]"));

    devices_ = devices;
    props_ = props;
    joystick_ = joystick;
    positions_ = positions;
    cameras_ = cameras;
    autofocus_ = autofocus;
    prefs_ = prefs;
    posUpdater_ = posUpdater;
    gui_ = gui;
    core_ = gui_.getMMCore();
    PanelUtils pu = new PanelUtils(prefs_, props_, devices);
    final SetupPanel setupPanel = this;

    piezoImagingDeviceKey_ = Devices.getSideSpecificKey(Devices.Keys.PIEZOA, side);
    piezoIlluminationDeviceKey_ =
        Devices.getSideSpecificKey(Devices.Keys.PIEZOA, Devices.getOppositeSide(side));
    micromirrorDeviceKey_ = Devices.getSideSpecificKey(Devices.Keys.GALVOA, side);

    sheetStartPositionLabel_ =
        new StoredFloatLabel(
            panelName_,
            Properties.Keys.PLUGIN_SHEET_START_POS.toString(),
            -0.5f,
            prefs_,
            " \u00B0");
    sliceStartPos_ = sheetStartPositionLabel_.getFloat();
    sheetStopPositionLabel_ =
        new StoredFloatLabel(
            panelName_, Properties.Keys.PLUGIN_SHEET_END_POS.toString(), 0.5f, prefs_, " \u00B0");
    sliceStopPos_ = sheetStopPositionLabel_.getFloat();
    imagingPiezoStartPositionLabel_ =
        new StoredFloatLabel(
            panelName_,
            Properties.Keys.PLUGIN_PIEZO_START_POS.toString(),
            -50f,
            prefs_,
            " \u00B5" + "m");
    imagingPiezoStartPos_ = imagingPiezoStartPositionLabel_.getFloat();
    imagingPiezoStopPositionLabel_ =
        new StoredFloatLabel(
            panelName_,
            Properties.Keys.PLUGIN_PIEZO_END_POS.toString(),
            50f,
            prefs_,
            " \u00B5" + "m");
    imagingPiezoStopPos_ = imagingPiezoStopPositionLabel_.getFloat();

    JButton tmp_but;

    JPanel calibrationPanel =
        new JPanel(
            new MigLayout(
                "", "[right]2[center]2[right]4[left]8[center]8[center]8[center]", "[]8[]"));

    offsetField_ =
        pu.makeFloatEntryField(
            panelName_, Properties.Keys.PLUGIN_OFFSET_PIEZO_SHEET.toString(), 0, 5);
    rateField_ =
        pu.makeFloatEntryField(
            panelName_, Properties.Keys.PLUGIN_RATE_PIEZO_SHEET.toString(), 100, 5);
    piezoDeltaField_ =
        pu.makeFloatEntryField(
            panelName_, Properties.Keys.PLUGIN_PIEZO_SHEET_INCREMENT.toString(), 5, 3);
    piezoDeltaField_.setToolTipText("Piezo increment used by up/down arrow buttons");

    JButton upButton = new JButton();
    upButton.setIcon(SwingResourceManager.getIcon(MMStudio.class, "icons/arrow_up.png"));
    upButton.setText("");
    upButton.setToolTipText("Move slice and piezo up together");
    upButton.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            stepPiezoAndGalvo(1.);
          }
        });

    JButton downButton = new JButton();
    downButton.setIcon(SwingResourceManager.getIcon(MMStudio.class, "icons/arrow_down.png"));
    downButton.setText("");
    downButton.setToolTipText("Move slice and piezo down together");
    downButton.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            stepPiezoAndGalvo(-1.);
          }
        });

    calibrationPanel.add(new JLabel("Piezo/Slice Calibration"), "span 5, center");
    calibrationPanel.add(
        new JSeparator(SwingConstants.VERTICAL), "span 1 3, growy, shrinkx, center");
    calibrationPanel.add(new JLabel("Step"), "wrap");

    calibrationPanel.add(new JLabel("Slope: "));
    calibrationPanel.add(rateField_, "span 2, right");
    // TODO make calibration be in degrees instead of um
    // calibrationPanel.add(new JLabel("\u00B0/\u00B5m"));
    calibrationPanel.add(new JLabel("\u00B5m/\u00B0"));
    tmp_but = new JButton("Update");
    tmp_but.setMargin(new Insets(4, 8, 4, 8));
    tmp_but.setToolTipText(
        "Computes piezo vs. slice slope and offset from start and end positions");
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            updateCalibrationSlopeAndOffset();
          }
        });
    tmp_but.setBackground(Color.green);
    calibrationPanel.add(tmp_but);

    calibrationPanel.add(upButton, "wrap");

    calibrationPanel.add(new JLabel("Offset: "));
    calibrationPanel.add(offsetField_, "span 2, right");
    // calibrationPanel.add(new JLabel("\u00B0"));
    calibrationPanel.add(new JLabel("\u00B5m"));
    tmp_but = new JButton("Update");
    tmp_but.setMargin(new Insets(4, 8, 4, 8));
    tmp_but.setToolTipText("Adjusts piezo vs. slice offset from current position");
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            updateCalibrationOffset();
          }
        });
    tmp_but.setBackground(Color.green);
    calibrationPanel.add(tmp_but);

    calibrationPanel.add(downButton, "wrap");

    calibrationPanel.add(new JLabel("Step size: "), "span 2, left");
    calibrationPanel.add(piezoDeltaField_);
    calibrationPanel.add(new JLabel("\u00B5m"));

    tmp_but = new JButton("Focus");
    tmp_but.setMargin(new Insets(4, 8, 4, 8));
    tmp_but.setToolTipText("Autofocus at current piezo position");
    tmp_but.setBackground(Color.green);
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            autofocus_.runFocus(
                setupPanel,
                side,
                true,
                ASIdiSPIM.getFrame().getAcquisitionPanel().getSliceTiming(),
                true);
          }
        });
    calibrationPanel.add(tmp_but, "center, span 3, wrap");

    // start 2-point calibration frame
    // this frame is separate from main plugin window

    slopeCalibrationFrame_ = new MMFrame();
    slopeCalibrationFrame_.setTitle("Slope and Offset Calibration");
    slopeCalibrationFrame_.loadPosition(100, 100);

    JPanel slopeCalibrationPanel =
        new JPanel(new MigLayout("", "[center]8[center]8[center]8[center]8[center]", "[]8[]"));

    // TODO improve interface with multi-page UI and forward/back buttons
    // e.g. \mmstudio\src\org\micromanager\conf2\ConfiguratorDlg2.java

    slopeCalibrationPanel.add(new JLabel("Calibration Start Position"), "span 3, center");
    slopeCalibrationPanel.add(new JLabel("Calibration End Position"), "span 3, center, wrap");

    slopeCalibrationPanel.add(sheetStartPositionLabel_);

    // Go to start button
    tmp_but = new JButton("Go to");
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            try {
              positions_.setPosition(micromirrorDeviceKey_, Directions.Y, sliceStartPos_, true);
              positions_.setPosition(piezoImagingDeviceKey_, imagingPiezoStartPos_, true);
            } catch (Exception ex) {
              MyDialogUtils.showError(ex);
            }
          }
        });
    slopeCalibrationPanel.add(tmp_but, "");
    slopeCalibrationPanel.add(new JSeparator(SwingConstants.VERTICAL), "spany 2, growy");

    slopeCalibrationPanel.add(sheetStopPositionLabel_);

    // go to end button
    tmp_but = new JButton("Go to");
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            try {
              positions_.setPosition(micromirrorDeviceKey_, Directions.Y, sliceStopPos_, true);
              positions_.setPosition(piezoImagingDeviceKey_, imagingPiezoStopPos_, true);
            } catch (Exception ex) {
              MyDialogUtils.showError(ex);
            }
          }
        });
    slopeCalibrationPanel.add(tmp_but, "wrap");

    slopeCalibrationPanel.add(imagingPiezoStartPositionLabel_);

    tmp_but = new JButton("Set");
    tmp_but.setToolTipText(
        "Saves calibration start position for imaging piezo and scanner slice (should be focused)");
    tmp_but.setBackground(Color.red);
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            try {
              // bypass cached positions in positions_ in case they aren't current
              sliceStartPos_ = positions_.getUpdatedPosition(micromirrorDeviceKey_, Directions.Y);
              sheetStartPositionLabel_.setFloat((float) sliceStartPos_);
              imagingPiezoStartPos_ = positions_.getUpdatedPosition(piezoImagingDeviceKey_);
              imagingPiezoStartPositionLabel_.setFloat((float) imagingPiezoStartPos_);
            } catch (Exception ex) {
              MyDialogUtils.showError(ex);
            }
          }
        });
    slopeCalibrationPanel.add(tmp_but);

    slopeCalibrationPanel.add(imagingPiezoStopPositionLabel_);

    tmp_but = new JButton("Set");
    tmp_but.setToolTipText(
        "Saves calibration end position for imaging piezo and scanner slice (should be focused)");
    tmp_but.setBackground(Color.red);
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            try {
              // bypass cached positions in positions_ in case they aren't current
              sliceStopPos_ = positions_.getUpdatedPosition(micromirrorDeviceKey_, Directions.Y);
              sheetStopPositionLabel_.setFloat((float) sliceStopPos_);
              imagingPiezoStopPos_ = positions_.getUpdatedPosition(piezoImagingDeviceKey_);
              imagingPiezoStopPositionLabel_.setFloat((float) imagingPiezoStopPos_);
            } catch (Exception ex) {
              MyDialogUtils.showError(ex);
            }
          }
        });
    slopeCalibrationPanel.add(tmp_but, "wrap");

    slopeCalibrationPanel.add(
        new JSeparator(SwingConstants.HORIZONTAL), "span 5, growx, shrinky, wrap");

    tmp_but = new JButton("Use these!");
    tmp_but.setBackground(Color.green);
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            try {
              double rate =
                  (imagingPiezoStopPos_ - imagingPiezoStartPos_) / (sliceStopPos_ - sliceStartPos_);
              rateField_.setValue((Double) rate);
              double offset =
                  (imagingPiezoStopPos_ + imagingPiezoStartPos_) / 2
                      - (rate * ((sliceStopPos_ + sliceStartPos_) / 2));
              offsetField_.setValue((Double) offset);
            } catch (Exception ex) {
              MyDialogUtils.showError(ex);
            }
            slopeCalibrationFrame_.setVisible(false);
          }
        });
    slopeCalibrationPanel.add(tmp_but, "span 5, split 3");

    tmp_but = new JButton("Focus");
    tmp_but.setToolTipText("Autofocus at current piezo position");
    tmp_but.setBackground(Color.green);
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            autofocus_.runFocus(
                setupPanel,
                side,
                true,
                ASIdiSPIM.getFrame().getAcquisitionPanel().getSliceTiming(),
                true);
          }
        });
    slopeCalibrationPanel.add(tmp_but);

    tmp_but = new JButton("Cancel");
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            slopeCalibrationFrame_.setVisible(false);
          }
        });
    slopeCalibrationPanel.add(tmp_but, "wrap");

    slopeCalibrationFrame_.add(slopeCalibrationPanel);
    slopeCalibrationFrame_.pack();
    slopeCalibrationFrame_.setResizable(false);

    final int positionWidth = 50;
    final int labelWidth = 80;

    JPanel slicePanel =
        new JPanel(
            new MigLayout(
                "",
                "[" + labelWidth + "px!,right]8[" + positionWidth + "px!,center]8[center]8[center]",
                "[]8[]"));

    JLabel tmp_lbl = new JLabel("Imaging center: ", JLabel.RIGHT);
    tmp_lbl.setMaximumSize(new Dimension(labelWidth, 20));
    tmp_lbl.setMinimumSize(new Dimension(labelWidth, 20));
    slicePanel.add(tmp_lbl);
    imagingCenterPosLabel_ =
        new StoredFloatLabel(
            panelName_,
            Properties.Keys.PLUGIN_PIEZO_CENTER_POS.toString(),
            0,
            prefs_,
            " \u00B5" + "m");
    imagingCenterPosLabel_.setMaximumSize(new Dimension(positionWidth, 20));
    imagingCenterPosLabel_.setMinimumSize(new Dimension(positionWidth, 20));
    slicePanel.add(imagingCenterPosLabel_);

    // initialize the center position variable
    imagingCenterPos_ =
        prefs_.getFloat(
            MyStrings.PanelNames.SETUP.toString() + side.toString(),
            Properties.Keys.PLUGIN_PIEZO_CENTER_POS,
            0);

    tmp_but = new JButton("Go");
    tmp_but.setToolTipText("Moves piezo to specified center and also slice");
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            centerPiezoAndGalvo();
          }
        });
    slicePanel.add(tmp_but);

    tmp_but = new JButton("Set");
    tmp_but.setToolTipText("Sets piezo center position for acquisition");
    tmp_but.setBackground(Color.red);
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            try {
              imagingCenterPos_ = positions_.getUpdatedPosition(piezoImagingDeviceKey_);
              imagingCenterPosLabel_.setFloat((float) imagingCenterPos_);
            } catch (Exception ex) {
              MyDialogUtils.showError(ex);
            }
          }
        });
    slicePanel.add(tmp_but, "wrap");

    slicePanel.add(new JLabel("XY center: "));
    slicePanel.add(new JLabel("")); // TODO update this label with current value

    tmp_but = new JButton("Go");
    tmp_but.setToolTipText("Moves XY stage to specified center");
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            // TODO replace with positions_ call to 2D position set (need to implement still)
            try {
              core_.setXYPosition(xyCenterPos_.x, xyCenterPos_.y);
            } catch (Exception ex) {
              ReportingUtils.showError(ex);
            }
          }
        });
    slicePanel.add(tmp_but);

    tmp_but = new JButton("Set");
    tmp_but.setToolTipText("Sets XY center position for acquisition");
    tmp_but.setBackground(Color.red);
    tmp_but.addActionListener(
        new ActionListener() {

          @Override
          public void actionPerformed(ActionEvent e) {
            // TODO replace with positions_ call to 2D position set (need to implement still)
            try {
              xyCenterPos_ =
                  core_.getXYStagePosition(devices_.getMMDeviceException(Devices.Keys.XYSTAGE));
            } catch (Exception ex) {
              MyDialogUtils.showError(ex);
            }
          }
        });
    slicePanel.add(tmp_but, "wrap");

    slicePanel.add(new JSeparator(SwingConstants.HORIZONTAL), "span 5, growx, shrinky, wrap");

    slicePanel.add(new JLabel("Slice position:"));
    sheetPositionLabel_ = new JLabel("");
    slicePanel.add(sheetPositionLabel_);
    slicePanel.add(pu.makeSetPositionField(micromirrorDeviceKey_, Directions.Y, positions_));

    tmp_but = new JButton("Go to 0");
    tmp_but.setMargin(new Insets(4, 4, 4, 4));
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            positions_.setPosition(micromirrorDeviceKey_, Directions.Y, 0.0, true);
          }
        });
    slicePanel.add(tmp_but, "wrap");

    slicePanel.add(new JLabel("Imaging piezo:"));
    imagingPiezoPositionLabel_ = new JLabel("");
    slicePanel.add(imagingPiezoPositionLabel_);
    slicePanel.add(pu.makeSetPositionField(piezoImagingDeviceKey_, Directions.NONE, positions_));
    tmp_but = new JButton("Go to 0");
    tmp_but.setMargin(new Insets(4, 4, 4, 4));
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            positions_.setPosition(piezoImagingDeviceKey_, 0.0, true);
          }
        });
    slicePanel.add(tmp_but, "wrap");

    // Create sheet controls
    JPanel sheetPanel =
        new JPanel(
            new MigLayout(
                "",
                "[" + labelWidth + "px!,right]8[" + positionWidth + "px!,center]8[center]8[center]",
                "[]8[]8[]"));

    tmp_lbl = new JLabel("Illum. piezo:", JLabel.RIGHT);
    tmp_lbl.setMaximumSize(new Dimension(labelWidth, 20));
    tmp_lbl.setMinimumSize(new Dimension(labelWidth, 20));
    sheetPanel.add(tmp_lbl, "center");
    illuminationPiezoPositionLabel_ = new JLabel("");
    illuminationPiezoPositionLabel_.setMaximumSize(new Dimension(positionWidth, 20));
    illuminationPiezoPositionLabel_.setMinimumSize(new Dimension(positionWidth, 20));
    sheetPanel.add(illuminationPiezoPositionLabel_);
    sheetPanel.add(
        pu.makeSetPositionField(piezoIlluminationDeviceKey_, Directions.NONE, positions_));

    tmp_but = new JButton("Set home");
    tmp_but.setMargin(new Insets(4, 4, 4, 4));
    tmp_but.setToolTipText("During SPIM, illumination piezo is moved to home position");
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            if (devices_.isValidMMDevice(piezoIlluminationDeviceKey_)) {
              props_.setPropValue(
                  piezoIlluminationDeviceKey_,
                  Properties.Keys.SET_HOME_HERE,
                  Properties.Values.DO_IT);
            }
          }
        });
    sheetPanel.add(tmp_but);

    tmp_but = new JButton("Go home");
    tmp_but.setMargin(new Insets(4, 4, 4, 4));
    tmp_but.setToolTipText("During SPIM, illumination piezo is moved to home position");
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            if (devices_.isValidMMDevice(piezoIlluminationDeviceKey_)) {
              props_.setPropValue(
                  piezoIlluminationDeviceKey_,
                  Properties.Keys.MOVE_TO_HOME,
                  Properties.Values.DO_IT);
            }
          }
        });
    sheetPanel.add(tmp_but);

    illumPiezoHomeEnable_ =
        pu.makeCheckBox(
            "Go home on tab activate",
            Properties.Keys.PREFS_ENABLE_ILLUM_PIEZO_HOME,
            panelName_,
            false);
    sheetPanel.add(illumPiezoHomeEnable_, "span 3, wrap");

    sheetPanel.add(new JLabel("Sheet width:"));
    sheetPanel.add(
        new JLabel(""),
        "span 2"); // TODO update this label with current value and/or allow user to directly enter
                   // value
    sheetPanel.add(
        makeIncrementButton(
            micromirrorDeviceKey_, Properties.Keys.SA_AMPLITUDE_X_DEG, "-", (float) -0.01),
        "split 2");
    sheetPanel.add(
        makeIncrementButton(
            micromirrorDeviceKey_, Properties.Keys.SA_AMPLITUDE_X_DEG, "+", (float) 0.01));
    JSlider tmp_sl =
        pu.makeSlider(
            0, // 0 is min amplitude
            props_.getPropValueFloat(micromirrorDeviceKey_, Properties.Keys.MAX_DEFLECTION_X)
                - props_.getPropValueFloat(
                    micromirrorDeviceKey_,
                    Properties.Keys.MIN_DEFLECTION_X), // compute max amplitude
            1000, // the scale factor between internal integer representation and float
                  // representation
            micromirrorDeviceKey_,
            Properties.Keys.SA_AMPLITUDE_X_DEG);
    sheetPanel.add(tmp_sl, "span 5, growx, center, wrap");

    sheetPanel.add(new JLabel("Sheet offset:"));
    sheetPanel.add(
        new JLabel(""),
        "span 2"); // TODO update this label with current value and/or allow user to directly enter
                   // value
    sheetPanel.add(
        makeIncrementButton(
            micromirrorDeviceKey_, Properties.Keys.SA_OFFSET_X_DEG, "-", (float) -0.01),
        "split 2");
    sheetPanel.add(
        makeIncrementButton(
            micromirrorDeviceKey_, Properties.Keys.SA_OFFSET_X_DEG, "+", (float) 0.01));
    tmp_but = new JButton("Center");
    tmp_but.setMargin(new Insets(4, 8, 4, 8));
    tmp_but.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            props_.setPropValue(micromirrorDeviceKey_, Properties.Keys.SA_OFFSET_X_DEG, 0f, true);
            props_.callListeners(); // update plot
          }
        });
    sheetPanel.add(tmp_but);
    tmp_sl =
        pu.makeSlider(
            props.getPropValueFloat(micromirrorDeviceKey_, Properties.Keys.MIN_DEFLECTION_X)
                / 4, // min value
            props.getPropValueFloat(micromirrorDeviceKey_, Properties.Keys.MAX_DEFLECTION_X)
                / 4, // max value
            1000, // the scale factor between internal integer representation and float
                  // representation
            micromirrorDeviceKey_,
            Properties.Keys.SA_OFFSET_X_DEG);
    sheetPanel.add(tmp_sl, "span 4, growx, center, wrap");

    // Create larger panel with slice, sheet, and calibration panels
    JPanel superPanel = new JPanel(new MigLayout("", "[]8[]", "[]8[]"));
    superPanel.setBorder(BorderFactory.createLineBorder(ASIdiSPIM.borderColor));

    superPanel.add(slicePanel);
    superPanel.add(new JSeparator(SwingConstants.VERTICAL), "growy, shrinkx, center");
    superPanel.add(calibrationPanel, "wrap");
    superPanel.add(new JSeparator(SwingConstants.HORIZONTAL), "span 3, growx, shrinky, wrap");
    superPanel.add(sheetPanel, "span 3");

    // Layout of the SetupPanel
    joystickPanel_ = new JoystickSubPanel(joystick_, devices_, panelName_, side, prefs_);
    add(joystickPanel_, "center");

    add(superPanel, "center, aligny top, span 1 3, wrap");

    beamPanel_ = new BeamSubPanel(gui_, devices_, panelName_, side, prefs_, props_);
    add(beamPanel_, "center, wrap");

    cameraPanel_ = new CameraSubPanel(gui_, cameras_, devices_, panelName_, side, prefs_, true);
    add(cameraPanel_, "center");
  } // end of SetupPanel constructor