<commit_before>
package uk.ac.imperial.pseye;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeSupport;
import net.sf.jaer.aemonitor.AEListener;
import net.sf.jaer.aemonitor.AEMonitorInterface;
import net.sf.jaer.aemonitor.AEPacketRaw;
import net.sf.jaer.chip.AEChip;
import net.sf.jaer.hardwareinterface.HardwareInterfaceException;

/**
 * Extends the frame based PSEyeCamera to add packing and return of AEPacketRaw object holding frame data.
 * 
 */
public class PSEyeHardwareInterface extends PSEyeCamera implements AEMonitorInterface {

    /**
     * event supplied to listeners when new events are collected. this is final because it is just a marker for the listeners that new events are available
     */
    public final PropertyChangeEvent newEventPropertyChange = new PropertyChangeEvent(this, "NewEvents", null, null);
    private int frameCounter = 0;
    private long startTimeUs = System.currentTimeMillis() * 1000;
    protected AEChip chip = null;
    protected PropertyChangeSupport support = new PropertyChangeSupport(this);
    private AEPacketRaw packet = new AEPacketRaw(320 * 240);

    public PSEyeHardwareInterface(int cameraIndex) {
        super(cameraIndex);
    }
        
    /**
     * This camera returns frames. 
     * This method returns all frames of image data produced by the data capture thread. 
     * We pack this data into the AEPacketRaw and the 
     * consumer (the event extractor) interprets these to make events.
     * 
     * @return the raw RGBA pixel data from frames of the camera. The pixel data is packed in the AEPacketRaw addresses array. The pixel color data depends on the CameraMode of the CLCamera.
     * The timestamp of the frame is in the first timestamp of the packets timestamp array - the rest of the elements are untouched. The timestamps are untouched except for the first one, which is set to the System.currentTimeMillis*1000-startTimeUs.
     *
     */
    @Override
    public AEPacketRaw acquireAvailableEventsFromDriver() throws HardwareInterfaceException {
        // keep consuming until queue empty
        int nframes = frameManager.getFrameCount();
        if (nframes == 0) return null;
        
        PSEyeFrame frame = null;
        int count = 0;
        int frameSize = 0;
        // loop across available frames
        for (int i = 0; i < nframes; i++) {
            // load frame
            frame = frameManager.popFrame();
            if (frame != null) {
                frameSize = frame.getSize();
                packet.ensureCapacity(count + frameSize);
                
                // copy frame data to passed array
                frame.copyData(packet.getAddresses(), i * frameSize);
                packet.getTimestamps()[i * frameSize] = (int) (frame.getTimeStamp() - startTimeUs);
                
                // put frame back into producer queue
                frameManager.pushFrame(frame);
                frameCounter++; // TODO notify AE listeners here or in thread acquiring frames
                count += frameSize;
            }
        }
        packet.setNumEvents(count);
        support.firePropertyChange(newEventPropertyChange);
        return packet;
    }

    @Override
    public int getNumEventsAcquired() {
        if (packet == null) {
            return 0;
        } else {
            return packet.getNumEvents();
        }
    }

    /** Returns the collected event packet.
     * 
     * @return the packet of raw events, consisting of the pixels values.
     */
    @Override
    public AEPacketRaw getEvents() {
        return packet;
    }

    /** Resets the timestamps to the current system time in ms.
     * 
     */
    @Override
    public void resetTimestamps() {
        frameCounter = 0;
        startTimeUs = System.currentTimeMillis() * 1000;
    }

    @Override
    public boolean overrunOccurred() {
        return false;
    }<commit_msg>Changed code to protect packet synchronisation during resolution change<commit_after>
package uk.ac.imperial.pseye;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeSupport;
import net.sf.jaer.aemonitor.AEListener;
import net.sf.jaer.aemonitor.AEMonitorInterface;
import net.sf.jaer.aemonitor.AEPacketRaw;
import net.sf.jaer.chip.AEChip;
import net.sf.jaer.hardwareinterface.HardwareInterfaceException;

/**
 * Extends the frame based PSEyeCamera to add packing and return of AEPacketRaw object holding frame data.
 * 
 */
public class PSEyeHardwareInterface extends PSEyeCamera implements AEMonitorInterface {

    /**
     * event supplied to listeners when new events are collected. this is final because it is just a marker for the listeners that new events are available
     */
    public final PropertyChangeEvent newEventPropertyChange = new PropertyChangeEvent(this, "NewEvents", null, null);
    private int frameCounter = 0;
    private long startTimeUs = System.currentTimeMillis() * 1000;
    protected AEChip chip = null;
    protected PropertyChangeSupport support = new PropertyChangeSupport(this);
    private PSEyeFramePacketRaw packet = new PSEyeFramePacketRaw(320 * 240);

    public PSEyeHardwareInterface(int cameraIndex) {
        super(cameraIndex);
    }
        
    /**
     * This camera returns frames. 
     * This method returns all frames of image data produced by the data capture thread. 
     * We pack this data into the AEPacketRaw and the 
     * consumer (the event extractor) interprets these to make events.
     * 
     * @return the raw RGBA pixel data from frames of the camera. The pixel data is packed in the AEPacketRaw addresses array. The pixel color data depends on the CameraMode of the CLCamera.
     * The timestamp of the frame is in the first timestamp of the packets timestamp array - the rest of the elements are untouched. The timestamps are untouched except for the first one, which is set to the System.currentTimeMillis*1000-startTimeUs.
     *
     */
    @Override
    public AEPacketRaw acquireAvailableEventsFromDriver() throws HardwareInterfaceException {
        // check manager running
        if (!frameManager.running) return null;
        
        // keep consuming until queue empty
        int nframes = frameManager.getFrameCount();
        if (nframes == 0) return null;
        
        PSEyeFrame frame = null;
        int count = 0;
        packet.nFrames = 0;
        int frameSize = frameManager.frameSize;
        // loop across available frames
        for (int i = 0; i < nframes; i++) {
            // load frame
            frame = frameManager.popFrame();
            if (frame != null) {
                // check to see if resolution change (unlikely but possible here)
                if (frameSize != frame.getSize()) {
                    // if already read frames of diffrent size, break
                    // otherwise rest frame size and continue
                    if (count > 0) 
                        break;
                    else
                        frameSize = frame.getSize();
                }
                packet.ensureCapacity(count + frameSize);
                
                // copy frame data to passed array
                frame.copyData(packet.getAddresses(), i * frameSize);
                packet.getTimestamps()[i * frameSize] = (int) (frame.getTimeStamp() - startTimeUs);
                packet.nFrames++;
                
                // put frame back into producer queue
                frameManager.pushFrame(frame);
                frameCounter++; // TODO notify AE listeners here or in thread acquiring frames
                count += frameSize;
            }
            // check to see if frame manager has been stopped
            if (!frameManager.running) {
                if (count > 0) break;
                else return null;
            }
        }
        packet.frameSize = frameSize;
        packet.setNumEvents(count);
        support.firePropertyChange(newEventPropertyChange);
        return (AEPacketRaw) packet;
    }

    @Override
    public int getNumEventsAcquired() {
        if (packet == null) {
            return 0;
        } else {
            return packet.getNumEvents();
        }
    }

    /** Returns the collected event packet.
     * 
     * @return the packet of raw events, consisting of the pixels values.
     */
    @Override
    public AEPacketRaw getEvents() {
        return (AEPacketRaw) packet;
    }

    /** Resets the timestamps to the current system time in ms.
     * 
     */
    @Override
    public void resetTimestamps() {
        frameCounter = 0;
        startTimeUs = System.currentTimeMillis() * 1000;
    }

    @Override
    public boolean overrunOccurred() {
        return false;
    }
{'fraction_non_alphanumeric': 0.0722629409070087, 'fraction_numerical': 0.005955107650022904, 'mean_word_length': 2.2513030528667164, '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': '5623818', 'n_tokens_mistral': 2297, 'n_tokens_neox': 2180, 'n_words': 782}