/** * Constructs an image information class based on the 5D image source, and the individual set of * pixels desired in that image. Needs Factory to query the database about statistics. (this might * not be a good thing) * * @param imageSource The image to store information about. * @param pixels The pixel source of the image. * @param dataSource The factory used to access the OME database. Is there a better way to do * this? */ public ImageInformation(Image imageSource, ImagePixels pixels, Factory dataSource) { this.imageSource = imageSource; this.pixels = pixels; this.pixelsAttribute = pixels.getPixelsAttribute(); this.dataSource = dataSource; Map imageSourceMap = new HashMap(); imageSourceMap.put("target", imageSource); // extract the channel/wavelength information for this image. List channelComponents = dataSource.findAttributes("PixelChannelComponent", imageSourceMap); final int pixelsID = pixelsAttribute.getID(); // this taken straight out of the SVG viewer code // might be a faster/better/less OME-call-intensive way to do it channelComponents = Filter.grep( channelComponents, new GrepOperator() { public boolean eval(Object o) { Attribute attribute = (Attribute) o; Attribute pixels = attribute.getAttributeElement("Pixels"); return pixels.getID() == pixelsID; } }); channelInfo = new Wavelength[channelComponents.size()]; for (int i = 0; i < channelComponents.size(); i++) { Attribute channel = (Attribute) channelComponents.get(i); channelInfo[i] = new Wavelength(channel.getIntElement("Index")); } CBS = ChannelBlackScaleData.getDefaultChannelScale(channelInfo); cbsMap = new HashMap(); // hopefully this doesn't break right here // extract the proper stack statistics for this image, // this might be done the hard way (I dunno) Map moduleConstraints = new HashMap(); moduleConstraints.put("name", "Fast Stack statistics"); Module stackModule = (Module) dataSource.findObject("OME::Module", moduleConstraints); Map formalInputConstraints = new HashMap(); formalInputConstraints.put("module_id", new Integer(stackModule.getID())); formalInputConstraints.put("name", "Pixels"); Module.FormalInput formalInput = (Module.FormalInput) dataSource.findObject("OME::Module::FormalInput", formalInputConstraints); RemoteModuleExecution moduleExecution = (RemoteModuleExecution) pixelsAttribute.getModuleExecution(); Map actualInputConstraints = new HashMap(); actualInputConstraints.put("formal_input_id", new Integer(formalInput.getID())); actualInputConstraints.put("input_module_execution_id", new Integer(moduleExecution.getID())); ModuleExecution.ActualInput actualInput = (ModuleExecution.ActualInput) dataSource.findObject("OME::ModuleExecution::ActualInput", actualInputConstraints); final int stackAnalysisID = actualInput.getModuleExecution().getID(); // retrieve statistics List stackMins = dataSource.findAttributes("StackMinimum", imageSourceMap); List stackMaxes = dataSource.findAttributes("StackMaximum", imageSourceMap); List stackMeans = dataSource.findAttributes("StackMean", imageSourceMap); List stackSigmas = dataSource.findAttributes("StackSigma", imageSourceMap); List stackGeomeans = dataSource.findAttributes("StackGeometricMean", imageSourceMap); List stackGeosigmas = dataSource.findAttributes("StackGeometricSigma", imageSourceMap); GrepOperator stackIDOperator = new GrepOperator() { public boolean eval(Object o) { Attribute attribute = (Attribute) o; RemoteModuleExecution execution = (RemoteModuleExecution) attribute.getModuleExecution(); if (execution.getID() == stackAnalysisID) { return true; } else return false; } }; List usableMins = Filter.grep(stackMins, stackIDOperator); List usableMaxes = Filter.grep(stackMaxes, stackIDOperator); List usableMeans = Filter.grep(stackMeans, stackIDOperator); List usableSigmas = Filter.grep(stackSigmas, stackIDOperator); List usableGeomeans = Filter.grep(stackGeomeans, stackIDOperator); List usableGeosigmas = Filter.grep(stackGeosigmas, stackIDOperator); sizeX = pixelsAttribute.getIntElement("SizeX"); sizeY = pixelsAttribute.getIntElement("SizeY"); sizeZ = pixelsAttribute.getIntElement("SizeZ"); sizeC = pixelsAttribute.getIntElement("SizeC"); sizeT = pixelsAttribute.getIntElement("SizeT"); bitsPerPixel = pixelsAttribute.getIntElement("BitsPerPixel"); stackStats = new StackStatistics[sizeC][sizeT]; // initialize array for (int i = 0; i < sizeC; i++) { for (int j = 0; j < sizeT; j++) { stackStats[i][j] = new StackStatistics(); } } // populate internal data structures for (Iterator iter = usableMins.iterator(); iter.hasNext(); ) { Attribute stackMin = (Attribute) iter.next(); int theC = stackMin.getIntElement("TheC"); int theT = stackMin.getIntElement("TheT"); stackStats[theC][theT].setMin(stackMin.getIntElement("Minimum")); } for (Iterator iter = usableMaxes.iterator(); iter.hasNext(); ) { Attribute stackMax = (Attribute) iter.next(); int theC = stackMax.getIntElement("TheC"); int theT = stackMax.getIntElement("TheT"); stackStats[theC][theT].setMax(stackMax.getIntElement("Maximum")); } for (Iterator iter = usableMeans.iterator(); iter.hasNext(); ) { Attribute stackMean = (Attribute) iter.next(); int theC = stackMean.getIntElement("TheC"); int theT = stackMean.getIntElement("TheT"); stackStats[theC][theT].setMean(stackMean.getFloatElement("Mean")); } for (Iterator iter = usableSigmas.iterator(); iter.hasNext(); ) { Attribute stackSigma = (Attribute) iter.next(); int theC = stackSigma.getIntElement("TheC"); int theT = stackSigma.getIntElement("TheT"); stackStats[theC][theT].setSigma(stackSigma.getFloatElement("Sigma")); } for (Iterator iter = usableGeomeans.iterator(); iter.hasNext(); ) { Attribute stackMean = (Attribute) iter.next(); int theC = stackMean.getIntElement("TheC"); int theT = stackMean.getIntElement("TheT"); stackStats[theC][theT].setGeoMean(stackMean.getFloatElement("GeometricMean")); } for (Iterator iter = usableGeosigmas.iterator(); iter.hasNext(); ) { Attribute stackSigma = (Attribute) iter.next(); int theC = stackSigma.getIntElement("TheC"); int theT = stackSigma.getIntElement("TheT"); stackStats[theC][theT].setGeoSigma(stackSigma.getFloatElement("GeometricSigma")); } }
// analogous to getConvertedWBS4OME_JPEG in OMEimage.js // and boundary conditions modifier in updatePic in OMEimage.js public ChannelBlackScaleData getNormalizedScale(int t) { if (t < 0 || t >= getDimT()) { return null; } Integer tObj = new Integer(t); if (cbsMap.containsKey(tObj)) { return (ChannelBlackScaleData) cbsMap.get(tObj); } ChannelBlackScaleData convertedData = new ChannelBlackScaleData(); ChannelBlackScaleData.CBSChunk[] dataChunks = { CBS.getCBSChunk(ChannelBlackScaleData.RED_CHUNK), CBS.getCBSChunk(ChannelBlackScaleData.GREEN_CHUNK), CBS.getCBSChunk(ChannelBlackScaleData.BLUE_CHUNK), CBS.getCBSChunk(ChannelBlackScaleData.GRAY_CHUNK) }; ChannelBlackScaleData.CBSChunk[] newChunks = new ChannelBlackScaleData.CBSChunk[dataChunks.length]; for (int i = 0; i < dataChunks.length; i++) { ChannelBlackScaleData.CBSChunk chunk = dataChunks[i]; int channel = chunk.getChannel(); int blackLevel = chunk.getBlackLevel(); float scale = chunk.getScale(); float newBlack = getStackGeoMean(channel, t) + getStackGeoSigma(channel, t) * blackLevel; float scaleMod = scale == 0f ? 0.00001f : scale; float newScale = 255f / (getStackGeoSigma(channel, t) * scaleMod); int newB = Math.round(newBlack); float newS = Math.round(newScale * 100000f) / 100000f; // black-level overcorrection adjustment if (newB < getStackMin(channel, t)) { newB = Math.round((float) Math.ceil(getStackMin(channel, t))); } if (newB > getStackMax(channel, t)) { newB = Math.round((float) Math.floor(getStackMax(channel, t))); } // end black-level overcorrection adjustment // white-level overcorrection adjustment float whiteLevel = getStackGeoMean(channel, t) + dataChunks[i].getScale() * getStackGeoSigma(channel, t); boolean recalculate = false; if (whiteLevel < getStackMin(channel, t)) { whiteLevel = getStackMin(channel, t); recalculate = true; } if (whiteLevel > getStackMax(channel, t)) { whiteLevel = getStackMax(channel, t); recalculate = true; } if (recalculate) { if (whiteLevel - getStackGeoMean(channel, t) == 0f) { whiteLevel += 0.00001f; } newS = 255f / (whiteLevel - getStackGeoMean(channel, t)); } // end white-level correction adjustment newChunks[i] = new ChannelBlackScaleData.CBSChunk(channel, newB, newS); } convertedData.setCBSChunk(ChannelBlackScaleData.RED_CHUNK, newChunks[0]); convertedData.setCBSChunk(ChannelBlackScaleData.GREEN_CHUNK, newChunks[1]); convertedData.setCBSChunk(ChannelBlackScaleData.BLUE_CHUNK, newChunks[2]); convertedData.setCBSChunk(ChannelBlackScaleData.RED_CHUNK, newChunks[3]); cbsMap.put(tObj, convertedData); return convertedData; }