<commit_before>#include "ofApp.h"
#include <opencv2/opencv.hpp>

using namespace ofxCv;
using namespace cv;

void ofApp::onCharacterReceived(SSHKeyListenerEventData& e)
{
	keyPressed((int)e.character);
}
//--------------------------------------------------------------
void ofApp::setup(){

    ofLog() << "RPid " << RPiId;
    gui.setup("panel");
    gui.setPosition(650,10);
    gui.add(cutDown.set( "cutDown", 110, 1, 255 ));
    gui.add(fps.set("fps", 16, 1, 30));
    gui.add(learningTime.set("learningTime",100,1,1000));
    gui.add(backgroundThreshold.set("backgroundThreshold",15,1,300));
    gui.add(erodeFactor.set("erodeFactor",0,0,3));
    gui.add(dilateFactor.set("dilateFactor",0,0,3));
    gui.add(medianBlurFactor.set("medianBlur",1,0,5));
    gui.add(minContourArea.set("minContourArea",20, 5, 40));
    gui.add(maxContourArea.set("maxContourArea",(160*120)/3,40, 160*120)); // one third of the screen.
    gui.add(maxContours.set("maxContours", 5, 1, 10));
    ofSetFrameRate(fps);

    filename_save = "RPi_" + RPiId + "_params.json";

    if(ofFile::doesFileExist(filename_save)){
        ofLog(OF_LOG_NOTICE)<< "loading from file" + filename_save << endl;
        gui.loadFromFile(filename_save);
    }

    consoleListener.setup(this);
    consoleListener.startThread(false, false);

    background.setLearningTime(learningTime);
    background.setThresholdValue(backgroundThreshold);

    fps.addListener(this, &ofApp::fpsChanged);
    learningTime.addListener(this, &ofApp::learningTimeChanged);
    backgroundThreshold.addListener(this, &ofApp::backgroundThresholdChanged);

#ifdef __arm__
    cam.setup(160,120,false);//setup camera (w,h,color = true,gray = false);
    cam.setExposureMode(MMAL_PARAM_EXPOSUREMODE_FIXEDFPS);
    //cam.setExposureCompensation(0);
    //cam.setAWBMode(MMAL_PARAM_AWBMODE_OFF);
    //cam.setExposureCompensation(0);
#else
    cam.initGrabber(160,120);
#endif

    sender.setup("192.168.255.255", 8000);
    //sender.setup("127.0.0.1", 8000);
 	receiver.setup(OSC_PORT);
}

static int framenr = 1;

//--------------------------------------------------------------
void ofApp::update(){
    framenr++;
#ifdef __arm__
    frame = Mat(cam.grab());
    stringstream ss;
    ss << "rpi_" << RPiId << ".png";
    if(framenr % 100 == 0) {
      toOf(frame,tosave);

      ofSaveImage(tosave, ss.str());
    }
#else
    ofImage image;

    stringstream filename;
    filename << "images/"<< "file" << framenr << ".png";
    image.loadImage(filename.str());
    image.rotate90(2);
    frame = toCv(image);

#endif

    if (framenr == 130) {
        background.reset();
    }

    if (!frame.empty()) {

        //threshold( frame, frame, cutDown, 255,2 );

        background.update(frame, thresholded);
        thresholded.update();

        frameProcessed = toCv(thresholded);
        medianBlur ( frameProcessed, frameProcessed, medianBlurFactor );
        erode( frameProcessed, frameProcessed, erodeFactor );
        dilate( frameProcessed, frameProcessed, dilateFactor );

        ofPixels pix;
        ofImage img;
        toOf(frameProcessed, pix);
        grayImage.setFromPixels(pix);

        contourFinder.findContours(grayImage, minContourArea, maxContourArea, maxContours, true); // find holes

        ofxOscMessage numContours;
        stringstream addr;
        addr << "/RPi_" << RPiId << "/total_contours/";
        numContours.setAddress(addr.str());
        numContours.addIntArg(contourFinder.nBlobs);
        sender.sendMessage(numContours);

        for (int i = 0; i < contourFinder.nBlobs; i++){

            ofxOscMessage message;
            stringstream messageAddress;
            messageAddress << "/RPi_" << RPiId << "/contour_" << (i + 1) << "/";
            message.setAddress(messageAddress.str());
            float x = contourFinder.blobs[i].boundingRect.x;
            float y = contourFinder.blobs[i].boundingRect.y;
            float width = contourFinder.blobs[i].boundingRect.width;
            float height = contourFinder.blobs[i].boundingRect.height;

            //normalization
            x = x / 160;
            y = y / 120;
            width = width / 160;
            height = height / 120;

            //openGl standard
            x = x + width/2;
            y = y + height /2;
            x = x * 2 - 1;
            y = y * -2 + 1;
            width*=2;
            height*=2;

            if ( y - height/2 < 0 ) {
                message.addFloatArg(x);
                message.addFloatArg(y);
                message.addFloatArg(width);
                message.addFloatArg(height);

                sender.sendMessage(message);
            }

            //ofLog() << x << " and " << y;
        }
    }
	// hide old messages
	for(int i = 0; i < NUM_MSG_STRINGS; i++){
		if(timers[i] < ofGetElapsedTimef()){
			msg_strings[i] = "";
		}
	}

	// check for waiting messages
	while(receiver.hasWaitingMessages()){
		// get the next message
		ofxOscMessage rm;//receivedMessage
		ofxOscMessage sm;//sentMessage
		receiver.getNextMessage(&rm);
                //probably we need to move it out of the update
            if(rm.getAddress() == "/save"){

                gui.saveToFile(filename_save);
            }
            if(rm.getAddress() == "/getParams"){
                sm.setAddress("/allParams");
                sm.addStringArg(RPiId);
                sm.addIntArg(cutDown);
                sm.addIntArg(fps);
                sm.addIntArg(learningTime);
                sm.addIntArg(backgroundThreshold);
                sm.addIntArg(erodeFactor);
                sm.addIntArg(dilateFactor);
                sm.addIntArg(medianBlurFactor);
                sm.addIntArg(minContourArea);
                sm.addIntArg(maxContourArea);
                sm.addIntArg(maxContours);

                sender.sendMessage(sm);
            }
            else if(rm.getAddress() == "/whoIsThere"){
                sm.setAddress("/RPiId");
                sm.addStringArg(RPiId);
                sender.sendMessage(sm);
            }
            else if(rm.getAddress() == "/cutDown" + RPiId){
                cutDown = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/fps" + RPiId){
                fps = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/learningTime" + RPiId){
                learningTime = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/backgroundThreshold" + RPiId){
                backgroundThreshold = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/erodeFactor" + RPiId){
                erodeFactor = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/dilateFactor" + RPiId){
                dilateFactor = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/medianBlurFactor" + RPiId){
                medianBlurFactor = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/minContourArea" + RPiId){
                minContourArea = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/maxContourArea" + RPiId){
                maxContourArea = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/maxContours" + RPiId){
                maxContours = rm.getArgAsInt32(0);
            }
			else if(rm.getAddress() == "/resetBG" + RPiId){
				background.reset();
			}

	}
}

//-- Parameters events listeners

void ofApp::fpsChanged(int &fps) {
    ofSetFrameRate(fps);
}

void ofApp::learningTimeChanged(int &learningTime) {
    background.setLearningTime(learningTime);
}

void ofApp::backgroundThresholdChanged(int &backgroundThreshold) {
    background.setThresholdValue(backgroundThreshold);
}

//--------------------------------------------------------------
void ofApp::draw(){
//#ifdef __arm__
    drawMat(frame,0,0,320,240);
    drawMat(frameProcessed,0,240,320,240);
    thresholded.draw(320, 0,320,240);

    contourFinder.draw(320,240,320,240);

    gui.draw();
//#endif
}

//--------------------------------------------------------------
void ofApp::keyPressed  (int key){
    ofLogVerbose() << "keyPressed: " << key;

    if(key == ' ') {
        background.reset();
    }

    if(key == 'r') {
        framenr = 1;
        ofLog()<< "restarting video";
    }
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){
    //thresh = ofMap(x,0,ofGetWidth(),0,255);
}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
<commit_msg>added load command<commit_after>#include "ofApp.h"
#include <opencv2/opencv.hpp>

using namespace ofxCv;
using namespace cv;

void ofApp::onCharacterReceived(SSHKeyListenerEventData& e)
{
	keyPressed((int)e.character);
}
//--------------------------------------------------------------
void ofApp::setup(){

    ofLog() << "RPid " << RPiId;
    gui.setup("panel");
    gui.setPosition(650,10);
    gui.add(cutDown.set( "cutDown", 110, 1, 255 ));
    gui.add(fps.set("fps", 16, 1, 30));
    gui.add(learningTime.set("learningTime",100,1,1000));
    gui.add(backgroundThreshold.set("backgroundThreshold",15,1,300));
    gui.add(erodeFactor.set("erodeFactor",0,0,3));
    gui.add(dilateFactor.set("dilateFactor",0,0,3));
    gui.add(medianBlurFactor.set("medianBlur",1,0,5));
    gui.add(minContourArea.set("minContourArea",20, 5, 40));
    gui.add(maxContourArea.set("maxContourArea",(160*120)/3,40, 160*120)); // one third of the screen.
    gui.add(maxContours.set("maxContours", 5, 1, 10));
    ofSetFrameRate(fps);

    filename_save = "RPi_" + RPiId + "_params.json";

    if(ofFile::doesFileExist(filename_save)){
        ofLog(OF_LOG_NOTICE)<< "loading from file" + filename_save << endl;
        gui.loadFromFile(filename_save);
    }

    consoleListener.setup(this);
    consoleListener.startThread(false, false);

    background.setLearningTime(learningTime);
    background.setThresholdValue(backgroundThreshold);

    fps.addListener(this, &ofApp::fpsChanged);
    learningTime.addListener(this, &ofApp::learningTimeChanged);
    backgroundThreshold.addListener(this, &ofApp::backgroundThresholdChanged);

#ifdef __arm__
    cam.setup(160,120,false);//setup camera (w,h,color = true,gray = false);
    cam.setExposureMode(MMAL_PARAM_EXPOSUREMODE_FIXEDFPS);
    //cam.setExposureCompensation(0);
    //cam.setAWBMode(MMAL_PARAM_AWBMODE_OFF);
    //cam.setExposureCompensation(0);
#else
    cam.initGrabber(160,120);
#endif

    sender.setup("192.168.255.255", 8000);
    //sender.setup("127.0.0.1", 8000);
 	receiver.setup(OSC_PORT);
}

static int framenr = 1;

//--------------------------------------------------------------
void ofApp::update(){
    framenr++;
#ifdef __arm__
    frame = Mat(cam.grab());
    stringstream ss;
    ss << "rpi_" << RPiId << ".png";
    if(framenr % 100 == 0) {
      toOf(frame,tosave);

      ofSaveImage(tosave, ss.str());
    }
#else
    ofImage image;

    stringstream filename;
    filename << "images/"<< "file" << framenr << ".png";
    image.loadImage(filename.str());
    image.rotate90(2);
    frame = toCv(image);

#endif

    if (framenr == 130) {
        background.reset();
    }

    if (!frame.empty()) {

        //threshold( frame, frame, cutDown, 255,2 );

        background.update(frame, thresholded);
        thresholded.update();

        frameProcessed = toCv(thresholded);
        medianBlur ( frameProcessed, frameProcessed, medianBlurFactor );
        erode( frameProcessed, frameProcessed, erodeFactor );
        dilate( frameProcessed, frameProcessed, dilateFactor );

        ofPixels pix;
        ofImage img;
        toOf(frameProcessed, pix);
        grayImage.setFromPixels(pix);

        contourFinder.findContours(grayImage, minContourArea, maxContourArea, maxContours, true); // find holes

        ofxOscMessage numContours;
        stringstream addr;
        addr << "/RPi_" << RPiId << "/total_contours/";
        numContours.setAddress(addr.str());
        numContours.addIntArg(contourFinder.nBlobs);
        sender.sendMessage(numContours);

        for (int i = 0; i < contourFinder.nBlobs; i++){

            ofxOscMessage message;
            stringstream messageAddress;
            messageAddress << "/RPi_" << RPiId << "/contour_" << (i + 1) << "/";
            message.setAddress(messageAddress.str());
            float x = contourFinder.blobs[i].boundingRect.x;
            float y = contourFinder.blobs[i].boundingRect.y;
            float width = contourFinder.blobs[i].boundingRect.width;
            float height = contourFinder.blobs[i].boundingRect.height;

            //normalization
            x = x / 160;
            y = y / 120;
            width = width / 160;
            height = height / 120;

            //openGl standard
            x = x + width/2;
            y = y + height /2;
            x = x * 2 - 1;
            y = y * -2 + 1;
            width*=2;
            height*=2;

            if ( y - height/2 < 0 ) {
                message.addFloatArg(x);
                message.addFloatArg(y);
                message.addFloatArg(width);
                message.addFloatArg(height);

                sender.sendMessage(message);
            }

            //ofLog() << x << " and " << y;
        }
    }
	// hide old messages
	for(int i = 0; i < NUM_MSG_STRINGS; i++){
		if(timers[i] < ofGetElapsedTimef()){
			msg_strings[i] = "";
		}
	}

	// check for waiting messages
	while(receiver.hasWaitingMessages()){
		// get the next message
		ofxOscMessage rm;//receivedMessage
		ofxOscMessage sm;//sentMessage
		receiver.getNextMessage(&rm);
                //probably we need to move it out of the update
            if(rm.getAddress() == "/save"){

                gui.saveToFile(filename_save);
            }
            if(rm.getAddress() == "/getParams"){
                sm.setAddress("/allParams");
                sm.addStringArg(RPiId);
                sm.addIntArg(cutDown);
                sm.addIntArg(fps);
                sm.addIntArg(learningTime);
                sm.addIntArg(backgroundThreshold);
                sm.addIntArg(erodeFactor);
                sm.addIntArg(dilateFactor);
                sm.addIntArg(medianBlurFactor);
                sm.addIntArg(minContourArea);
                sm.addIntArg(maxContourArea);
                sm.addIntArg(maxContours);

                sender.sendMessage(sm);
            }
            else if(rm.getAddress() == "/whoIsThere"){
                sm.setAddress("/RPiId");
                sm.addStringArg(RPiId);
                sender.sendMessage(sm);
            }
            else if(rm.getAddress() == "/cutDown" + RPiId){
                cutDown = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/fps" + RPiId){
                fps = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/learningTime" + RPiId){
                learningTime = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/backgroundThreshold" + RPiId){
                backgroundThreshold = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/erodeFactor" + RPiId){
                erodeFactor = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/dilateFactor" + RPiId){
                dilateFactor = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/medianBlurFactor" + RPiId){
                medianBlurFactor = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/minContourArea" + RPiId){
                minContourArea = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/maxContourArea" + RPiId){
                maxContourArea = rm.getArgAsInt32(0);
            }
            else if(rm.getAddress() == "/maxContours" + RPiId){
                maxContours = rm.getArgAsInt32(0);
            }
	    else if(rm.getAddress() == "/resetBG" + RPiId){
		background.reset();
	    }
	    else if(rm.getAddress() == "/loadFromFile" + RPiId){
		if(ofFile::doesFileExist(filename_save)){
		    ofLog(OF_LOG_NOTICE) << "loading from file" + filename_save << endl;
		    gui.loadFromFile(filename_save);
		}
		else{
		    ofLog(OF_LOG_NOTICE) << "save file doesn't exist" << endl;
		}
	    }

	}
}

//-- Parameters events listeners

void ofApp::fpsChanged(int &fps) {
    ofSetFrameRate(fps);
}

void ofApp::learningTimeChanged(int &learningTime) {
    background.setLearningTime(learningTime);
}

void ofApp::backgroundThresholdChanged(int &backgroundThreshold) {
    background.setThresholdValue(backgroundThreshold);
}

//--------------------------------------------------------------
void ofApp::draw(){
//#ifdef __arm__
    drawMat(frame,0,0,320,240);
    drawMat(frameProcessed,0,240,320,240);
    thresholded.draw(320, 0,320,240);

    contourFinder.draw(320,240,320,240);

    gui.draw();
//#endif
}

//--------------------------------------------------------------
void ofApp::keyPressed  (int key){
    ofLogVerbose() << "keyPressed: " << key;

    if(key == ' ') {
        background.reset();
    }

    if(key == 'r') {
        framenr = 1;
        ofLog()<< "restarting video";
    }
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){
    //thresh = ofMap(x,0,ofGetWidth(),0,255);
}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
<|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <iomanip>
#include <map>
#include <utility>
#include <unordered_set>

using ull = unsigned long long;

struct LogEntry {
    ull endtime, starttime;
    unsigned int bitrate;
    double streamed, prev_streamed, duration;
};

using LogEntries = std::vector<LogEntry>;

LogEntries reorder(const LogEntries&);
void repl(const LogEntries&, int);
bool compare(const LogEntry&, const LogEntry&);
std::istream &operator >> (std::istream&, LogEntry&);

#ifdef DEBUG
template <typename T>
std::ostream &operator << (std::ostream&, const std::vector<T>&);

std::ostream &operator << (std::ostream&, const LogEntry&);

template <typename F, typename S>
std::ostream &operator << (std::ostream&, const std::pair<F, S>&);
#endif

int main() {

    // Remove synchronization between cstdio and iostream
    std::ios_base::sync_with_stdio(false);
    // Prevent flushing of output stream before each io operation
    std::cin.tie(nullptr);

    LogEntries logEntries;
    int logsize;
    std::cin >> logsize;

    std::copy_n(std::istream_iterator<LogEntry>(std::cin), logsize,
        std::back_inserter(logEntries));

    #ifdef DEBUG
    // std::cout << "\n" << logEntries << "\n\n";
    #endif

    logEntries = std::move(reorder(logEntries));

    #ifdef DEBUG
    std::cout << "Count: " << logEntries.size() << '\n';
    for (auto& ent : logEntries) {
        std::cout << ent << '\n';
    }
    std::cout << "\n\n";
    #endif

    if (std::cin >> logsize) {
        repl(logEntries, logsize);
    }

    return 0;
}

/**
 * @brief Reads time ranges and sells lambourghinis'
 * @details The repl stands for READ-EVALUATE-PRINT-LOOP.
 * This method in particular will read any time range given, determine which log entries
 * fall under this time range. It will then take the streams available under this
 * time range and print what percentage of those streams were fully contained
 * within the range given
 *
 * @param entries The collection of logs. This must have gone through the reorder
 * function before it can be used here
 * @param count The number of queries to expect
 */
void repl(const LogEntries& entries, int count) {
    LogEntries::const_iterator hi, lo;
    LogEntry query;
    std::cout.precision(3);
    std::cout.setf(std::ios_base::fixed);

    for (std::cin >> query.starttime >> query.endtime; count--;
        std::cin >> query.starttime >> query.endtime) {

        std::tie(lo, hi) = std::equal_range(entries.begin(), entries.end(),
            query, compare);

        hi--;
        #ifdef DEBUG
        std::cout << query << std::endl << *lo << std::endl << *hi << std::endl;
        #endif

        if (query.starttime < lo->starttime) {
            query.starttime = lo->starttime;
        }

        if (query.endtime > hi->endtime) {
            query.endtime = hi->endtime;
        }

        if (hi != lo) {
            query.streamed = (hi->prev_streamed - lo->prev_streamed - lo->streamed) +
            ((lo->endtime - query.starttime) / lo->duration * lo->streamed) +
            ((query.endtime - hi->starttime) / hi->duration * hi->streamed);
        } else {
            query.duration = query.endtime - query.starttime;
            query.streamed = query.duration / 1000 * lo->bitrate;
        }
        std::cout << query.streamed << '\n';
    }
}

/**
 * @brief Aranges the logs into non overlapping ranges for easier usage
 * @details The logs are taken one by one and we cut them up into smaller
 * logs which do not overlap. By doing this, it is easier to work with ranges
 * because you don't have to worry about anything they overlap
 *
 * @param entries The initial entries we got as input
 */
LogEntries reorder(const LogEntries &entries) {
    using index_set = std::unordered_set<std::size_t>;

    std::map<ull, index_set> rng_to_entries;
    std::map<ull, index_set>::const_iterator iter;

    for (std::size_t v = 0; v < entries.size(); v++) {
        rng_to_entries[entries[v].starttime].insert(v);
        rng_to_entries[entries[v].endtime].insert(v);
    }

    LogEntries merged;
    index_set main_set, var_set;

    unsigned int curr_bitrate = 0;

    for (iter = rng_to_entries.begin(); ++iter != rng_to_entries.end(); ) {
        --iter;
        LogEntry range = {};
        std::tie(range.starttime, var_set) = *iter++;
        range.endtime = iter->first;
        range.duration = range.endtime - range.starttime;

        // determine all entries that overlap this range
        for (auto &v : var_set) {
            if (main_set.erase(v) == 0) {
                curr_bitrate += entries[v].bitrate;
                main_set.insert(v);
            } else {
                curr_bitrate -= entries[v].bitrate;
            }
        }

        // set the bitrate of this range to be an aggregate of bitrate of the overlaps
        range.bitrate = curr_bitrate;

        // calculate the amount streamed
        range.streamed = range.duration / 1000 * range.bitrate;

        if (!merged.empty()) {
            range.prev_streamed = merged.back().streamed + merged.back().prev_streamed;
        }
        merged.push_back(range);
    }
    return merged;
}

inline bool compare(const LogEntry& lhs, const LogEntry& rhs) {
    return lhs.endtime <= rhs.starttime;
}

std::istream &operator >> (std::istream& iss, LogEntry& entry) {
    iss >> entry.endtime >> entry.duration >> entry.bitrate;
    entry.starttime = entry.endtime - entry.duration;
    return iss;
}

std::ostream &operator << (std::ostream& oss, const LogEntry& entry) {
    oss << "start=" << entry.starttime << ", end=" << entry.endtime
    << ", bitrate(s)=" << entry.bitrate << ", streamed(kb)="
    << std::setprecision(3) << std::fixed << entry.streamed;

    return oss;
}

template <typename F, typename S>
std::ostream &operator << (std::ostream& oss, const std::pair<F, S> &p) {
    return oss << "(First=>" << p.first << ", second=>" << p.second << ")";
}

template <typename T>
std::ostream &operator << (std::ostream& oss, const std::vector<T>& v) {
    for (auto& item : v) {
        oss << item << "\n";
    }
    return oss;
}
<commit_msg>OMG it worked! Runs in 0.26 secs! I will take it!<commit_after>#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <iomanip>
#include <map>
#include <cmath>

struct LogEntry {
    long long time;
    int bitrate;
    double total_streamed;

    operator long long () const { return this->time; }
};

constexpr double MS_PER_SEC = 10 * 10 * 10;

using LogEntries = std::vector<LogEntry>;

void repl(const LogEntries&, std::size_t);
void read_entries(LogEntries&, std::size_t);
LogEntries reorder(LogEntries&);

#ifdef DEBUG
template <typename T>
std::ostream &operator << (std::ostream&, const std::vector<T>&);

std::ostream &operator << (std::ostream&, const LogEntry&);
#endif

int main() {

    // Remove synchronization between cstdio and iostream
    std::ios_base::sync_with_stdio(false);
    // Prevent flushing of output stream before each io operation
    std::cin.tie(nullptr);

    LogEntries logEntries;
    std::size_t logsize;
    std::cin >> logsize;

    read_entries(logEntries, logsize);

    #ifdef DEBUG
    std::cout << "\n" << logEntries << "\n\n";
    #endif

    logEntries = reorder(logEntries);

    #ifdef DEBUG
    std::cout << "Count: " << logEntries.size() << '\n';
    std::cout << logEntries << "\n\n";
    #endif

    if (std::cin >> logsize) {
        repl(logEntries, logsize);
    }

    return 0;
}

/**
 * @brief Reads time ranges and sells lambourghinis'
 * @details The repl stands for READ-EVALUATE-PRINT-LOOP.
 * This method in particular will read any time range given, determine which log entries
 * fall under this time range. It will then take the streams available under this
 * time range and print what percentage of those streams were fully contained
 * within the range given
 *
 * @param entries The collection of logs. This must have gone through the reorder
 * function before it can be used here
 * @param count The number of queries to expect
 */
void repl(const LogEntries& entries, std::size_t count) {
    LogEntries::const_iterator hi, lo;
    long long start, end;
    double streamed;

    std::cout.precision(3);
    std::cout.setf(std::ios_base::fixed);

    for (std::cin >> start >> end; count--; std::cin >> start >> end) {

        lo = std::lower_bound(entries.begin(), entries.end(), start);
        hi = std::upper_bound(lo, entries.end(), end);

        if (hi == entries.end()) {
            end = (hi - 1)->time;
        }

        #ifdef DEBUG
        std::cout << lo->time << " <= " << start << "\n"
        << (hi == entries.end() ? hi - 1 : hi)->time << " >= " << end << std::endl;
        #endif

        streamed = (lo->time - start) / MS_PER_SEC * (lo == entries.begin() ? 0 : (lo - 1)->bitrate)
        + (hi - 1)->total_streamed - lo->total_streamed +
        (end - (hi - 1)->time) / MS_PER_SEC * (hi - 1)->bitrate;

        std::cout << streamed << '\n';
    }
}

/**
 * @brief Aranges the logs into non overlapping ranges for easier usage
 * @details The logs are taken one by one and we cut them up into smaller
 * logs which do not overlap. By doing this, it is easier to work with ranges
 * because you don't have to worry about anything they overlap
 *
 * @param entries The initial entries we got as input
 */
LogEntries reorder(LogEntries &entries) {
    std::sort(entries.begin(), entries.end(),
        [](const LogEntry& lhs, const LogEntry& rhs) {
            return lhs.time < rhs.time;
        });

    LogEntries merged;

    int bits = 0;
    LogEntries::iterator iter;
    LogEntry* prev = nullptr;

    for (iter = entries.begin(); iter != entries.end(); ++iter) {
        bits += iter->bitrate;

        if (prev == nullptr) {
            prev = &(*iter);
            continue;
        }

        if (iter->time == prev->time) {
            prev->bitrate = bits;
            continue;
        }

        iter->total_streamed = prev->total_streamed + (iter->time - prev->time) / MS_PER_SEC * prev->bitrate;
        iter->bitrate = bits;
        merged.push_back(*prev);
        prev = &(*iter);
    }
    prev->bitrate = bits;
    merged.push_back(*prev);

    return merged;
}

void read_entries(LogEntries& vec, std::size_t num) {
    vec.reserve(num << 1);
    long long tm;
    int bit, dur;

    while (num--) {
        std::cin >> tm >> dur >> bit;
        vec.push_back({tm, -bit, 0});
        vec.push_back({tm - dur, bit, 0});
    }
}

std::ostream &operator << (std::ostream& oss, const LogEntry& entry) {
    return oss << "start=" << entry.time << ", bitrate(s)=" << entry.bitrate
    << ", streamed(kb)=" << std::setprecision(3) << std::fixed << entry.total_streamed;
}

template <typename T>
std::ostream &operator << (std::ostream& oss, const std::vector<T>& v) {
    for (auto& item : v) {
        oss << item << "\n";
    }
    return oss;
}
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.11  2000/10/13 13:14:08  hristov
Bug fixes and code cleaning

Revision 1.10  2000/10/02 21:28:13  fca
Removal of useless dependecies via forward declarations

Revision 1.9  2000/07/13 16:41:29  fca
New START corrected for coding conventions

Revision 1.8  2000/03/27 17:24:25  alla
Modifing geometry

Revision 1.6  2000/01/21 15:45:23  fca
New Version from Alla

Revision 1.5  2000/01/19 17:17:15  fca
Introducing a list of lists of hits -- more hits allowed for detector now

Revision 1.4  1999/11/12 15:04:00  fca
Modifications from A.Maevskaya

Revision 1.3  1999/09/29 09:24:29  fca
Introduction of the Copyright and cvs Log

*/

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  START (T-Zero) Detector                                            //
//  This class contains the base procedures for the START     //
//  detector                                                                 //
//                                                                           //
//Begin_Html
/*

The responsible person for this module is
Alla Maevskaia.

*/
//End_Html
//                                                                           //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <iostream.h>
#include <fstream.h>

#include "TMath.h"
#include "TTUBE.h"
#include "TNode.h"
#include "TRandom.h"
#include "TGeometry.h"
#include "TParticle.h"
#include "AliRun.h"
#include "AliSTART.h"
#include "AliSTARTdigit.h"
#include "AliMC.h"
#include "AliSTARThit.h"
#include "AliSTARTvertex.h"

ClassImp(AliSTART)

static  AliSTARTdigit *digits;

//_____________________________________________________________________________
AliSTART::AliSTART()
{
  //
  // Default constructor for class AliSTART
  //
  fIshunt   = 0;
  fHits     = 0;
  fDigits   = 0;
}

//_____________________________________________________________________________
AliSTART::AliSTART(const char *name, const char *title)
       : AliDetector(name,title)
{
  //
  // Standard constructor for START Detector
  //

  //
  // Initialise Hit array
  fHits       = new TClonesArray("AliSTARThit",  405);
  //  gAlice->AddHitList(fHits);
  //  fDigits     = new TClonesArray("AliSTARTdigit",500);

  fIshunt     =  0;
  fIdSens   =  0;
  SetMarkerColor(kRed);
}

//_____________________________________________________________________________
void AliSTART::AddHit(Int_t track, Int_t *vol, Float_t *hits)
{
  //
  // Add a START hit
  //
  TClonesArray &lhits = *fHits;
  new(lhits[fNhits++]) AliSTARThit(fIshunt,track,vol,hits);
}

//_____________________________________________________________________________

void AliSTART::AddDigit(Int_t *tracks,Int_t *digits)
{

  //  Add a START digit to the list

//  printf (" AddDigit*******");
    // TClonesArray &ldigits = *fDigits;
    // new(ldigits[fNdigits++]) AliSTARTdigit(tracks,digits);
}

//_____________________________________________________________________________
void AliSTART::BuildGeometry()
{
  //
  // Build simple ROOT TNode geometry for event display
  //
  TNode *node, *top;
  const int kColorSTART  = 19;
  //
  top=gAlice->GetGeometry()->GetNode("alice");

  // START define the different volumes
  new TRotMatrix("rot999","rot999",  90,0,90,90,180,0);

  new TTUBE("S_STR1","START  volume 1","void",5.,10.7,5.3);
  top->cd();
  node = new TNode("STR1","STR1","S_STR1",0,0,75.,"");
  node->SetLineColor(kColorSTART);
  fNodes->Add(node);

  new TTUBE("S_STR2","START volume 2","void",5.,10.7,5.3);
  top->cd();
  node = new TNode("STR2","STR2","S_STR2",0,0,-75,"rot999");
  node->SetLineColor(kColorSTART);
  fNodes->Add(node);
}

//_____________________________________________________________________________
Int_t AliSTART::DistanceToPrimitive(Int_t px, Int_t py)
{
  //
  // Calculate the distance from the mouse to the START on the screen
  // Dummy routine
  //
  return 9999;
}

//-------------------------------------------------------------------------
void AliSTART::Init()
{
  //
  // Initialis the START after it has been built
  Int_t i;
  //
  printf("\n");
  for(i=0;i<35;i++) printf("*");
  printf(" START_INIT ");
  for(i=0;i<35;i++) printf("*");
  printf("\n");
  //
  // Here the START initialisation code (if any!)
  for(i=0;i<80;i++) printf("*");
  printf("\n");
  //
  //
  //  fIdSensRad=gMC->VolId("PTOP");
  //  fIdSensPC =gMC->VolId("T0PC");

}

//---------------------------------------------------------------------------
void AliSTART::MakeBranch(Option_t* option)
{
  //
  // Specific START branches
  //
  AliSTARTdigit *digits;
  // Create Tree branches for the START.
  Int_t buffersize = 400;
  char branchname[10];
  sprintf(branchname,"%s",GetName());

  AliDetector::MakeBranch(option);

  TTree *td = gAlice->TreeD();
  digits = new AliSTARTdigit();
  td->Branch(branchname,"AliSTARTdigit",digits, buffersize);
  printf("Making Branch %s for digits\n",branchname);

/*
  gAlice->TreeR()->Branch(branchname,"Int_t",&fZposit, buffersize);
  printf("Making Branch %s for vertex position %d\n",branchname);
  */
}

//_____________________________________________________________________________

void AliSTART::Hit2digit(Int_t evnum)
{
  //
  // From hits to digits
  //
  Float_t x,y,e;
  Int_t nbytes = 0;
  Int_t hit;
  Int_t nhits;
  Int_t volume,pmt;
  char nameTH[8],nameTD[8];
  Float_t timediff,timeright,timeleft,timeav;
  Float_t besttimeright,besttimeleft,meanTime;
  Int_t channelWidth=10;

  TParticle *particle;
  AliSTARThit  *startHit;

  Int_t buffersize=256;
  Int_t split=1;

  digits= new AliSTARTdigit();
  TBranch *bDig=0;

 // Event ------------------------- LOOP

    sprintf(nameTD,"TreeD%d",evnum);
    TTree *td = new TTree(nameTD,"START");
    bDig = td->Branch("START","AliSTARTdigit",&digits,buffersize,split);

    besttimeright=9999.;
    besttimeleft=9999.;
    Int_t timeDiff=0;
    Int_t timeAv=0;

    Int_t nparticles = gAlice->GetEvent(evnum);
    if (nparticles <= 0) return;
    printf("\n nparticles %d\n",nparticles);

    TClonesArray *particles = gAlice->Particles();

    sprintf(nameTH,"TreeH%d",evnum);
    printf("%s\n",nameTH);
    TTree *th = gAlice->TreeH();
    Int_t ntracks    = (Int_t) th->GetEntries();
    if (ntracks<=0) return;
    // Start loop on tracks in the hits containers
    for (Int_t track=0; track<ntracks;track++) {
      gAlice->ResetHits();
      nbytes += th->GetEvent(track);
      particle=(TParticle*)particles->UncheckedAt(track);
      nhits =fHits->GetEntriesFast();

      for (hit=0;hit<nhits;hit++) {
	startHit   = (AliSTARThit*)fHits->UncheckedAt(hit);
	pmt=startHit->fPmt;
	e=startHit->fEtot;
	x=startHit->X();
	y=startHit->Y();
	volume = startHit->fVolume;
	if(volume==1){
	  timeright = startHit->fTime;
	  if(timeright<besttimeright) {
	    besttimeright=timeright;
	  } //timeright
	}//time for right shoulder
	if(volume==2){
	  timeleft = startHit->fTime;
	  //                printf("timeleft %f\n",timeleft);
	  if(timeleft<besttimeleft) {
	    besttimeleft=timeleft;
	  } //timeleftbest
	}//time for left shoulder
      } //hit loop
    } //track loop

    //folding with experimental time distribution
    Float_t besttimerightGaus=gRandom->Gaus(besttimeright,0.05);
    Float_t besttimeleftGaus=gRandom->Gaus(besttimeleft,0.05);
    timediff=besttimerightGaus-besttimeleftGaus;
    meanTime=(besttimerightGaus+besttimeleftGaus)/2.;
    if ( TMath::Abs(timediff)<2. && meanTime<3.)
     {
       //we assume centre of bunch is 5ns after TTS signal
       //TOF values are relative of the end of bunch
       Float_t ppBunch=25;

       ppBunch=ppBunch-10/2;
       Float_t t1=1000.*besttimeleftGaus;
       Float_t t2=1000.*besttimerightGaus;
       t1=t1/channelWidth+ppBunch; //time in ps to channelWidth
       t2=t2/channelWidth+ppBunch; //time in ps to channelWidth

       timeav=(t1+t2)/2.;

       // Time to TDC signal
       // 256 channels for timediff, range 1ns

       timediff=128+1000*timediff/channelWidth; // time in ps

       timeAv = (Int_t)(timeav);   // time (ps) channel numbres
       timeDiff = (Int_t)(timediff); // time ( ps) channel numbres
       digits->Set(timeAv,timeDiff);
     }
       else
	 {timeAv=999999; timeDiff=99999;}
       td->Fill();
       digits->MyDump();
       printf("digits-> %d \n",digits->GetTime());
       td->Write();
       //     } //timediff

} // end macro

<commit_msg>Quick fix to avoid crash in display waiting for new version<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.12  2000/12/04 08:48:19  alibrary
Fixing problems in the HEAD

Revision 1.11  2000/10/13 13:14:08  hristov
Bug fixes and code cleaning

Revision 1.10  2000/10/02 21:28:13  fca
Removal of useless dependecies via forward declarations

Revision 1.9  2000/07/13 16:41:29  fca
New START corrected for coding conventions

Revision 1.8  2000/03/27 17:24:25  alla
Modifing geometry

Revision 1.6  2000/01/21 15:45:23  fca
New Version from Alla

Revision 1.5  2000/01/19 17:17:15  fca
Introducing a list of lists of hits -- more hits allowed for detector now

Revision 1.4  1999/11/12 15:04:00  fca
Modifications from A.Maevskaya

Revision 1.3  1999/09/29 09:24:29  fca
Introduction of the Copyright and cvs Log

*/

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  START (T-Zero) Detector                                            //
//  This class contains the base procedures for the START     //
//  detector                                                                 //
//                                                                           //
//Begin_Html
/*

The responsible person for this module is
Alla Maevskaia.

*/
//End_Html
//                                                                           //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <iostream.h>
#include <fstream.h>

#include "TMath.h"
#include "TTUBE.h"
#include "TNode.h"
#include "TRandom.h"
#include "TGeometry.h"
#include "TParticle.h"
#include "AliRun.h"
#include "AliSTART.h"
#include "AliSTARTdigit.h"
#include "AliMC.h"
#include "AliSTARThit.h"
#include "AliSTARTvertex.h"

ClassImp(AliSTART)

static  AliSTARTdigit *digits;

//_____________________________________________________________________________
AliSTART::AliSTART()
{
  //
  // Default constructor for class AliSTART
  //
  fIshunt   = 0;
  fHits     = 0;
  fDigits   = 0;
}

//_____________________________________________________________________________
AliSTART::AliSTART(const char *name, const char *title)
       : AliDetector(name,title)
{
  //
  // Standard constructor for START Detector
  //

  //
  // Initialise Hit array
  fHits       = new TClonesArray("AliSTARThit",  405);
  gAlice->AddHitList(fHits);
  //  fDigits     = new TClonesArray("AliSTARTdigit",500);

  fIshunt     =  0;
  fIdSens   =  0;
  SetMarkerColor(kRed);
}

//_____________________________________________________________________________
void AliSTART::AddHit(Int_t track, Int_t *vol, Float_t *hits)
{
  //
  // Add a START hit
  //
  TClonesArray &lhits = *fHits;
  new(lhits[fNhits++]) AliSTARThit(fIshunt,track,vol,hits);
}

//_____________________________________________________________________________

void AliSTART::AddDigit(Int_t *tracks,Int_t *digits)
{

  //  Add a START digit to the list

//  printf (" AddDigit*******");
    // TClonesArray &ldigits = *fDigits;
    // new(ldigits[fNdigits++]) AliSTARTdigit(tracks,digits);
}

//_____________________________________________________________________________
void AliSTART::BuildGeometry()
{
  //
  // Build simple ROOT TNode geometry for event display
  //
  TNode *node, *top;
  const int kColorSTART  = 19;
  //
  top=gAlice->GetGeometry()->GetNode("alice");

  // START define the different volumes
  new TRotMatrix("rot999","rot999",  90,0,90,90,180,0);

  new TTUBE("S_STR1","START  volume 1","void",5.,10.7,5.3);
  top->cd();
  node = new TNode("STR1","STR1","S_STR1",0,0,75.,"");
  node->SetLineColor(kColorSTART);
  fNodes->Add(node);

  new TTUBE("S_STR2","START volume 2","void",5.,10.7,5.3);
  top->cd();
  node = new TNode("STR2","STR2","S_STR2",0,0,-75,"rot999");
  node->SetLineColor(kColorSTART);
  fNodes->Add(node);
}

//_____________________________________________________________________________
Int_t AliSTART::DistanceToPrimitive(Int_t px, Int_t py)
{
  //
  // Calculate the distance from the mouse to the START on the screen
  // Dummy routine
  //
  return 9999;
}

//-------------------------------------------------------------------------
void AliSTART::Init()
{
  //
  // Initialis the START after it has been built
  Int_t i;
  //
  printf("\n");
  for(i=0;i<35;i++) printf("*");
  printf(" START_INIT ");
  for(i=0;i<35;i++) printf("*");
  printf("\n");
  //
  // Here the START initialisation code (if any!)
  for(i=0;i<80;i++) printf("*");
  printf("\n");
  //
  //
  //  fIdSensRad=gMC->VolId("PTOP");
  //  fIdSensPC =gMC->VolId("T0PC");

}

//---------------------------------------------------------------------------
void AliSTART::MakeBranch(Option_t* option)
{
  //
  // Specific START branches
  //
  AliSTARTdigit *digits;
  // Create Tree branches for the START.
  Int_t buffersize = 400;
  char branchname[10];
  sprintf(branchname,"%s",GetName());

  AliDetector::MakeBranch(option);

  TTree *td = gAlice->TreeD();
  digits = new AliSTARTdigit();
  td->Branch(branchname,"AliSTARTdigit",digits, buffersize);
  printf("Making Branch %s for digits\n",branchname);

/*
  gAlice->TreeR()->Branch(branchname,"Int_t",&fZposit, buffersize);
  printf("Making Branch %s for vertex position %d\n",branchname);
  */
}

//_____________________________________________________________________________

void AliSTART::Hit2digit(Int_t evnum)
{
  //
  // From hits to digits
  //
  Float_t x,y,e;
  Int_t nbytes = 0;
  Int_t hit;
  Int_t nhits;
  Int_t volume,pmt;
  char nameTH[8],nameTD[8];
  Float_t timediff,timeright,timeleft,timeav;
  Float_t besttimeright,besttimeleft,meanTime;
  Int_t channelWidth=10;

  TParticle *particle;
  AliSTARThit  *startHit;

  Int_t buffersize=256;
  Int_t split=1;

  digits= new AliSTARTdigit();
  TBranch *bDig=0;

 // Event ------------------------- LOOP

    sprintf(nameTD,"TreeD%d",evnum);
    TTree *td = new TTree(nameTD,"START");
    bDig = td->Branch("START","AliSTARTdigit",&digits,buffersize,split);

    besttimeright=9999.;
    besttimeleft=9999.;
    Int_t timeDiff=0;
    Int_t timeAv=0;

    Int_t nparticles = gAlice->GetEvent(evnum);
    if (nparticles <= 0) return;
    printf("\n nparticles %d\n",nparticles);

    TClonesArray *particles = gAlice->Particles();

    sprintf(nameTH,"TreeH%d",evnum);
    printf("%s\n",nameTH);
    TTree *th = gAlice->TreeH();
    Int_t ntracks    = (Int_t) th->GetEntries();
    if (ntracks<=0) return;
    // Start loop on tracks in the hits containers
    for (Int_t track=0; track<ntracks;track++) {
      gAlice->ResetHits();
      nbytes += th->GetEvent(track);
      particle=(TParticle*)particles->UncheckedAt(track);
      nhits =fHits->GetEntriesFast();

      for (hit=0;hit<nhits;hit++) {
	startHit   = (AliSTARThit*)fHits->UncheckedAt(hit);
	pmt=startHit->fPmt;
	e=startHit->fEtot;
	x=startHit->X();
	y=startHit->Y();
	volume = startHit->fVolume;
	if(volume==1){
	  timeright = startHit->fTime;
	  if(timeright<besttimeright) {
	    besttimeright=timeright;
	  } //timeright
	}//time for right shoulder
	if(volume==2){
	  timeleft = startHit->fTime;
	  //                printf("timeleft %f\n",timeleft);
	  if(timeleft<besttimeleft) {
	    besttimeleft=timeleft;
	  } //timeleftbest
	}//time for left shoulder
      } //hit loop
    } //track loop

    //folding with experimental time distribution
    Float_t besttimerightGaus=gRandom->Gaus(besttimeright,0.05);
    Float_t besttimeleftGaus=gRandom->Gaus(besttimeleft,0.05);
    timediff=besttimerightGaus-besttimeleftGaus;
    meanTime=(besttimerightGaus+besttimeleftGaus)/2.;
    if ( TMath::Abs(timediff)<2. && meanTime<3.)
     {
       //we assume centre of bunch is 5ns after TTS signal
       //TOF values are relative of the end of bunch
       Float_t ppBunch=25;

       ppBunch=ppBunch-10/2;
       Float_t t1=1000.*besttimeleftGaus;
       Float_t t2=1000.*besttimerightGaus;
       t1=t1/channelWidth+ppBunch; //time in ps to channelWidth
       t2=t2/channelWidth+ppBunch; //time in ps to channelWidth

       timeav=(t1+t2)/2.;

       // Time to TDC signal
       // 256 channels for timediff, range 1ns

       timediff=128+1000*timediff/channelWidth; // time in ps

       timeAv = (Int_t)(timeav);   // time (ps) channel numbres
       timeDiff = (Int_t)(timediff); // time ( ps) channel numbres
       digits->Set(timeAv,timeDiff);
     }
       else
	 {timeAv=999999; timeDiff=99999;}
       td->Fill();
       digits->MyDump();
       printf("digits-> %d \n",digits->GetTime());
       td->Write();
       //     } //timediff

} // end macro

<|endoftext|>


<commit_before>//********************************************************************
//     Example of the reconstruction that generates the ESD
// Input files:
//   a) file containing the ITS clusters
//      (the AliITSFindClustersV2.C macro can be used to generate it)
//   b) file containing the TPC clusters
//      (the AliTPCFindClusters.C macro can be used to generate it)
//   c) file containing the TRD clusters
//      (the AliTRDdigits2cluster.C macro can be used to generate it)
//   d) file containing the TOF digits
//      (the AliTOFSDigits2Digits.C macro can be used to generate it)
// Ouput file:
//      AliESDs.root containing the ESD events
//
// Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
//********************************************************************

#if !defined(__CINT__) || defined(__MAKECINT__)
  #include <Riostream.h>
  #include "TFile.h"
  #include "TSystem.h"
  #include "TStopwatch.h"
  #include "TArrayF.h"

  #include "AliMagF.h"
  #include "AliRun.h"
  #include "AliRunLoader.h"
  #include "AliLoader.h"
  #include "AliHeader.h"
  #include "AliGenEventHeader.h"

  #include "AliESD.h"
  #include "AliESDpid.h"

  #include "AliITS.h"
  #include "AliITSgeom.h"
  #include "AliITStrackerV2.h"
  #include "AliV0vertexer.h"
  #include "AliCascadeVertexer.h"
  #include "AliITSpidESD.h"
  #include "AliITSLoader.h"

  #include "AliTPCParam.h"
  #include "AliTPCtracker.h"
  #include "AliTPCpidESD.h"
  #include "AliTPCLoader.h"

  #include "AliTRDtracker.h"
  #include "AliTRDPartID.h"

  #include "AliTOFpidESD.h"
  #include "AliTOF.h"
  #include "AliTOFGeometry.h"
#endif

extern AliRun *gAlice;
extern TFile *gFile;

Int_t AliESDtest(Int_t nev=1,Int_t run=0) {

/**** Initialization of the NewIO *******/

   if (gAlice) {
      delete gAlice->GetRunLoader();
      delete gAlice;
      gAlice=0;
   }

   AliRunLoader *rl = AliRunLoader::Open("galice.root");
   if (rl == 0x0) {
      cerr<<"Can not open session"<<endl;
      return 1;
   }
   Int_t retval = rl->LoadgAlice();
   if (retval) {
      cerr<<"AliESDtest.C : LoadgAlice returned error"<<endl;
      delete rl;
      return 1;
   }
   retval = rl->LoadHeader();
   if (retval) {
      cerr<<"AliESDtest.C : LoadHeader returned error"<<endl;
      delete rl;
      return 2;
   }
   gAlice=rl->GetAliRun();

   AliKalmanTrack::SetConvConst(
      1000/0.299792458/gAlice->Field()->SolenoidField()
   );

/**** The ITS corner ********************/

   AliITSLoader* itsl = (AliITSLoader*)rl->GetLoader("ITSLoader");
   if (itsl == 0x0) {
      cerr<<"AliESDtest.C : Can not get the ITS loader"<<endl;
      return 3;
   }
   itsl->LoadRecPoints("read");

   AliITS *dITS = (AliITS*)gAlice->GetDetector("ITS");
   if (!dITS) {
      cerr<<"AliESDtest.C : Can not find the ITS detector !"<<endl;
      return 4;
   }
   AliITSgeom *geom = dITS->GetITSgeom();

   //An instance of the ITS tracker
   AliITStrackerV2 itsTracker(geom);

   //An instance of the ITS PID maker
   Double_t parITS[]={35.5,0.11,10.};
   AliITSpidESD itsPID(parITS);

   //An instance of the V0 finder
   Double_t cuts[]={33,  // max. allowed chi2
                    0.16,// min. allowed negative daughter's impact parameter
                    0.05,// min. allowed positive daughter's impact parameter
                    0.080,// max. allowed DCA between the daughter tracks
                    0.998,// max. allowed cosine of V0's pointing angle
                    0.9,  // min. radius of the fiducial volume
                    2.9   // max. radius of the fiducial volume
                   };
   AliV0vertexer vtxer(cuts);

   Double_t cts[]={33.,    // max. allowed chi2
                    0.05,   // min. allowed V0 impact parameter
                    0.008,  // window around the Lambda mass
                    0.035,  // min. allowed bachelor's impact parameter
                    0.10,   // max. allowed DCA between a V0 and a track
                    0.9985, //max. allowed cosine of the cascade pointing angle
                    0.9,    // min. radius of the fiducial volume
                    2.9     // max. radius of the fiducial volume
                   };
   AliCascadeVertexer cvtxer=AliCascadeVertexer(cts);

/**** The TPC corner ********************/

   AliTPCLoader* tpcl = (AliTPCLoader*)rl->GetLoader("TPCLoader");
   if (tpcl == 0x0) {
      cerr<<"AliESDtest.C : can not get the TPC loader"<<endl;
      return 5;
   }
   tpcl->LoadRecPoints("read");

   rl->CdGAFile();
   AliTPCParam *par=(AliTPCParam *)gDirectory->Get("75x40_100x60_150x60");
   if (!par) {
      cerr<<"TPC parameters have not been found !\n";
      return 6;
   }

   //An instance of the TPC tracker
   AliTPCtracker tpcTracker(par);

   //An instance of the TPC PID maker
   Double_t parTPC[]={45.0,0.08,10.};
   AliTPCpidESD tpcPID(parTPC);

/**** The TRD corner ********************/

   AliLoader* trdl = rl->GetLoader("TRDLoader");
   if (trdl == 0x0) {
      cerr<<"AliESDtest.C : can not get the TRD loader"<<endl;
      return 5;
   }
   trdl->LoadRecPoints("read");

   //An instance of the TRD tracker
   rl->CdGAFile();
   AliTRDtracker trdTracker(gFile);  //galice.root file

/*
   //An instance of the TRD PID maker
   TFile* pidFile = TFile::Open("pid.root");
   if (!pidFile->IsOpen()) {
     cerr << "Can't get pid.root !\n";
     return 7;
   }
   AliTRDPartID* trdPID = (AliTRDPartID*) pidFile->Get("AliTRDPartID");
   if (!trdPID) {
     cerr << "Can't get PID object !\n";
     return 8;
   }
*/

/**** The TOF corner ********************/
   AliTOF *dTOF = (AliTOF*)gAlice->GetDetector("TOF");
   if (!dTOF) {
      cerr<<"AliESDtest.C : Can not find the TOF detector !"<<endl;
      return 4;
   }
   AliTOFGeometry *tofGeo = dTOF->GetGeometry();
   if (!tofGeo) {
      cerr<<"AliESDtest.C : Can not find the TOF geometry !"<<endl;
      return 4;
   }

   AliLoader* tofl = rl->GetLoader("TOFLoader");
   if (tofl == 0x0) {
      cerr<<"AliESDtest.C : can not get the TOF loader"<<endl;
      return 5;
   }
   tofl->LoadDigits("read");

   //Instance of the TOF PID maker
   Double_t parTOF[]={130.,5.};
   AliTOFpidESD tofPID(parTOF);

   //rl->UnloadgAlice();

   TFile *ef=TFile::Open("AliESDs.root","RECREATE");
   if (!ef->IsOpen()) {cerr<<"Can't AliESDs.root !\n"; return 1;}

   TStopwatch timer;
   Int_t rc=0;
   if (nev>rl->GetNumberOfEvents()) nev=rl->GetNumberOfEvents();
   //The loop over events
   for (Int_t i=0; i<nev; i++) {
     cerr<<"\n\nProcessing event number : "<<i<<endl;
     AliESD *event=new AliESD();
     event->SetRunNumber(run);
     event->SetEventNumber(i);

     rl->GetEvent(i);

//***** Primary vertex reconstruction (MC vertex position, for the moment)
     TArrayF v(3);
     rl->GetHeader()->GenEventHeader()->PrimaryVertex(v);
     Double_t vtx[3]={v[0],v[1],v[2]};
     Double_t cvtx[6]={
       0.005,
       0.000, 0.005,
       0.000, 0.000, 0.010
     };
     event->SetVertex(vtx,cvtx);
     cvtx[1]=cvtx[0]; cvtx[2]=cvtx[5]; //trackers use only the diag.elements

//***** Initial path towards the primary vertex
     tpcTracker.SetVertex(vtx,cvtx);
     TTree *tpcTree=tpcl->TreeR();
     if (!tpcTree) {
        cerr<<"Can't get the TPC cluster tree !\n";
        return 4;
     }
     tpcTracker.LoadClusters(tpcTree);
     rc+=tpcTracker.Clusters2Tracks(event);

     itsTracker.SetVertex(vtx,cvtx);
     TTree *itsTree=itsl->TreeR();
     if (!itsTree) {
        cerr<<"Can't get the ITS cluster tree !\n";
        return 4;
     }
     itsTracker.LoadClusters(itsTree);
     rc+=itsTracker.Clusters2Tracks(event);

//***** Back propagation towards the outer barrel detectors
     rc+=itsTracker.PropagateBack(event);

     rc+=tpcTracker.PropagateBack(event);

     TTree *trdTree=trdl->TreeR();
     if (!trdTree) {
        cerr<<"Can't get the TRD cluster tree !\n";
        return 4;
     }
     trdTracker.LoadClusters(trdTree);
     rc+=trdTracker.PropagateBack(event);

/*
     for (Int_t iTrack = 0; iTrack < event->GetNumberOfTracks(); iTrack++) {
       AliESDtrack* track = event->GetTrack(iTrack);
       trdPID->MakePID(track);
     }
*/

     TTree *tofTree=tofl->TreeD();
     if (!tofTree) {
        cerr<<"Can't get the TOF cluster tree !\n";
        return 4;
     }
     tofPID.LoadClusters(tofTree,tofGeo);
     tofPID.MakePID(event);
     tofPID.UnloadClusters();

//***** Now the final refit at the primary vertex...
     rc+=trdTracker.RefitInward(event);
     trdTracker.UnloadClusters();

     rc+=tpcTracker.RefitInward(event);
     tpcTracker.UnloadClusters();
     tpcPID.MakePID(event);

     rc+=itsTracker.RefitInward(event);
     itsTracker.UnloadClusters();
     itsPID.MakePID(event);

//***** Here is the combined PID
     AliESDpid::MakePID(event);

//***** Hyperon reconstruction
     vtxer.SetVertex(vtx);
     rc+=vtxer.Tracks2V0vertices(event);            // V0 finding
     rc+=cvtxer.V0sTracks2CascadeVertices(event);   // cascade finding

//***** Some final manipulations with this event
     if (rc==0) {
        Char_t ename[100];
        sprintf(ename,"%d",i);
	ef->cd();
        if (!event->Write(ename)) rc++;
     }
     if (rc) {
        cerr<<"Something bad happened...\n";
     }
     delete event;
   }
   timer.Stop(); timer.Print();

   //pidFile->Close();

   delete par;

   ef->Close();

   delete rl;

   return rc;
}
<commit_msg>Preliminary PID for the ITS tracker added (Yu.Belikov)<commit_after>//********************************************************************
//     Example of the reconstruction that generates the ESD
// Input files:
//   a) file containing the ITS clusters
//      (the AliITSFindClustersV2.C macro can be used to generate it)
//   b) file containing the TPC clusters
//      (the AliTPCFindClusters.C macro can be used to generate it)
//   c) file containing the TRD clusters
//      (the AliTRDdigits2cluster.C macro can be used to generate it)
//   d) file containing the TOF digits
//      (the AliTOFSDigits2Digits.C macro can be used to generate it)
// Ouput file:
//      AliESDs.root containing the ESD events
//
// Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
//********************************************************************

#if !defined(__CINT__) || defined(__MAKECINT__)
  #include <Riostream.h>
  #include "TFile.h"
  #include "TSystem.h"
  #include "TStopwatch.h"
  #include "TArrayF.h"

  #include "AliMagF.h"
  #include "AliRun.h"
  #include "AliRunLoader.h"
  #include "AliLoader.h"
  #include "AliHeader.h"
  #include "AliGenEventHeader.h"

  #include "AliESD.h"
  #include "AliESDpid.h"

  #include "AliITS.h"
  #include "AliITSgeom.h"
  #include "AliITStrackerV2.h"
  #include "AliV0vertexer.h"
  #include "AliCascadeVertexer.h"
  #include "AliITSpidESD.h"
  #include "AliITSLoader.h"

  #include "AliTPCParam.h"
  #include "AliTPCtracker.h"
  #include "AliTPCpidESD.h"
  #include "AliTPCLoader.h"

  #include "AliTRDtracker.h"
  #include "AliTRDPartID.h"

  #include "AliTOFpidESD.h"
  #include "AliTOF.h"
  #include "AliTOFGeometry.h"
#endif

extern AliRun *gAlice;
extern TFile *gFile;

Int_t AliESDtest(Int_t nev=1,Int_t run=0) {

/**** Initialization of the NewIO *******/

   if (gAlice) {
      delete gAlice->GetRunLoader();
      delete gAlice;
      gAlice=0;
   }

   AliRunLoader *rl = AliRunLoader::Open("galice.root");
   if (rl == 0x0) {
      cerr<<"Can not open session"<<endl;
      return 1;
   }
   Int_t retval = rl->LoadgAlice();
   if (retval) {
      cerr<<"AliESDtest.C : LoadgAlice returned error"<<endl;
      delete rl;
      return 1;
   }
   retval = rl->LoadHeader();
   if (retval) {
      cerr<<"AliESDtest.C : LoadHeader returned error"<<endl;
      delete rl;
      return 2;
   }
   gAlice=rl->GetAliRun();

   AliKalmanTrack::SetConvConst(
      1000/0.299792458/gAlice->Field()->SolenoidField()
   );

/**** The ITS corner ********************/

   AliITSLoader* itsl = (AliITSLoader*)rl->GetLoader("ITSLoader");
   if (itsl == 0x0) {
      cerr<<"AliESDtest.C : Can not get the ITS loader"<<endl;
      return 3;
   }
   itsl->LoadRecPoints("read");

   AliITS *dITS = (AliITS*)gAlice->GetDetector("ITS");
   if (!dITS) {
      cerr<<"AliESDtest.C : Can not find the ITS detector !"<<endl;
      return 4;
   }
   AliITSgeom *geom = dITS->GetITSgeom();

   //An instance of the ITS tracker
   AliITStrackerV2 itsTracker(geom);

   //An instance of the ITS PID maker
   Double_t parITS[]={35.5,0.11,10.};
   AliITSpidESD itsPID(parITS);

   //An instance of the V0 finder
   Double_t cuts[]={33,  // max. allowed chi2
                    0.16,// min. allowed negative daughter's impact parameter
                    0.05,// min. allowed positive daughter's impact parameter
                    0.080,// max. allowed DCA between the daughter tracks
                    0.998,// max. allowed cosine of V0's pointing angle
                    0.9,  // min. radius of the fiducial volume
                    2.9   // max. radius of the fiducial volume
                   };
   AliV0vertexer vtxer(cuts);

   Double_t cts[]={33.,    // max. allowed chi2
                    0.05,   // min. allowed V0 impact parameter
                    0.008,  // window around the Lambda mass
                    0.035,  // min. allowed bachelor's impact parameter
                    0.10,   // max. allowed DCA between a V0 and a track
                    0.9985, //max. allowed cosine of the cascade pointing angle
                    0.9,    // min. radius of the fiducial volume
                    2.9     // max. radius of the fiducial volume
                   };
   AliCascadeVertexer cvtxer=AliCascadeVertexer(cts);

/**** The TPC corner ********************/

   AliTPCLoader* tpcl = (AliTPCLoader*)rl->GetLoader("TPCLoader");
   if (tpcl == 0x0) {
      cerr<<"AliESDtest.C : can not get the TPC loader"<<endl;
      return 5;
   }
   tpcl->LoadRecPoints("read");

   rl->CdGAFile();
   AliTPCParam *par=(AliTPCParam *)gDirectory->Get("75x40_100x60_150x60");
   if (!par) {
      cerr<<"TPC parameters have not been found !\n";
      return 6;
   }

   //An instance of the TPC tracker
   AliTPCtracker tpcTracker(par);

   //An instance of the TPC PID maker
   Double_t parTPC[]={45.0,0.08,10.};
   AliTPCpidESD tpcPID(parTPC);

/**** The TRD corner ********************/

   AliLoader* trdl = rl->GetLoader("TRDLoader");
   if (trdl == 0x0) {
      cerr<<"AliESDtest.C : can not get the TRD loader"<<endl;
      return 5;
   }
   trdl->LoadRecPoints("read");

   //An instance of the TRD tracker
   rl->CdGAFile();
   AliTRDtracker trdTracker(gFile);  //galice.root file

/*
   //An instance of the TRD PID maker
   TFile* pidFile = TFile::Open("pid.root");
   if (!pidFile->IsOpen()) {
     cerr << "Can't get pid.root !\n";
     return 7;
   }
   AliTRDPartID* trdPID = (AliTRDPartID*) pidFile->Get("AliTRDPartID");
   if (!trdPID) {
     cerr << "Can't get PID object !\n";
     return 8;
   }
*/

/**** The TOF corner ********************/
   AliTOF *dTOF = (AliTOF*)gAlice->GetDetector("TOF");
   if (!dTOF) {
      cerr<<"AliESDtest.C : Can not find the TOF detector !"<<endl;
      return 4;
   }
   AliTOFGeometry *tofGeo = dTOF->GetGeometry();
   if (!tofGeo) {
      cerr<<"AliESDtest.C : Can not find the TOF geometry !"<<endl;
      return 4;
   }

   AliLoader* tofl = rl->GetLoader("TOFLoader");
   if (tofl == 0x0) {
      cerr<<"AliESDtest.C : can not get the TOF loader"<<endl;
      return 5;
   }
   tofl->LoadDigits("read");

   //Instance of the TOF PID maker
   Double_t parTOF[]={130.,5.};
   AliTOFpidESD tofPID(parTOF);

   //rl->UnloadgAlice();

   TFile *ef=TFile::Open("AliESDs.root","RECREATE");
   if (!ef->IsOpen()) {cerr<<"Can't AliESDs.root !\n"; return 1;}

   TStopwatch timer;
   Int_t rc=0;
   if (nev>rl->GetNumberOfEvents()) nev=rl->GetNumberOfEvents();
   //The loop over events
   for (Int_t i=0; i<nev; i++) {
     cerr<<"\n\nProcessing event number : "<<i<<endl;
     AliESD *event=new AliESD();
     event->SetRunNumber(run);
     event->SetEventNumber(i);

     rl->GetEvent(i);

//***** Primary vertex reconstruction (MC vertex position, for the moment)
     TArrayF v(3);
     rl->GetHeader()->GenEventHeader()->PrimaryVertex(v);
     Double_t vtx[3]={v[0],v[1],v[2]};
     Double_t cvtx[6]={
       0.005,
       0.000, 0.005,
       0.000, 0.000, 0.010
     };
     event->SetVertex(vtx,cvtx);
     cvtx[1]=cvtx[0]; cvtx[2]=cvtx[5]; //trackers use only the diag.elements

//***** Initial path towards the primary vertex
     tpcTracker.SetVertex(vtx,cvtx);
     TTree *tpcTree=tpcl->TreeR();
     if (!tpcTree) {
        cerr<<"Can't get the TPC cluster tree !\n";
        return 4;
     }
     tpcTracker.LoadClusters(tpcTree);
     rc+=tpcTracker.Clusters2Tracks(event);
     tpcPID.MakePID(event);                 // preliminary PID
     AliESDpid::MakePID(event);             // for the ITS tracker

     itsTracker.SetVertex(vtx,cvtx);
     TTree *itsTree=itsl->TreeR();
     if (!itsTree) {
        cerr<<"Can't get the ITS cluster tree !\n";
        return 4;
     }
     itsTracker.LoadClusters(itsTree);
     rc+=itsTracker.Clusters2Tracks(event);

//***** Back propagation towards the outer barrel detectors
     rc+=itsTracker.PropagateBack(event);

     rc+=tpcTracker.PropagateBack(event);

     TTree *trdTree=trdl->TreeR();
     if (!trdTree) {
        cerr<<"Can't get the TRD cluster tree !\n";
        return 4;
     }
     trdTracker.LoadClusters(trdTree);
     rc+=trdTracker.PropagateBack(event);

/*
     for (Int_t iTrack = 0; iTrack < event->GetNumberOfTracks(); iTrack++) {
       AliESDtrack* track = event->GetTrack(iTrack);
       trdPID->MakePID(track);
     }
*/

     TTree *tofTree=tofl->TreeD();
     if (!tofTree) {
        cerr<<"Can't get the TOF cluster tree !\n";
        return 4;
     }
     tofPID.LoadClusters(tofTree,tofGeo);
     tofPID.MakePID(event);
     tofPID.UnloadClusters();

//***** Now the final refit at the primary vertex...
     rc+=trdTracker.RefitInward(event);
     trdTracker.UnloadClusters();

     rc+=tpcTracker.RefitInward(event);
     tpcTracker.UnloadClusters();
     tpcPID.MakePID(event);

     rc+=itsTracker.RefitInward(event);
     itsTracker.UnloadClusters();
     itsPID.MakePID(event);

//***** Here is the combined PID
     AliESDpid::MakePID(event);

//***** Hyperon reconstruction
     vtxer.SetVertex(vtx);
     rc+=vtxer.Tracks2V0vertices(event);            // V0 finding
     rc+=cvtxer.V0sTracks2CascadeVertices(event);   // cascade finding

//***** Some final manipulations with this event
     if (rc==0) {
        Char_t ename[100];
        sprintf(ename,"%d",i);
	ef->cd();
        if (!event->Write(ename)) rc++;
     }
     if (rc) {
        cerr<<"Something bad happened...\n";
     }
     delete event;
   }
   timer.Stop(); timer.Print();

   //pidFile->Close();

   delete par;

   ef->Close();

   delete rl;

   return rc;
}
<|endoftext|>


<commit_before>#include <Args.h>
#include <libs/include/Socket.h>
#include <libs/include/Timer.h>
#include <libs/include/TSCTimer.h>
#include <inttypes.h>
#include <iostream>
#include <stdio.h>
#include <unistd.h>

#ifndef PRIu64
#define PRIu64 "ull"
#endif

#define TSC_MHZ 3000

int main(int argc, char *argv[]) {

  Args opts(argc, argv);

  uint64_t tx_total = 0;
  uint64_t tx = 0;
  uint64_t txp = 0;
  const int intervalUs = 1000000;
  const int B1M = 1000000;

  Socket::Endpoint local("0.0.0.0", 0);
  Socket::Endpoint remote(opts.dest_ip.c_str(), opts.port);
  UDPClient udptx(local, remote);
  udptx.buflen(opts.buflen);
  udptx.setbuffers(4000000, 4000000);
  udptx.printbuffers();

  Timer rate_timer;
  TSCTimer report_timer;

  uint32_t seqno = 1;
  for (;;) {
    char buffer[10000];
    *((uint32_t*)buffer) = seqno;
    auto txtmp = udptx.send(buffer, opts.buflen);
    seqno++;

    if (txtmp > 0) {
      txp++;
      tx += txtmp;
    }
    // if (txp % 500 == 0) {
    //    usleep(1000);
    // }

    if (report_timer.timetsc() >= 1000000UL * TSC_MHZ) {
      auto usecs = rate_timer.timeus();
      tx_total += tx;
      printf("Tx rate: %.2f Mbps, %.0f pps, tx %" PRIu64 " MB (total: %" PRIu64
             " MB) %llu usecs\n",
             tx * 8.0 / usecs,
             txp * 1000000.0 / usecs,
             tx / B1M,
             tx_total / B1M,
             usecs);
      tx = 0;
      txp = 0;
      rate_timer.now();
      report_timer.now();
    }
  }
}
<commit_msg>remove usleep in udptx<commit_after>#include <Args.h>
#include <libs/include/Socket.h>
#include <libs/include/Timer.h>
#include <libs/include/TSCTimer.h>
#include <inttypes.h>
#include <iostream>
#include <stdio.h>
#include <unistd.h>

#ifndef PRIu64
#define PRIu64 "ull"
#endif

#define TSC_MHZ 3000

int main(int argc, char *argv[]) {

  Args opts(argc, argv);

  uint64_t tx_total = 0;
  uint64_t tx = 0;
  uint64_t txp = 0;
  const int intervalUs = 1000000;
  const int B1M = 1000000;

  Socket::Endpoint local("0.0.0.0", 0);
  Socket::Endpoint remote(opts.dest_ip.c_str(), opts.port);
  UDPClient udptx(local, remote);
  udptx.buflen(opts.buflen);
  udptx.setbuffers(4000000, 4000000);
  udptx.printbuffers();

  Timer rate_timer;
  TSCTimer report_timer;

  uint32_t seqno = 1;
  for (;;) {
    char buffer[10000];
    *((uint32_t*)buffer) = seqno;
    auto txtmp = udptx.send(buffer, opts.buflen);
    seqno++;

    if (txtmp > 0) {
      txp++;
      tx += txtmp;
    }

    if (report_timer.timetsc() >= 1000000UL * TSC_MHZ) {
      auto usecs = rate_timer.timeus();
      tx_total += tx;
      printf("Tx rate: %.2f Mbps, %.0f pps, tx %" PRIu64 " MB (total: %" PRIu64
             " MB) %llu usecs\n",
             tx * 8.0 / usecs,
             txp * 1000000.0 / usecs,
             tx / B1M,
             tx_total / B1M,
             usecs);
      tx = 0;
      txp = 0;
      rate_timer.now();
      report_timer.now();
    }
  }
}
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2018-2019 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "GLFWOSPRayWindow.h"
#include <iostream>
#include <stdexcept>

#include <imgui.h>
#include "imgui/imgui_impl_glfw_gl3.h"

GLFWOSPRayWindow *GLFWOSPRayWindow::activeWindow = nullptr;

static bool g_quitNextFrame = false;

GLFWOSPRayWindow::GLFWOSPRayWindow(const ospcommon::vec2i &windowSize,
                                   const ospcommon::box3f &worldBounds,
                                   OSPModel model,
                                   OSPRenderer renderer)
    : windowSize(windowSize),
      worldBounds(worldBounds),
      model(model),
      renderer(renderer)
{
  if (activeWindow != nullptr)
    throw std::runtime_error("Cannot create more than one GLFWOSPRayWindow!");

  activeWindow = this;

  // initialize GLFW
  if (!glfwInit())
    throw std::runtime_error("Failed to initialize GLFW!");

  // create GLFW window
  glfwWindow = glfwCreateWindow(
      windowSize.x, windowSize.y, "OSPRay Tutorial", NULL, NULL);

  if (!glfwWindow) {
    glfwTerminate();
    throw std::runtime_error("Failed to create GLFW window!");
  }

  // make the window's context current
  glfwMakeContextCurrent(glfwWindow);

  ImGui_ImplGlfwGL3_Init(glfwWindow, true);

  // set initial OpenGL state
  glEnable(GL_TEXTURE_2D);
  glDisable(GL_LIGHTING);

  // create OpenGL frame buffer texture
  glGenTextures(1, &framebufferTexture);
  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, framebufferTexture);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  // set GLFW callbacks
  glfwSetFramebufferSizeCallback(
      glfwWindow, [](GLFWwindow *, int newWidth, int newHeight) {
        activeWindow->reshape(ospcommon::vec2i{newWidth, newHeight});
      });

  glfwSetCursorPosCallback(glfwWindow, [](GLFWwindow *, double x, double y) {
    ImGuiIO &io = ImGui::GetIO();
    if (!io.WantCaptureMouse)
      activeWindow->motion(ospcommon::vec2f{float(x), float(y)});
  });

  glfwSetKeyCallback(glfwWindow,
                     [](GLFWwindow *, int key, int, int action, int) {
                       if (action == GLFW_PRESS) {
                         switch (key) {
                         case GLFW_KEY_G:
                           activeWindow->showUi = !(activeWindow->showUi);
                           break;
                         case GLFW_KEY_Q:
                           g_quitNextFrame = true;
                           break;
                         }
                       }
                     });

  // OSPRay setup

  // set the model on the renderer
  ospSetObject(renderer, "model", model);

  // create the arcball camera model
  arcballCamera = std::unique_ptr<ArcballCamera>(
      new ArcballCamera(worldBounds, windowSize));

  // create camera
  camera = ospNewCamera("perspective");
  ospSetf(camera, "aspect", windowSize.x / float(windowSize.y));

  ospSet3f(camera,
           "pos",
           arcballCamera->eyePos().x,
           arcballCamera->eyePos().y,
           arcballCamera->eyePos().z);
  ospSet3f(camera,
           "dir",
           arcballCamera->lookDir().x,
           arcballCamera->lookDir().y,
           arcballCamera->lookDir().z);
  ospSet3f(camera,
           "up",
           arcballCamera->upDir().x,
           arcballCamera->upDir().y,
           arcballCamera->upDir().z);

  ospCommit(camera);

  // set camera on the renderer
  ospSetObject(renderer, "camera", camera);

  // finally, commit the renderer
  ospCommit(renderer);

  // trigger window reshape events with current window size
  glfwGetFramebufferSize(glfwWindow, &this->windowSize.x, &this->windowSize.y);
  reshape(this->windowSize);
}

GLFWOSPRayWindow::~GLFWOSPRayWindow()
{
  ImGui_ImplGlfwGL3_Shutdown();
  // cleanly terminate GLFW
  glfwTerminate();
}

GLFWOSPRayWindow *GLFWOSPRayWindow::getActiveWindow()
{
  return activeWindow;
}

OSPModel GLFWOSPRayWindow::getModel()
{
  return model;
}

void GLFWOSPRayWindow::setModel(OSPModel newModel)
{
  model = newModel;

  // set the model on the renderer
  ospSetObject(renderer, "model", model);

  // commit the renderer
  addObjectToCommit(renderer);
}

void GLFWOSPRayWindow::clearFrameBuffer()
{
  ospFrameBufferClear(framebuffer, OSP_FB_COLOR | OSP_FB_ACCUM);
}

void GLFWOSPRayWindow::registerDisplayCallback(
    std::function<void(GLFWOSPRayWindow *)> callback)
{
  displayCallback = callback;
}

void GLFWOSPRayWindow::registerImGuiCallback(std::function<void()> callback)
{
  uiCallback = callback;
}

void GLFWOSPRayWindow::mainLoop()
{
  // continue until the user closes the window
  startNewOSPRayFrame();

  while (!glfwWindowShouldClose(glfwWindow) && !g_quitNextFrame) {
    ImGui_ImplGlfwGL3_NewFrame();

    display();

    // poll and process events
    glfwPollEvents();
  }

  waitOnOSPRayFrame();
  if (currentFrame != nullptr)
    ospRelease(currentFrame);
}

void GLFWOSPRayWindow::reshape(const ospcommon::vec2i &newWindowSize)
{
  windowSize = newWindowSize;

  // release the current frame buffer, if it exists
  if (framebuffer)
    ospRelease(framebuffer);

  // create new frame buffer
  framebuffer = ospNewFrameBuffer(reinterpret_cast<osp_vec2i &>(windowSize),
                                  OSP_FB_SRGBA,
                                  OSP_FB_COLOR | OSP_FB_ACCUM);

  // reset OpenGL viewport and orthographic projection
  glViewport(0, 0, windowSize.x, windowSize.y);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0.0, windowSize.x, 0.0, windowSize.y, -1.0, 1.0);

  // update camera
  arcballCamera->updateWindowSize(windowSize);

  ospSetf(camera, "aspect", windowSize.x / float(windowSize.y));
  ospCommit(camera);
}

void GLFWOSPRayWindow::motion(const ospcommon::vec2f &position)
{
  static ospcommon::vec2f previousMouse(-1);

  const ospcommon::vec2f mouse(position.x, position.y);
  if (previousMouse != ospcommon::vec2f(-1)) {
    const bool leftDown =
        glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS;
    const bool rightDown =
        glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS;
    const bool middleDown =
        glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS;
    const ospcommon::vec2f prev = previousMouse;

    bool cameraChanged = leftDown || rightDown || middleDown;

    if (leftDown) {
      const ospcommon::vec2f mouseFrom(
          ospcommon::clamp(prev.x * 2.f / windowSize.x - 1.f, -1.f, 1.f),
          ospcommon::clamp(prev.y * 2.f / windowSize.y - 1.f, -1.f, 1.f));
      const ospcommon::vec2f mouseTo(
          ospcommon::clamp(mouse.x * 2.f / windowSize.x - 1.f, -1.f, 1.f),
          ospcommon::clamp(mouse.y * 2.f / windowSize.y - 1.f, -1.f, 1.f));
      arcballCamera->rotate(mouseFrom, mouseTo);
    } else if (rightDown) {
      arcballCamera->zoom(mouse.y - prev.y);
    } else if (middleDown) {
      arcballCamera->pan(ospcommon::vec2f(mouse.x - prev.x, prev.y - mouse.y));
    }

    if (cameraChanged) {
      ospSetf(camera, "aspect", windowSize.x / float(windowSize.y));
      ospSet3f(camera,
               "pos",
               arcballCamera->eyePos().x,
               arcballCamera->eyePos().y,
               arcballCamera->eyePos().z);
      ospSet3f(camera,
               "dir",
               arcballCamera->lookDir().x,
               arcballCamera->lookDir().y,
               arcballCamera->lookDir().z);
      ospSet3f(camera,
               "up",
               arcballCamera->upDir().x,
               arcballCamera->upDir().y,
               arcballCamera->upDir().z);

      addObjectToCommit(camera);
    }
  }

  previousMouse = mouse;
}

void GLFWOSPRayWindow::display()
{
  // clock used to compute frame rate
  static auto displayStart = std::chrono::high_resolution_clock::now();

  if (showUi && uiCallback) {
    ImGuiWindowFlags flags = ImGuiWindowFlags_AlwaysAutoResize;
    ImGui::Begin(
        "Tutorial Controls (press 'g' to hide / show)", nullptr, flags);
    uiCallback();
    ImGui::End();
  }

  // if a display callback has been registered, call it
  if (displayCallback) {
    displayCallback(this);
  }

  static bool firstFrame = true;

  if (firstFrame || ospIsReady(currentFrame)) {
    waitOnOSPRayFrame();

    // map OSPRay frame buffer, update OpenGL texture with its contents, then
    // unmap
    uint32_t *fb = (uint32_t *)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR);

    glBindTexture(GL_TEXTURE_2D, framebufferTexture);
    glTexImage2D(GL_TEXTURE_2D,
                 0,
                 GL_RGBA,
                 windowSize.x,
                 windowSize.y,
                 0,
                 GL_RGBA,
                 GL_UNSIGNED_BYTE,
                 fb);

    ospUnmapFrameBuffer(fb, framebuffer);

    auto handles = objectsToCommit.consume();
    if (!handles.empty()) {
      for (auto &h : handles)
        ospCommit(h);
      ospFrameBufferClear(framebuffer, OSP_FB_COLOR | OSP_FB_ACCUM);
    }

    startNewOSPRayFrame();

    firstFrame = false;

    // display frame rate in window title
    auto displayEnd = std::chrono::high_resolution_clock::now();
    auto durationMilliseconds =
        std::chrono::duration_cast<std::chrono::milliseconds>(displayEnd -
                                                              displayStart);
    displayStart = displayEnd;

    const float frameRate = 1000.f / float(durationMilliseconds.count());

    std::stringstream windowTitle;
    windowTitle << "OSPRay: " << std::setprecision(3) << frameRate << " fps";
    glfwSetWindowTitle(glfwWindow, windowTitle.str().c_str());
  }

  // clear current OpenGL color buffer
  glClear(GL_COLOR_BUFFER_BIT);

  // render textured quad with OSPRay frame buffer contents
  glBegin(GL_QUADS);

  glTexCoord2f(0.f, 0.f);
  glVertex2f(0.f, 0.f);

  glTexCoord2f(0.f, 1.f);
  glVertex2f(0.f, windowSize.y);

  glTexCoord2f(1.f, 1.f);
  glVertex2f(windowSize.x, windowSize.y);

  glTexCoord2f(1.f, 0.f);
  glVertex2f(windowSize.x, 0.f);

  glEnd();

  if (showUi && uiCallback) {
    ImGui::Render();
  }

  // swap buffers
  glfwSwapBuffers(glfwWindow);
}

void GLFWOSPRayWindow::startNewOSPRayFrame()
{
  if (currentFrame != nullptr)
    ospRelease(currentFrame);

  currentFrame =
      ospRenderFrameAsync(framebuffer, renderer, OSP_FB_COLOR | OSP_FB_ACCUM);
}

void GLFWOSPRayWindow::waitOnOSPRayFrame()
{
  if (currentFrame != nullptr) {
    ospWait(currentFrame, OSP_FRAME_FINISHED);
  }
}

void GLFWOSPRayWindow::addObjectToCommit(OSPObject obj)
{
  objectsToCommit.push_back(obj);
}
<commit_msg>exclude GL texture upload time in FPS inidcator for tutorials<commit_after>// ======================================================================== //
// Copyright 2018-2019 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "GLFWOSPRayWindow.h"
#include <iostream>
#include <stdexcept>

#include <imgui.h>
#include "imgui/imgui_impl_glfw_gl3.h"

GLFWOSPRayWindow *GLFWOSPRayWindow::activeWindow = nullptr;

static bool g_quitNextFrame = false;

GLFWOSPRayWindow::GLFWOSPRayWindow(const ospcommon::vec2i &windowSize,
                                   const ospcommon::box3f &worldBounds,
                                   OSPModel model,
                                   OSPRenderer renderer)
    : windowSize(windowSize),
      worldBounds(worldBounds),
      model(model),
      renderer(renderer)
{
  if (activeWindow != nullptr)
    throw std::runtime_error("Cannot create more than one GLFWOSPRayWindow!");

  activeWindow = this;

  // initialize GLFW
  if (!glfwInit())
    throw std::runtime_error("Failed to initialize GLFW!");

  // create GLFW window
  glfwWindow = glfwCreateWindow(
      windowSize.x, windowSize.y, "OSPRay Tutorial", NULL, NULL);

  if (!glfwWindow) {
    glfwTerminate();
    throw std::runtime_error("Failed to create GLFW window!");
  }

  // make the window's context current
  glfwMakeContextCurrent(glfwWindow);

  ImGui_ImplGlfwGL3_Init(glfwWindow, true);

  // set initial OpenGL state
  glEnable(GL_TEXTURE_2D);
  glDisable(GL_LIGHTING);

  // create OpenGL frame buffer texture
  glGenTextures(1, &framebufferTexture);
  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D, framebufferTexture);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  // set GLFW callbacks
  glfwSetFramebufferSizeCallback(
      glfwWindow, [](GLFWwindow *, int newWidth, int newHeight) {
        activeWindow->reshape(ospcommon::vec2i{newWidth, newHeight});
      });

  glfwSetCursorPosCallback(glfwWindow, [](GLFWwindow *, double x, double y) {
    ImGuiIO &io = ImGui::GetIO();
    if (!io.WantCaptureMouse)
      activeWindow->motion(ospcommon::vec2f{float(x), float(y)});
  });

  glfwSetKeyCallback(glfwWindow,
                     [](GLFWwindow *, int key, int, int action, int) {
                       if (action == GLFW_PRESS) {
                         switch (key) {
                         case GLFW_KEY_G:
                           activeWindow->showUi = !(activeWindow->showUi);
                           break;
                         case GLFW_KEY_Q:
                           g_quitNextFrame = true;
                           break;
                         }
                       }
                     });

  // OSPRay setup

  // set the model on the renderer
  ospSetObject(renderer, "model", model);

  // create the arcball camera model
  arcballCamera = std::unique_ptr<ArcballCamera>(
      new ArcballCamera(worldBounds, windowSize));

  // create camera
  camera = ospNewCamera("perspective");
  ospSetf(camera, "aspect", windowSize.x / float(windowSize.y));

  ospSet3f(camera,
           "pos",
           arcballCamera->eyePos().x,
           arcballCamera->eyePos().y,
           arcballCamera->eyePos().z);
  ospSet3f(camera,
           "dir",
           arcballCamera->lookDir().x,
           arcballCamera->lookDir().y,
           arcballCamera->lookDir().z);
  ospSet3f(camera,
           "up",
           arcballCamera->upDir().x,
           arcballCamera->upDir().y,
           arcballCamera->upDir().z);

  ospCommit(camera);

  // set camera on the renderer
  ospSetObject(renderer, "camera", camera);

  // finally, commit the renderer
  ospCommit(renderer);

  // trigger window reshape events with current window size
  glfwGetFramebufferSize(glfwWindow, &this->windowSize.x, &this->windowSize.y);
  reshape(this->windowSize);
}

GLFWOSPRayWindow::~GLFWOSPRayWindow()
{
  ImGui_ImplGlfwGL3_Shutdown();
  // cleanly terminate GLFW
  glfwTerminate();
}

GLFWOSPRayWindow *GLFWOSPRayWindow::getActiveWindow()
{
  return activeWindow;
}

OSPModel GLFWOSPRayWindow::getModel()
{
  return model;
}

void GLFWOSPRayWindow::setModel(OSPModel newModel)
{
  model = newModel;

  // set the model on the renderer
  ospSetObject(renderer, "model", model);

  // commit the renderer
  addObjectToCommit(renderer);
}

void GLFWOSPRayWindow::clearFrameBuffer()
{
  ospFrameBufferClear(framebuffer, OSP_FB_COLOR | OSP_FB_ACCUM);
}

void GLFWOSPRayWindow::registerDisplayCallback(
    std::function<void(GLFWOSPRayWindow *)> callback)
{
  displayCallback = callback;
}

void GLFWOSPRayWindow::registerImGuiCallback(std::function<void()> callback)
{
  uiCallback = callback;
}

void GLFWOSPRayWindow::mainLoop()
{
  // continue until the user closes the window
  startNewOSPRayFrame();

  while (!glfwWindowShouldClose(glfwWindow) && !g_quitNextFrame) {
    ImGui_ImplGlfwGL3_NewFrame();

    display();

    // poll and process events
    glfwPollEvents();
  }

  waitOnOSPRayFrame();
  if (currentFrame != nullptr)
    ospRelease(currentFrame);
}

void GLFWOSPRayWindow::reshape(const ospcommon::vec2i &newWindowSize)
{
  windowSize = newWindowSize;

  // release the current frame buffer, if it exists
  if (framebuffer)
    ospRelease(framebuffer);

  // create new frame buffer
  framebuffer = ospNewFrameBuffer(reinterpret_cast<osp_vec2i &>(windowSize),
                                  OSP_FB_SRGBA,
                                  OSP_FB_COLOR | OSP_FB_ACCUM);

  // reset OpenGL viewport and orthographic projection
  glViewport(0, 0, windowSize.x, windowSize.y);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0.0, windowSize.x, 0.0, windowSize.y, -1.0, 1.0);

  // update camera
  arcballCamera->updateWindowSize(windowSize);

  ospSetf(camera, "aspect", windowSize.x / float(windowSize.y));
  ospCommit(camera);
}

void GLFWOSPRayWindow::motion(const ospcommon::vec2f &position)
{
  static ospcommon::vec2f previousMouse(-1);

  const ospcommon::vec2f mouse(position.x, position.y);
  if (previousMouse != ospcommon::vec2f(-1)) {
    const bool leftDown =
        glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS;
    const bool rightDown =
        glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS;
    const bool middleDown =
        glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS;
    const ospcommon::vec2f prev = previousMouse;

    bool cameraChanged = leftDown || rightDown || middleDown;

    if (leftDown) {
      const ospcommon::vec2f mouseFrom(
          ospcommon::clamp(prev.x * 2.f / windowSize.x - 1.f, -1.f, 1.f),
          ospcommon::clamp(prev.y * 2.f / windowSize.y - 1.f, -1.f, 1.f));
      const ospcommon::vec2f mouseTo(
          ospcommon::clamp(mouse.x * 2.f / windowSize.x - 1.f, -1.f, 1.f),
          ospcommon::clamp(mouse.y * 2.f / windowSize.y - 1.f, -1.f, 1.f));
      arcballCamera->rotate(mouseFrom, mouseTo);
    } else if (rightDown) {
      arcballCamera->zoom(mouse.y - prev.y);
    } else if (middleDown) {
      arcballCamera->pan(ospcommon::vec2f(mouse.x - prev.x, prev.y - mouse.y));
    }

    if (cameraChanged) {
      ospSetf(camera, "aspect", windowSize.x / float(windowSize.y));
      ospSet3f(camera,
               "pos",
               arcballCamera->eyePos().x,
               arcballCamera->eyePos().y,
               arcballCamera->eyePos().z);
      ospSet3f(camera,
               "dir",
               arcballCamera->lookDir().x,
               arcballCamera->lookDir().y,
               arcballCamera->lookDir().z);
      ospSet3f(camera,
               "up",
               arcballCamera->upDir().x,
               arcballCamera->upDir().y,
               arcballCamera->upDir().z);

      addObjectToCommit(camera);
    }
  }

  previousMouse = mouse;
}

void GLFWOSPRayWindow::display()
{
  // clock used to compute frame rate
  static auto displayStart = std::chrono::high_resolution_clock::now();

  if (showUi && uiCallback) {
    ImGuiWindowFlags flags = ImGuiWindowFlags_AlwaysAutoResize;
    ImGui::Begin(
        "Tutorial Controls (press 'g' to hide / show)", nullptr, flags);
    uiCallback();
    ImGui::End();
  }

  // if a display callback has been registered, call it
  if (displayCallback) {
    displayCallback(this);
  }

  static bool firstFrame = true;

  if (firstFrame || ospIsReady(currentFrame)) {
    // display frame rate in window title
    auto displayEnd = std::chrono::high_resolution_clock::now();
    auto durationMilliseconds =
        std::chrono::duration_cast<std::chrono::milliseconds>(displayEnd -
                                                              displayStart);

    const float frameRate = 1000.f / float(durationMilliseconds.count());

    std::stringstream windowTitle;
    windowTitle << "OSPRay: " << std::setprecision(3) << frameRate << " fps";
    glfwSetWindowTitle(glfwWindow, windowTitle.str().c_str());

    // map OSPRay frame buffer, update OpenGL texture with its contents, then
    // unmap

    waitOnOSPRayFrame();

    uint32_t *fb = (uint32_t *)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR);

    glBindTexture(GL_TEXTURE_2D, framebufferTexture);
    glTexImage2D(GL_TEXTURE_2D,
                 0,
                 GL_RGBA,
                 windowSize.x,
                 windowSize.y,
                 0,
                 GL_RGBA,
                 GL_UNSIGNED_BYTE,
                 fb);

    ospUnmapFrameBuffer(fb, framebuffer);

    auto handles = objectsToCommit.consume();
    if (!handles.empty()) {
      for (auto &h : handles)
        ospCommit(h);
      ospFrameBufferClear(framebuffer, OSP_FB_COLOR | OSP_FB_ACCUM);
    }

    // Start new frame and reset frame timing interval start
    displayStart = std::chrono::high_resolution_clock::now();
    startNewOSPRayFrame();
    firstFrame = false;
  }

  // clear current OpenGL color buffer
  glClear(GL_COLOR_BUFFER_BIT);

  // render textured quad with OSPRay frame buffer contents
  glBegin(GL_QUADS);

  glTexCoord2f(0.f, 0.f);
  glVertex2f(0.f, 0.f);

  glTexCoord2f(0.f, 1.f);
  glVertex2f(0.f, windowSize.y);

  glTexCoord2f(1.f, 1.f);
  glVertex2f(windowSize.x, windowSize.y);

  glTexCoord2f(1.f, 0.f);
  glVertex2f(windowSize.x, 0.f);

  glEnd();

  if (showUi && uiCallback) {
    ImGui::Render();
  }

  // swap buffers
  glfwSwapBuffers(glfwWindow);
}

void GLFWOSPRayWindow::startNewOSPRayFrame()
{
  if (currentFrame != nullptr)
    ospRelease(currentFrame);

  currentFrame =
      ospRenderFrameAsync(framebuffer, renderer, OSP_FB_COLOR | OSP_FB_ACCUM);
}

void GLFWOSPRayWindow::waitOnOSPRayFrame()
{
  if (currentFrame != nullptr) {
    ospWait(currentFrame, OSP_FRAME_FINISHED);
  }
}

void GLFWOSPRayWindow::addObjectToCommit(OSPObject obj)
{
  objectsToCommit.push_back(obj);
}
<|endoftext|>