/** Opens the file. */
  private void openFile() {
    if (!(data instanceof FileAnnotationData)) return;

    FileAnnotationData fa = (FileAnnotationData) data;
    Registry reg = MetadataViewerAgent.getRegistry();
    UserNotifier un = reg.getUserNotifier();
    OriginalFile f = (OriginalFile) fa.getContent();
    Environment env = (Environment) reg.lookup(LookupNames.ENV);
    DownloadAndLaunchActivityParam activity;
    final long dataId = fa.getId();
    final File dir =
        new File(env.getOmeroFilesHome() + File.separatorChar + "file annotation " + dataId);
    if (!dir.exists()) {
      dir.mkdir();
    }
    if (f != null && f.isLoaded()) {
      activity = new DownloadAndLaunchActivityParam(f, dir, null);
    } else {
      activity =
          new DownloadAndLaunchActivityParam(
              dataId, DownloadAndLaunchActivityParam.FILE_ANNOTATION, dir, null);
    }
    un.notifyActivity(model.getSecurityContext(), activity);
    return;
  }
 /**
  * Shuts downs the caching service.
  *
  * @param container Reference to the container.
  */
 public static void shutdown(Container container) {
   // NB: this can't be called outside of container b/c agents have no refs
   // to the singleton container. So we can be sure this method is going to
   // create services just once.
   if (container == null) return;
   Registry reg = container.getRegistry();
   ((CacheServiceImpl) reg.getCacheService()).shutDown();
 }
 /**
  * Returns the compression quality related to the passed level.
  *
  * @param compressionLevel The level to handle.
  * @return See above.
  */
 static final float getCompressionQuality(int compressionLevel) {
   Float value;
   switch (compressionLevel) {
     default:
     case RenderingControl.UNCOMPRESSED:
     case RenderingControl.MEDIUM:
       value = (Float) registry.lookup(LookupNames.COMPRESSIOM_MEDIUM_QUALITY);
       return value.floatValue();
     case RenderingControl.LOW:
       value = (Float) registry.lookup(LookupNames.COMPRESSIOM_LOW_QUALITY);
       return value.floatValue();
   }
 }
 /**
  * Returns <code>true</code> if the proxy is used elsewhere.
  *
  * @param context Reference to the registry. To ensure that agents cannot call the method. It must
  *     be a reference to the container's registry.
  * @param pixelsID The id of the pixels set.
  * @return See above.
  */
 public static boolean isRenderingControlShared(Registry context, Long pixelsID) {
   if (!(context.equals(registry)))
     throw new IllegalArgumentException("Not allow to access method.");
   if (!singleton.rndSvcProxiesCount.containsKey(pixelsID)) return false;
   Integer count = singleton.rndSvcProxiesCount.get(pixelsID);
   return (count > 1);
 }
 /**
  * Resets the rendering engine.
  *
  * @param context Reference to the registry. To ensure that agents cannot call the method. It must
  *     be a reference to the container's registry.
  * @param pixelsID The ID of the pixels set.
  * @param reList The {@link RenderingEngine}s.
  * @param def The rendering def linked to the rendering engine. This is passed to speed up the
  *     initialization sequence.
  * @return See above.
  * @throws RenderingServiceException If an error occurred while setting the value.
  * @throws DSOutOfServiceException If the connection is broken.
  */
 public static RenderingControlProxy resetRenderingControl(
     Registry context, long pixelsID, List<RenderingEnginePrx> reList, RenderingDef def)
     throws RenderingServiceException, DSOutOfServiceException {
   if (!(registry.equals(context)))
     throw new IllegalArgumentException("Not allow to access method.");
   if (reList == null || reList.size() == 0)
     throw new IllegalArgumentException("No RE specified.");
   RenderingControlProxy proxy = (RenderingControlProxy) singleton.rndSvcProxies.get(pixelsID);
   if (proxy != null) {
     RndProxyDef converted = convert(def);
     proxy.resetRenderingEngine(reList.get(0), converted);
     reList.remove(0);
     List<RenderingControl> slaves = proxy.getSlaves();
     if (slaves.size() == reList.size()) {
       Iterator<RenderingControl> i = slaves.iterator();
       int index = 0;
       while (i.hasNext()) {
         proxy = (RenderingControlProxy) i.next();
         proxy.resetRenderingEngine(reList.get(index), converted);
       }
       index++;
     }
   }
   return proxy;
 }
 /**
  * Renders the specified {@link PlaneDef 2D-plane}.
  *
  * @param context Reference to the registry. To ensure that agents cannot call the method. It must
  *     be a reference to the container's registry.
  * @param pixelsID The id of the pixels set.
  * @param pDef The plane to render.
  * @param largeImage Indicates to set the resolution to <code>0</code>.
  * @param compression The compression level.
  * @return The image representing the plane.
  * @return See above.
  * @throws RenderingServiceException If an error occurred while setting the value.
  * @throws DSOutOfServiceException If the connection is broken.
  */
 public static Object render(
     Registry context,
     SecurityContext ctx,
     Long pixelsID,
     PlaneDef pDef,
     boolean largeImage,
     int compression)
     throws RenderingServiceException, DSOutOfServiceException {
   if (!(context.equals(registry)))
     throw new IllegalArgumentException("Not allow to access method.");
   RenderingControlProxy proxy = (RenderingControlProxy) singleton.rndSvcProxies.get(pixelsID);
   if (proxy == null)
     throw new RuntimeException(
         "No rendering service " + "initialized for the specified pixels set.");
   int level = proxy.getSelectedResolutionLevel();
   if (compression < RenderingControl.UNCOMPRESSED) compression = RenderingControl.UNCOMPRESSED;
   if (compression > RenderingControl.LOW) compression = RenderingControl.LOW;
   proxy.setCompression(compression);
   if (largeImage) {
     proxy.setSelectedResolutionLevel(0);
   }
   Object o = proxy.render(pDef);
   if (largeImage) proxy.setSelectedResolutionLevel(level);
   return o;
 }
 /**
  * Creates a new data sink for the specified set of pixels.
  *
  * @param pixels The pixels set the data sink is for.
  * @return See above.
  */
 public static DataSink createDataSink(PixelsData pixels) {
   if (pixels == null) throw new IllegalArgumentException("Pixels cannot be null.");
   if (singleton.pixelsSource != null && singleton.pixelsSource.isSame(pixels.getId()))
     return singleton.pixelsSource;
   registry.getCacheService().clearAllCaches();
   int size = getCacheSize();
   if (size <= 0) size = 0;
   singleton.pixelsSource = DataSink.makeNew(pixels, registry, size);
   return singleton.pixelsSource;
 }
 /**
  * Shuts downs the data sink attached to the specified pixels set.
  *
  * @param context Reference to the registry. To ensure that agents cannot call the method. It must
  *     be a reference to the container's registry.
  * @param pixelsID The ID of the pixels set.
  */
 public static void shutDownDataSink(Registry context, long pixelsID) {
   if (!(context.equals(registry)))
     throw new IllegalArgumentException("Not allow to access method.");
   if (singleton.pixelsSource != null && singleton.pixelsSource.isSame(pixelsID)) {
     int size = getCacheSize();
     boolean cacheInMemory = true;
     if (size <= 0) cacheInMemory = false;
     singleton.pixelsSource.clearCache();
     singleton.pixelsSource.setCacheInMemory(cacheInMemory);
   }
 }
 /**
  * Returns the {@link RenderingControl} linked to the passed set of pixels, returns <code>null
  * </code> if no proxy associated.
  *
  * @param context Reference to the registry. To ensure that agents cannot call the method. It must
  *     be a reference to the container's registry.
  * @param pixelsID The id of the pixels set.
  * @param init Pass <code>true</code> if the rendering control is going to be initialized, <code>
  *     false</code> otherwise.
  * @return See above.
  */
 public static RenderingControl getRenderingControl(
     Registry context, Long pixelsID, boolean init) {
   if (!(context.equals(registry)))
     throw new IllegalArgumentException("Not allow to access method.");
   if (init && singleton.rndSvcProxiesCount.containsKey(pixelsID)) {
     Integer count = singleton.rndSvcProxiesCount.get(pixelsID);
     count++;
     singleton.rndSvcProxiesCount.put(pixelsID, count);
   }
   return singleton.rndSvcProxies.get(pixelsID);
 }
 /**
  * Creates a new {@link RenderingControl}. We pass a reference to the the registry to ensure that
  * agents don't call the method.
  *
  * @param context Reference to the registry. To ensure that agents cannot call the method. It must
  *     be a reference to the container's registry.
  * @param reList The {@link RenderingEngine}s.
  * @param pixels The pixels set.
  * @param metadata The channel metadata.
  * @param compression Pass <code>0</code> if no compression otherwise pass the compression used.
  * @param defs The rendering defs linked to the rendering engine. This is passed to speed up the
  *     initialization sequence.
  * @return See above.
  * @throws IllegalArgumentException If an Agent try to access the method.
  */
 public static RenderingControl createRenderingControl(
     Registry context,
     SecurityContext ctx,
     List<RenderingEnginePrx> reList,
     Pixels pixels,
     List<ChannelData> metadata,
     int compression,
     List<RndProxyDef> defs) {
   if (!(context.equals(registry)))
     throw new IllegalArgumentException("Not allow to access method.");
   return singleton.makeNew(ctx, reList, pixels, metadata, compression, defs);
 }
 /**
  * Renders the specified {@link PlaneDef 2D-plane}.
  *
  * @param context Reference to the registry. To ensure that agents cannot call the method. It must
  *     be a reference to the container's registry.
  * @param pixelsID The id of the pixels set.
  * @param pDef The plane to render.
  * @param tableID The id of the table hosting the mask.
  * @param overlays The overlays to render or <code>null</code>.
  * @return See above.
  * @throws RenderingServiceException If an error occurred while setting the value.
  * @throws DSOutOfServiceException If the connection is broken.
  */
 public static Object renderOverlays(
     Registry context, long pixelsID, PlaneDef pd, long tableID, Map<Long, Integer> overlays)
     throws RenderingServiceException, DSOutOfServiceException {
   if (!(context.equals(registry)))
     throw new IllegalArgumentException("Not allow to access method.");
   RenderingControlProxy proxy = (RenderingControlProxy) singleton.rndSvcProxies.get(pixelsID);
   if (proxy == null)
     throw new RuntimeException(
         "No rendering service " + "initialized for the specified pixels set.");
   proxy.setOverlays(tableID, overlays);
   return proxy.render(pd);
 }
  /**
   * Creates a new {@link CacheService}.
   *
   * @param container Reference to the container.
   * @return See above.
   */
  public static CacheService makeNew(Container container) {
    // NB: this can't be called outside of container b/c agents have no refs
    // to the singleton container. So we can be sure this method is going to
    // create services just once.
    if (container == null) return null;
    // If caching is off, then we return the no-op adapter.
    Registry reg = container.getRegistry();
    Boolean isCachingOn = (Boolean) reg.lookup(LookupNames.CACHE_ON);
    if (!isCachingOn.booleanValue()) return makeNoOpCache();

    // Ok we have to cache, so try and read the config file.
    InputStream config = loadConfig(container.getConfigFileRelative(CACHE_CONFIG_FILE));
    if (config == null) return makeNoOpCache();

    // We have a config file, set up ehcache.
    CacheService cache = new CacheServiceImpl(config, container.getRegistry().getLogger());
    try {
      config.close();
    } catch (Exception e) {
    }
    return cache;
  }
  /**
   * Checks if the rendering controls are still active. Shuts the inactive ones.
   *
   * @param context Reference to the registry. To ensure that agents cannot call the method. It must
   *     be a reference to the container's registry.
   */
  public static void checkRenderingControls(Registry context) {
    // TODO Auto-generated method stub
    if (!(context.equals(registry)))
      throw new IllegalArgumentException("Not allow to access method.");
    RenderingControlProxy proxy;
    Entry<Long, RenderingControl> e;
    Iterator<Entry<Long, RenderingControl>> i = singleton.rndSvcProxies.entrySet().iterator();
    Long value = (Long) context.lookup(LookupNames.RE_TIMEOUT);

    long timeout = 60000; // 1min
    if (value != null && value.longValue() > timeout) timeout = value.longValue();

    Logger logger = context.getLogger();
    while (i.hasNext()) {
      e = i.next();
      proxy = (RenderingControlProxy) e.getValue();
      if (!proxy.isProxyActive(timeout)) {
        if (!proxy.shutDown(true))
          logger.info(singleton, "Rendering Engine shut down: PixelsID " + e.getKey());
      }
    }
  }
 /**
  * Creates a new instance. This can't be called outside of container b/c agents have no refs to
  * the singleton container. So we can be sure this method is going to create services just once.
  *
  * @param c Reference to the container.
  * @return The sole instance.
  * @throws NullPointerException If the reference to the {@link Container} is <code>null</code>.
  */
 public static PixelsServicesFactory getInstance(Container c) {
   if (c == null) throw new NullPointerException(); // An agent called this method?
   if (singleton == null) {
     registry = c.getRegistry();
     singleton = new PixelsServicesFactory();
     // Retrieve the maximum heap size.
     MemoryUsage usage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
     String message = "Heap memory usage: max " + usage.getMax();
     registry.getLogger().info(singleton, message);
     // percentage of memory used for caching.
     maxSize = (int) (RATIO * usage.getMax()) / FACTOR;
   }
   return singleton;
 }
  /**
   * Renders the projected images.
   *
   * @param context Reference to the registry. To ensure that agents cannot call the method. It must
   *     be a reference to the container's registry.
   * @param pixelsID The id of the pixels set.
   * @param startZ The first optical section.
   * @param endZ The last optical section.
   * @param stepping Stepping value to use while calculating the projection.
   * @param type One of the projection type defined by this class.
   * @param channels The collection of channels to project.
   * @return See above.
   * @throws RenderingServiceException If an error occurred while setting the value.
   * @throws DSOutOfServiceException If the connection is broken.
   */
  public static BufferedImage renderProjected(
      Registry context,
      Long pixelsID,
      int startZ,
      int endZ,
      int type,
      int stepping,
      List<Integer> channels)
      throws RenderingServiceException, DSOutOfServiceException {
    if (!(context.equals(registry)))
      throw new IllegalArgumentException("Not allow to access method.");
    RenderingControlProxy proxy = (RenderingControlProxy) singleton.rndSvcProxies.get(pixelsID);
    if (proxy == null)
      throw new RuntimeException(
          "No rendering service " + "initialized for the specified pixels set.");

    return proxy.renderProjected(startZ, endZ, stepping, type, channels);
  }
 /**
  * Shuts downs the rendering service attached to the specified pixels set. Returns <code>true
  * </code> if the rendering control is shared, <code>false</code> otherwise.
  *
  * @param context Reference to the registry. To ensure that agents cannot call the method. It must
  *     be a reference to the container's registry.
  * @param pixelsID The ID of the pixels set.
  * @return See above.
  */
 public static boolean shutDownRenderingControl(Registry context, long pixelsID) {
   if (!(context.equals(registry)))
     throw new IllegalArgumentException("Not allow to access method.");
   RenderingControlProxy proxy = (RenderingControlProxy) singleton.rndSvcProxies.get(pixelsID);
   Integer count = singleton.rndSvcProxiesCount.get(pixelsID);
   if (proxy != null) {
     if (count == 1) {
       proxy.shutDown();
       singleton.rndSvcProxies.remove(pixelsID);
       singleton.rndSvcProxiesCount.remove(pixelsID);
       getCacheSize();
     } else {
       count--;
       singleton.rndSvcProxiesCount.put(pixelsID, count);
     }
     return (singleton.rndSvcProxiesCount.containsKey(pixelsID));
   }
   return false;
 }
Beispiel #17
0
  /**
   * Builds the UI component hosting the UI component used to modify the password.
   *
   * @return See above.
   */
  private JPanel buildPasswordPanel() {
    JPanel content = new JPanel();
    content.setBackground(UIUtilities.BACKGROUND_COLOR);
    Registry reg = MetadataViewerAgent.getRegistry();
    String ldap = (String) reg.lookup(LookupNames.USER_AUTHENTICATION);
    if (ldap != null && ldap.length() > 0) {
      content.setBorder(BorderFactory.createTitledBorder("LDAP Authentication"));
      content.setLayout(new FlowLayout(FlowLayout.LEFT));
      content.add(new JLabel(ldap));
      return content;
    }
    content.setBorder(BorderFactory.createTitledBorder("Change Password"));

    content.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.fill = GridBagConstraints.HORIZONTAL;
    c.anchor = GridBagConstraints.WEST;
    c.insets = new Insets(0, 2, 2, 0);
    c.gridx = 0;
    c.gridy = 0;
    c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
    c.fill = GridBagConstraints.NONE; // reset to default
    c.weightx = 0.0;
    if (MetadataViewerAgent.isAdministrator()) {
      content.add(UIUtilities.setTextFont(PASSWORD_NEW), c);
      c.gridx++;
      c.gridwidth = GridBagConstraints.REMAINDER; // end row
      c.fill = GridBagConstraints.HORIZONTAL;
      c.weightx = 1.0;
      content.add(passwordNew, c);
    } else {
      content.add(UIUtilities.setTextFont(PASSWORD_OLD), c);
      c.gridx++;
      c.gridwidth = GridBagConstraints.REMAINDER; // end row
      c.fill = GridBagConstraints.HORIZONTAL;
      c.weightx = 1.0;
      content.add(oldPassword, c);
      c.gridy++;
      c.gridx = 0;
      c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
      c.fill = GridBagConstraints.NONE; // reset to default
      c.weightx = 0.0;
      content.add(UIUtilities.setTextFont(PASSWORD_NEW), c);
      c.gridx++;
      c.gridwidth = GridBagConstraints.REMAINDER; // end row
      c.fill = GridBagConstraints.HORIZONTAL;
      c.weightx = 1.0;
      content.add(passwordNew, c);
      c.gridy++;
      c.gridx = 0;
      c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
      c.fill = GridBagConstraints.NONE; // reset to default
      c.weightx = 0.0;
      content.add(UIUtilities.setTextFont(PASSWORD_CONFIRMATION), c);
      c.gridx++;
      c.gridwidth = GridBagConstraints.REMAINDER; // end row
      c.fill = GridBagConstraints.HORIZONTAL;
      c.weightx = 1.0;
      content.add(passwordConfirm, c);
      c.gridy++;
      c.gridx = 0;
    }

    JPanel p = new JPanel();
    p.setBackground(UIUtilities.BACKGROUND_COLOR);
    p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
    p.add(content);
    JPanel buttonPanel = UIUtilities.buildComponentPanel(passwordButton);
    buttonPanel.setBackground(UIUtilities.BACKGROUND_COLOR);
    p.add(buttonPanel);
    return p;
  }
Beispiel #18
0
 /**
  * Logs off from the current server.
  *
  * @see java.awt.event.ActionListener#actionPerformed(ActionEvent)
  */
 public void actionPerformed(ActionEvent e) {
   Registry reg = TreeViewerAgent.getRegistry();
   reg.getEventBus().post(new LogOff());
 }
 /**
  * Implemented as specified by the {@link Importer} interface.
  *
  * @see Importer#logOff()
  */
 public void logOff() {
   if (model.getState() == IMPORTING) return;
   Registry reg = ImporterAgent.getRegistry();
   reg.getEventBus().post(new LogOff());
 }
 /**
  * Returns an implementation of {@link ExecMonitor} that works as an adapter to notify the
  * specified <code>observer</code> of execution events. Specifically, the returned adapter will
  * notify the <code>observer</code> of the tree's execution progress and of the eventual outcome
  * of the computation.
  *
  * @param observer The adaptee.
  * @return The adapter.
  * @see BatchCallMonitor
  */
 protected ExecMonitor getMonitor(AgentEventListener observer) {
   MonitorFactory mf = (MonitorFactory) context.lookup(LookupNames.MONITOR_FACTORY);
   return mf.makeNew(this, observer);
 }
 /**
  * Returns a concrete {@link CmdProcessor} to {@link #exec(AgentEventListener) execute} the call
  * tree.
  *
  * @return See above.
  */
 protected CmdProcessor getProcessor() {
   return (CmdProcessor) context.lookup(LookupNames.CMD_PROCESSOR);
 }
  /**
   * Sets the file to edit. If the file cannot be read by {@link TreeModelFactory#getTree()} then
   * the state of this model is re-set to {@link Editor#NEW}.
   *
   * @param file The file to edit.
   * @return See above.
   */
  boolean setFileToEdit(File file) {
    if (file == null) {
      fileToEdit = null;
      state = Editor.NEW;
      fileName = EditorFactory.BLANK_MODEL;
      return false;
    }
    TreeModel treeModel = null;

    // try opening file as recognised OMERO.editor file (pro.xml or cpe.xml)
    try {
      treeModel = TreeModelFactory.getTree(file);
      fileToEdit = file;
    } catch (ParsingException e) {

      // may get a parsing exception simply because the file was not
      // recognised as Editor File..

      Registry reg = EditorAgent.getRegistry();
      UserNotifier un = reg.getUserNotifier();

      // ... try opening as ANY xml file
      try {
        treeModel = TreeModelFactory.getTreeXml(file);
        // if this worked, we have an XML file converted to cpe.xml
        // .. tell user..
        un.notifyInfo(
            "File not recognised",
            "File was converted from an unrecognised format into\n"
                + "OMERO.editor's cpe.xml format.\nOverwriting the "
                + "original file will erase the original XML format.");
        // must avoid overwriting the original file...
        // 'Save' won't work.
        if (fileID > 0) { // try to read a file downloaded
          file.delete();
        }
        fileToEdit = null;
        setFileAnnotationData(null);

      } catch (ParsingException ex) {

        LogMessage message = new LogMessage();
        message.print(ex);
        reg.getLogger().error(this, message);

        // ...and notify the user. Use the exception message.
        String errMsg = ex.getMessage();
        un.notifyInfo("File Failed to Open", errMsg);
      }
    }

    if (treeModel == null) {
      fileToEdit = null;
      state = Editor.NEW;
      fileName = EditorFactory.BLANK_MODEL;
      return false;
    }

    fileName = file.getName();
    browser.setTreeModel(treeModel);
    state = Editor.READY;
    return true;
  }
  /** Save the results to an Excel File. */
  private void saveResults() {
    channelsSelectionForm = new ChannelSelectionForm(channelName);
    FileChooser chooser = view.createSaveToExcelChooser();
    chooser.addComponentToControls(channelsSelectionForm);
    int results = chooser.showDialog();
    if (results != JFileChooser.APPROVE_OPTION) return;
    File file = chooser.getFormattedSelectedFile();
    // TODO: Modify that code when we have various writer.

    if (!file.getAbsolutePath().endsWith(ExcelFilter.EXCEL)) {
      String fileName = file.getAbsolutePath() + "." + ExcelFilter.EXCEL;
      file = new File(fileName);
    }

    List<Integer> channels = channelsSelectionForm.getUserSelection();
    if (channels == null || channels.size() == 0) {
      UserNotifier un = MeasurementAgent.getRegistry().getUserNotifier();
      un.notifyInfo("Save Results", " Please select at least a channel.");
      view.setStatus("No Channel selected to output.");

      return;
    }

    try {
      ExcelWriter writer = new ExcelWriter(file.getAbsolutePath());
      writer.openFile();
      writer.createSheet("Channel Summary");
      Iterator<Coord3D> coordMapIterator = shapeMap.keySet().iterator();
      Coord3D currentCoord;
      int n = channels.size();
      Integer channel;
      if (channelSummarySelected(channels)) outputSummary(writer, shapeMap);
      BufferedImage originalImage = model.getRenderedImage();
      if (originalImage != null) {
        BufferedImage image = Factory.copyBufferedImage(originalImage);

        // Add the ROI for the current plane to the image.
        // TODO: Need to check that.
        model.setAttributes(MeasurementAttributes.SHOWID, true);
        model.getDrawingView().print(image.getGraphics());
        model.setAttributes(MeasurementAttributes.SHOWID, false);
        try {
          writer.addImageToWorkbook("ThumbnailImage", image);
        } catch (Exception e) {
          // TODO
        }
        int col = writer.getMaxColumn(0);
        writer.writeImage(0, col + 1, 256, 256, "ThumbnailImage");
      }
      if (channelSummarySelected(channels) && channels.size() != 1)
        while (coordMapIterator.hasNext()) {
          currentCoord = coordMapIterator.next();
          for (int i = 0; i < n; i++) {
            channel = channels.get(i);
            if (channel == ChannelSelectionForm.SUMMARYVALUE) continue;
            if (!nameMap.containsKey(channelName.get(channel))) continue;
            int rowIndex = 0;

            writer.createSheet("Channel Number " + channelName.get(channel));
            writeHeader(writer, rowIndex, currentCoord);
            channel = nameMap.get(channelName.get(channel));
            writeData(writer, rowIndex, currentCoord, channel.intValue());
          }
        }
      writer.close();
    } catch (Exception e) {
      Logger logger = MeasurementAgent.getRegistry().getLogger();
      logger.error(this, "Cannot save ROI results: " + e.toString());

      UserNotifier un = MeasurementAgent.getRegistry().getUserNotifier();
      String message = "An error occurred while trying to" + " save the data.\nPlease try again.";
      if (e instanceof NumberFormatException) {
        message =
            "We only support the British/American style of "
                + "representing numbers,\nusing a decimal point rather "
                + "than a comma.";
      }
      un.notifyInfo("Save Results", message);
      return;
    }

    Registry reg = MeasurementAgent.getRegistry();
    UserNotifier un = reg.getUserNotifier();
    un.notifyInfo("Save ROI results", "The ROI results have been " + "successfully saved.");
  }