<commit_before>/*
 * AEChip.java
 *
 * Created on October 5, 2005, 11:33 AM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */
package net.sf.jaer.chip;

import eu.seebetter.ini.chips.davis.HotPixelFilter;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.BackingStoreException;

import net.sf.jaer.Description;
import net.sf.jaer.event.BasicEvent;
import net.sf.jaer.eventio.AEDataFile;
import net.sf.jaer.eventio.AEFileInputStream;
import net.sf.jaer.eventio.AEFileOutputStream;
import net.sf.jaer.eventprocessing.EventFilter;
import net.sf.jaer.eventprocessing.FilterChain;
import net.sf.jaer.eventprocessing.FilterFrame;
import net.sf.jaer.eventprocessing.filter.BackgroundActivityFilter;
import net.sf.jaer.eventprocessing.filter.Info;
import net.sf.jaer.eventprocessing.filter.RefractoryFilter;
import net.sf.jaer.eventprocessing.filter.RotateFilter;
import net.sf.jaer.eventprocessing.filter.XYTypeFilter;
import net.sf.jaer.graphics.AEChipRenderer;
import net.sf.jaer.graphics.AEViewer;
import net.sf.jaer.graphics.ChipCanvas;
import net.sf.jaer.graphics.ChipRendererDisplayMethod;
import net.sf.jaer.graphics.DisplayMethod;
import net.sf.jaer.graphics.SpaceTimeEventDisplayMethod;
import net.sf.jaer.graphics.SpaceTimeRollingEventDisplayMethod;
import net.sf.jaer.util.avioutput.JaerAviWriter;

/**
 * Describes a generic address-event chip, and includes fields for associated
 * classes like its renderer, its rendering paint surface, file input and output
 * event streams, and the event filters that can operate on its output. A
 * subclass can add it's own default EventFilters so that users need not
 * customize the FilterChain.\
 * <p>
 * The {@link #onRegistration()} and {@link #onDeregistration() } allows
 * arbitrary actions after the chip is constructed and registered in the
 * AEViewer.
 *
 * @author tobi
 */
@Description("Address-Event Chip")
public class AEChip extends Chip2D {

    /** The current and previous event extractors. The previous extractor is set whenever #setEventExtractor is called. */
    protected EventExtractor2D eventExtractor = null, previousEventExtractor = null;
    protected AEChipRenderer renderer = null;
    protected AEFileInputStream aeInputStream = null;
    protected AEFileOutputStream aeOutputStream = null;
    protected FilterChain filterChain = null;
    protected AEViewer aeViewer = null;
    private boolean subSamplingEnabled = getPrefs().getBoolean("AEChip.subSamplingEnabled", false);
    private Class<? extends BasicEvent> eventClass = BasicEvent.class;
    /**
     * List of default EventFilter2D filters
     */
    protected ArrayList<Class> defaultEventFilters = new ArrayList<Class>();
    /**
     * The number of bits on an AE bus used for the raw device address.
     * rawAddressNumBits/16 should set the number of bytes used to read and log
     * captured data. E.g. 16 bits reads and writes <code>short</code>, and 32
     * bits reads and writes <code>int</code>. At present all chips write and
     * read the same address data width, int (32 bits) as of data file format
     * 2.0. Old data files will still be read correctly.
     */
    private int rawAddressNumBits = 16;

    /**
     * @return list of default filter classes
     * @return list of Class default filter classes for this AEChip
     */
    public ArrayList<Class> getDefaultEventFilterClasses() {
        return defaultEventFilters;
    }

    /**
     * return list of default filter class names (strings)
     *
     * @return list of String fully qualified class names
     */
    public ArrayList<String> getDefaultEventFilterClassNames() {
        ArrayList<String> list = new ArrayList<String>();
        for (Class c : defaultEventFilters) {
            list.add(c.getName());
        }
        return list;
    }

    /**
     * add a filter that is available by default
     */
    public void addDefaultEventFilter(Class f) {
        if (!EventFilter.class.isAssignableFrom(f)) {
            log.warning("In trying to addDefaultEventFilter, " + f + " is not an EventFilter, ignoring");
            return;
        }
        defaultEventFilters.add(f);
    }

    /**
     * Creates a new instance of AEChip
     */
    public AEChip() {
//        setName("unnamed AEChip");
        setRenderer(new AEChipRenderer(this));

        // add canvas before filters so that filters have a canvas to add annotator to
        setCanvas(new ChipCanvas(this)); // note that we need to do this again even though Chip2D did it, because the AEChipRenderer here shadows the Chip2D renderer and the renderer will be returned null, preventing installation of mouse listeners
        // instancing there display methods does NOT add them to the menu automatically

        getCanvas().addDisplayMethod(new ChipRendererDisplayMethod(getCanvas()));
        getCanvas().addDisplayMethod(new SpaceTimeEventDisplayMethod(getCanvas()));
        getCanvas().addDisplayMethod(new SpaceTimeRollingEventDisplayMethod(getCanvas()));
//        getCanvas().addDisplayMethod(new Histogram3dDisplayMethod(getCanvas())); // preesntly broken - tobi

        //set default display method
        DisplayMethod m = getPreferredDisplayMethod();
        m.setChipCanvas(getCanvas());
        getCanvas().setDisplayMethod(m);

        // add default filters
        addDefaultEventFilter(XYTypeFilter.class);
        addDefaultEventFilter(RotateFilter.class);
//        addDefaultEventFilter(RepetitiousFilter.class);
        addDefaultEventFilter(BackgroundActivityFilter.class);
//        addDefaultEventFilter(SubSampler.class);
        addDefaultEventFilter(RefractoryFilter.class);
        addDefaultEventFilter(HotPixelFilter.class);
        addDefaultEventFilter(Info.class);
        addDefaultEventFilter(JaerAviWriter.class);

        filterChain = new FilterChain(this);
        filterChain.contructPreferredFilters();
    }

    /**
     * Closes the RemoteControl if there is one.
     */
    @Override
    public void cleanup() {
        super.cleanup();
        if (getRemoteControl() != null) {
            getRemoteControl().close();
        }
    }

    /**
     * Gets the current extractor of the chip.
     *
     * @return the extractor
     */
    public EventExtractor2D getEventExtractor() {
        return eventExtractor;
    }

    /**
     * Sets the EventExtractor2D and notifies Observers with the new extractor.
     * The previousEventExtractor is set to the prior value unless the prior value is null; then it is set to the supplied eventExtractor.
     * This way, the previousEventExtractor is never set to a null.
     *
     * @param eventExtractor the extractor; notifies Observers.
     * @see #previousEventExtractor
     */
    public void setEventExtractor(EventExtractor2D eventExtractor) {
        if(this.eventExtractor!=null) {
            previousEventExtractor = this.eventExtractor;
        } else{
            previousEventExtractor=eventExtractor;
        }
        this.eventExtractor = eventExtractor;
        setChanged();
        notifyObservers(eventExtractor);
    }

    /**
     * This method is used to restore the previous extractor of the chip class,<commit_msg>added TODO about fixing logic of saving/restoring EventExtractor<commit_after>/*
 * AEChip.java
 *
 * Created on October 5, 2005, 11:33 AM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */
package net.sf.jaer.chip;

import eu.seebetter.ini.chips.davis.HotPixelFilter;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.BackingStoreException;

import net.sf.jaer.Description;
import net.sf.jaer.event.BasicEvent;
import net.sf.jaer.eventio.AEDataFile;
import net.sf.jaer.eventio.AEFileInputStream;
import net.sf.jaer.eventio.AEFileOutputStream;
import net.sf.jaer.eventprocessing.EventFilter;
import net.sf.jaer.eventprocessing.FilterChain;
import net.sf.jaer.eventprocessing.FilterFrame;
import net.sf.jaer.eventprocessing.filter.BackgroundActivityFilter;
import net.sf.jaer.eventprocessing.filter.Info;
import net.sf.jaer.eventprocessing.filter.RefractoryFilter;
import net.sf.jaer.eventprocessing.filter.RotateFilter;
import net.sf.jaer.eventprocessing.filter.XYTypeFilter;
import net.sf.jaer.graphics.AEChipRenderer;
import net.sf.jaer.graphics.AEViewer;
import net.sf.jaer.graphics.ChipCanvas;
import net.sf.jaer.graphics.ChipRendererDisplayMethod;
import net.sf.jaer.graphics.DisplayMethod;
import net.sf.jaer.graphics.SpaceTimeEventDisplayMethod;
import net.sf.jaer.graphics.SpaceTimeRollingEventDisplayMethod;
import net.sf.jaer.util.avioutput.JaerAviWriter;

/**
 * Describes a generic address-event chip, and includes fields for associated
 * classes like its renderer, its rendering paint surface, file input and output
 * event streams, and the event filters that can operate on its output. A
 * subclass can add it's own default EventFilters so that users need not
 * customize the FilterChain.\
 * <p>
 * The {@link #onRegistration()} and {@link #onDeregistration() } allows
 * arbitrary actions after the chip is constructed and registered in the
 * AEViewer.
 *
 * @author tobi
 */
@Description("Address-Event Chip")
public class AEChip extends Chip2D {

    /** The current and previous event extractors. The previous extractor is set whenever #setEventExtractor is called. */
    protected EventExtractor2D eventExtractor = null, previousEventExtractor = null;
    protected AEChipRenderer renderer = null;
    protected AEFileInputStream aeInputStream = null;
    protected AEFileOutputStream aeOutputStream = null;
    protected FilterChain filterChain = null;
    protected AEViewer aeViewer = null;
    private boolean subSamplingEnabled = getPrefs().getBoolean("AEChip.subSamplingEnabled", false);
    private Class<? extends BasicEvent> eventClass = BasicEvent.class;
    /**
     * List of default EventFilter2D filters
     */
    protected ArrayList<Class> defaultEventFilters = new ArrayList<Class>();
    /**
     * The number of bits on an AE bus used for the raw device address.
     * rawAddressNumBits/16 should set the number of bytes used to read and log
     * captured data. E.g. 16 bits reads and writes <code>short</code>, and 32
     * bits reads and writes <code>int</code>. At present all chips write and
     * read the same address data width, int (32 bits) as of data file format
     * 2.0. Old data files will still be read correctly.
     */
    private int rawAddressNumBits = 16;

    /**
     * @return list of default filter classes
     * @return list of Class default filter classes for this AEChip
     */
    public ArrayList<Class> getDefaultEventFilterClasses() {
        return defaultEventFilters;
    }

    /**
     * return list of default filter class names (strings)
     *
     * @return list of String fully qualified class names
     */
    public ArrayList<String> getDefaultEventFilterClassNames() {
        ArrayList<String> list = new ArrayList<String>();
        for (Class c : defaultEventFilters) {
            list.add(c.getName());
        }
        return list;
    }

    /**
     * add a filter that is available by default
     */
    public void addDefaultEventFilter(Class f) {
        if (!EventFilter.class.isAssignableFrom(f)) {
            log.warning("In trying to addDefaultEventFilter, " + f + " is not an EventFilter, ignoring");
            return;
        }
        defaultEventFilters.add(f);
    }

    /**
     * Creates a new instance of AEChip
     */
    public AEChip() {
//        setName("unnamed AEChip");
        setRenderer(new AEChipRenderer(this));

        // add canvas before filters so that filters have a canvas to add annotator to
        setCanvas(new ChipCanvas(this)); // note that we need to do this again even though Chip2D did it, because the AEChipRenderer here shadows the Chip2D renderer and the renderer will be returned null, preventing installation of mouse listeners
        // instancing there display methods does NOT add them to the menu automatically

        getCanvas().addDisplayMethod(new ChipRendererDisplayMethod(getCanvas()));
        getCanvas().addDisplayMethod(new SpaceTimeEventDisplayMethod(getCanvas()));
        getCanvas().addDisplayMethod(new SpaceTimeRollingEventDisplayMethod(getCanvas()));
//        getCanvas().addDisplayMethod(new Histogram3dDisplayMethod(getCanvas())); // preesntly broken - tobi

        //set default display method
        DisplayMethod m = getPreferredDisplayMethod();
        m.setChipCanvas(getCanvas());
        getCanvas().setDisplayMethod(m);

        // add default filters
        addDefaultEventFilter(XYTypeFilter.class);
        addDefaultEventFilter(RotateFilter.class);
//        addDefaultEventFilter(RepetitiousFilter.class);
        addDefaultEventFilter(BackgroundActivityFilter.class);
//        addDefaultEventFilter(SubSampler.class);
        addDefaultEventFilter(RefractoryFilter.class);
        addDefaultEventFilter(HotPixelFilter.class);
        addDefaultEventFilter(Info.class);
        addDefaultEventFilter(JaerAviWriter.class);

        filterChain = new FilterChain(this);
        filterChain.contructPreferredFilters();
    }

    /**
     * Closes the RemoteControl if there is one.
     */
    @Override
    public void cleanup() {
        super.cleanup();
        if (getRemoteControl() != null) {
            getRemoteControl().close();
        }
    }

    /**
     * Gets the current extractor of the chip.
     *
     * @return the extractor
     */
    public EventExtractor2D getEventExtractor() {
        return eventExtractor;
    }

    /**
     * Sets the EventExtractor2D and notifies Observers with the new extractor.
     * The previousEventExtractor is set to the prior value unless the prior value is null; then it is set to the supplied eventExtractor.
     * This way, the previousEventExtractor is never set to a null.
     *
     * @param eventExtractor the extractor; notifies Observers.
     * @see #previousEventExtractor
     */
    public void setEventExtractor(EventExtractor2D eventExtractor) {
        if(this.eventExtractor!=null) { // TODO this logic is broken if the original event extractor is set from a base class that this AEChip subclasses, also broken if multiple AEDAT3 files are opened, etc. Job of saving extractor should fall on AEFileInputStream, not AEChip.
            previousEventExtractor = this.eventExtractor;
        } else{
            previousEventExtractor=eventExtractor;
        }
        this.eventExtractor = eventExtractor;
        setChanged();
        notifyObservers(eventExtractor);
    }

    /**
     * This method is used to restore the previous extractor of the chip class,
{'fraction_non_alphanumeric': 0.08447987655908448, 'fraction_numerical': 0.003921820753503922, 'mean_word_length': 3.4102636801814574, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 27, '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': '2342014', 'n_tokens_mistral': 4267, 'n_tokens_neox': 4157, 'n_words': 1289}