<commit_before>/* RetinaBackgrondActivityFilter.java
 *
 * Created on October 21, 2005, 12:33 PM */
package net.sf.jaer.eventprocessing.filter;

import java.util.Arrays;
import java.util.Observable;
import java.util.Observer;

import net.sf.jaer.Description;
import net.sf.jaer.DevelopmentStatus;
import net.sf.jaer.chip.AEChip;
import net.sf.jaer.chip.Chip2D;
import net.sf.jaer.event.BasicEvent;
import net.sf.jaer.event.EventPacket;
import net.sf.jaer.eventprocessing.EventFilter2D;

/**
 * An filter that filters out noise according to <NAME>., <NAME>, <NAME>, <NAME>, and <NAME>. 2020. 
 * “HashHeat: An O(C) Complexity Hashing-Based Filter for Dynamic Vision Sensor.” 
 * In 2020 25th Asia and South Pacific Design Automation Conference (ASP-DAC), 452–57. 
 * ieeexplore.ieee.org. https://doi.org/10.1109/ASP-DAC47756.2020.9045268.
 *
 * @author <NAME>, tobi
 */
@Description("Filters out uncorrelated background activity noise according to "
        + "<NAME>., <NAME>, <NAME>, <NAME>, and <NAME>. 2020. 'HashHeat: An O(C) Complexity Hashing-Based Filter for Dynamic Vision Sensor.' "
        + "In 2020 25th Asia and South Pacific Design Automation Conference (ASP-DAC), 452–57. ieeexplore.ieee.org. https://doi.org/10.1109/ASP-DAC47756.2020.9045268..")
@DevelopmentStatus(DevelopmentStatus.Status.InDevelopment)
public class HashHeatNoiseFilter extends AbstractNoiseFilter implements Observer {


    /**
     * the time in timestamp ticks (1us at present) that a spike needs to be
     * supported by a prior event in the neighborhood by to pass through
     */
    private boolean letFirstEventThrough = getBoolean("letFirstEventThrough", true);

    /**
     * the amount to subsample x and y event location by in bit shifts when
     * writing to past event times map. This effectively increases the range of
     * support. E.g. setting subSamplingShift to 1 quadruples range because both
     * x and y are shifted right by one bit
     */
    private int subsampleBy = getInt("subsampleBy", 0);

    int[][] lastTimesMap;
    private int ts = 0; // used to reset filter
    private int sx;
    private int sy;
    private final int DEFAULT_TIMESTAMP=Integer.MIN_VALUE;
    
    private int randomSeed=getInt("randomSeed",0); // seed for hash functions
    private int numHashFunctions=getInt("numHashFunctions",4);
    private int mArrayLength=getInt("mArrayLength",128);
    private int mArrayBits=getInt("mArrayBits",8);
    private int eventCountWindow=getInt("eventCountWindow",5000);

    public HashHeatNoiseFilter(AEChip chip) {
        super(chip);
        chip.addObserver(this);
        initFilter();
        setPropertyTooltip("subsampleBy", "Past events are spatially subsampled (address right shifted) by this many bits");
        setPropertyTooltip("letFirstEventThrough", "After reset, let's first event through; if false, first event from each pixel is blocked");
        setPropertyTooltip("randomSeed", "random seed for hash functions");
        setPropertyTooltip("numHashFunctions", "number of hash functions");
        setPropertyTooltip("mArrayLength", "number of bins of hash function output histogram");
        setPropertyTooltip("mArrayBits", "number of bits in each mArrayHistogramBin");
        setPropertyTooltip("eventCountWindow", "constant-count window length in events");
    }

    
    /**
     * filters in to out. if filtering is enabled, the number of out may be less
     * than the number putString in
     *
     * @param in input events can be null or empty.
     * @return the processed events, may be fewer in number. filtering may occur
     * in place in the in packet.
     */
    @Override
    synchronized public EventPacket filterPacket(EventPacket in) {
        if (lastTimesMap == null) {
            allocateMaps(chip);
        }
        totalEventCount = 0;
        filteredOutEventCount = 0;

        // for each event only keep it if it is within dt of the last time
        // an event happened in the direct neighborhood
        for (Object eIn : in) {
            if (eIn == null) {
                break;  // this can occur if we are supplied packet that has data (eIn.g. APS samples) but no events
            }
            BasicEvent e = (BasicEvent) eIn;
            if (e.isSpecial()) {
                continue;
            }

            totalEventCount++;
            short x = (short) (e.x >>> subsampleBy), y = (short) (e.y >>> subsampleBy);
            if ((x < 0) || (x > sx) || (y < 0) || (y > sy)) {
                filteredOutEventCount++;
                continue;
            }

            ts = e.timestamp;
            int lastT = lastTimesMap[x][y];
            int deltaT = (ts - lastT);

            if (false) {
                e.setFilteredOut(true);
                filteredOutEventCount++;
            }

            // For each event write the event's timestamp into the
            // lastTimesMap array at neighboring locations lastTimesMap[x][y]=ts;
            // Don't write to ourselves, we need support from neighbor for
            // next event.
            // Bounds checking here to avoid throwing expensive exceptions.
            if (((x > 0) && (x < sx)) && ((y > 0) && (y < sy))) {
                lastTimesMap[x - 1][y] = ts;
                lastTimesMap[x + 1][y] = ts;
                lastTimesMap[x][y - 1] = ts;
                lastTimesMap[x][y + 1] = ts;
                lastTimesMap[x - 1][y - 1] = ts;
                lastTimesMap[x + 1][y + 1] = ts;
                lastTimesMap[x - 1][y + 1] = ts;
                lastTimesMap[x + 1][y - 1] = ts;
            }
        }

        return in;
    }

    @Override
    public synchronized final void resetFilter() {
        initFilter();
    }

    @Override
    public void update(Observable o, Object arg) {
        if ((arg != null) && ((arg == Chip2D.EVENT_SIZEX) || (arg == Chip2D.EVENT_SIZEY))) {
            resetFilter();
        }
    }

    @Override
    public final void initFilter() {
        allocateMaps(chip);
        sx = chip.getSizeX() - 1;
        sy = chip.getSizeY() - 1;
    }

    private void allocateMaps(AEChip chip) {<commit_msg>added fields for hashCoefficients<commit_after>/* RetinaBackgrondActivityFilter.java
 *
 * Created on October 21, 2005, 12:33 PM */
package net.sf.jaer.eventprocessing.filter;

import java.util.Arrays;
import java.util.Observable;
import java.util.Observer;

import net.sf.jaer.Description;
import net.sf.jaer.DevelopmentStatus;
import net.sf.jaer.chip.AEChip;
import net.sf.jaer.chip.Chip2D;
import net.sf.jaer.event.BasicEvent;
import net.sf.jaer.event.EventPacket;
import net.sf.jaer.eventprocessing.EventFilter2D;

/**
 * An filter that filters out noise according to <NAME>., <NAME>, <NAME>, <NAME>, and <NAME>. 2020. 
 * “HashHeat: An O(C) Complexity Hashing-Based Filter for Dynamic Vision Sensor.” 
 * In 2020 25th Asia and South Pacific Design Automation Conference (ASP-DAC), 452–57. 
 * ieeexplore.ieee.org. https://doi.org/10.1109/ASP-DAC47756.2020.9045268.
 *
 * @author <NAME>, tobi
 */
@Description("Filters out uncorrelated background activity noise according to "
        + "<NAME>., <NAME>, <NAME>, <NAME>, and <NAME>. 2020. 'HashHeat: An O(C) Complexity Hashing-Based Filter for Dynamic Vision Sensor.' "
        + "In 2020 25th Asia and South Pacific Design Automation Conference (ASP-DAC), 452–57. ieeexplore.ieee.org. https://doi.org/10.1109/ASP-DAC47756.2020.9045268..")
@DevelopmentStatus(DevelopmentStatus.Status.InDevelopment)
public class HashHeatNoiseFilter extends AbstractNoiseFilter implements Observer {


    /**
     * the time in timestamp ticks (1us at present) that a spike needs to be
     * supported by a prior event in the neighborhood by to pass through
     */
    private boolean letFirstEventThrough = getBoolean("letFirstEventThrough", true);

    /**
     * the amount to subsample x and y event location by in bit shifts when
     * writing to past event times map. This effectively increases the range of
     * support. E.g. setting subSamplingShift to 1 quadruples range because both
     * x and y are shifted right by one bit
     */
    private int subsampleBy = getInt("subsampleBy", 0);

    int[][] lastTimesMap;
    private int ts = 0; // used to reset filter
    private int sx;
    private int sy;
    private final int DEFAULT_TIMESTAMP=Integer.MIN_VALUE;
    
    private int randomSeed=getInt("randomSeed",0); // seed for hash functions
    private int numHashFunctions=getInt("numHashFunctions",4);
    private int mArrayLength=getInt("mArrayLength",128);
    private int mArrayBits=getInt("mArrayBits",8);
    private int eventCountWindow=getInt("eventCountWindow",5000);

    private int[][] hashCooeficients;
    private int[][] mArrays;
    private int mArrayResetEventCount=0;
    
    public HashHeatNoiseFilter(AEChip chip) {
        super(chip);
        chip.addObserver(this);
        initFilter();
        setPropertyTooltip("subsampleBy", "Past events are spatially subsampled (address right shifted) by this many bits");
        setPropertyTooltip("letFirstEventThrough", "After reset, let's first event through; if false, first event from each pixel is blocked");
        setPropertyTooltip("randomSeed", "random seed for hash functions");
        setPropertyTooltip("numHashFunctions", "number of hash functions");
        setPropertyTooltip("mArrayLength", "number of bins of hash function output histogram");
        setPropertyTooltip("mArrayBits", "number of bits in each mArrayHistogramBin");
        setPropertyTooltip("eventCountWindow", "constant-count window length in events");
    }

    
    /**
     * filters in to out. if filtering is enabled, the number of out may be less
     * than the number putString in
     *
     * @param in input events can be null or empty.
     * @return the processed events, may be fewer in number. filtering may occur
     * in place in the in packet.
     */
    @Override
    synchronized public EventPacket filterPacket(EventPacket in) {
        if (lastTimesMap == null) {
            allocateMemory(chip);
        }
        totalEventCount = 0;
        filteredOutEventCount = 0;

        // for each event only keep it if it is within dt of the last time
        // an event happened in the direct neighborhood
        for (Object eIn : in) {
            if (eIn == null) {
                break;  // this can occur if we are supplied packet that has data (eIn.g. APS samples) but no events
            }
            BasicEvent e = (BasicEvent) eIn;
            if (e.isSpecial()) {
                continue;
            }

            totalEventCount++;
            short x = (short) (e.x >>> subsampleBy), y = (short) (e.y >>> subsampleBy);
            if ((x < 0) || (x > sx) || (y < 0) || (y > sy)) {
                filteredOutEventCount++;
                continue;
            }

            ts = e.timestamp;
            int lastT = lastTimesMap[x][y];
            int deltaT = (ts - lastT);

            if (false) {
                e.setFilteredOut(true);
                filteredOutEventCount++;
            }

            // For each event write the event's timestamp into the
            // lastTimesMap array at neighboring locations lastTimesMap[x][y]=ts;
            // Don't write to ourselves, we need support from neighbor for
            // next event.
            // Bounds checking here to avoid throwing expensive exceptions.
            if (((x > 0) && (x < sx)) && ((y > 0) && (y < sy))) {
                lastTimesMap[x - 1][y] = ts;
                lastTimesMap[x + 1][y] = ts;
                lastTimesMap[x][y - 1] = ts;
                lastTimesMap[x][y + 1] = ts;
                lastTimesMap[x - 1][y - 1] = ts;
                lastTimesMap[x + 1][y + 1] = ts;
                lastTimesMap[x - 1][y + 1] = ts;
                lastTimesMap[x + 1][y - 1] = ts;
            }
        }

        return in;
    }

    @Override
    public synchronized final void resetFilter() {
        initFilter();
    }

    @Override
    public void update(Observable o, Object arg) {
        if ((arg != null) && ((arg == Chip2D.EVENT_SIZEX) || (arg == Chip2D.EVENT_SIZEY))) {
            resetFilter();
        }
    }

    @Override
    public final void initFilter() {
        allocateMemory(chip);
        sx = chip.getSizeX() - 1;
        sy = chip.getSizeY() - 1;
    }

    private void allocateMemory(AEChip chip) {
{'fraction_non_alphanumeric': 0.10771587519148593, 'fraction_numerical': 0.01975328549544465, 'mean_word_length': 2.4265193370165745, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 45, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2652394', 'n_tokens_mistral': 3804, 'n_tokens_neox': 3490, 'n_words': 1150}