public DisplayPlus(
      final ImageCache stitchedCache,
      AcquisitionEngine eng,
      JSONObject summaryMD,
      boolean invX,
      boolean invY,
      boolean swapXY) {
    eng_ = eng;
    invertX_ = invX;
    invertY_ = invY;
    swapXY_ = swapXY;
    try {
      MultiStagePosition pos0 = MMStudioMainFrame.getInstance().getPositionList().getPosition(0);
      pos0x_ = pos0.getX();
      pos0y_ = pos0.getY();
      tileWidth_ = MDUtils.getHeight(summaryMD);
      tileHeight_ = MDUtils.getWidth(summaryMD);
    } catch (Exception e) {
      ReportingUtils.showError("Couldnt get grid info");
    }
    vad_ =
        new VirtualAcquisitionDisplay(stitchedCache, eng, WINDOW_TITLE) {
          public void showImage(final JSONObject tags, boolean waitForDisplay)
              throws InterruptedException, InvocationTargetException {
            // Since this is multichannel camera, only show when last channel arrives
            try {
              if (MDUtils.getChannelIndex(tags) == super.getNumChannels() - 1) {
                super.showImage(tags, waitForDisplay);
              } else {
                ImagePlus ip = super.getHyperImage();
                if (ip != null) {
                  // canvas never gets painted so need to set painpending false
                  ip.getCanvas().setPaintPending(false);
                }
              }
            } catch (JSONException ex) {
            }
          }
        };
    DisplayControls controls = new Controls();

    // Add in custom controls
    try {
      JavaUtils.setRestrictedFieldValue(
          vad_, VirtualAcquisitionDisplay.class, "controls_", controls);
    } catch (NoSuchFieldException ex) {
      ReportingUtils.showError("Couldn't create display controls");
    }
    vad_.show();
    // Zoom to 100%
    vad_.getImagePlus().getWindow().getCanvas().unzoom();

    // add mouse listeners for moving grids
    addMouseListeners();

    stitchedCache.addImageCacheListener(this);
  }
  @Override
  public void imageReceived(TaggedImage taggedImage) {
    try {
      // duplicate so image storage doesnt see incorrect tags
      JSONObject newTags = new JSONObject(taggedImage.tags.toString());
      MDUtils.setPositionIndex(newTags, 0);
      taggedImage = new TaggedImage(taggedImage.pix, newTags);
    } catch (JSONException ex) {
      ReportingUtils.showError("Couldn't manipulate image tags for display");
    }

    vad_.imageReceived(taggedImage);
  }