Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alternating solver for intensity correction #166

Merged
merged 5 commits into from
Dec 22, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ public class FilterSpec {
private final String className;
private final Map<String, String> parameters;

private transient Class clazz;
private transient Class<?> clazz;

// no-arg constructor needed for JSON deserialization
@SuppressWarnings("unused")
@@ -68,10 +68,10 @@ public Map<String, String> getParameters() {
public Filter buildInstance()
throws IllegalArgumentException {

final Class clazz = getClazz();
final Class<?> clazz = getClazz();
final Object instance;
try {
instance = clazz.newInstance();
instance = clazz.getDeclaredConstructor().newInstance();
} catch (final Exception e) {
throw new IllegalArgumentException("failed to create instance of filter class '" + className + "'", e);
}
@@ -111,7 +111,7 @@ public static FilterSpec forFilter(final Filter filter) {
return new FilterSpec(filter.getClass().getName(), filter.toParametersMap());
}

private Class getClazz() throws IllegalArgumentException {
private Class<?> getClazz() throws IllegalArgumentException {
if (clazz == null) {
if (className == null) {
throw new IllegalArgumentException("no className defined for filter spec");
Original file line number Diff line number Diff line change
@@ -28,6 +28,25 @@ public LinearIntensityMap8BitFilter(final int numberOfRegionRows,
super(numberOfRegionRows, numberOfRegionColumns, coefficientsPerRegion, coefficients);
}

/**
* Merges the current filter with another filter such that the result of the merge is equivalent to applying the
* other filter first and then the current filter.
*
* @param otherFilter An instance of LinearIntensityMap8BitFilter that should be applied first.
*/
public void after(final LinearIntensityMap8BitFilter otherFilter) {
final double[][] otherCoefficients = otherFilter.getCoefficients();

for (int i = 0; i < coefficients.length; ++i) {
final double[] ab = coefficients[i];
final double[] otherAb = otherCoefficients[i];

// chaining of two linear functions of the form y = ax + b
ab[1] = ab[1] + ab[0] * otherAb[1];
ab[0] = ab[0] * otherAb[0];
}
}


/**
* Adapted from render-java-ws-client module implementation of:
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@

import javax.imageio.ImageIO;

import org.janelia.alignment.filter.FilterSpec;
import org.janelia.alignment.spec.TileSpec;
import org.janelia.alignment.util.ImageProcessorCache;
import org.janelia.render.client.solver.visualize.VisualizeTools;
@@ -199,9 +200,13 @@ public static void render(
final ImageProcessorWithMasks impOriginal =
VisualizeTools.getUntransformedProcessorWithMasks(patch, imageProcessorCache);

// apply filters if there are any
final FilterSpec filterSpec = patch.getFilterSpec();
if (filterSpec != null) {
filterSpec.buildInstance().process(impOriginal.ip, scale);
}

/* assemble coordinate transformations and add bounding box offset */
//final CoordinateTransformList< CoordinateTransform > ctl = new CoordinateTransformList< CoordinateTransform >();
//ctl.add( patch.getA() );
final CoordinateTransformList< CoordinateTransform > ctl = patch.getTransformList();
final AffineModel2D affineScale = new AffineModel2D();
affineScale.set( scale, 0, 0, scale, -x * scale, -y * scale );
@@ -212,12 +217,8 @@ public static void render(
// TODO: the last parameter is an integer division; should this be a float dvision instead?
final double s = sampleAverageScale( ctl, width, height, width / meshResolution );
final int mipmapLevel = bestMipmapLevel( s );
//System.out.println( s + " " + mipmapLevel );
final ImageProcessor ipMipmap = Downsampler.downsampleImageProcessor( impOriginal.ip, mipmapLevel );

//new ImagePlus( "impOriginal.ip", impOriginal.ip ).show();
//new ImagePlus( "ipMipmap", ipMipmap ).show();

/* create a target */
final ImageProcessor tp = ipMipmap.createProcessor( targetImage.getWidth(), targetImage.getHeight() );

@@ -265,11 +266,8 @@ public static void render(
alphaPixels = ( byte[] )target.outside.getPixels();

/* convert */
//FloatProcessor fp = impOriginal.ip.convertToFloatProcessor();
//fp.resetMinAndMax();
final double min = 0;//fp.getMin();//patch.getMin();
final double max = 255;//fp.getMax();//patch.getMax();
//System.out.println( min + ", " + max );
final double min = 0;
final double max = 255;
final double a = 1.0 / ( max - min );
final double b = 1.0 / 255.0;

Original file line number Diff line number Diff line change
@@ -17,8 +17,10 @@
import mpicbg.models.NoninvertibleModelException;
import mpicbg.models.TranslationModel1D;

import org.janelia.alignment.filter.Filter;
import org.janelia.alignment.filter.FilterSpec;
import org.janelia.alignment.filter.IntensityMap8BitFilter;
import org.janelia.alignment.filter.LinearIntensityMap8BitFilter;
import org.janelia.alignment.spec.ResolvedTileSpecCollection;
import org.janelia.alignment.spec.TileSpec;
import org.janelia.alignment.spec.stack.StackMetaData;
@@ -246,10 +248,14 @@ private static Map<String, FilterSpec> convertCoefficientsToFilter(

final Map<String, FilterSpec> idToFilterSpec = new HashMap<>();
for (final OnTheFlyIntensity onTheFlyIntensity : corrected) {
final String tileId = onTheFlyIntensity.getTileSpec().getTileId();
final IntensityMap8BitFilter filter = onTheFlyIntensity.toFilter();
final FilterSpec filterSpec = new FilterSpec(filter.getClass().getName(), filter.toParametersMap());
idToFilterSpec.put(tileId, filterSpec);
final TileSpec tileSpec = onTheFlyIntensity.getTileSpec();
final IntensityMap8BitFilter newFilter = onTheFlyIntensity.toFilter();
final FilterSpec existingFilterSpec = tileSpec.getFilterSpec();
if (existingFilterSpec != null) {
checkAndMergeFilters(existingFilterSpec.buildInstance(), newFilter);
}
final FilterSpec filterSpec = new FilterSpec(newFilter.getClass().getName(), newFilter.toParametersMap());
idToFilterSpec.put(tileSpec.getTileId(), filterSpec);
}

return idToFilterSpec;
@@ -277,6 +283,18 @@ private static ArrayList<OnTheFlyIntensity> convertModelsToOtfIntensities(
return correctedOnTheFly;
}

private static void checkAndMergeFilters(final Filter oldFilter, final IntensityMap8BitFilter newFilter) {
if (oldFilter instanceof LinearIntensityMap8BitFilter
&& newFilter instanceof LinearIntensityMap8BitFilter) {
final LinearIntensityMap8BitFilter oldLinearFilter = (LinearIntensityMap8BitFilter) oldFilter;
final LinearIntensityMap8BitFilter newLinearFilter = (LinearIntensityMap8BitFilter) newFilter;
newLinearFilter.after(oldLinearFilter);
} else {
throw new IllegalArgumentException("Cannot merge filters of type " + oldFilter.getClass().getName() +
" and " + newFilter.getClass().getName());
}
}

private static void addFilters(final ResolvedTileSpecCollection rtsc,
final Map<String, FilterSpec> idToFilterSpec) {
idToFilterSpec.forEach((tileId, filterSpec) -> {
Original file line number Diff line number Diff line change
@@ -741,6 +741,7 @@ public static ImageProcessorWithMasks getImage(final TileSpec tileSpec, final do
return imp;
}

// TODO: this does not only visualize but also load data; move it somewhere else?
public static ImageProcessorWithMasks getUntransformedProcessorWithMasks(final TileSpec tileSpec,
final ImageProcessorCache imageProcessorCache) {
final String tileId = tileSpec.getTileId();