/*
* $Id$
* Copyright 2006-2015 University of Dundee. All rights reserved.
* Use is subject to license terms supplied in LICENSE.txt
*/
package ome.logic;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.perf4j.StopWatch;
import org.perf4j.slf4j.Slf4JStopWatch;
import org.springframework.transaction.annotation.Transactional;
import ome.annotations.NotNull;
import ome.annotations.RolesAllowed;
import ome.api.IPixels;
import ome.api.IRenderingSettings;
import ome.api.ServiceInterface;
import ome.conditions.ConcurrencyException;
import ome.conditions.ResourceError;
import ome.conditions.ValidationException;
import ome.io.nio.PixelBuffer;
import ome.io.nio.PixelsService;
import ome.model.IObject;
import ome.model.acquisition.Filter;
import ome.model.acquisition.Laser;
import ome.model.acquisition.LightSource;
import ome.model.acquisition.TransmittanceRange;
import ome.model.containers.Dataset;
import ome.model.containers.Project;
import ome.model.core.Channel;
import ome.model.core.Image;
import ome.model.core.LogicalChannel;
import ome.model.core.Pixels;
import ome.model.display.ChannelBinding;
import ome.model.display.QuantumDef;
import ome.model.display.RenderingDef;
import ome.model.enums.Family;
import ome.model.enums.RenderingModel;
import ome.model.screen.PlateAcquisition;
import ome.model.screen.Screen;
import ome.model.screen.Plate;
import ome.model.stats.StatsInfo;
import ome.model.units.Length;
import ome.parameters.Parameters;
import omeis.providers.re.ColorsFactory;
import omeis.providers.re.Renderer;
import omeis.providers.re.data.PlaneDef;
import omeis.providers.re.metadata.StatsFactory;
import omeis.providers.re.quantum.QuantumFactory;
import omeis.providers.re.quantum.QuantumStrategy;
/**
* Implementation of the {@link IRenderingSettings} I/F.
*
* @author Aleksandra Tarkowska <a
* href="mailto:a.tarkowska@dundee.ac.uk">a.tarkowska@dundee.ac.uk</a>
* @version 3.0 <small> (<b>Internal version:</b> $Revision: 1696 $ $Date:
* 2007/09/06 23:27:31 $) </small>
* @since OME3.0
*/
@Transactional
public class RenderingSettingsImpl extends AbstractLevel2Service implements
IRenderingSettings, Serializable {
/**
*
*/
private static final long serialVersionUID = -4383698215540637039L;
/** The value used to compare double and float. */
public final static double EPSILON = 0.00001;
/** The logger for this class. */
private transient static Logger log =
LoggerFactory.getLogger(RenderingSettingsImpl.class);
/** Reference to the service used to retrieve the pixels data. */
protected transient PixelsService pixelsData;
/** Reference to the service used to retrieve the pixels metadata. */
protected transient IPixels pixelsMetadata;
/**
* Returns the min/max depending on the pixels type if the values
* have not seen stored.
*
* @param pixels The pixels.
* @return See above.
*/
private double[] initPixelsRange(Pixels pixels)
{
StatsFactory factory = new StatsFactory();
return factory.initPixelsRange(pixels);
}
/**
* Returns the Id of the currently logged in user. Opposed to ThumbnailBean,
* here we do not support share contexts since this service requires a viable
* write context which doesn't exist in shares.
*
* @return See above.
*/
private Long getCurrentUserId()
{
return getSecuritySystem().getEventContext().getCurrentUserId();
}
/**
* Checks to see if a given class is a valid container.
* @param klass IObject derived class to check for validity.
* @throws IllegalArgumentException If the class <code>klass</code> is
* an invalid container.
*/
private void checkValidContainerClass(Class<? extends IObject> klass)
{
if (!Project.class.equals(klass)
&& !Dataset.class.equals(klass)
&& !Image.class.equals(klass)
&& !Plate.class.equals(klass)
&& !Pixels.class.equals(klass)
&& !Screen.class.equals(klass)
&& !PlateAcquisition.class.equals(klass))
{
throw new IllegalArgumentException(
"Class parameter for changing settings must be in " +
"{Project, Dataset, Image, Plate, Screen, PlateAcquisition, " +
"Pixels}, not " +
klass);
}
}
/**
* Updates a collection of Pixels from an arbitrary set of nodes.
* @param pixels Collection to update.
* @param klass Instance type of the objects for which <code>nodeIds</code>
* represent a primary ID for.
* @param nodeIds Set of node IDs to lookup Pixels against.
*/
private void updatePixelsForNodes(List<Pixels> pixels,
Class<? extends IObject> klass,
Set<Long> nodeIds)
{
// Pre-process our list of potential containers. This will resolve down
// to a list of Pixels objects for us to work on.
if (Project.class.equals(klass))
{
pixels.addAll(loadProjectPixels(nodeIds));
}
else if (Dataset.class.equals(klass))
{
pixels.addAll(loadDatasetPixels(nodeIds));
}
else if (Plate.class.equals(klass))
{
pixels.addAll(loadPlatePixels(nodeIds));
}
else if (PlateAcquisition.class.equals(klass))
{
pixels.addAll(loadPlateAcquisitionPixels(nodeIds));
}
else if (Screen.class.equals(klass))
{
pixels.addAll(loadScreenPixels(nodeIds));
}
else if (Image.class.equals(klass))
{
pixels.addAll(loadPixelsByImage(nodeIds));
}
else if (Pixels.class.equals(klass))
{
pixels.addAll(loadPixels(nodeIds));
}
}
/**
* Retrieves all Pixels by ID.
*
* @param pixelsIds Pixels IDs to retrieve Pixels for.
* @return List of Pixels with the given Pixels IDs.
*/
private List<Pixels> loadPixels(Set<Long> pixelsIds)
{
StopWatch s1 = new Slf4JStopWatch("omero.loadPixels");
Parameters p = new Parameters();
p.addIds(pixelsIds);
String sql = "select pix from Pixels as pix " +
"join fetch pix.image " +
"join fetch pix.pixelsType " +
"join fetch pix.channels as c " +
"join fetch c.logicalChannel " +
"where pix.id in (:ids)";
List<Pixels> pixels = iQuery.findAllByQuery(sql, p);
s1.stop();
return pixels;
}
/**
* Retrieves all Pixels linked to a given set of Image IDs.
*
* @param imageIds Image IDs to retrieve Pixels for.
* @return List of Pixels associated with the given Image IDs.
*/
private List<Pixels> loadPixelsByImage(Set<Long> imageIds)
{
StopWatch s1 = new Slf4JStopWatch("omero.loadPixelsByImage");
Parameters p = new Parameters();
p.addIds(imageIds);
String sql = "select pix from Pixels as pix " +
"join fetch pix.image as i " +
"join fetch pix.pixelsType " +
"join fetch pix.channels as c " +
"join fetch c.logicalChannel " +
"where i.id in (:ids)";
List<Pixels> pixels = iQuery.findAllByQuery(sql, p);
s1.stop();
return pixels;
}
/**
* Retrieves all Pixels associated with the specified <code>Plate</code>s.
*
* @param plateIds The identifiers of the plate to retrieve Pixels for.
* @return List of Pixels associated with the Plate.
*/
private List<Pixels> loadPlatePixels(Set<Long> plateIds)
{
StopWatch s1 = new Slf4JStopWatch("omero.loadPlatePixels");
Parameters p = new Parameters();
p.addIds(plateIds);
String sql = "select pix from Pixels as pix " +
"join fetch pix.image as i " +
"join fetch pix.pixelsType " +
"join fetch pix.channels as c " +
"join fetch c.logicalChannel " +
"left outer join i.wellSamples as s " +
"left outer join s.well as w " +
"left outer join w.plate as p " +
"where p.id in (:ids)";
List<Pixels> pixels = iQuery.findAllByQuery(sql, p);
s1.stop();
return pixels;
}
/**
* Retrieves all Pixels associated with the specified <code>Plate</code>s.
*
* @param ids The identifiers of the plate acquisition to retrieve Pixels for.
* @return List of Pixels associated with the Plate.
*/
private List<Pixels> loadPlateAcquisitionPixels(Set<Long> ids)
{
StopWatch s1 = new Slf4JStopWatch("omero.loadPlatePixels");
Parameters p = new Parameters();
p.addIds(ids);
String sql = "select pix from Pixels as pix " +
"join fetch pix.image as i " +
"join fetch pix.pixelsType " +
"join fetch pix.channels as c " +
"join fetch c.logicalChannel " +
"left outer join i.wellSamples as s " +
"left outer join s.plateAcquisition as p " +
"where p.id in (:ids)";
List<Pixels> pixels = iQuery.findAllByQuery(sql, p);
s1.stop();
return pixels;
}
/**
* Retrieves all Pixels associated with the specified <code>Screen</code>.
*
* @param screenIds The identifiers of the Screen to retrieve Pixels for.
* @return List of Pixels associated with the Screen.
*/
private List<Pixels> loadScreenPixels(Set<Long> screenIds)
{
StopWatch s1 = new Slf4JStopWatch("omero.loadScreenPixels");
Parameters p = new Parameters();
p.addIds(screenIds);
String sql = "select pix from Pixels as pix " +
"join fetch pix.image as i " +
"join fetch pix.pixelsType " +
"join fetch pix.channels as c " +
"join fetch c.logicalChannel " +
"left outer join i.wellSamples as s " +
"left outer join s.well as w " +
"left outer join w.plate as p " +
"left outer join p.screenLinks as spl " +
"left outer join spl.parent as s " +
"where s.id in (:ids)";
List<Pixels> pixels = iQuery.findAllByQuery(sql, p);
s1.stop();
return pixels;
}
/**
* Retrieves all Pixels associated with the specified <code>Dataset</code>s.
*
* @param datasetIds Dataset ID to retrieve Pixels for.
* @return List of Pixels associated with the Dataset.
*/
private List<Pixels> loadDatasetPixels(Set<Long> datasetIds)
{
StopWatch s1 = new Slf4JStopWatch("omero.loadDatasetPixels");
Parameters p = new Parameters();
p.addIds(datasetIds);
String sql = "select pix from Pixels as pix " +
"join fetch pix.image as i " +
"join fetch pix.pixelsType " +
"join fetch pix.channels as c " +
"join fetch c.logicalChannel " +
"left outer join i.datasetLinks dil " +
"left outer join dil.parent d " +
"where d.id in (:ids)";
List<Pixels> pixels = iQuery.findAllByQuery(sql, p);
s1.stop();
return pixels;
}
/**
* Retrieves all Pixels associated with a Project from the database.
*
* @param projectIds Project ID to retrieve Pixels for.
* @return List of Pixels associated with the Project.
*/
private List<Pixels> loadProjectPixels(Set<Long> projectIds)
{
StopWatch s1 = new Slf4JStopWatch("omero.loadProjectPixels");
Parameters p = new Parameters();
p.addIds(projectIds);
String sql = "select pix from Pixels as pix " +
"join fetch pix.image as i " +
"join fetch pix.pixelsType " +
"join fetch pix.channels as c " +
"join fetch c.logicalChannel " +
"left outer join i.datasetLinks dil " +
"left outer join dil.parent as d " +
"left outer join d.projectLinks as pdl " +
"left outer join pdl.parent as p " +
"where p.id in (:ids)";
List<Pixels> pixels = iQuery.findAllByQuery(sql, p);
s1.stop();
return pixels;
}
/**
* Loads the logical channel to determine the color correctly.
*
* @param id The id of the channel.
* @return See above.
*/
private LogicalChannel loadLogicalChannel(Long id)
{
StopWatch s1 = new Slf4JStopWatch("omero.loadLogicalChannel");
Parameters p = new Parameters();
p.addId(id);
String sql =
"select channel from LogicalChannel as channel " +
"left outer join fetch channel.filterSet as filter " +
"left outer join fetch channel.lightPath as lp " +
"left outer join fetch lp.emissionFilterLink as em_link " +
"left outer join fetch em_link.child as emFilter " +
"left outer join fetch emFilter.transmittanceRange " +
"left outer join fetch lp.excitationFilterLink as ex_link " +
"left outer join fetch ex_link.child as exFilter " +
"left outer join fetch exFilter.transmittanceRange " +
"left outer join fetch channel.lightSourceSettings as lss " +
"left outer join fetch lss.lightSource as ls " +
"where channel.id = :id";
LogicalChannel lc = iQuery.findByQuery(sql, p);
s1.stop();
return lc;
}
/**
* Retrieves all rendering settings associated with a given set of Pixels.
* @param pixels List of Pixels to retrieve settings for.
* @return A map of <Pixels.Id,RenderingDef> for the list of Pixels
* given.
*/
private Map<Long, RenderingDef> loadRenderingSettings(List<Pixels> pixels)
{
return loadRenderingSettings(pixels, getCurrentUserId());
}
/**
* Retrieves all rendering settings associated with a given set of Pixels.
* @param pixels List of Pixels to retrieve settings for.
* @param userId User ID of the owner of the settings to query for.
* @return A map of <Pixels.Id,RenderingDef> for the list of Pixels
* given.
*/
private Map<Long, RenderingDef> loadRenderingSettings(List<Pixels> pixels,
Long ownerId)
{
StopWatch s1 = new Slf4JStopWatch(
"omero.loadRenderingSettingsByUser");
Set<Long> pixelsIds = new HashSet<Long>();
for (Pixels p : pixels)
{
pixelsIds.add(p.getId());
}
Parameters p = new Parameters();
p.addIds(pixelsIds);
p.addId(ownerId);
String sql = PixelsImpl.RENDERING_DEF_QUERY_PREFIX +
"rdef.pixels.id in (:ids) and " +
"rdef.details.owner.id = :id";
Map<Long, RenderingDef> settingsMap = new HashMap<Long, RenderingDef>();
List<RenderingDef> settingsList = iQuery.findAllByQuery(sql, p);
for (RenderingDef settings : settingsList)
{
settingsMap.put(settings.getPixels().getId(), settings);
}
s1.stop();
return settingsMap;
}
/**
* Retrieves all rendering settings associated with a given set of Pixels
* that belong to the owner of each Pixels set.
* @param pixels List of Pixels to retrieve settings for.
* @return A map of <Pixels.Id,RenderingDef> for the list of Pixels
* given.
*/
private Map<Long, RenderingDef> loadRenderingSettingsByOwner(
List<Pixels> pixels)
{
StopWatch s1 = new Slf4JStopWatch(
"omero.loadRenderingSettingsByOwner");
Set<Long> pixelsIds = new HashSet<Long>();
for (Pixels p : pixels)
{
pixelsIds.add(p.getId());
}
Parameters p = new Parameters();
p.addIds(pixelsIds);
String sql = PixelsImpl.RENDERING_DEF_QUERY_PREFIX +
"rdef.pixels.id in (:ids) and " +
"rdef.details.owner.id = rdef.pixels.details.owner.id";
Map<Long, RenderingDef> settingsMap = new HashMap<Long, RenderingDef>();
List<RenderingDef> settingsList = iQuery.findAllByQuery(sql, p);
for (RenderingDef settings : settingsList)
{
settingsMap.put(settings.getPixels().getId(), settings);
}
s1.stop();
return settingsMap;
}
/**
* Resets a specific set of rendering settings back to those that are
* specified by the rendering engine intelligent <i>pretty good image
* (PG)</i> logic and a given pixels set.
*
* @param pixels The pixels object whose rendering settings are to be reset.
* @param settings The rendering settings which are to be reset.
* @param save Whether or not the rendering settings should be saved.
* @param computeStats Pass <code>true</code> to compute the stats
* determining the input interval, <code>false</code>
* otherwise.
* @param families The valid rendering family enumerations.
* @param renderingModels The valid rendering model enumerations.
* @return See above.
*/
private RenderingDef resetDefaults(RenderingDef settings, Pixels pixels,
boolean save, boolean computeStats,
List<Family> families,
List<RenderingModel> renderingModels)
{
// Handle the case where we have no rendering settings so that we can
// reset "pretty good image" or "original" (channel minimum and
// maximum) when they don't exist.
if (settings == null)
{
settings = createNewRenderingDef(pixels);
}
QuantumFactory quantumFactory = new QuantumFactory(families);
try
{
PixelBuffer buffer = null;
if (computeStats)
{
buffer = pixelsData.getPixelBuffer(pixels, false);
}
try
{
resetDefaults(settings, pixels, quantumFactory,
renderingModels, buffer, computeStats);
}
finally
{
if (buffer != null) {
buffer.close();
}
}
// Increment the version of the rendering settings so that we
// can have some notification that either the RenderingDef
// object itself or one of its children in the object graph has
// been updated. FIXME: This should be implemented using
// IUpdate.touch() or similar once that functionality exists.
settings.setVersion(settings.getVersion() + 1);
if (save)
{
log.info("Saving settings: " + settings);
pixelsMetadata.saveRndSettings(settings);
}
return settings;
}
catch (IOException e)
{
log.debug("An I/O error occurred while attempting to reset " +
"rendering settings " + settings + " for pixels set " +
pixels, e);
throw new ResourceError(
e.getMessage() + " Please check server log.");
}
}
/**
* Resets a rendering definition to its predefined defaults.
*
* @param def The rendering definition to reset.
* @param pixels The pixels set to reset the definition based upon.
* @param quantumFactory A populated quantum factory.
* @param renderingModels An enumerated list of all rendering models.
* @param buffer A pixel buffer which maps to the <i>planeDef</i>.
* @param computeStats Pass <code>true</code> to compute the stats,
* <code>false</code> otherwise
*/
private void resetDefaults(RenderingDef def, Pixels pixels,
QuantumFactory quantumFactory, List<RenderingModel> renderingModels,
PixelBuffer buffer, boolean computeStats) {
// The default rendering definition settings
def.setDefaultZ(pixels.getSizeZ() / 2);
def.setDefaultT(0);
// Set the rendering model to RGB if there is more than one channel,
// otherwise set it to greyscale.
RenderingModel defaultModel = null;
int sizeC = pixels.getSizeC();
if (sizeC > 1 && sizeC < Renderer.MAX_CHANNELS) {
for (RenderingModel model : renderingModels)
{
if (model.getValue().equals(Renderer.MODEL_RGB))
defaultModel = model;
}
} else {
for (RenderingModel model : renderingModels)
{
if (model.getValue().equals(Renderer.MODEL_GREYSCALE))
defaultModel = model;
}
}
if (defaultModel == null)
{
throw new IllegalArgumentException(
"Unable to find default rendering model in enumerated list.");
}
def.setModel(defaultModel);
// Quantization settings
QuantumDef quantumDef = def.getQuantization();
quantumDef.setCdStart(0);
quantumDef.setCdEnd(QuantumFactory.DEPTH_8BIT);
quantumDef.setBitResolution(QuantumFactory.DEPTH_8BIT);
def.setQuantization(quantumDef);
// Reset the channel bindings
resetChannelBindings(def, pixels, quantumFactory, buffer, computeStats);
}
/**
* Performs the logic specified by {@link #resetDefaultsInSet()} and
* {@link #setOriginalSettingsInSet()}.
*/
private <T extends IObject> Set<Long> resetDefaultsInSet(
Class<T> klass, Set<Long> nodeIds, boolean computeStats)
{
checkValidContainerClass(klass);
// Load our dependencies for rendering settings manipulation
StopWatch s1 = new Slf4JStopWatch("omero.resetDefaultsInSet");
// Pre-process our list of potential containers. This will resolve down
// to a list of Pixels objects for us to work on.
List<Pixels> pixels = new ArrayList<Pixels>();
updatePixelsForNodes(pixels, klass, nodeIds);
// Perform the actual work of resetting rendering settings, collecting
// the settings that need to be saved and saving the newly modified or
// created rendering settings in the database.
Set<Long> imageIds = new HashSet<Long>();
if (pixels.size() == 0) return imageIds; //nothing retrieve.
List<Family> families = pixelsMetadata.getAllEnumerations(Family.class);
List<RenderingModel> renderingModels =
pixelsMetadata.getAllEnumerations(RenderingModel.class);
List<RenderingDef> toSave = new ArrayList<RenderingDef>(pixels.size());
Map<Long, RenderingDef> settingsMap = loadRenderingSettings(pixels);
RenderingDef settings;
for (Pixels p : pixels)
{
settings = settingsMap.get(p.getId());
if (settings == null)
{
settings = createNewRenderingDef(p);
}
try {
RenderingDef newSettings =
resetDefaults(settings, p, false, computeStats,
families, renderingModels);
if (newSettings != null) {
toSave.add(newSettings);
}
imageIds.add(p.getImage().getId());
} catch (ResourceError e) {
//Exception has already been written to log file.
} catch (ConcurrencyException e) {
log.warn(e.getClass().getSimpleName() + ", " +
"not resetting settings for Image:"
+ p.getImage().getId());
} catch (Exception e) {
log.warn("Exception while resetting settings for Image:"
+ p.getImage().getId(), e);
}
}
StopWatch s2 = new Slf4JStopWatch(
"omero.resetDefaultsInSet.saveAndReturn");
if (toSave.size() > 0) {
RenderingDef[] toSaveArray =
toSave.toArray(new RenderingDef[toSave.size()]);
iUpdate.saveAndReturnArray(toSaveArray);
}
s2.stop();
s1.stop();
return imageIds;
}
/**
* Returns the cut in value if available.
*
* @param f The filter to handle.
* @return See above.
*/
private String getValueFromFilter(Filter f)
{
if (f == null) return null;
TransmittanceRange transmittance = f.getTransmittanceRange();
if (transmittance == null) return null;
return ""+transmittance.getCutIn();
}
/**
* Determines the name of the channel if possible.
*
* @param lc The channel to handle.
* @return See above.
*/
private String getChannelName(LogicalChannel lc)
{
String name = null;
Length value = lc.getEmissionWave();
if (value != null) return ""+value.getValue();
if (lc.getFilterSet() != null) {
Iterator<Filter> it = lc.getFilterSet().linkedEmissionFilterIterator();
while (name == null && it.hasNext()) {
name = getValueFromFilter(it.next());
}
if (name != null) return name;
}
//Laser
if (lc.getLightSourceSettings() != null) {
LightSource src = lc.getLightSourceSettings().getLightSource();
if (src instanceof Laser) {
Laser laser = (Laser) src;
value = laser.getWavelength();
if (value != null) return ""+value.getValue();
}
}
value = lc.getExcitationWave();
if (value != null) return ""+value.getValue();
if (lc.getFilterSet() != null) {
Iterator<Filter> it = lc.getFilterSet().linkedExcitationFilterIterator();
while (name == null && it.hasNext()) {
name = getValueFromFilter(it.next());
}
if (name != null) return name;
}
return name;
}
/**
* Returns the original color if set at import or <code>null</code>.
* if no color was set.
*
* @param channel The channel to handle.
* @return See above.
*/
private int[] hasOriginalColor(Channel channel)
{
Integer red = channel.getRed();
Integer green = channel.getGreen();
Integer blue = channel.getBlue();
Integer alpha = channel.getAlpha();
if (red != null && green != null && blue != null && alpha != null)
return new int[] { red, green, blue, alpha };
return null;
}
/**
* Resets the channel bindings for the current active pixels set.
*
* @param def
* the rendering definition to link to.
* @param pixels
* the pixels set to reset the bindings based upon.
* @param quantumFactory
* a populated quantum factory.
* @param buffer
* a pixel buffer which maps to the <i>planeDef</i>.
* @param computeStats
* Pass <code>true</code> to compute the stats,
* <code>false</code> otherwise
*/
private void resetChannelBindings(RenderingDef def, Pixels pixels,
QuantumFactory quantumFactory, PixelBuffer buffer, boolean
computeStats) {
// The actual channel bindings we are returning
List<ChannelBinding>
channelBindings = def.<ChannelBinding>collectWaveRendering(null);
// Default plane definition for our rendering definition
PlaneDef planeDef = getDefaultPlaneDef(def);
int i = 0;
ChannelBinding channelBinding;
LogicalChannel lc;
Family family;
int[] defaultColor;
//int n = channelBindings.size();
Map<ChannelBinding, Boolean> m = new HashMap<ChannelBinding, Boolean>();
List<Boolean> values = new ArrayList<Boolean>();
boolean v;
int count = 0;
List<LogicalChannel> toUpdate = new ArrayList<LogicalChannel>();
for (Channel channel : pixels.<Channel>collectChannels(null)) {
family = quantumFactory.getFamily(QuantumFactory.LINEAR);
channelBinding = channelBindings.get(i);
channelBinding.setFamily(family);
channelBinding.setCoefficient(1.0);
// If we have more than one channel set each of the first three
// active, otherwise only activate the first.
channelBinding.setActive(i < 3);
// Handle updating or recreating a color for this channel.
defaultColor = hasOriginalColor(channel);
if (defaultColor == null) {
lc = channel.getLogicalChannel();
if (lc != null) lc = loadLogicalChannel(lc.getId());
//Update the name of the channel if no name, to be moved.
/*
* v = ColorsFactory.hasEmissionData(lc);
name = lc.getName();
if (name == null || name.trim().length() == 0) {
name = getChannelName(lc);
if (name != null) {
lc.setName(name);
toUpdate.add(lc);
}
}
if (!v) values.add(v);
m.put(channelBinding, v);
*/
//Need to turn that back on.
v = ColorsFactory.hasEmissionData(lc);
if (!v) count++;
m.put(channelBinding, v);
defaultColor = ColorsFactory.getColor(i, channel, lc);
}
channelBinding.setRed(defaultColor[ColorsFactory.RED_INDEX]);
channelBinding.setGreen(defaultColor[ColorsFactory.GREEN_INDEX]);
channelBinding.setBlue(defaultColor[ColorsFactory.BLUE_INDEX]);
channelBinding.setAlpha(defaultColor[ColorsFactory.ALPHA_INDEX]);
channelBinding.setNoiseReduction(false);
i++;
}
if (count > 0 && count != m.size()) {
Iterator<ChannelBinding> k = m.keySet().iterator();
while (k.hasNext()) {
channelBinding = k.next();
if (!m.get(channelBinding)) {
defaultColor = ColorsFactory.newWhiteColor();
channelBinding.setRed(
defaultColor[ColorsFactory.RED_INDEX]);
channelBinding.setGreen(
defaultColor[ColorsFactory.GREEN_INDEX]);
channelBinding.setBlue(
defaultColor[ColorsFactory.BLUE_INDEX]);
channelBinding.setAlpha(
defaultColor[ColorsFactory.ALPHA_INDEX]);
}
}
}
QuantumDef qDef = def.getQuantization();
// Set the input start and input end for each channel binding based upon
// the computation of the pixels set's location statistics.
if (computeStats)
computeLocationStats(pixels, channelBindings, planeDef, buffer,
quantumFactory, qDef);
else {
StatsInfo stats;
double min, max;
QuantumStrategy qs;
double[] range;
for (int w = 0; w < pixels.sizeOfChannels(); w++) {
// FIXME: This is where we need to have the ChannelBinding -->
// Channel linkage. Without it, we have to assume that the order in
// which the channel bindings was created matches up with the order
// of the channels linked to the pixels set.
channelBinding = channelBindings.get(w);
stats = pixels.getChannel(w).getStatsInfo();
if (stats == null) {
range = initPixelsRange(pixels);
min = range[0];
max = range[1];
} else {
min = stats.getGlobalMin().doubleValue();
max = stats.getGlobalMax().doubleValue();
}
if (Math.abs(min-max) < EPSILON) { //to be on the save side
qs = quantumFactory.getStrategy(qDef, pixels);
min = qs.getPixelsTypeMin();
max = qs.getPixelsTypeMax();
}
channelBinding.setInputStart(min);
channelBinding.setInputEnd(max);
}
}
//update the value.
if (toUpdate.size() > 0) {
StopWatch s1 = new Slf4JStopWatch(
"omero.resetChannelBindings.saveAndReturn");
LogicalChannel[] toSaveArray =
toUpdate.toArray(new LogicalChannel[toUpdate.size()]);
iUpdate.saveAndReturnArray(toSaveArray);
s1.stop();
}
}
/**
* Computes the location statistics for a set of rendering settings.
*
* @param pixels The pixels set.
* @param cbs The collection of settings corresponding to channel.
* @param planeDef The 2D-plane. Mustn't be <code>null</code>
* @param buf The buffer.
* @param quantumFactory A populated quantum factory.
* @param qDef The object hosting information about how to map data.
*/
private void computeLocationStats(Pixels pixels,
List<ChannelBinding> cbs, PlaneDef planeDef, PixelBuffer buf,
QuantumFactory quantumFactory, QuantumDef qDef) {
if (planeDef == null) {
throw new NullPointerException("No plane definition.");
}
StatsFactory sf = new StatsFactory();
ChannelBinding cb;
double min, max;
QuantumStrategy qs;
for (int w = 0; w < pixels.sizeOfChannels(); w++) {
// FIXME: This is where we need to have the ChannelBinding -->
// Channel linkage. Without it, we have to assume that the order in
// which the channel bindings was created matches up with the order
// of the channels linked to the pixels set.
cb = cbs.get(w);
sf.computeLocationStats(pixels, buf, planeDef, w);
cb.setNoiseReduction(sf.isNoiseReduction());
min = sf.getInputStart();
max = sf.getInputEnd();
if (Math.abs(min-max) < EPSILON) {
qs = quantumFactory.getStrategy(qDef, pixels);
min = qs.getPixelsTypeMin();
max = qs.getPixelsTypeMax();
}
cb.setInputStart(new Double(min));
cb.setInputEnd(new Double(max));
}
}
/**
* Creates the default plane definition to use for generation of the very
* first image displayed by <i>2D</i> viewers based upon a rendering
* definition.
*
* @param renderingDef
* the rendering definition to base the plane definition upon.
* @return The default <i>XY</i>-plane for the <i>renderingDef</i>.
*/
private PlaneDef getDefaultPlaneDef(RenderingDef renderingDef) {
PlaneDef pd = new PlaneDef(PlaneDef.XY, renderingDef.getDefaultT());
pd.setZ(renderingDef.getDefaultZ());
return pd;
}
/**
* Creates new channel bindings for each channel in the pixels set.
*
* @param p
* the pixels set to create channel bindings based upon.
* @return a new set of blank channel bindings.
*/
private List<ChannelBinding> createNewChannelBindings(Pixels p)
{
List<ChannelBinding> cbs = new ArrayList<ChannelBinding>();
ChannelBinding binding;
for (int i = 0; i < p.getSizeC(); i++) {
binding = new ChannelBinding();
cbs.add(binding);
}
return cbs;
}
/**
* Applies rendering settings from a source set of pixels and settings to
* a destination set of pixels and settings.
* @param pixelsFrom Source pixels object.
* @param pixelsTo Source renderings settings.
* @param settingsFrom Source rendering settings.
* @param settingsTo Destination rendering settings. If <code>null</code>
* these will be created on the fly.
* @return The rendering settings modified or created. It is up to the
* caller to save these settings.
*/
private RenderingDef applySettings(Pixels pixelsFrom, Pixels pixelsTo,
RenderingDef settingsFrom,
RenderingDef settingsTo)
{
// Sanity checks
log.debug(String.format(
"Applying settings. From %s to %s and from %s to %s",
pixelsFrom, pixelsTo, settingsFrom, settingsTo));
boolean b = sanityCheckPixels(pixelsFrom, pixelsTo);
if (!b)
{
return null;
}
if (settingsFrom == null)
{
return null;
}
if (settingsTo == null)
{
settingsTo = createNewRenderingDef(pixelsTo);
}
int z = settingsFrom.getDefaultZ();
if (z < pixelsTo.getSizeZ())
settingsTo.setDefaultZ(z);
int t = settingsFrom.getDefaultT();
if (t < pixelsTo.getSizeT())
settingsTo.setDefaultT(t);
settingsTo.setModel(settingsFrom.getModel());
QuantumDef qDefFrom = settingsFrom.getQuantization();
QuantumDef qDefTo = settingsTo.getQuantization();
qDefTo.setBitResolution(qDefFrom.getBitResolution());
//Check if end > start
Integer end = qDefFrom.getCdEnd();
Integer start = qDefFrom.getCdStart();
if (end != null && start != null) {
if (end < start) {
end = start;
start = qDefFrom.getCdEnd();
}
}
qDefTo.setCdEnd(end);
qDefTo.setCdStart(start);
Iterator<ChannelBinding> i = settingsFrom.iterateWaveRendering();
Iterator<ChannelBinding> iTo = settingsTo.iterateWaveRendering();
ChannelBinding binding, bindingTo;
while (i.hasNext())
{
binding = i.next();
bindingTo = iTo.next();
// channel on or off
bindingTo.setActive(binding.getActive());
// mapping coefficient
bindingTo.setCoefficient(binding.getCoefficient());
// type of map used
bindingTo.setFamily(binding.getFamily());
// lower bound of the pixels intensity interval
bindingTo.setInputStart(binding.getInputStart());
// upper bound of the pixels intensity interval
bindingTo.setInputEnd(binding.getInputEnd());
// turn on or off the noise reduction algo.
bindingTo.setNoiseReduction(binding.getNoiseReduction());
// color used
bindingTo.setAlpha(binding.getAlpha());
bindingTo.setBlue(binding.getBlue());
bindingTo.setGreen(binding.getGreen());
bindingTo.setRed(binding.getRed());
}
// Increment the version of the rendering settings so that we
// can have some notification that either the RenderingDef
// object itself or one of its children in the object graph has
// been updated. FIXME: This should be implemented using
// IUpdate.touch() or similar once that functionality exists.
settingsTo.setVersion(settingsTo.getVersion() + 1);
return settingsTo;
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F
*
* @see IRenderingSettings#sanityCheckPixels(Pixels, Pixels)
*/
public boolean sanityCheckPixels(Pixels pFrom, Pixels pTo) {
if (pTo == null || pFrom == null)
return false;
String vFrom = pFrom.getPixelsType().getValue();
String vTo = pTo.getPixelsType().getValue();
if (!vFrom.equals(vTo))
return false;
if (pFrom.getSizeC().compareTo(pTo.getSizeC()) != 0)
return false;
Iterator<Channel> i = pFrom.iterateChannels();
Channel c;
List<Length> wavelengths = new ArrayList<Length>(pFrom
.sizeOfChannels());
// Problem no access to channel index.
LogicalChannel lc;
while (i.hasNext()) {
c = i.next();
lc = c.getLogicalChannel();
if (lc != null)
wavelengths.add(lc.getEmissionWave());
}
i = pTo.iterateChannels();
int r = 0;
while (i.hasNext()) {
c = i.next();
lc = c.getLogicalChannel();
if (lc != null && wavelengths.contains(lc.getEmissionWave()))
r++;
}
if (r != wavelengths.size())
return false;
return true;
}
/**
* Sets injector. For use during configuration. Can only be called once.
*
* @param metaService
* The value to set.
*/
public void setPixelsMetadata(IPixels metaService) {
getBeanHelper().throwIfAlreadySet(this.pixelsMetadata, metaService);
pixelsMetadata = metaService;
}
/**
* Sets injector. For use during configuration. Can only be called once.
*
* @param dataService
* The value to set.
*/
public void setPixelsData(PixelsService dataService) {
getBeanHelper().throwIfAlreadySet(this.pixelsData, dataService);
pixelsData = dataService;
}
/**
* Returns the interface this implementation is for.
* @see AbstractLevel2Service#getServiceInterface()
*/
public Class<? extends ServiceInterface> getServiceInterface() {
return IRenderingSettings.class;
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
* @see IRenderingSettings#applySettingsToSet(long, Class, Set)
*/
@RolesAllowed("user")
public <T extends IObject> Map<Boolean, List<Long>> applySettingsToSet(
long from, Class<T> klass, Set<Long> nodeIds) {
checkValidContainerClass(klass);
// Load our dependencies for rendering settings manipulation
StopWatch s1 = new Slf4JStopWatch("omero.applySettingsToSet");
//nodeIds.add(from);
// Pre-process our list of potential containers. This will resolve down
// to a list of Pixels objects for us to work on.
List<Pixels> pixels = new ArrayList<Pixels>();
updatePixelsForNodes(pixels, klass, nodeIds);
Pixels pixelsFrom = null;
for (Pixels p : pixels)
{
if (p.getId() == from)
{
pixelsFrom = p;
break;
}
}
// Perform the actual work of copying rendering settings, collecting
// the settings that need to be saved and saving the newly modified or
// created rendering settings in the database.
List<Long> toReturnTrue = new ArrayList<Long>();
List<Long> toReturnFalse = new ArrayList<Long>();
Map<Boolean, List<Long>> toReturn = new HashMap<Boolean, List<Long>>();
if (pixels.size() == 0) {
toReturn.put(Boolean.valueOf(true), toReturnTrue);
toReturn.put(Boolean.valueOf(false), toReturnFalse);
return toReturn;
}
List<RenderingDef> toSave = new ArrayList<RenderingDef>();
Map<Long, RenderingDef> settingsMap = loadRenderingSettings(pixels);
RenderingDef settingsFrom = settingsMap.get(from);
if (pixelsFrom != null) {
pixels.remove(pixelsFrom);
toReturnTrue.add(pixelsFrom.getImage().getId());
}
else {
//load pixels from
Set<Long> ids = new HashSet<Long>();
ids.add(from);
List<Pixels> l = loadPixels(ids);
if (l.size() != 1)
throw new ValidationException("No pixels set with ID: " + from);
pixelsFrom = l.get(0);
if (settingsFrom == null) {
List<Pixels> list = new ArrayList<Pixels>(1);
list.add(pixelsFrom);
Map<Long, RenderingDef> map = loadRenderingSettings(list);
settingsFrom = map.get(from);
}
}
RenderingDef settingsTo;
for (Pixels p : pixels)
{
settingsTo = settingsMap.get(p.getId());
settingsTo = applySettings(pixelsFrom, p, settingsFrom, settingsTo);
if (settingsTo == null)
{
toReturnFalse.add(p.getImage().getId());
}
else
{
toSave.add(settingsTo);
toReturnTrue.add(p.getImage().getId());
}
}
StopWatch s2 = new Slf4JStopWatch(
"omero.applySettingsToSet.saveAndReturn");
RenderingDef[] toSaveArray =
toSave.toArray(new RenderingDef[toSave.size()]);
iUpdate.saveAndReturnArray(toSaveArray);
s2.stop();
s1.stop();
toReturn.put(Boolean.valueOf(true), toReturnTrue);
toReturn.put(Boolean.valueOf(false), toReturnFalse);
return toReturn;
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
* @see IRenderingSettings#applySettingsToProject(long, long)
*/
@RolesAllowed("user")
public Map<Boolean, List<Long>> applySettingsToProject(long from, long to)
{
Set<Long> nodeIds = new HashSet<Long>();
nodeIds.add(to);
return applySettingsToSet(from, Project.class, nodeIds);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
* @see IRenderingSettings#applySettingsToDataset(long, long)
*/
@RolesAllowed("user")
public Map<Boolean, List<Long>> applySettingsToDataset(long from, long to)
{
Set<Long> nodeIds = new HashSet<Long>();
nodeIds.add(to);
return applySettingsToSet(from, Dataset.class, nodeIds);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F
*
* @see IRenderingSettings#applySettingsToImage(long, long)
*/
@RolesAllowed("user")
public boolean applySettingsToImage(long from, long to) {
Set<Long> nodeIds = new HashSet<Long>();
nodeIds.add(to);
Map<Boolean, List<Long>> returnValue =
applySettingsToSet(from, Image.class, nodeIds);
if (returnValue.get(Boolean.TRUE).contains(to))
{
return true;
}
return false;
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F
*
* @see IRenderingSettings#applySettingsToImages(long, List)
*/
@RolesAllowed("user")
public Map<Boolean, List<Long>> applySettingsToImages(long from,
List<Long> nodeIds) {
Set<Long> nodeIdSet = new HashSet<Long>(nodeIds);
return applySettingsToSet(from, Image.class, nodeIdSet);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F
*
* @see IRenderingSettings#applySettingsToPixels(long, long)
*/
@RolesAllowed("user")
public boolean applySettingsToPixels(long from, long to)
{
Pixels pixelsFrom = pixelsMetadata.retrievePixDescription(from);
Pixels pixelsTo = pixelsMetadata.retrievePixDescription(to);
List<Pixels> pixelsList = new ArrayList<Pixels>(2);
pixelsList.add(pixelsFrom);
pixelsList.add(pixelsTo);
Map<Long, RenderingDef> settingsMap = loadRenderingSettings(pixelsList);
RenderingDef settingsFrom = settingsMap.get(from);
RenderingDef settingsTo = settingsMap.get(to);
settingsTo = applySettings(pixelsFrom, pixelsTo,
settingsFrom, settingsTo);
if (settingsTo == null)
{
return false;
}
iUpdate.saveObject(settingsTo);
return true;
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F
*
* @see IRenderingSettings#getRenderingSettings(long)
*/
@RolesAllowed("user")
public RenderingDef getRenderingSettings(long pixelsId) {
return pixelsMetadata.retrieveRndSettings(pixelsId);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F
*
* @see IRenderingSettings#createNewRenderingDef(Pixels)
*/
public RenderingDef createNewRenderingDef(@NotNull Pixels pixels) {
if (pixels == null) return null;
RenderingDef r = new RenderingDef();
//The default rendering definition settings
r.setDefaultZ(pixels.getSizeZ() / 2);
r.setDefaultT(0);
r.setQuantization(new QuantumDef());
List<ChannelBinding> list = createNewChannelBindings(pixels);
r.clearWaveRendering();
for (ChannelBinding channelBinding : list) {
r.addChannelBinding(channelBinding);
}
// Unload the pixels object to avoid transactional headaches
Pixels unloadedPixels = new Pixels();
unloadedPixels.setId(pixels.getId());
unloadedPixels.unload();
r.setPixels(unloadedPixels);
return r;
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F
*
* @see IRenderingSettings#resetDefaults(RenderingDef, Pixels)
*/
@RolesAllowed("user")
public void resetDefaults(RenderingDef def, Pixels pixels) {
List<Family> families = pixelsMetadata.getAllEnumerations(Family.class);
List<RenderingModel> renderingModels =
pixelsMetadata.getAllEnumerations(RenderingModel.class);
resetDefaults(def, pixels, true, true, families, renderingModels);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F
*
* @see IRenderingSettings#resetDefaultsNoSave(RenderingDef, Pixels)
*/
@RolesAllowed("user")
public RenderingDef resetDefaultsNoSave(RenderingDef def, Pixels pixels) {
List<Family> families = pixelsMetadata.getAllEnumerations(Family.class);
List<RenderingModel> renderingModels =
pixelsMetadata.getAllEnumerations(RenderingModel.class);
return resetDefaults(def, pixels, false, true, families,
renderingModels);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
* @see IRenderingSettings#resetDefaultsInImage(long)
*/
@RolesAllowed("user")
public void resetDefaultsInImage(long to) {
Set<Long> nodeIds = new HashSet<Long>();
nodeIds.add(to);
resetDefaultsInSet(Image.class, nodeIds);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
* @see IRenderingSettings#resetDefaultsForPixels(long)
*/
@RolesAllowed("user")
public void resetDefaultsForPixels(long to) {
Set<Long> nodeIds = new HashSet<Long>();
nodeIds.add(to);
resetDefaultsInSet(Pixels.class, nodeIds);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
*
* @see IRenderingSettings#resetDefaultsInDataset(long)
*/
@RolesAllowed("user")
public Set<Long> resetDefaultsInDataset(long to) {
Set<Long> nodeIds = new HashSet<Long>();
nodeIds.add(to);
return resetDefaultsInSet(Dataset.class, nodeIds);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
* @see IRenderingSettings#resetDefaultsInSet(Class, Set)
*/
@RolesAllowed("user")
public <T extends IObject> Set<Long> resetDefaultsInSet(Class<T> klass,
Set<Long> nodeIds)
{
return resetDefaultsInSet(klass, nodeIds, true);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
* @see IRenderingSettings#resetDefaultsInSet(Class, Set)
*/
@RolesAllowed("user")
public <T extends IObject> Set<Long> resetDefaultsByOwnerInSet(
Class<T> klass, Set<Long> nodeIds)
{
checkValidContainerClass(klass);
// Pre-process our list of potential containers. This will resolve down
// to a list of Pixels objects for us to work on.
Set<Long> toReturn = new HashSet<Long>();
List<Pixels> pixelsList = new ArrayList<Pixels>();
updatePixelsForNodes(pixelsList, klass, nodeIds);
if (pixelsList.size() == 0)
return toReturn;
Map<Long, RenderingDef> ownerSettings =
loadRenderingSettingsByOwner(pixelsList);
Map<Long, RenderingDef> mySettings =
loadRenderingSettings(pixelsList);
Set<IObject> toSave = new HashSet<IObject>();
RenderingDef def, from, to;
for (Pixels pixels : pixelsList)
{
from = ownerSettings.get(pixels.getId());
to = mySettings.get(pixels.getId());
try
{
def = applySettings(pixels, pixels, from, to);
if (def != null) {
toSave.add(def);
toReturn.add(pixels.getImage().getId());
}
}
catch (Exception e)
{
log.warn(String.format(
"Exception while applying settings from owner. " +
"%s from %s to %s", pixels, from, to), e);
}
}
if (toSave.size() > 0) iUpdate.saveCollection(toSave);
return toReturn;
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
* @see IRenderingSettings#resetMinMaxInSet(Class, Set)
*/
@RolesAllowed("user")
public <T extends IObject> Set<Long> resetMinMaxInSet(Class<T> klass,
Set<Long> nodeIds)
{
checkValidContainerClass(klass);
StopWatch s1 = new Slf4JStopWatch("omero.resetMinMaxInSet");
// Load our dependencies for rendering settings manipulation
List<Family> families = pixelsMetadata.getAllEnumerations(Family.class);
List<RenderingModel> renderingModels =
pixelsMetadata.getAllEnumerations(RenderingModel.class);
// Pre-process our list of potential containers. This will resolve down
// to a list of Pixels objects for us to work on.
List<Pixels> pixelsList = new ArrayList<Pixels>();
updatePixelsForNodes(pixelsList, klass, nodeIds);
Set<Long> toReturn = new HashSet<Long>();
if (pixelsList.size() == 0) return toReturn;
Map<Long, RenderingDef> mySettings =
loadRenderingSettings(pixelsList);
Set<IObject> toSave = new HashSet<IObject>();
RenderingDef settings;
ChannelBinding cb;
StatsInfo stats;
double[] range;
double min, max;
for (Pixels pixels : pixelsList)
{
settings = mySettings.get(pixels.getId());
if (settings == null)
{
try
{
settings = resetDefaults(settings, pixels, false, false,
families, renderingModels);
if (settings != null) {
toReturn.add(pixels.getId());
toSave.add(settings);
}
}
catch (Exception e)
{
log.warn("Exception while resetting settings.", e);
}
}
else
{
for (int i = 0; i < pixels.sizeOfChannels(); i++)
{
cb = settings.getChannelBinding(i);
stats = pixels.getChannel(i).getStatsInfo();
if (stats == null) {
range = initPixelsRange(pixels);
min = range[0];
max = range[1];
} else {
min = stats.getGlobalMin();
max = stats.getGlobalMax();
}
cb.setInputStart(min);
cb.setInputEnd(max);
}
toReturn.add(pixels.getId());
toSave.add(settings);
}
// Increment the version of the rendering settings so that we
// can have some notification that either the RenderingDef
// object itself or one of its children in the object graph has
// been updated. FIXME: This should be implemented using
// IUpdate.touch() or similar once that functionality exists.
settings.setVersion(settings.getVersion() + 1);
}
if (toSave.size() > 0) iUpdate.saveCollection(toSave);
s1.stop();
return toReturn;
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
* @see IRenderingSettings#setOriginalSettingsInImage(long)
*/
@RolesAllowed("user")
public void setOriginalSettingsInImage(long to) {
Set<Long> nodeIds = new HashSet<Long>();
nodeIds.add(to);
setOriginalSettingsInSet(Image.class, nodeIds);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
* @see IRenderingSettings#setOriginalSettingsForPixels(long)
*/
@RolesAllowed("user")
public void setOriginalSettingsForPixels(long to) {
Set<Long> nodeIds = new HashSet<Long>();
nodeIds.add(to);
setOriginalSettingsInSet(Pixels.class, nodeIds);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
* @see IRenderingSettings#setOriginalSettingsInDataset(long)
*/
@RolesAllowed("user")
public Set<Long> setOriginalSettingsInDataset(long to) {
Set<Long> nodeIds = new HashSet<Long>();
nodeIds.add(to);
return setOriginalSettingsInSet(Dataset.class, nodeIds);
}
/**
* Implemented as specified by the {@link IRenderingSettings} I/F.
* @see IRenderingSettings#setOriginalSettingsInSet(Class, Set)
*/
@RolesAllowed("user")
public <T extends IObject> Set<Long> setOriginalSettingsInSet(
Class<T> klass, Set<Long> nodeIds)
{
return resetDefaultsInSet(klass, nodeIds, false);
}
}