<commit_before>package net.sf.jaer.util.avioutput;

import static net.sf.jaer.graphics.AEViewer.DEFAULT_CHIP_CLASS;
import static net.sf.jaer.graphics.AEViewer.prefs;

import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.BoxLayout;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;

import com.jogamp.opengl.GLAutoDrawable;

import ch.unizh.ini.jaer.projects.davis.frames.ApsFrameExtractor;
import ch.unizh.ini.jaer.projects.npp.DvsFramer.TimeSliceMethod;
import ch.unizh.ini.jaer.projects.npp.DvsFramerSingleFrame;
import ch.unizh.ini.jaer.projects.npp.TargetLabeler;
import ch.unizh.ini.jaer.projects.npp.TargetLabeler.TargetLocation;
import eu.seebetter.ini.chips.DavisChip;
import ml.options.Options;
import ml.options.Options.Multiplicity;
import ml.options.Options.Separator;
import net.sf.jaer.Description;
import net.sf.jaer.DevelopmentStatus;
import net.sf.jaer.aemonitor.AEPacketRaw;
import net.sf.jaer.chip.AEChip;
import net.sf.jaer.chip.EventExtractor2D;
import net.sf.jaer.event.BasicEvent;
import net.sf.jaer.event.EventPacket;
import net.sf.jaer.event.PolarityEvent;
import net.sf.jaer.eventio.AEFileInputStream;
import net.sf.jaer.eventio.AEInputStream;
import net.sf.jaer.eventprocessing.FilterChain;
import net.sf.jaer.graphics.FrameAnnotater;
import net.sf.jaer.graphics.ImageDisplay;
import net.sf.jaer.graphics.MultilineAnnotationTextRenderer;
import net.sf.jaer.util.avioutput.AVIOutputStream.VideoFormat;
import net.sf.jaer.util.filter.LowpassFilter;

/**
 * Writes out AVI movie with DVS time or event slices as AVI frame images with
 * desired output resolution
 *
 * @author <NAME>
 */
@Description("Writes out AVI movie with DVS constant-number-of-event subsampled 2D histogram slices as AVI frame images with desired output resolution")
@DevelopmentStatus(DevelopmentStatus.Status.Stable)
public class DvsSliceAviWriter extends AbstractAviWriter implements FrameAnnotater {

    private DvsFramerSingleFrame dvsFrame = null;
    private ApsFrameExtractor frameExtractor = null;
    private TargetLabeler targetLabeler = null;
    private float frameRateEstimatorTimeConstantMs = getFloat("frameRateEstimatorTimeConstantMs", 10f);
    private JFrame frame = null;
    public ImageDisplay display;
    private boolean showOutput;
    private volatile boolean newApsFrameAvailable = false;
    private int endOfFrameTimestamp = Integer.MIN_VALUE, lastTimestamp = 0;
    protected boolean writeDvsSliceImageOnApsFrame = getBoolean("writeDvsSliceImageOnApsFrame", false);
    private boolean writeDvsFrames = getBoolean("writeDvsFrames", true);
    private boolean writeApsFrames = getBoolean("writeApsFrames", false);
    private boolean writeTargetLocations = getBoolean("writeTargetLocations", true);
    private boolean writeDvsEventsToTextFile = getBoolean("writeDvsEventsToTextFile", false);
    protected static final String EVENTS_SUFFIX = "-events.txt";
    protected FileWriter eventsWriter = null;
    protected File eventsFile = null;
    protected File targetLocationsFile = null;
    private FileWriter targetLocationsWriter = null;
    private boolean rendererPropertyChangeListenerAdded = false;
    private LowpassFilter lowpassFilter = new LowpassFilter(frameRateEstimatorTimeConstantMs);
    private int lastDvsFrameTimestamp = 0;
    private float avgDvsFrameIntervalMs = 0;
    private boolean showStatistics = getBoolean("showStatistics", false);
    private String TARGETS_LOCATIONS_SUFFIX = "-targetLocations.txt";
    private String APS_OUTPUT_SUFFIX = "-aps.avi";
    private String DVS_OUTPUT_SUFFIX = "-dvs.avi"; // used for separate output option
    private BufferedImage aviOutputImage = null; // holds either dvs or aps or both iamges

    public DvsSliceAviWriter(AEChip chip) {
        super(chip);
        FilterChain chain = new FilterChain(chip);
        if (chip instanceof DavisChip) {
            frameExtractor = new ApsFrameExtractor(chip);
            chain.add(frameExtractor);
            frameExtractor.getSupport().addPropertyChangeListener(this);
        }
        targetLabeler = new TargetLabeler(chip);
        chain.add(targetLabeler);
        dvsFrame = new DvsFramerSingleFrame(chip);
        chain.add(dvsFrame);
        setEnclosedFilterChain(chain);
        showOutput = getBoolean("showOutput", true);
        DEFAULT_FILENAME = "DvsEventSlices.avi";
        setPropertyTooltip("showOutput", "shows output in JFrame/ImageDisplay");
        setPropertyTooltip("frameRateEstimatorTimeConstantMs", "time constant of lowpass filter that shows average DVS slice frame rate");
        setPropertyTooltip("writeDvsSliceImageOnApsFrame", "<html>write DVS slice image for each APS frame end event (dvsMinEvents ignored).<br>The frame is written at the end of frame APS event.<br><b>Warning: to capture all frames, ensure that playback time slices are slow enough that all frames are rendered</b>");
        setPropertyTooltip("writeApsFrames", "<html>write APS frames to file<br><b>Warning: to capture all frames, ensure that playback time slices are slow enough that all frames are rendered</b>");
        setPropertyTooltip("writeDvsFrames", "<html>write DVS frames to file<br>");
        setPropertyTooltip("writeTargetLocations", "<html>If TargetLabeler has locations, write them to a file named XXX-targetlocations.txt<br>");
        setPropertyTooltip("writeDvsEventsToTextFile", "<html>write DVS events to text file, one event per line, timestamp, x, y, pol<br>");
        setPropertyTooltip("showStatistics", "shows statistics of DVS frame (most off and on counts, frame rate, sparsity)");
    }

    @Override
    synchronized public EventPacket<?> filterPacket(EventPacket<?> in) {
//        frameExtractor.filterPacket(in); // extracts frames with nornalization (brightness, contrast) and sends to apsNet on each frame in PropertyChangeListener
        // send DVS timeslice to convnet
        super.filterPacket(in);
        frameExtractor.filterPacket(in); // process frame extractor, target labeler and dvsframer
        targetLabeler.filterPacket(in);
        dvsFrame.checkParameters();
        if (aviOutputImage == null || aviOutputImage.getWidth() != getOutputImageWidth() || aviOutputImage.getHeight() != getOutputImageHeight()) {
            aviOutputImage = new BufferedImage(getOutputImageWidth(),
                    dvsFrame.getOutputImageHeight(), BufferedImage.TYPE_INT_BGR);
        }

        checkSubsampler();
        for (BasicEvent e : in) {
            if (e.isSpecial() || e.isFilteredOut()) {
                continue;
            }
            PolarityEvent p = (PolarityEvent) e;
            lastTimestamp = e.timestamp;
            dvsFrame.addEvent(p);
            try {
                writeEvent(p);
            } catch (IOException ex) {
                Logger.getLogger(DvsSliceAviWriter.class.getName()).log(Level.SEVERE, null, ex);
                doCloseFile();
            }
            if ((writeDvsSliceImageOnApsFrame && newApsFrameAvailable && (e.timestamp >= endOfFrameTimestamp))
                    || ((!writeDvsSliceImageOnApsFrame && dvsFrame.getDvsFrame().isFilled())
                    && ((chip.getAeViewer() == null) || !chip.getAeViewer().isPaused()))) { // added check for nonnull aeviewer in case filter is called from separate program<commit_msg>added check for DAVIS to fix crash when using DVS<commit_after>package net.sf.jaer.util.avioutput;

import static net.sf.jaer.graphics.AEViewer.DEFAULT_CHIP_CLASS;
import static net.sf.jaer.graphics.AEViewer.prefs;

import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.BoxLayout;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;

import com.jogamp.opengl.GLAutoDrawable;

import ch.unizh.ini.jaer.projects.davis.frames.ApsFrameExtractor;
import ch.unizh.ini.jaer.projects.npp.DvsFramer.TimeSliceMethod;
import ch.unizh.ini.jaer.projects.npp.DvsFramerSingleFrame;
import ch.unizh.ini.jaer.projects.npp.TargetLabeler;
import ch.unizh.ini.jaer.projects.npp.TargetLabeler.TargetLocation;
import eu.seebetter.ini.chips.DavisChip;
import ml.options.Options;
import ml.options.Options.Multiplicity;
import ml.options.Options.Separator;
import net.sf.jaer.Description;
import net.sf.jaer.DevelopmentStatus;
import net.sf.jaer.aemonitor.AEPacketRaw;
import net.sf.jaer.chip.AEChip;
import net.sf.jaer.chip.EventExtractor2D;
import net.sf.jaer.event.BasicEvent;
import net.sf.jaer.event.EventPacket;
import net.sf.jaer.event.PolarityEvent;
import net.sf.jaer.eventio.AEFileInputStream;
import net.sf.jaer.eventio.AEInputStream;
import net.sf.jaer.eventprocessing.FilterChain;
import net.sf.jaer.graphics.FrameAnnotater;
import net.sf.jaer.graphics.ImageDisplay;
import net.sf.jaer.graphics.MultilineAnnotationTextRenderer;
import net.sf.jaer.util.avioutput.AVIOutputStream.VideoFormat;
import net.sf.jaer.util.filter.LowpassFilter;

/**
 * Writes out AVI movie with DVS time or event slices as AVI frame images with
 * desired output resolution
 *
 * @author <NAME>
 */
@Description("Writes out AVI movie with DVS constant-number-of-event subsampled 2D histogram slices as AVI frame images with desired output resolution")
@DevelopmentStatus(DevelopmentStatus.Status.Stable)
public class DvsSliceAviWriter extends AbstractAviWriter implements FrameAnnotater {

    private DvsFramerSingleFrame dvsFrame = null;
    private ApsFrameExtractor frameExtractor = null;
    private TargetLabeler targetLabeler = null;
    private float frameRateEstimatorTimeConstantMs = getFloat("frameRateEstimatorTimeConstantMs", 10f);
    private JFrame frame = null;
    public ImageDisplay display;
    private boolean showOutput;
    private volatile boolean newApsFrameAvailable = false;
    private int endOfFrameTimestamp = Integer.MIN_VALUE, lastTimestamp = 0;
    protected boolean writeDvsSliceImageOnApsFrame = getBoolean("writeDvsSliceImageOnApsFrame", false);
    private boolean writeDvsFrames = getBoolean("writeDvsFrames", true);
    private boolean writeApsFrames = getBoolean("writeApsFrames", false);
    private boolean writeTargetLocations = getBoolean("writeTargetLocations", true);
    private boolean writeDvsEventsToTextFile = getBoolean("writeDvsEventsToTextFile", false);
    protected static final String EVENTS_SUFFIX = "-events.txt";
    protected FileWriter eventsWriter = null;
    protected File eventsFile = null;
    protected File targetLocationsFile = null;
    private FileWriter targetLocationsWriter = null;
    private boolean rendererPropertyChangeListenerAdded = false;
    private LowpassFilter lowpassFilter = new LowpassFilter(frameRateEstimatorTimeConstantMs);
    private int lastDvsFrameTimestamp = 0;
    private float avgDvsFrameIntervalMs = 0;
    private boolean showStatistics = getBoolean("showStatistics", false);
    private String TARGETS_LOCATIONS_SUFFIX = "-targetLocations.txt";
    private String APS_OUTPUT_SUFFIX = "-aps.avi";
    private String DVS_OUTPUT_SUFFIX = "-dvs.avi"; // used for separate output option
    private BufferedImage aviOutputImage = null; // holds either dvs or aps or both iamges

    public DvsSliceAviWriter(AEChip chip) {
        super(chip);
        FilterChain chain = new FilterChain(chip);
        if (chip instanceof DavisChip) {
            frameExtractor = new ApsFrameExtractor(chip);
            chain.add(frameExtractor);
            frameExtractor.getSupport().addPropertyChangeListener(this);
        }
        targetLabeler = new TargetLabeler(chip);
        chain.add(targetLabeler);
        dvsFrame = new DvsFramerSingleFrame(chip);
        chain.add(dvsFrame);
        setEnclosedFilterChain(chain);
        showOutput = getBoolean("showOutput", true);
        DEFAULT_FILENAME = "DvsEventSlices.avi";
        setPropertyTooltip("showOutput", "shows output in JFrame/ImageDisplay");
        setPropertyTooltip("frameRateEstimatorTimeConstantMs", "time constant of lowpass filter that shows average DVS slice frame rate");
        setPropertyTooltip("writeDvsSliceImageOnApsFrame", "<html>write DVS slice image for each APS frame end event (dvsMinEvents ignored).<br>The frame is written at the end of frame APS event.<br><b>Warning: to capture all frames, ensure that playback time slices are slow enough that all frames are rendered</b>");
        setPropertyTooltip("writeApsFrames", "<html>write APS frames to file<br><b>Warning: to capture all frames, ensure that playback time slices are slow enough that all frames are rendered</b>");
        setPropertyTooltip("writeDvsFrames", "<html>write DVS frames to file<br>");
        setPropertyTooltip("writeTargetLocations", "<html>If TargetLabeler has locations, write them to a file named XXX-targetlocations.txt<br>");
        setPropertyTooltip("writeDvsEventsToTextFile", "<html>write DVS events to text file, one event per line, timestamp, x, y, pol<br>");
        setPropertyTooltip("showStatistics", "shows statistics of DVS frame (most off and on counts, frame rate, sparsity)");
    }

    @Override
    synchronized public EventPacket<?> filterPacket(EventPacket<?> in) {
//        frameExtractor.filterPacket(in); // extracts frames with nornalization (brightness, contrast) and sends to apsNet on each frame in PropertyChangeListener
        // send DVS timeslice to convnet
        super.filterPacket(in);
        if (frameExtractor != null) {
            frameExtractor.filterPacket(in); // process frame extractor, target labeler and dvsframer
        }
        if (targetLabeler != null) {
            targetLabeler.filterPacket(in);
        }
        dvsFrame.checkParameters();
        if (aviOutputImage == null || aviOutputImage.getWidth() != getOutputImageWidth() || aviOutputImage.getHeight() != getOutputImageHeight()) {
            aviOutputImage = new BufferedImage(getOutputImageWidth(),
                    dvsFrame.getOutputImageHeight(), BufferedImage.TYPE_INT_BGR);
        }

        checkSubsampler();
        for (BasicEvent e : in) {
            if (e.isSpecial() || e.isFilteredOut()) {
                continue;
            }
            PolarityEvent p = (PolarityEvent) e;
            lastTimestamp = e.timestamp;
            dvsFrame.addEvent(p);
            try {
                writeEvent(p);
            } catch (IOException ex) {
                Logger.getLogger(DvsSliceAviWriter.class.getName()).log(Level.SEVERE, null, ex);
                doCloseFile();
            }
            if ((writeDvsSliceImageOnApsFrame && newApsFrameAvailable && (e.timestamp >= endOfFrameTimestamp))
                    || ((!writeDvsSliceImageOnApsFrame && dvsFrame.getDvsFrame().isFilled())
                    && ((chip.getAeViewer() == null) || !chip.getAeViewer().isPaused()))) { // added check for nonnull aeviewer in case filter is called from separate program
{'fraction_non_alphanumeric': 0.09352382151173769, 'fraction_numerical': 0.0008811127194914721, 'mean_word_length': 4.112612612612613, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '822622', 'n_tokens_mistral': 4611, 'n_tokens_neox': 4537, 'n_words': 1102}