<commit_before>/*
 * #%L
 * SCIFIO library for reading and converting scientific file formats.
 * %%
 * Copyright (C) 2011 - 2013 Open Microscopy Environment:
 *   - Board of Regents of the University of Wisconsin-Madison
 *   - Glencoe Software, Inc.
 *   - University of Dundee
 * %%
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of any organization.
 * #L%
 */

package io.scif.filters;

import io.scif.ByteArrayPlane;
import io.scif.ByteArrayReader;
import io.scif.FormatException;
import io.scif.Plane;
import io.scif.common.DataTools;

import java.io.IOException;
import java.util.Arrays;

import net.imglib2.display.ColorTable;
import net.imglib2.meta.Axes;

import org.scijava.plugin.Attr;
import org.scijava.plugin.Plugin;

/**
 * For indexed color data representing true color, factors out the indices,
 * replacing them with the color table values directly. For all other data
 * (either non-indexed, or indexed with "false color" tables), does nothing. NB:
 * lut length is not guaranteed to be accurate until a plane has been read
 */
@Plugin(
	type = Filter.class,
	priority = ChannelFiller.PRIORITY,
	attrs = {
		@Attr(name = ChannelFiller.FILTER_KEY, value = ChannelFiller.FILTER_VALUE),
		@Attr(name = ChannelFiller.ENABLED_KEY, value = ChannelFiller.ENABLED_VAULE) })
public class ChannelFiller extends AbstractReaderFilter {

	// -- Constants --

	public static final double PRIORITY = 1.0;
	public static final String FILTER_VALUE = "io.scif.Reader";

	// -- Fields --

	/**
	 * Last image index opened.
	 */
	private int lastImageIndex = -1;

	/**
	 * Last plane index opened.
	 */
	private long lastPlaneIndex = -1;

	/**
	 * Cached last plane opened.
	 */
	private Plane lastPlane = null;

	/** Offsets of last plane opened. */
	private long[] lastPlaneOffsets = null;

	/** Lengths of last plane opened. */
	private long[] lastPlaneLengths = null;

	// -- Constructor --

	public ChannelFiller() {
		super(ChannelFillerMetadata.class);
	}

	// -- Filter API Methods --

	@Override
	public boolean isCompatible(final Class<?> c) {
		return ByteArrayReader.class.isAssignableFrom(c);
	}

	// -- Reader API methods --

	@Override
	public Plane openPlane(final int imageIndex, final long planeIndex)
		throws FormatException, IOException
	{
		int planarAxes = getMetadata().get(imageIndex).getPlanarAxisCount();
		return openPlane(imageIndex, planeIndex, new long[planarAxes],
			getMetadata().get(imageIndex).getAxesLengthsPlanar());
	}

	@Override
	public Plane openPlane(final int imageIndex, final long planeIndex,
		final Plane plane) throws FormatException, IOException
	{
		int planarAxes = getMetadata().get(imageIndex).getPlanarAxisCount();
		return openPlane(imageIndex, planeIndex, plane, new long[planarAxes],
			getMetadata().get(imageIndex).getAxesLengthsPlanar());
	}

	@Override
	public Plane openPlane(final int imageIndex, final long planeIndex,
		final long[] offsets, final long[] lengths) throws FormatException,
		IOException
	{
		return openPlane(imageIndex, planeIndex, createPlane(getMetadata().get(
			imageIndex), offsets, lengths), offsets, lengths);
	}

	@Override
	public Plane openPlane(final int imageIndex, final long planeIndex,
		Plane plane, final long[] offsets, final long[] lengths)
		throws FormatException, IOException
	{
		// If the wrapped Metadata wasn't indexed, we can use the parent reader
		// directly
		if (!getParentMeta().get(imageIndex).isIndexed()) {
			if (!haveCached(imageIndex, planeIndex, offsets, lengths)) {
				lastPlaneOffsets = offsets;
				lastPlaneLengths = lengths;
				lastPlaneIndex = planeIndex;
				lastImageIndex = imageIndex;
				lastPlane =
					getParent()
						.openPlane(imageIndex, planeIndex, plane, offsets, lengths);
			}
			return lastPlane;
		}

		// If we have the cached base plane we can use it to expand, otherwise we'll
		// have to open the plane still.
		final int lutLength = ((ChannelFillerMetadata)getMetadata()).getLutLength();

		if (!haveCached(imageIndex, planeIndex, offsets, lengths)) {
			updateLastPlaneInfo(imageIndex, lutLength, offsets, lengths);

			// Now we can read the desired plane
			lastPlane =
				getParent().openPlane(imageIndex, planeIndex, lastPlaneOffsets,
					lastPlaneLengths);
			lastPlaneIndex = planeIndex;
			lastImageIndex = imageIndex;
			lastPlaneOffsets = offsets;
			lastPlaneLengths = lengths;<commit_msg>ChannelFiller: avoid race conditions with the cache<commit_after>/*
 * #%L
 * SCIFIO library for reading and converting scientific file formats.
 * %%
 * Copyright (C) 2011 - 2013 Open Microscopy Environment:
 *   - Board of Regents of the University of Wisconsin-Madison
 *   - Glencoe Software, Inc.
 *   - University of Dundee
 * %%
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of any organization.
 * #L%
 */

package io.scif.filters;

import io.scif.ByteArrayPlane;
import io.scif.ByteArrayReader;
import io.scif.FormatException;
import io.scif.Plane;
import io.scif.common.DataTools;

import java.io.IOException;
import java.util.Arrays;

import net.imglib2.display.ColorTable;
import net.imglib2.meta.Axes;

import org.scijava.plugin.Attr;
import org.scijava.plugin.Plugin;

/**
 * For indexed color data representing true color, factors out the indices,
 * replacing them with the color table values directly. For all other data
 * (either non-indexed, or indexed with "false color" tables), does nothing. NB:
 * lut length is not guaranteed to be accurate until a plane has been read
 */
@Plugin(
	type = Filter.class,
	priority = ChannelFiller.PRIORITY,
	attrs = {
		@Attr(name = ChannelFiller.FILTER_KEY, value = ChannelFiller.FILTER_VALUE),
		@Attr(name = ChannelFiller.ENABLED_KEY, value = ChannelFiller.ENABLED_VAULE) })
public class ChannelFiller extends AbstractReaderFilter {

	// -- Constants --

	public static final double PRIORITY = 1.0;
	public static final String FILTER_VALUE = "io.scif.Reader";

	// -- Fields --

	/**
	 * Last image index opened.
	 */
	private int lastImageIndex = -1;

	/**
	 * Last plane index opened.
	 */
	private long lastPlaneIndex = -1;

	/**
	 * Cached last plane opened.
	 */
	private Plane lastPlane = null;

	/** Offsets of last plane opened. */
	private long[] lastPlaneOffsets = null;

	/** Lengths of last plane opened. */
	private long[] lastPlaneLengths = null;

	// -- Constructor --

	public ChannelFiller() {
		super(ChannelFillerMetadata.class);
	}

	// -- Filter API Methods --

	@Override
	public boolean isCompatible(final Class<?> c) {
		return ByteArrayReader.class.isAssignableFrom(c);
	}

	// -- Reader API methods --

	@Override
	public Plane openPlane(final int imageIndex, final long planeIndex)
		throws FormatException, IOException
	{
		int planarAxes = getMetadata().get(imageIndex).getPlanarAxisCount();
		return openPlane(imageIndex, planeIndex, new long[planarAxes],
			getMetadata().get(imageIndex).getAxesLengthsPlanar());
	}

	@Override
	public Plane openPlane(final int imageIndex, final long planeIndex,
		final Plane plane) throws FormatException, IOException
	{
		int planarAxes = getMetadata().get(imageIndex).getPlanarAxisCount();
		return openPlane(imageIndex, planeIndex, plane, new long[planarAxes],
			getMetadata().get(imageIndex).getAxesLengthsPlanar());
	}

	@Override
	public Plane openPlane(final int imageIndex, final long planeIndex,
		final long[] offsets, final long[] lengths) throws FormatException,
		IOException
	{
		return openPlane(imageIndex, planeIndex, createPlane(getMetadata().get(
			imageIndex), offsets, lengths), offsets, lengths);
	}

	@Override
	public Plane openPlane(final int imageIndex, final long planeIndex,
		Plane plane, final long[] offsets, final long[] lengths)
		throws FormatException, IOException
	{
		// If the wrapped Metadata wasn't indexed, we can use the parent reader
		// directly
		if (!getParentMeta().get(imageIndex).isIndexed()) {
			if (!haveCached(imageIndex, planeIndex, offsets, lengths)) {
				lastPlaneOffsets = Arrays.copyOf(offsets, offsets.length);
				lastPlaneLengths = Arrays.copyOf(lengths, lengths.length);
				lastPlaneIndex = planeIndex;
				lastImageIndex = imageIndex;
				lastPlane =
					getParent()
						.openPlane(imageIndex, planeIndex, plane, offsets, lengths);
			}
			return lastPlane;
		}

		// If we have the cached base plane we can use it to expand, otherwise we'll
		// have to open the plane still.
		final int lutLength = ((ChannelFillerMetadata)getMetadata()).getLutLength();

		if (!haveCached(imageIndex, planeIndex, offsets, lengths)) {
			updateLastPlaneInfo(imageIndex, lutLength, offsets, lengths);

			// Now we can read the desired plane
			lastPlane =
				getParent().openPlane(imageIndex, planeIndex, lastPlaneOffsets,
					lastPlaneLengths);
			lastPlaneIndex = planeIndex;
			lastImageIndex = imageIndex;
			lastPlaneOffsets = Arrays.copyOf(offsets, offsets.length);
			lastPlaneLengths = Arrays.copyOf(lengths, lengths.length);
{'fraction_non_alphanumeric': 0.08840481437531784, 'fraction_numerical': 0.0027123241227326664, 'mean_word_length': 4.237017310252996, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2271751', 'n_tokens_mistral': 3676, 'n_tokens_neox': 3280, 'n_words': 1205}