<commit_before>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Manjeet Dahiya
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "QXmppUtils.h"
#include "QXmppIq.h"

#include <QDomElement>
#include <QXmlStreamWriter>

/// Constructs a QXmppIq with the specified \a type.
///
/// \param type

QXmppIq::QXmppIq(QXmppIq::Type type)
    : QXmppStanza(), m_type(type)
{
    generateAndSetNextId();
}

/// Returns the IQ's type.
///

QXmppIq::Type QXmppIq::type() const
{
    return m_type;
}

/// Sets the IQ's type.
///
/// \param type

void QXmppIq::setType(QXmppIq::Type type)
{
    m_type = type;
}

void QXmppIq::parse(const QDomElement &element)
{
    QXmppStanza::parse(element);
    setTypeFromStr(element.attribute("type"));
    parseElementFromChild(element);
}

void QXmppIq::parseElementFromChild(const QDomElement &element)
{
    QXmppElementList extensions;
    QDomElement itemElement = element.firstChildElement();
    while (!itemElement.isNull())
    {
        extensions.append(QXmppElement(itemElement));
        itemElement = itemElement.nextSiblingElement();
    }
    setExtensions(extensions);
}

void QXmppIq::toXml( QXmlStreamWriter *xmlWriter ) const
{
    xmlWriter->writeStartElement("iq");

    helperToXmlAddAttribute(xmlWriter, "id", id());
    helperToXmlAddAttribute(xmlWriter, "to", to());
    helperToXmlAddAttribute(xmlWriter, "from", from());
    if(getTypeStr().isEmpty())
        helperToXmlAddAttribute(xmlWriter, "type", "get");
    else
        helperToXmlAddAttribute(xmlWriter,  "type", getTypeStr());
    toXmlElementFromChild(xmlWriter);
    error().toXml(xmlWriter);
    xmlWriter->writeEndElement();
}

void QXmppIq::toXmlElementFromChild( QXmlStreamWriter *writer ) const
{
    foreach (const QXmppElement &extension, extensions())
        extension.toXml(writer);
}

QString QXmppIq::getTypeStr() const
{
    switch(m_type)
    {
    case QXmppIq::Error:
        return "error";
    case QXmppIq::Get:
        return "get";
    case QXmppIq::Set:
        return "set";
    case QXmppIq::Result:
        return "result";
    default:
        qWarning("QXmppIq::getTypeStr() invalid type %d", (int)m_type);
        return "";
    }
}

void QXmppIq::setTypeFromStr(const QString& str)
{
    if(str == "error")
    {
        setType(QXmppIq::Error);
        return;
    }
    else if(str == "get")
    {
        setType(QXmppIq::Get);
        return;
    }
    else if(str == "set")
    {
        setType(QXmppIq::Set);
        return;
    }
    else if(str == "result")
    {
        setType(QXmppIq::Result);
        return;
    }
    else
    {
        setType(static_cast<QXmppIq::Type>(-1));
        qWarning("QXmppIq::setTypeFromStr() invalid input string type: %s",
                 qPrintable(str));
        return;
    }
}

// deprecated

QXmppIq::Type QXmppIq::getType() const
{
    return m_type;
}

<commit_msg>doc improvement<commit_after>/*
 * Copyright (C) 2008-2010 The QXmpp developers
 *
 * Author:
 *  Manjeet Dahiya
 *
 * Source:
 *  http://code.google.com/p/qxmpp
 *
 * This file is a part of QXmpp library.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 */

#include "QXmppUtils.h"
#include "QXmppIq.h"

#include <QDomElement>
#include <QXmlStreamWriter>

/// Constructs a QXmppIq with the specified \a type.
///
/// \param type

QXmppIq::QXmppIq(QXmppIq::Type type)
    : QXmppStanza(), m_type(type)
{
    generateAndSetNextId();
}

/// Returns the IQ's type.
///
/// \return QXmppIq::Type

QXmppIq::Type QXmppIq::type() const
{
    return m_type;
}

/// Sets the IQ's type.
///
/// \param type as QXmppIq::Type

void QXmppIq::setType(QXmppIq::Type type)
{
    m_type = type;
}

void QXmppIq::parse(const QDomElement &element)
{
    QXmppStanza::parse(element);
    setTypeFromStr(element.attribute("type"));
    parseElementFromChild(element);
}

void QXmppIq::parseElementFromChild(const QDomElement &element)
{
    QXmppElementList extensions;
    QDomElement itemElement = element.firstChildElement();
    while (!itemElement.isNull())
    {
        extensions.append(QXmppElement(itemElement));
        itemElement = itemElement.nextSiblingElement();
    }
    setExtensions(extensions);
}

void QXmppIq::toXml( QXmlStreamWriter *xmlWriter ) const
{
    xmlWriter->writeStartElement("iq");

    helperToXmlAddAttribute(xmlWriter, "id", id());
    helperToXmlAddAttribute(xmlWriter, "to", to());
    helperToXmlAddAttribute(xmlWriter, "from", from());
    if(getTypeStr().isEmpty())
        helperToXmlAddAttribute(xmlWriter, "type", "get");
    else
        helperToXmlAddAttribute(xmlWriter,  "type", getTypeStr());
    toXmlElementFromChild(xmlWriter);
    error().toXml(xmlWriter);
    xmlWriter->writeEndElement();
}

void QXmppIq::toXmlElementFromChild( QXmlStreamWriter *writer ) const
{
    foreach (const QXmppElement &extension, extensions())
        extension.toXml(writer);
}

QString QXmppIq::getTypeStr() const
{
    switch(m_type)
    {
    case QXmppIq::Error:
        return "error";
    case QXmppIq::Get:
        return "get";
    case QXmppIq::Set:
        return "set";
    case QXmppIq::Result:
        return "result";
    default:
        qWarning("QXmppIq::getTypeStr() invalid type %d", (int)m_type);
        return "";
    }
}

void QXmppIq::setTypeFromStr(const QString& str)
{
    if(str == "error")
    {
        setType(QXmppIq::Error);
        return;
    }
    else if(str == "get")
    {
        setType(QXmppIq::Get);
        return;
    }
    else if(str == "set")
    {
        setType(QXmppIq::Set);
        return;
    }
    else if(str == "result")
    {
        setType(QXmppIq::Result);
        return;
    }
    else
    {
        setType(static_cast<QXmppIq::Type>(-1));
        qWarning("QXmppIq::setTypeFromStr() invalid input string type: %s",
                 qPrintable(str));
        return;
    }
}

// deprecated

QXmppIq::Type QXmppIq::getType() const
{
    return m_type;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

int constexpr hsplit_default = 16;
int constexpr vsplit_default = 16;
int constexpr selectable_default = 16;
int constexpr select_cost_default = 1;
int constexpr change_cost_default = 1;
std::string const ext = ".ppm";

int main(int argc, char* argv[])
{
    std::vector<std::string> input_filenames;
    std::string output_filename_base;
    int hsplit, vsplit;
    int selectable;
    int select_cost, change_cost;

    // コマンドラインオプションの定義
    boost::program_options::options_description options(argv[0]);
    options.add_options()
        ("input,i",         boost::program_options::value<std::vector<std::string>>(&input_filenames)   ->multitoken() ->required(),            "入力ファイル名")
        ("output,o",        boost::program_options::value<std::string>(&output_filename_base),                                                  "出力ファイル名")
        ("hsplit,h",        boost::program_options::value<int>(&hsplit)                                 ->default_value(hsplit_default),        "横分割数")
        ("vsplit,v",        boost::program_options::value<int>(&vsplit)                                 ->default_value(vsplit_default),        "縦分割数")
        ("selectable,n",    boost::program_options::value<int>(&selectable)                             ->default_value(selectable_default),    "選択可能回数")
        ("select_cost,s",   boost::program_options::value<int>(&select_cost)                            ->default_value(select_cost_default),   "選択コスト変換レート")
        ("change_cost,c",   boost::program_options::value<int>(&change_cost)                            ->default_value(change_cost_default),   "交換コスト変換レート")
    ;

    // コマンドラインオプションのチェック
    boost::program_options::variables_map options_map;
    try {
        boost::program_options::store(boost::program_options::parse_command_line(argc, argv, options), options_map);
        boost::program_options::notify(options_map);
    } catch (boost::program_options::error_with_option_name const& e) {
        std::cout << e.what() << std::endl;
        std::cout << options << std::endl;
        return -1;
    }

    // 入力ファイル名でループ
    cv::Mat input_image;
    std::vector<uchar> output_buffer;
    std::string header;
    std::string output_filename;
    int count = 0;
    for (std::string const& input_filename : input_filenames) {
        // 出力ファイル名の設定
        if (output_filename_base.size() == 0) {
            output_filename = input_filename;
        } else {
            output_filename = output_filename_base;
        }
        auto dotpos = output_filename.find_last_of('.');
        if (dotpos != std::string::npos) {
            output_filename.resize(dotpos);
        }
        output_filename += (boost::format("_%1$02d") % count).str();
        output_filename += ext;

        // ヘッダ文字列の設定
        header.erase();
        header += (boost::format("# %1% %2%\n") % hsplit % vsplit).str();
        header += (boost::format("# %1%\n") % selectable).str();
        header += (boost::format("# %1% %2%\n") % select_cost % change_cost).str();

        // 画像読み込み
        input_image = cv::imread(input_filename);
        if (input_image.data == nullptr) {
            std::cout << "Fatal: " << input_filename << " を読み込めませんでした。" << std::endl;
            return -1;
        }

        // バッファへ書き込み
        cv::imencode(ext, input_image, output_buffer, std::vector<int>(CV_IMWRITE_PXM_BINARY));

        // ヘッダ流し込み
        output_buffer.insert(output_buffer.begin() + 3, header.begin(), header.end());

        // ファイル書き出し
        std::ofstream output_file(output_filename, std::ofstream::binary);
        if (!output_file) {
            std::cout << "Fatal: " << output_filename << " へ書き込めませんでした。" << std::endl;
            return -1;
        }
        std::copy(output_buffer.begin(), output_buffer.end(), std::ostream_iterator<uchar>(output_file));
    }
    return 0;
}
<commit_msg>エラー処理には例外を使うようにした<commit_after>#include <iostream>
#include <fstream>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

int constexpr hsplit_default = 16;
int constexpr vsplit_default = 16;
int constexpr selectable_default = 16;
int constexpr select_cost_default = 1;
int constexpr change_cost_default = 1;
std::string const ext = ".ppm";

int main(int argc, char* argv[])
{
    std::vector<std::string> input_filenames;
    std::string output_filename_base;
    int hsplit, vsplit;
    int selectable;
    int select_cost, change_cost;

    // コマンドラインオプションの定義
    boost::program_options::options_description options(argv[0]);
    options.add_options()
        ("input,i",         boost::program_options::value<std::vector<std::string>>(&input_filenames)   ->multitoken() ->required(),            "入力ファイル名")
        ("output,o",        boost::program_options::value<std::string>(&output_filename_base),                                                  "出力ファイル名")
        ("hsplit,h",        boost::program_options::value<int>(&hsplit)                                 ->default_value(hsplit_default),        "横分割数")
        ("vsplit,v",        boost::program_options::value<int>(&vsplit)                                 ->default_value(vsplit_default),        "縦分割数")
        ("selectable,n",    boost::program_options::value<int>(&selectable)                             ->default_value(selectable_default),    "選択可能回数")
        ("select_cost,s",   boost::program_options::value<int>(&select_cost)                            ->default_value(select_cost_default),   "選択コスト変換レート")
        ("change_cost,c",   boost::program_options::value<int>(&change_cost)                            ->default_value(change_cost_default),   "交換コスト変換レート")
    ;

    // コマンドラインオプションのチェック
    boost::program_options::variables_map options_map;
    try {
        boost::program_options::store(boost::program_options::parse_command_line(argc, argv, options), options_map);
        boost::program_options::notify(options_map);
    } catch (boost::program_options::error_with_option_name const& e) {
        std::cout << e.what() << std::endl;
        std::cout << options << std::endl;
        return -1;
    }

    // 入力ファイル名でループ
    cv::Mat input_image;
    std::string header;
    std::vector<uchar> output_buffer;
    std::string output_filename;
    std::ofstream output_file;
    output_file.exceptions(std::ofstream::eofbit | std::ofstream::failbit | std::ofstream::badbit);

    for (std::string const& input_filename : input_filenames) {
        // 出力ファイル名の設定
        if (output_filename_base.size() == 0) {
            output_filename = input_filename;
        } else {
            output_filename = output_filename_base;
        }
        auto dotpos = output_filename.find_last_of('.');
        if (dotpos != std::string::npos) {
            output_filename.resize(dotpos);
        }
        output_filename += ext;

        // ヘッダ文字列の設定
        header.erase();
        header += (boost::format("# %1% %2%\n") % hsplit % vsplit).str();
        header += (boost::format("# %1%\n") % selectable).str();
        header += (boost::format("# %1% %2%\n") % select_cost % change_cost).str();

        // 画像読み込み
        input_image = cv::imread(input_filename);
        if (input_image.data == nullptr) {
            std::cerr << "Fatal: " << input_filename << " を読み込めませんでした" << std::endl;
            return -1;
        }

        // バッファへ書き込み
        cv::imencode(ext, input_image, output_buffer, std::vector<int>(CV_IMWRITE_PXM_BINARY));

        // ヘッダ流し込み
        // 先頭の "P6\n" の後にヘッダ文字列を挿入する
        output_buffer.insert(output_buffer.begin() + 3, header.begin(), header.end());

        // ファイル書き出し
        try {
            output_file.open(output_filename, std::ofstream::binary);
            std::copy(output_buffer.begin(), output_buffer.end(), std::ostream_iterator<uchar>(output_file));
            output_file.close();
        } catch (std::ofstream::failure e) {
            std::cerr << "Fatal: " << output_filename << " へ書き込めません";
            if (output_file.bad()) {
                std::cerr << " (bad)";
            } else if (output_file.fail()) {
                std::cerr << " (fail)";
            } else {
                std::cerr << " (eof)";
            }
            std::cerr << std::endl;
            return -1;
        }
    }
    return 0;
}
<|endoftext|>


<commit_before>//************************************************************/
//
//	Plot Implementation
//
//	Implements the SPXPlot class, which connects all of the
//  other non-configuration classes (non-steering/options) and
//	manages the plotting, drawing, and ROOT objects
//
//	@Author: 	J. Gibson, C. Embree, T. Carli - CERN ATLAS
//	@Date:		13.10.2014
//	@Email:		gibsjose@mail.gvsu.edu
//
//************************************************************/

#include <sstream>

#include "SPXPlot.h"
#include "SPXUtilities.h"

const std::string cn = "SPXPlot::";

//Must define the static debug variable in the implementation
bool SPXPlot::debug;

//Initialize all plots
void SPXPlot::Initialize(void) {
	try {
		InitializeData();
		InitializeCrossSections();
		NormalizeCrossSections();
	} catch(const SPXException &e) {
		throw;
	}
}

void SPXPlot::Plot(void) {
	std::string mn = "Plot:: ";

	SPXPlotConfiguration &pc = steeringFile->GetPlotConfiguration(id);

	std::ostringstream oss;
	oss << "canvas" << id;
	std::string canvasID = oss.str();

	//@TODO Where should these come from? Or are they just initial values that are set later?
	int wtopx = 200;	//Window top x
	int wtopy = 10;		//Window top y
	int ww = 700;		//Window width
	int wh = 500;		//Window height

	canvas = new TCanvas(canvasID.c_str(), pc.GetDescription().c_str(), wtopx, wtopy, ww, wh);
	canvas->SetFillColor(0);
	canvas->SetGrid();

	if(debug) {
		std::cout << cn << mn << "Canvas (" << canvasID << ") created for Plot ID " << id <<
			" with dimensions: " << ww << " x " << wh << " and title: " << pc.GetDescription() << std::endl;
	}

	//@TODO Where should these come from?
	double xMin; // = 0;
	double xMax; // = 3000;
	double yMin; // = 0;
	double yMax; // = 0.003;

	//Determine frame bounds by calculating the xmin, xmax, ymin, ymax from ALL graphs being drawn
	std::vector<TGraphAsymmErrors *> graphs;
	{
		//Data graphs
		for(int i = 0; i < data.size(); i++) {
			graphs.push_back(data[i].GetStatisticalErrorGraph());
			graphs.push_back(data[i].GetSystematicErrorGraph());
		}

		//Cross sections
		for(int i = 0; i < crossSections.size(); i++) {
			graphs.push_back(crossSections[i].GetPDFBandResults());
		}

		xMin = SPXGraphUtilities::GetXMin(graphs);
		xMax = SPXGraphUtilities::GetXMax(graphs);
		yMin = SPXGraphUtilities::GetYMin(graphs);
		yMax = SPXGraphUtilities::GetYMax(graphs);

		//Sanity check
		if(xMin > xMax) {
			throw SPXGraphException("xMin calculated to be larger than xMax");
		}

		if(yMin > yMax) {
			throw SPXGraphException("yMin calculated to be larger than yMax");
		}
	}

	//Draw the frame (xmin, ymin, xmax, ymax)
	canvas->DrawFrame(xMin, yMin, xMax, yMax);

	if(debug) {
		std::cout << cn << mn << "Canvas (" << canvasID << ") frame drawn with dimensions: " << std::endl;
		std::cout << "\t xMin = " << xMin << std::endl;
		std::cout << "\t xMax = " << xMax << std::endl;
		std::cout << "\t yMin = " << yMin << std::endl;
		std::cout << "\t yMax = " << yMax << std::endl;
	}

	//Draw data graphs
	for(int i = 0; i < data.size(); i++) {
		data[i].GetSystematicErrorGraph()->Draw("P");
		data[i].GetStatisticalErrorGraph()->Draw("||");
	}

	//Draw cross sections
	for(int i = 0; i < crossSections.size(); i++) {
		crossSections[i].GetPDFBandResults()->Draw("P");
	}

	//Update canvas
	canvas->Update();
}

//@TODO Where do I normalize cross section???
void SPXPlot::InitializeCrossSections(void) {
	std::string mn = "InitializeCrossSections: ";

	//Create cross sections for each configuration instance (and each PDF)
	for(int i = 0; i < steeringFile->GetNumberOfConfigurationInstances(id); i++) {
		for(int j = 0; j < steeringFile->GetNumberOfPDFSteeringFiles(); j++) {
			SPXPDFSteeringFile &psf = steeringFile->GetPDFSteeringFile(j);
			SPXPlotConfigurationInstance &pci = steeringFile->GetPlotConfigurationInstance(id, i);

			SPXCrossSection crossSectionInstance = SPXCrossSection(&psf, &pci);

			try {
				crossSectionInstance.Create();
				crossSections.push_back(crossSectionInstance);
			} catch(const SPXException &e) {
				throw;
			}
		}
	}
}

void SPXPlot::NormalizeCrossSections(void) {
	std::string mn = "NormalizeCrossSections: ";

	for(int i = 0; i < crossSections.size(); i++) {
		try {
			if(debug) std::cout << cn << mn << "Normalizing Cross Section at index " << i << std::endl;

			SPXPDFSteeringFile *psf = crossSections[i].GetPDFSteeringFile();
			SPXPlotConfigurationInstance *pci = crossSections[i].GetPlotConfigurationInstance();

			std::string masterXUnits = pci->dataSteeringFile.GetXUnits();
			std::string slaveXUnits = pci->gridSteeringFile.GetXUnits();
			std::string masterYUnits = pci->dataSteeringFile.GetYUnits();
			std::string slaveYUnits = pci->gridSteeringFile.GetYUnits();

			//Determine the scale from the unit difference between data and grid
			double xScale = SPXGraphUtilities::GetXUnitsScale(masterXUnits, slaveXUnits);
			double yScale = SPXGraphUtilities::GetYUnitsScale(masterYUnits, slaveYUnits);

			if(debug) {
				std::cout << cn << mn << "Scales determined from data/grid unit differential: " << std::endl;
				std::cout << "\t Data X Units: " << masterXUnits << std::endl;
				std::cout << "\t Grid X Units: " << slaveXUnits << std::endl << std::endl;
				std::cout << "\t Data Y Units: " << masterYUnits << std::endl;
				std::cout << "\t Grid Y Units: " << slaveYUnits << std::endl << std::endl;
				std::cout << "\t ---> X Unit Scale Determined: " << xScale << std::endl;
				std::cout << "\t ---> Y Unit Scale Determined: " << yScale << std::endl << std::endl;
			}

			//Also scale by the artificial scale from the plot configuration instance
			xScale *= pci->xScale;
			yScale *= pci->yScale;

			SPXGraphUtilities::Scale(crossSections[i].GetPDFBandResults(), xScale, yScale);

			if(debug) {
				std::cout << cn << mn << "Additional artificial scale for Cross Section: " << std::endl;
				std::cout << "\t X Scale: " << pci->xScale << std::endl;
				std::cout << "\t Y Scale: " << pci->yScale << std::endl << std::endl;
			}

			//Normalized to total sigma from the DATA steering file
			bool normalizeToTotalSigma = pci->dataSteeringFile.IsNormalizedToTotalSigma();
			bool dataDividedByBinWidth = pci->dataSteeringFile.IsDividedByBinWidth();
			bool gridDividedByBinWidth = pci->gridSteeringFile.IsDividedByBinWidth();

			bool divideByBinWidth = false;

			if(dataDividedByBinWidth && !gridDividedByBinWidth) {
				if(debug) std::cout << cn << mn << "Data IS divided by bin width but the grid IS NOT. Will call Normalize with divideByBinWidth = true" << std::endl;
				divideByBinWidth = true;
			}

			double yBinWidthScale = 1.0;

			//If the data is divided by the bin width, then set the yBinWidthScale, which is the scaling of the Data's Y Bin Width Units to the Data's X Units
			if(dataDividedByBinWidth) {
				yBinWidthScale = SPXGraphUtilities::GetYBinWidthUnitsScale(pci->dataSteeringFile.GetXUnits(), pci->dataSteeringFile.GetYBinWidthUnits());
			}

			if(debug) std::cout << cn << mn << "Y Bin Width Scale = " << yBinWidthScale << std::endl;
			if(debug) std::cout << cn << mn << "Normalize to Total Sigma is " << (normalizeToTotalSigma ? "ON" : "OFF") << std::endl;
			if(debug) std::cout << cn << mn << "Divide by Bin Width is " << (divideByBinWidth ? "ON" : "OFF") << std::endl;

			//Normalize the cross section
			SPXGraphUtilities::Normalize(crossSections[i].GetPDFBandResults(), yBinWidthScale, normalizeToTotalSigma, divideByBinWidth);

			if(debug) std::cout << cn << mn << "Sucessfully normalized Cross Section " << i << std::endl;
		} catch(const SPXException &e) {
			std::cerr << e.what() << std::endl;
			throw SPXGraphException("SPXPlot::NormalizeCrossSections: Unable to obtain X/Y Scale based on Data/Grid Units");
		}

	}
}

void SPXPlot::InitializeData(void) {
	std::string mn = "InitializeData: ";

	//Create data objects for each configuration instance of this plot and add them to vector
	for(int i = 0; i < steeringFile->GetNumberOfConfigurationInstances(id); i++) {
		SPXPlotConfigurationInstance &pci = steeringFile->GetPlotConfigurationInstance(id, i);

		SPXData dataInstance = SPXData(pci);

		try {
			dataInstance.Parse();
			dataInstance.Print();
			data.push_back(dataInstance);
		} catch(const SPXException &e) {
			throw;
		}
	}

	//Go through data objects and create graphs, modify settings, etc.
	for(int i = 0; i < data.size(); i++) {

		//Create graphs: once this function is called, it is safe to manipulate graphs
		data[i].CreateGraphs();

		//Obtain the graphs
		TGraphAsymmErrors *statGraph = data[i].GetStatisticalErrorGraph();
		TGraphAsymmErrors *systGraph = data[i].GetSystematicErrorGraph();

		//Get settings
		SPXPlotConfigurationInstance &pci = steeringFile->GetPlotConfigurationInstance(id, i);

		//Normalize the graphs based on the settings
		double xScale = pci.xScale;
		double yScale = pci.yScale;

		if(debug) {
			std::cout << cn << mn << "Scaling Data with: " << std::endl;
			std::cout << "\t X Scale = " << xScale << std::endl;
			std::cout << "\t Y Scale = " << yScale << std::endl;
		}

		SPXGraphUtilities::Scale(statGraph, xScale, yScale);
		SPXGraphUtilities::Scale(systGraph, xScale, yScale);

		//Modify Data Graph styles
		statGraph->SetMarkerStyle(pci.markerStyle);
		systGraph->SetMarkerStyle(pci.markerStyle);

		statGraph->SetMarkerColor(pci.markerColor);
		systGraph->SetMarkerColor(pci.markerColor);

		statGraph->SetMarkerSize(1.0);
		systGraph->SetMarkerSize(1.0);

		statGraph->SetLineColor(4);
		systGraph->SetLineColor(1);

		statGraph->SetLineWidth(1);
		systGraph->SetLineWidth(1);
	}
}<commit_msg>Modified divideByBinWidth: NORMALIZATION ACTUALLY TAKES DIVIDED<------ the past participle, not the imperative verb form...<commit_after>//************************************************************/
//
//	Plot Implementation
//
//	Implements the SPXPlot class, which connects all of the
//  other non-configuration classes (non-steering/options) and
//	manages the plotting, drawing, and ROOT objects
//
//	@Author: 	J. Gibson, C. Embree, T. Carli - CERN ATLAS
//	@Date:		13.10.2014
//	@Email:		gibsjose@mail.gvsu.edu
//
//************************************************************/

#include <sstream>

#include "SPXPlot.h"
#include "SPXUtilities.h"

const std::string cn = "SPXPlot::";

//Must define the static debug variable in the implementation
bool SPXPlot::debug;

//Initialize all plots
void SPXPlot::Initialize(void) {
	try {
		InitializeData();
		InitializeCrossSections();
		NormalizeCrossSections();
	} catch(const SPXException &e) {
		throw;
	}
}

void SPXPlot::Plot(void) {
	std::string mn = "Plot:: ";

	SPXPlotConfiguration &pc = steeringFile->GetPlotConfiguration(id);

	std::ostringstream oss;
	oss << "canvas" << id;
	std::string canvasID = oss.str();

	//@TODO Where should these come from? Or are they just initial values that are set later?
	int wtopx = 200;	//Window top x
	int wtopy = 10;		//Window top y
	int ww = 700;		//Window width
	int wh = 500;		//Window height

	canvas = new TCanvas(canvasID.c_str(), pc.GetDescription().c_str(), wtopx, wtopy, ww, wh);
	canvas->SetFillColor(0);
	canvas->SetGrid();

	if(debug) {
		std::cout << cn << mn << "Canvas (" << canvasID << ") created for Plot ID " << id <<
			" with dimensions: " << ww << " x " << wh << " and title: " << pc.GetDescription() << std::endl;
	}

	//@TODO Where should these come from?
	double xMin; // = 0;
	double xMax; // = 3000;
	double yMin; // = 0;
	double yMax; // = 0.003;

	//Determine frame bounds by calculating the xmin, xmax, ymin, ymax from ALL graphs being drawn
	std::vector<TGraphAsymmErrors *> graphs;
	{
		//Data graphs
		for(int i = 0; i < data.size(); i++) {
			graphs.push_back(data[i].GetStatisticalErrorGraph());
			graphs.push_back(data[i].GetSystematicErrorGraph());
		}

		//Cross sections
		for(int i = 0; i < crossSections.size(); i++) {
			graphs.push_back(crossSections[i].GetPDFBandResults());
		}

		xMin = SPXGraphUtilities::GetXMin(graphs);
		xMax = SPXGraphUtilities::GetXMax(graphs);
		yMin = SPXGraphUtilities::GetYMin(graphs);
		yMax = SPXGraphUtilities::GetYMax(graphs);

		//Sanity check
		if(xMin > xMax) {
			throw SPXGraphException("xMin calculated to be larger than xMax");
		}

		if(yMin > yMax) {
			throw SPXGraphException("yMin calculated to be larger than yMax");
		}
	}

	//Draw the frame (xmin, ymin, xmax, ymax)
	canvas->DrawFrame(xMin, yMin, xMax, yMax);

	if(debug) {
		std::cout << cn << mn << "Canvas (" << canvasID << ") frame drawn with dimensions: " << std::endl;
		std::cout << "\t xMin = " << xMin << std::endl;
		std::cout << "\t xMax = " << xMax << std::endl;
		std::cout << "\t yMin = " << yMin << std::endl;
		std::cout << "\t yMax = " << yMax << std::endl;
	}

	//Draw data graphs
	for(int i = 0; i < data.size(); i++) {
		data[i].GetSystematicErrorGraph()->Draw("P");
		data[i].GetStatisticalErrorGraph()->Draw("||");
	}

	//Draw cross sections
	for(int i = 0; i < crossSections.size(); i++) {
		crossSections[i].GetPDFBandResults()->Draw("P");
	}

	//Update canvas
	canvas->Update();
}

//@TODO Where do I normalize cross section???
void SPXPlot::InitializeCrossSections(void) {
	std::string mn = "InitializeCrossSections: ";

	//Create cross sections for each configuration instance (and each PDF)
	for(int i = 0; i < steeringFile->GetNumberOfConfigurationInstances(id); i++) {
		for(int j = 0; j < steeringFile->GetNumberOfPDFSteeringFiles(); j++) {
			SPXPDFSteeringFile &psf = steeringFile->GetPDFSteeringFile(j);
			SPXPlotConfigurationInstance &pci = steeringFile->GetPlotConfigurationInstance(id, i);

			SPXCrossSection crossSectionInstance = SPXCrossSection(&psf, &pci);

			try {
				crossSectionInstance.Create();
				crossSections.push_back(crossSectionInstance);
			} catch(const SPXException &e) {
				throw;
			}
		}
	}
}

void SPXPlot::NormalizeCrossSections(void) {
	std::string mn = "NormalizeCrossSections: ";

	for(int i = 0; i < crossSections.size(); i++) {
		try {
			if(debug) std::cout << cn << mn << "Normalizing Cross Section at index " << i << std::endl;

			SPXPDFSteeringFile *psf = crossSections[i].GetPDFSteeringFile();
			SPXPlotConfigurationInstance *pci = crossSections[i].GetPlotConfigurationInstance();

			std::string masterXUnits = pci->dataSteeringFile.GetXUnits();
			std::string slaveXUnits = pci->gridSteeringFile.GetXUnits();
			std::string masterYUnits = pci->dataSteeringFile.GetYUnits();
			std::string slaveYUnits = pci->gridSteeringFile.GetYUnits();

			//Determine the scale from the unit difference between data and grid
			double xScale = SPXGraphUtilities::GetXUnitsScale(masterXUnits, slaveXUnits);
			double yScale = SPXGraphUtilities::GetYUnitsScale(masterYUnits, slaveYUnits);

			if(debug) {
				std::cout << cn << mn << "Scales determined from data/grid unit differential: " << std::endl;
				std::cout << "\t Data X Units: " << masterXUnits << std::endl;
				std::cout << "\t Grid X Units: " << slaveXUnits << std::endl << std::endl;
				std::cout << "\t Data Y Units: " << masterYUnits << std::endl;
				std::cout << "\t Grid Y Units: " << slaveYUnits << std::endl << std::endl;
				std::cout << "\t ---> X Unit Scale Determined: " << xScale << std::endl;
				std::cout << "\t ---> Y Unit Scale Determined: " << yScale << std::endl << std::endl;
			}

			//Also scale by the artificial scale from the plot configuration instance
			xScale *= pci->xScale;
			yScale *= pci->yScale;

			SPXGraphUtilities::Scale(crossSections[i].GetPDFBandResults(), xScale, yScale);

			if(debug) {
				std::cout << cn << mn << "Additional artificial scale for Cross Section: " << std::endl;
				std::cout << "\t X Scale: " << pci->xScale << std::endl;
				std::cout << "\t Y Scale: " << pci->yScale << std::endl << std::endl;
			}

			//Normalized to total sigma from the DATA steering file
			bool normalizeToTotalSigma = pci->dataSteeringFile.IsNormalizedToTotalSigma();
			bool dataDividedByBinWidth = pci->dataSteeringFile.IsDividedByBinWidth();
			bool gridDividedByBinWidth = pci->gridSteeringFile.IsDividedByBinWidth();

			//@TODO Change back to being initialized as false
			bool divideByBinWidth = true;

			if(dataDividedByBinWidth && !gridDividedByBinWidth) {
				if(debug) std::cout << cn << mn << "Data IS divided by bin width but the grid IS NOT. Will call Normalize with divideByBinWidth = true" << std::endl;
				divideByBinWidth = true;
			}

			double yBinWidthScale = 1.0;

			//If the data is divided by the bin width, then set the yBinWidthScale, which is the scaling of the Data's Y Bin Width Units to the Data's X Units
			if(dataDividedByBinWidth) {
				yBinWidthScale = SPXGraphUtilities::GetYBinWidthUnitsScale(pci->dataSteeringFile.GetXUnits(), pci->dataSteeringFile.GetYBinWidthUnits());
			}

			if(debug) std::cout << cn << mn << "Y Bin Width Scale = " << yBinWidthScale << std::endl;
			if(debug) std::cout << cn << mn << "Normalize to Total Sigma is " << (normalizeToTotalSigma ? "ON" : "OFF") << std::endl;
			if(debug) std::cout << cn << mn << "Divide by Bin Width is " << (divideByBinWidth ? "ON" : "OFF") << std::endl;

			//Normalize the cross section
			SPXGraphUtilities::Normalize(crossSections[i].GetPDFBandResults(), yBinWidthScale, normalizeToTotalSigma, divideByBinWidth);

			if(debug) std::cout << cn << mn << "Sucessfully normalized Cross Section " << i << std::endl;
		} catch(const SPXException &e) {
			std::cerr << e.what() << std::endl;
			throw SPXGraphException("SPXPlot::NormalizeCrossSections: Unable to obtain X/Y Scale based on Data/Grid Units");
		}

	}
}

void SPXPlot::InitializeData(void) {
	std::string mn = "InitializeData: ";

	//Create data objects for each configuration instance of this plot and add them to vector
	for(int i = 0; i < steeringFile->GetNumberOfConfigurationInstances(id); i++) {
		SPXPlotConfigurationInstance &pci = steeringFile->GetPlotConfigurationInstance(id, i);

		SPXData dataInstance = SPXData(pci);

		try {
			dataInstance.Parse();
			dataInstance.Print();
			data.push_back(dataInstance);
		} catch(const SPXException &e) {
			throw;
		}
	}

	//Go through data objects and create graphs, modify settings, etc.
	for(int i = 0; i < data.size(); i++) {

		//Create graphs: once this function is called, it is safe to manipulate graphs
		data[i].CreateGraphs();

		//Obtain the graphs
		TGraphAsymmErrors *statGraph = data[i].GetStatisticalErrorGraph();
		TGraphAsymmErrors *systGraph = data[i].GetSystematicErrorGraph();

		//Get settings
		SPXPlotConfigurationInstance &pci = steeringFile->GetPlotConfigurationInstance(id, i);

		//Normalize the graphs based on the settings
		double xScale = pci.xScale;
		double yScale = pci.yScale;

		if(debug) {
			std::cout << cn << mn << "Scaling Data with: " << std::endl;
			std::cout << "\t X Scale = " << xScale << std::endl;
			std::cout << "\t Y Scale = " << yScale << std::endl;
		}

		SPXGraphUtilities::Scale(statGraph, xScale, yScale);
		SPXGraphUtilities::Scale(systGraph, xScale, yScale);

		//Modify Data Graph styles
		statGraph->SetMarkerStyle(pci.markerStyle);
		systGraph->SetMarkerStyle(pci.markerStyle);

		statGraph->SetMarkerColor(pci.markerColor);
		systGraph->SetMarkerColor(pci.markerColor);

		statGraph->SetMarkerSize(1.0);
		systGraph->SetMarkerSize(1.0);

		statGraph->SetLineColor(4);
		systGraph->SetLineColor(1);

		statGraph->SetLineWidth(1);
		systGraph->SetLineWidth(1);
	}
}<|endoftext|>


<commit_before>/*
 *  Seek camera interface
 *  Author: Maarten Vandersteegen
 */

#include "SeekCam.h"
#include "SeekLogging.h"
#include <iomanip>

using namespace LibSeek;

SeekCam::SeekCam(int vendor_id, int product_id, uint16_t* buffer, size_t raw_height, size_t raw_width, size_t request_size, cv::Rect roi, std::string ffc_filename) :
    m_offset(0x4000),
    m_ffc_filename(ffc_filename),
    m_is_opened(false),
    m_dev(vendor_id, product_id),
    m_raw_data(buffer),
    m_raw_data_size(raw_height * raw_width),
    m_raw_frame(raw_height,
                raw_width,
                CV_16UC1,
                buffer,
                cv::Mat::AUTO_STEP),
    m_request_size(request_size),
    m_flat_field_calibration_frame(),
    m_additional_ffc(),
    m_dead_pixel_mask()
{
    /* set ROI to exclude metadata frame regions */
    m_raw_frame = m_raw_frame(roi);
}

SeekCam::~SeekCam()
{
    close();
}

bool SeekCam::open()
{
    if (m_ffc_filename != std::string()) {
        m_additional_ffc = cv::imread(m_ffc_filename, -1);

        if (m_additional_ffc.type() != m_raw_frame.type()) {
            error("Error: '%s' not found or it has the wrong type: %d\n",
                    m_ffc_filename.c_str(), m_additional_ffc.type());
            return false;
        }

        if (m_additional_ffc.size() != m_raw_frame.size()) {
            error("Error: expected '%s' to have size [%d,%d], got [%d,%d]\n",
                    m_ffc_filename.c_str(),
                    m_raw_frame.cols, m_raw_frame.rows,
                    m_additional_ffc.cols, m_additional_ffc.rows);
            return false;
        }
    }

    return open_cam();
}

void SeekCam::close()
{
    if (m_dev.isOpened()) {
        std::vector<uint8_t> data = { 0x00, 0x00 };
        m_dev.request_set(DeviceCommand::SET_OPERATION_MODE, data);
        m_dev.request_set(DeviceCommand::SET_OPERATION_MODE, data);
        m_dev.request_set(DeviceCommand::SET_OPERATION_MODE, data);
    }
    m_is_opened = false;
}

bool SeekCam::isOpened()
{
    return m_is_opened;
}

bool SeekCam::grab()
{
    int i;

    for (i=0; i<40; i++) {
        if(!get_frame()) {
            error("Error: frame acquisition failed\n");
            return false;
        }

        if (frame_id() == 3) {
            return true;

        } else if (frame_id() == 1) {
            m_raw_frame.copyTo(m_flat_field_calibration_frame);
        }
    }

    return false;
}

void SeekCam::retrieve(cv::Mat& dst)
{
    /* apply flat field calibration */
    m_raw_frame += m_offset - m_flat_field_calibration_frame;
    /* filter out dead pixels */
    apply_dead_pixel_filter(m_raw_frame, dst);
    /* apply additional flat field calibration for degradient */
    if (!m_additional_ffc.empty())
        dst += m_offset - m_additional_ffc;
}

bool SeekCam::read(cv::Mat& dst)
{
    if (!grab())
        return false;

    retrieve(dst);

    return true;
}

void SeekCam::convertToGreyScale(cv::Mat& src, cv::Mat& dst)
{
    double tmin, tmax, rsize;
    double rnint = 0;
    double rnstart = 0;
    size_t n;
    size_t num_of_pixels = src.rows * src.cols;

    cv::minMaxLoc(src, &tmin, &tmax);
    rsize = (tmax - tmin) / 10.0;

    for (n=0; n<10; n++) {
        double min = tmin + n * rsize;
        cv::Mat mask;
        cv::Mat temp;

        rnstart += rnint;
        cv::inRange(src, cv::Scalar(min), cv::Scalar(min + rsize), mask);
        /* num_of_pixels_in_range / total_num_of_pixels * 256 */
        rnint = (cv::countNonZero(mask) << 8) / num_of_pixels;

        temp = ((src - min) * rnint) / rsize + rnstart;
        temp.copyTo(dst, mask);
    }
    dst.convertTo(dst, CV_8UC1);
}

bool SeekCam::open_cam()
{
    int i;

    if (!m_dev.open()) {
        error("Error: open failed\n");
        return false;
    }

    /* init retry loop: sometimes cam skips first 512 bytes of first frame (needed for dead pixel filter) */
    for (i=0; i<3; i++) {
        /* cam specific configuration */
        if (!init_cam()) {
            error("Error: init_cam failed\n");
            return false;
        }

        if (!get_frame()) {
            error("Error: first frame acquisition failed, retry attempt %d\n", i+1);
            continue;
        }

        if (frame_id() != 4) {
            error("Error: expected first frame to have id 4\n");
            return false;
        }

        create_dead_pixel_list(m_raw_frame, m_dead_pixel_mask, m_dead_pixel_list);

        if (!grab()) {
            error("Error: first grab failed\n");
            return false;
        }

        m_is_opened = true;
        return true;
    }

    error("Error: max init retry count exceeded\n");
    return false;
}

bool SeekCam::get_frame()
{
    /* request new frame */
    uint8_t* s = reinterpret_cast<uint8_t*>(&m_raw_data_size);

    std::vector<uint8_t> data = { s[0], s[1], s[2], s[3] };
    if (!m_dev.request_set(DeviceCommand::START_GET_IMAGE_TRANSFER, data))
        return false;

    /* store frame data */
    if (!m_dev.fetch_frame(m_raw_data, m_raw_data_size, m_request_size))
        return false;

    return true;
}

void SeekCam::print_usb_data(std::vector<uint8_t>& data)
{
    std::stringstream ss;
    std::string out;

    ss << "Response:";
    for (size_t i = 0; i < data.size(); i++) {
        ss << " " << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(data[i]);
    }
    out = ss.str();
    debug("%s\n", out.c_str());
}

void SeekCam::create_dead_pixel_list(cv::Mat frame, cv::Mat& dead_pixel_mask,
                                            std::vector<cv::Point>& dead_pixel_list)
{
    int x, y;
    bool has_unlisted_pixels;
    double max_value;
    cv::Point hist_max_value;
    cv::Mat tmp, hist;
    int channels[] = {0};
    int histSize[] = {0x4000};
    float range[] = {0, 0x4000};
    const float* ranges[] = { range };

    /* calculate optimal threshold to determine what pixels are dead pixels */
    frame.convertTo(tmp, CV_32FC1);
    cv::minMaxLoc(tmp, nullptr, &max_value);
    cv::calcHist(&tmp, 1, channels, cv::Mat(), hist, 1, histSize, ranges,
                        true,       /* the histogram is uniform */
                        false);
    hist.at<float>(0, 0) = 0;       /* suppres 0th bin since its usual the highest,
                                    but we don't want this one */
    cv::minMaxLoc(hist, nullptr, nullptr, nullptr, &hist_max_value);
    const double threshold = hist_max_value.y - (max_value - hist_max_value.y);

    /* calculate the dead pixels mask */
    cv::threshold(tmp, tmp, threshold, 255, cv::THRESH_BINARY);
    tmp.convertTo(dead_pixel_mask, CV_8UC1);

    /* build dead pixel list in a certain order to assure that every dead pixel value
     * gets an estimated value in the filter stage */
    dead_pixel_mask.convertTo(tmp, CV_16UC1);
    dead_pixel_list.clear();
    do {
        has_unlisted_pixels = false;

        for (y=0; y<tmp.rows; y++) {
            for (x=0; x<tmp.cols; x++) {
                const cv::Point p(x, y);

                if (tmp.at<uint16_t>(y, x) != 0)
                    continue;   /* not a dead pixel */

                /* only add pixel to the list if we can estimate its value
                 * directly from its neighbor pixels */
                if (calc_mean_value(tmp, p, 0) != 0) {
                    dead_pixel_list.push_back(p);
                    tmp.at<uint16_t>(y, x) = 255;
                } else
                    has_unlisted_pixels = true;
            }
        }
    } while (has_unlisted_pixels);
}

void SeekCam::apply_dead_pixel_filter(cv::Mat& src, cv::Mat& dst)
{
    size_t i;
    const size_t size = m_dead_pixel_list.size();
    const uint32_t dead_pixel_marker = 0xffff;

    dst.create(src.rows, src.cols, src.type()); /* ensure dst is properly allocated */
    dst.setTo(dead_pixel_marker);               /* value to identify dead pixels */
    src.copyTo(dst, m_dead_pixel_mask);         /* only copy non dead pixel values */

    /* replace dead pixel values (0xffff) with the mean of its non dead surrounding pixels */
    for (i=0; i<size; i++) {
        cv::Point p = m_dead_pixel_list[i];
        dst.at<uint16_t>(p) = calc_mean_value(dst, p, dead_pixel_marker);
    }
}

uint16_t SeekCam::calc_mean_value(cv::Mat& img, cv::Point p, uint32_t dead_pixel_marker)
{
    uint32_t value = 0, temp;
    uint32_t div = 0;
    const int right_border = img.cols - 1;
    const int lower_border = img.rows - 1;

    if (p.x != 0) {
        /* if not on the left border of the image */
        temp = img.at<uint16_t>(p.y, p.x-1);
        if (temp != dead_pixel_marker) {
            value += temp;
            div++;
        }
    }
    if (p.x != right_border) {
        /* if not on the right border of the image */
        temp = img.at<uint16_t>(p.y, p.x+1);
        if (temp != dead_pixel_marker) {
            value += temp;
            div++;
        }
    }
    if (p.y != 0) {
        /* upper */
        temp = img.at<uint16_t>(p.y-1, p.x);
        if (temp != dead_pixel_marker) {
            value += temp;
            div++;
        }
    }
    if (p.y != lower_border) {
        /* lower */
        temp = img.at<uint16_t>(p.y+1, p.x);
        if (temp != dead_pixel_marker) {
            value += temp;
            div++;
        }
    }

    if (div)
        return (value / div);

    return 0;
}
<commit_msg>Fix warning (wrong initialization order) (#53)<commit_after>/*
 *  Seek camera interface
 *  Author: Maarten Vandersteegen
 */

#include "SeekCam.h"
#include "SeekLogging.h"
#include <iomanip>

using namespace LibSeek;

SeekCam::SeekCam(int vendor_id, int product_id, uint16_t* buffer, size_t raw_height, size_t raw_width, size_t request_size, cv::Rect roi, std::string ffc_filename) :
    m_offset(0x4000),
    m_ffc_filename(ffc_filename),
    m_is_opened(false),
    m_dev(vendor_id, product_id),
    m_raw_data(buffer),
    m_raw_data_size(raw_height * raw_width),
    m_request_size(request_size),
    m_raw_frame(raw_height,
                raw_width,
                CV_16UC1,
                buffer,
                cv::Mat::AUTO_STEP),
    m_flat_field_calibration_frame(),
    m_additional_ffc(),
    m_dead_pixel_mask()
{
    /* set ROI to exclude metadata frame regions */
    m_raw_frame = m_raw_frame(roi);
}

SeekCam::~SeekCam()
{
    close();
}

bool SeekCam::open()
{
    if (m_ffc_filename != std::string()) {
        m_additional_ffc = cv::imread(m_ffc_filename, -1);

        if (m_additional_ffc.type() != m_raw_frame.type()) {
            error("Error: '%s' not found or it has the wrong type: %d\n",
                    m_ffc_filename.c_str(), m_additional_ffc.type());
            return false;
        }

        if (m_additional_ffc.size() != m_raw_frame.size()) {
            error("Error: expected '%s' to have size [%d,%d], got [%d,%d]\n",
                    m_ffc_filename.c_str(),
                    m_raw_frame.cols, m_raw_frame.rows,
                    m_additional_ffc.cols, m_additional_ffc.rows);
            return false;
        }
    }

    return open_cam();
}

void SeekCam::close()
{
    if (m_dev.isOpened()) {
        std::vector<uint8_t> data = { 0x00, 0x00 };
        m_dev.request_set(DeviceCommand::SET_OPERATION_MODE, data);
        m_dev.request_set(DeviceCommand::SET_OPERATION_MODE, data);
        m_dev.request_set(DeviceCommand::SET_OPERATION_MODE, data);
    }
    m_is_opened = false;
}

bool SeekCam::isOpened()
{
    return m_is_opened;
}

bool SeekCam::grab()
{
    int i;

    for (i=0; i<40; i++) {
        if(!get_frame()) {
            error("Error: frame acquisition failed\n");
            return false;
        }

        if (frame_id() == 3) {
            return true;

        } else if (frame_id() == 1) {
            m_raw_frame.copyTo(m_flat_field_calibration_frame);
        }
    }

    return false;
}

void SeekCam::retrieve(cv::Mat& dst)
{
    /* apply flat field calibration */
    m_raw_frame += m_offset - m_flat_field_calibration_frame;
    /* filter out dead pixels */
    apply_dead_pixel_filter(m_raw_frame, dst);
    /* apply additional flat field calibration for degradient */
    if (!m_additional_ffc.empty())
        dst += m_offset - m_additional_ffc;
}

bool SeekCam::read(cv::Mat& dst)
{
    if (!grab())
        return false;

    retrieve(dst);

    return true;
}

void SeekCam::convertToGreyScale(cv::Mat& src, cv::Mat& dst)
{
    double tmin, tmax, rsize;
    double rnint = 0;
    double rnstart = 0;
    size_t n;
    size_t num_of_pixels = src.rows * src.cols;

    cv::minMaxLoc(src, &tmin, &tmax);
    rsize = (tmax - tmin) / 10.0;

    for (n=0; n<10; n++) {
        double min = tmin + n * rsize;
        cv::Mat mask;
        cv::Mat temp;

        rnstart += rnint;
        cv::inRange(src, cv::Scalar(min), cv::Scalar(min + rsize), mask);
        /* num_of_pixels_in_range / total_num_of_pixels * 256 */
        rnint = (cv::countNonZero(mask) << 8) / num_of_pixels;

        temp = ((src - min) * rnint) / rsize + rnstart;
        temp.copyTo(dst, mask);
    }
    dst.convertTo(dst, CV_8UC1);
}

bool SeekCam::open_cam()
{
    int i;

    if (!m_dev.open()) {
        error("Error: open failed\n");
        return false;
    }

    /* init retry loop: sometimes cam skips first 512 bytes of first frame (needed for dead pixel filter) */
    for (i=0; i<3; i++) {
        /* cam specific configuration */
        if (!init_cam()) {
            error("Error: init_cam failed\n");
            return false;
        }

        if (!get_frame()) {
            error("Error: first frame acquisition failed, retry attempt %d\n", i+1);
            continue;
        }

        if (frame_id() != 4) {
            error("Error: expected first frame to have id 4\n");
            return false;
        }

        create_dead_pixel_list(m_raw_frame, m_dead_pixel_mask, m_dead_pixel_list);

        if (!grab()) {
            error("Error: first grab failed\n");
            return false;
        }

        m_is_opened = true;
        return true;
    }

    error("Error: max init retry count exceeded\n");
    return false;
}

bool SeekCam::get_frame()
{
    /* request new frame */
    uint8_t* s = reinterpret_cast<uint8_t*>(&m_raw_data_size);

    std::vector<uint8_t> data = { s[0], s[1], s[2], s[3] };
    if (!m_dev.request_set(DeviceCommand::START_GET_IMAGE_TRANSFER, data))
        return false;

    /* store frame data */
    if (!m_dev.fetch_frame(m_raw_data, m_raw_data_size, m_request_size))
        return false;

    return true;
}

void SeekCam::print_usb_data(std::vector<uint8_t>& data)
{
    std::stringstream ss;
    std::string out;

    ss << "Response:";
    for (size_t i = 0; i < data.size(); i++) {
        ss << " " << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(data[i]);
    }
    out = ss.str();
    debug("%s\n", out.c_str());
}

void SeekCam::create_dead_pixel_list(cv::Mat frame, cv::Mat& dead_pixel_mask,
                                            std::vector<cv::Point>& dead_pixel_list)
{
    int x, y;
    bool has_unlisted_pixels;
    double max_value;
    cv::Point hist_max_value;
    cv::Mat tmp, hist;
    int channels[] = {0};
    int histSize[] = {0x4000};
    float range[] = {0, 0x4000};
    const float* ranges[] = { range };

    /* calculate optimal threshold to determine what pixels are dead pixels */
    frame.convertTo(tmp, CV_32FC1);
    cv::minMaxLoc(tmp, nullptr, &max_value);
    cv::calcHist(&tmp, 1, channels, cv::Mat(), hist, 1, histSize, ranges,
                        true,       /* the histogram is uniform */
                        false);
    hist.at<float>(0, 0) = 0;       /* suppres 0th bin since its usual the highest,
                                    but we don't want this one */
    cv::minMaxLoc(hist, nullptr, nullptr, nullptr, &hist_max_value);
    const double threshold = hist_max_value.y - (max_value - hist_max_value.y);

    /* calculate the dead pixels mask */
    cv::threshold(tmp, tmp, threshold, 255, cv::THRESH_BINARY);
    tmp.convertTo(dead_pixel_mask, CV_8UC1);

    /* build dead pixel list in a certain order to assure that every dead pixel value
     * gets an estimated value in the filter stage */
    dead_pixel_mask.convertTo(tmp, CV_16UC1);
    dead_pixel_list.clear();
    do {
        has_unlisted_pixels = false;

        for (y=0; y<tmp.rows; y++) {
            for (x=0; x<tmp.cols; x++) {
                const cv::Point p(x, y);

                if (tmp.at<uint16_t>(y, x) != 0)
                    continue;   /* not a dead pixel */

                /* only add pixel to the list if we can estimate its value
                 * directly from its neighbor pixels */
                if (calc_mean_value(tmp, p, 0) != 0) {
                    dead_pixel_list.push_back(p);
                    tmp.at<uint16_t>(y, x) = 255;
                } else
                    has_unlisted_pixels = true;
            }
        }
    } while (has_unlisted_pixels);
}

void SeekCam::apply_dead_pixel_filter(cv::Mat& src, cv::Mat& dst)
{
    size_t i;
    const size_t size = m_dead_pixel_list.size();
    const uint32_t dead_pixel_marker = 0xffff;

    dst.create(src.rows, src.cols, src.type()); /* ensure dst is properly allocated */
    dst.setTo(dead_pixel_marker);               /* value to identify dead pixels */
    src.copyTo(dst, m_dead_pixel_mask);         /* only copy non dead pixel values */

    /* replace dead pixel values (0xffff) with the mean of its non dead surrounding pixels */
    for (i=0; i<size; i++) {
        cv::Point p = m_dead_pixel_list[i];
        dst.at<uint16_t>(p) = calc_mean_value(dst, p, dead_pixel_marker);
    }
}

uint16_t SeekCam::calc_mean_value(cv::Mat& img, cv::Point p, uint32_t dead_pixel_marker)
{
    uint32_t value = 0, temp;
    uint32_t div = 0;
    const int right_border = img.cols - 1;
    const int lower_border = img.rows - 1;

    if (p.x != 0) {
        /* if not on the left border of the image */
        temp = img.at<uint16_t>(p.y, p.x-1);
        if (temp != dead_pixel_marker) {
            value += temp;
            div++;
        }
    }
    if (p.x != right_border) {
        /* if not on the right border of the image */
        temp = img.at<uint16_t>(p.y, p.x+1);
        if (temp != dead_pixel_marker) {
            value += temp;
            div++;
        }
    }
    if (p.y != 0) {
        /* upper */
        temp = img.at<uint16_t>(p.y-1, p.x);
        if (temp != dead_pixel_marker) {
            value += temp;
            div++;
        }
    }
    if (p.y != lower_border) {
        /* lower */
        temp = img.at<uint16_t>(p.y+1, p.x);
        if (temp != dead_pixel_marker) {
            value += temp;
            div++;
        }
    }

    if (div)
        return (value / div);

    return 0;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <numeric>
#include <vector>

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/array_view.h"
#include "webrtc/base/random.h"
#include "webrtc/modules/audio_processing/audio_buffer.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/modules/audio_processing/level_controller/level_controller.h"
#include "webrtc/modules/audio_processing/test/audio_buffer_tools.h"
#include "webrtc/modules/audio_processing/test/bitexactness_tools.h"
#include "webrtc/system_wrappers/include/clock.h"
#include "webrtc/test/testsupport/perf_test.h"

namespace webrtc {
namespace {

const size_t kNumFramesToProcess = 100;

struct SimulatorBuffers {
  SimulatorBuffers(int render_input_sample_rate_hz,
                   int capture_input_sample_rate_hz,
                   int render_output_sample_rate_hz,
                   int capture_output_sample_rate_hz,
                   size_t num_render_input_channels,
                   size_t num_capture_input_channels,
                   size_t num_render_output_channels,
                   size_t num_capture_output_channels) {
    Random rand_gen(42);
    CreateConfigAndBuffer(render_input_sample_rate_hz,
                          num_render_input_channels, &rand_gen,
                          &render_input_buffer, &render_input_config,
                          &render_input, &render_input_samples);

    CreateConfigAndBuffer(render_output_sample_rate_hz,
                          num_render_output_channels, &rand_gen,
                          &render_output_buffer, &render_output_config,
                          &render_output, &render_output_samples);

    CreateConfigAndBuffer(capture_input_sample_rate_hz,
                          num_capture_input_channels, &rand_gen,
                          &capture_input_buffer, &capture_input_config,
                          &capture_input, &capture_input_samples);

    CreateConfigAndBuffer(capture_output_sample_rate_hz,
                          num_capture_output_channels, &rand_gen,
                          &capture_output_buffer, &capture_output_config,
                          &capture_output, &capture_output_samples);

    UpdateInputBuffers();
  }

  void CreateConfigAndBuffer(int sample_rate_hz,
                             size_t num_channels,
                             Random* rand_gen,
                             std::unique_ptr<AudioBuffer>* buffer,
                             StreamConfig* config,
                             std::vector<float*>* buffer_data,
                             std::vector<float>* buffer_data_samples) {
    int samples_per_channel = rtc::CheckedDivExact(sample_rate_hz, 100);
    *config = StreamConfig(sample_rate_hz, num_channels, false);
    buffer->reset(new AudioBuffer(config->num_frames(), config->num_channels(),
                                  config->num_frames(), config->num_channels(),
                                  config->num_frames()));

    buffer_data_samples->resize(samples_per_channel * num_channels);
    for (auto& v : *buffer_data_samples) {
      v = rand_gen->Rand<float>();
    }

    buffer_data->resize(num_channels);
    for (size_t ch = 0; ch < num_channels; ++ch) {
      (*buffer_data)[ch] = &(*buffer_data_samples)[ch * samples_per_channel];
    }
  }

  void UpdateInputBuffers() {
    test::CopyVectorToAudioBuffer(capture_input_config, capture_input_samples,
                                  capture_input_buffer.get());
    test::CopyVectorToAudioBuffer(render_input_config, render_input_samples,
                                  render_input_buffer.get());
  }

  std::unique_ptr<AudioBuffer> render_input_buffer;
  std::unique_ptr<AudioBuffer> capture_input_buffer;
  std::unique_ptr<AudioBuffer> render_output_buffer;
  std::unique_ptr<AudioBuffer> capture_output_buffer;
  StreamConfig render_input_config;
  StreamConfig capture_input_config;
  StreamConfig render_output_config;
  StreamConfig capture_output_config;
  std::vector<float*> render_input;
  std::vector<float> render_input_samples;
  std::vector<float*> capture_input;
  std::vector<float> capture_input_samples;
  std::vector<float*> render_output;
  std::vector<float> render_output_samples;
  std::vector<float*> capture_output;
  std::vector<float> capture_output_samples;
};

class SubmodulePerformanceTimer {
 public:
  SubmodulePerformanceTimer() : clock_(webrtc::Clock::GetRealTimeClock()) {
    timestamps_us_.reserve(kNumFramesToProcess);
  }

  void StartTimer() {
    start_timestamp_us_ = rtc::Optional<int64_t>(clock_->TimeInMicroseconds());
  }
  void StopTimer() {
    RTC_DCHECK(start_timestamp_us_);
    timestamps_us_.push_back(clock_->TimeInMicroseconds() -
                             *start_timestamp_us_);
  }

  double GetDurationAverage() const {
    RTC_DCHECK(!timestamps_us_.empty());
    return static_cast<double>(std::accumulate(timestamps_us_.begin(),
                                               timestamps_us_.end(), 0)) /
           timestamps_us_.size();
  }

  double GetDurationStandardDeviation() const {
    RTC_DCHECK(!timestamps_us_.empty());
    double average_duration = GetDurationAverage();

    int64_t variance =
        std::accumulate(timestamps_us_.begin(), timestamps_us_.end(), 0,
                        [average_duration](const int64_t& a, const int64_t& b) {
                          return a + (b - average_duration);
                        });

    return sqrt(variance / timestamps_us_.size());
  }

 private:
  webrtc::Clock* clock_;
  rtc::Optional<int64_t> start_timestamp_us_;
  std::vector<int64_t> timestamps_us_;
};

std::string FormPerformanceMeasureString(
    const SubmodulePerformanceTimer& timer) {
  std::string s = std::to_string(timer.GetDurationAverage());
  s += ", ";
  s += std::to_string(timer.GetDurationStandardDeviation());
  return s;
}

void RunStandaloneSubmodule(int sample_rate_hz, size_t num_channels) {
  SimulatorBuffers buffers(sample_rate_hz, sample_rate_hz, sample_rate_hz,
                           sample_rate_hz, num_channels, num_channels,
                           num_channels, num_channels);
  SubmodulePerformanceTimer timer;

  LevelController level_controller;
  level_controller.Initialize(sample_rate_hz);

  for (size_t frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) {
    buffers.UpdateInputBuffers();

    timer.StartTimer();
    level_controller.Process(buffers.capture_input_buffer.get());
    timer.StopTimer();
  }
  webrtc::test::PrintResultMeanAndError(
      "level_controller_call_durations",
      "_" + std::to_string(sample_rate_hz) + "Hz_" +
          std::to_string(num_channels) + "_channels",
      "StandaloneLevelControl", FormPerformanceMeasureString(timer), "us",
      false);
}

void RunTogetherWithApm(std::string test_description,
                        int render_input_sample_rate_hz,
                        int render_output_sample_rate_hz,
                        int capture_input_sample_rate_hz,
                        int capture_output_sample_rate_hz,
                        size_t num_channels,
                        bool use_mobile_aec,
                        bool include_default_apm_processing) {
  SimulatorBuffers buffers(
      render_input_sample_rate_hz, capture_input_sample_rate_hz,
      render_output_sample_rate_hz, capture_output_sample_rate_hz, num_channels,
      num_channels, num_channels, num_channels);
  SubmodulePerformanceTimer render_timer;
  SubmodulePerformanceTimer capture_timer;
  SubmodulePerformanceTimer total_timer;

  Config config;
  if (include_default_apm_processing) {
    config.Set<DelayAgnostic>(new DelayAgnostic(true));
    config.Set<ExtendedFilter>(new ExtendedFilter(true));
  }
  config.Set<LevelControl>(new LevelControl(true));

  std::unique_ptr<AudioProcessing> apm;
  apm.reset(AudioProcessing::Create(config));
  ASSERT_TRUE(apm.get());

  ASSERT_EQ(AudioProcessing::kNoError,
            apm->gain_control()->Enable(include_default_apm_processing));
  if (use_mobile_aec) {
    ASSERT_EQ(AudioProcessing::kNoError,
              apm->echo_cancellation()->Enable(false));
    ASSERT_EQ(AudioProcessing::kNoError, apm->echo_control_mobile()->Enable(
                                             include_default_apm_processing));
  } else {
    ASSERT_EQ(AudioProcessing::kNoError,
              apm->echo_cancellation()->Enable(include_default_apm_processing));
    ASSERT_EQ(AudioProcessing::kNoError,
              apm->echo_control_mobile()->Enable(false));
  }
  ASSERT_EQ(AudioProcessing::kNoError,
            apm->high_pass_filter()->Enable(include_default_apm_processing));
  ASSERT_EQ(AudioProcessing::kNoError,
            apm->noise_suppression()->Enable(include_default_apm_processing));
  ASSERT_EQ(AudioProcessing::kNoError,
            apm->voice_detection()->Enable(include_default_apm_processing));
  ASSERT_EQ(AudioProcessing::kNoError,
            apm->level_estimator()->Enable(include_default_apm_processing));

  StreamConfig render_input_config(render_input_sample_rate_hz, num_channels,
                                   false);
  StreamConfig render_output_config(render_output_sample_rate_hz, num_channels,
                                    false);
  StreamConfig capture_input_config(capture_input_sample_rate_hz, num_channels,
                                    false);
  StreamConfig capture_output_config(capture_output_sample_rate_hz,
                                     num_channels, false);

  for (size_t frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) {
    buffers.UpdateInputBuffers();

    total_timer.StartTimer();
    render_timer.StartTimer();
    ASSERT_EQ(AudioProcessing::kNoError,
              apm->ProcessReverseStream(
                  &buffers.render_input[0], render_input_config,
                  render_output_config, &buffers.render_output[0]));

    render_timer.StopTimer();

    capture_timer.StartTimer();
    ASSERT_EQ(AudioProcessing::kNoError, apm->set_stream_delay_ms(0));
    ASSERT_EQ(
        AudioProcessing::kNoError,
        apm->ProcessStream(&buffers.capture_input[0], capture_input_config,
                           capture_output_config, &buffers.capture_output[0]));

    capture_timer.StopTimer();
    total_timer.StopTimer();
  }

  webrtc::test::PrintResultMeanAndError(
      "level_controller_call_durations",
      "_" + std::to_string(render_input_sample_rate_hz) + "_" +
          std::to_string(render_output_sample_rate_hz) + "_" +
          std::to_string(capture_input_sample_rate_hz) + "_" +
          std::to_string(capture_output_sample_rate_hz) + "Hz_" +
          std::to_string(num_channels) + "_channels" + "_render",
      test_description, FormPerformanceMeasureString(render_timer), "us",
      false);
  webrtc::test::PrintResultMeanAndError(
      "level_controller_call_durations",
      "_" + std::to_string(render_input_sample_rate_hz) + "_" +
          std::to_string(render_output_sample_rate_hz) + "_" +
          std::to_string(capture_input_sample_rate_hz) + "_" +
          std::to_string(capture_output_sample_rate_hz) + "Hz_" +
          std::to_string(num_channels) + "_channels" + "_capture",
      test_description, FormPerformanceMeasureString(capture_timer), "us",
      false);
  webrtc::test::PrintResultMeanAndError(
      "level_controller_call_durations",
      "_" + std::to_string(render_input_sample_rate_hz) + "_" +
          std::to_string(render_output_sample_rate_hz) + "_" +
          std::to_string(capture_input_sample_rate_hz) + "_" +
          std::to_string(capture_output_sample_rate_hz) + "Hz_" +
          std::to_string(num_channels) + "_channels" + "_total",
      test_description, FormPerformanceMeasureString(total_timer), "us", false);
}

}  // namespace

TEST(LevelControllerPerformanceTest, StandaloneProcessing) {
  int sample_rates_to_test[] = {
      AudioProcessing::kSampleRate8kHz, AudioProcessing::kSampleRate16kHz,
      AudioProcessing::kSampleRate32kHz, AudioProcessing::kSampleRate48kHz};
  for (auto sample_rate : sample_rates_to_test) {
    for (size_t num_channels = 1; num_channels <= 2; ++num_channels) {
      RunStandaloneSubmodule(sample_rate, num_channels);
    }
  }
}

TEST(LevelControllerPerformanceTest, ProcessingViaApm) {
  int sample_rates_to_test[] = {AudioProcessing::kSampleRate8kHz,
                                AudioProcessing::kSampleRate16kHz,
                                AudioProcessing::kSampleRate32kHz,
                                AudioProcessing::kSampleRate48kHz, 44100};
  for (auto capture_input_sample_rate_hz : sample_rates_to_test) {
    for (auto capture_output_sample_rate_hz : sample_rates_to_test) {
      for (size_t num_channels = 1; num_channels <= 2; ++num_channels) {
        RunTogetherWithApm("SimpleLevelControlViaApm", 48000, 48000,
                           capture_input_sample_rate_hz,
                           capture_output_sample_rate_hz, num_channels, false,
                           false);
      }
    }
  }
}

TEST(LevelControllerPerformanceTest, InteractionWithDefaultApm) {
  int sample_rates_to_test[] = {AudioProcessing::kSampleRate8kHz,
                                AudioProcessing::kSampleRate16kHz,
                                AudioProcessing::kSampleRate32kHz,
                                AudioProcessing::kSampleRate48kHz, 44100};
  for (auto capture_input_sample_rate_hz : sample_rates_to_test) {
    for (auto capture_output_sample_rate_hz : sample_rates_to_test) {
      for (size_t num_channels = 1; num_channels <= 2; ++num_channels) {
        RunTogetherWithApm("LevelControlAndDefaultDesktopApm", 48000, 48000,
                           capture_input_sample_rate_hz,
                           capture_output_sample_rate_hz, num_channels, false,
                           true);
        RunTogetherWithApm("LevelControlAndDefaultMobileApm", 48000, 48000,
                           capture_input_sample_rate_hz,
                           capture_output_sample_rate_hz, num_channels, true,
                           true);
      }
    }
  }
}

}  // namespace webrtc
<commit_msg>Disabling the performance unittests on Android for the level controller.<commit_after>/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <numeric>
#include <vector>

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/array_view.h"
#include "webrtc/base/random.h"
#include "webrtc/modules/audio_processing/audio_buffer.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/modules/audio_processing/level_controller/level_controller.h"
#include "webrtc/modules/audio_processing/test/audio_buffer_tools.h"
#include "webrtc/modules/audio_processing/test/bitexactness_tools.h"
#include "webrtc/system_wrappers/include/clock.h"
#include "webrtc/test/testsupport/perf_test.h"

namespace webrtc {
namespace {

const size_t kNumFramesToProcess = 100;

struct SimulatorBuffers {
  SimulatorBuffers(int render_input_sample_rate_hz,
                   int capture_input_sample_rate_hz,
                   int render_output_sample_rate_hz,
                   int capture_output_sample_rate_hz,
                   size_t num_render_input_channels,
                   size_t num_capture_input_channels,
                   size_t num_render_output_channels,
                   size_t num_capture_output_channels) {
    Random rand_gen(42);
    CreateConfigAndBuffer(render_input_sample_rate_hz,
                          num_render_input_channels, &rand_gen,
                          &render_input_buffer, &render_input_config,
                          &render_input, &render_input_samples);

    CreateConfigAndBuffer(render_output_sample_rate_hz,
                          num_render_output_channels, &rand_gen,
                          &render_output_buffer, &render_output_config,
                          &render_output, &render_output_samples);

    CreateConfigAndBuffer(capture_input_sample_rate_hz,
                          num_capture_input_channels, &rand_gen,
                          &capture_input_buffer, &capture_input_config,
                          &capture_input, &capture_input_samples);

    CreateConfigAndBuffer(capture_output_sample_rate_hz,
                          num_capture_output_channels, &rand_gen,
                          &capture_output_buffer, &capture_output_config,
                          &capture_output, &capture_output_samples);

    UpdateInputBuffers();
  }

  void CreateConfigAndBuffer(int sample_rate_hz,
                             size_t num_channels,
                             Random* rand_gen,
                             std::unique_ptr<AudioBuffer>* buffer,
                             StreamConfig* config,
                             std::vector<float*>* buffer_data,
                             std::vector<float>* buffer_data_samples) {
    int samples_per_channel = rtc::CheckedDivExact(sample_rate_hz, 100);
    *config = StreamConfig(sample_rate_hz, num_channels, false);
    buffer->reset(new AudioBuffer(config->num_frames(), config->num_channels(),
                                  config->num_frames(), config->num_channels(),
                                  config->num_frames()));

    buffer_data_samples->resize(samples_per_channel * num_channels);
    for (auto& v : *buffer_data_samples) {
      v = rand_gen->Rand<float>();
    }

    buffer_data->resize(num_channels);
    for (size_t ch = 0; ch < num_channels; ++ch) {
      (*buffer_data)[ch] = &(*buffer_data_samples)[ch * samples_per_channel];
    }
  }

  void UpdateInputBuffers() {
    test::CopyVectorToAudioBuffer(capture_input_config, capture_input_samples,
                                  capture_input_buffer.get());
    test::CopyVectorToAudioBuffer(render_input_config, render_input_samples,
                                  render_input_buffer.get());
  }

  std::unique_ptr<AudioBuffer> render_input_buffer;
  std::unique_ptr<AudioBuffer> capture_input_buffer;
  std::unique_ptr<AudioBuffer> render_output_buffer;
  std::unique_ptr<AudioBuffer> capture_output_buffer;
  StreamConfig render_input_config;
  StreamConfig capture_input_config;
  StreamConfig render_output_config;
  StreamConfig capture_output_config;
  std::vector<float*> render_input;
  std::vector<float> render_input_samples;
  std::vector<float*> capture_input;
  std::vector<float> capture_input_samples;
  std::vector<float*> render_output;
  std::vector<float> render_output_samples;
  std::vector<float*> capture_output;
  std::vector<float> capture_output_samples;
};

class SubmodulePerformanceTimer {
 public:
  SubmodulePerformanceTimer() : clock_(webrtc::Clock::GetRealTimeClock()) {
    timestamps_us_.reserve(kNumFramesToProcess);
  }

  void StartTimer() {
    start_timestamp_us_ = rtc::Optional<int64_t>(clock_->TimeInMicroseconds());
  }
  void StopTimer() {
    RTC_DCHECK(start_timestamp_us_);
    timestamps_us_.push_back(clock_->TimeInMicroseconds() -
                             *start_timestamp_us_);
  }

  double GetDurationAverage() const {
    RTC_DCHECK(!timestamps_us_.empty());
    return static_cast<double>(std::accumulate(timestamps_us_.begin(),
                                               timestamps_us_.end(), 0)) /
           timestamps_us_.size();
  }

  double GetDurationStandardDeviation() const {
    RTC_DCHECK(!timestamps_us_.empty());
    double average_duration = GetDurationAverage();

    int64_t variance =
        std::accumulate(timestamps_us_.begin(), timestamps_us_.end(), 0,
                        [average_duration](const int64_t& a, const int64_t& b) {
                          return a + (b - average_duration);
                        });

    return sqrt(variance / timestamps_us_.size());
  }

 private:
  webrtc::Clock* clock_;
  rtc::Optional<int64_t> start_timestamp_us_;
  std::vector<int64_t> timestamps_us_;
};

std::string FormPerformanceMeasureString(
    const SubmodulePerformanceTimer& timer) {
  std::string s = std::to_string(timer.GetDurationAverage());
  s += ", ";
  s += std::to_string(timer.GetDurationStandardDeviation());
  return s;
}

void RunStandaloneSubmodule(int sample_rate_hz, size_t num_channels) {
  SimulatorBuffers buffers(sample_rate_hz, sample_rate_hz, sample_rate_hz,
                           sample_rate_hz, num_channels, num_channels,
                           num_channels, num_channels);
  SubmodulePerformanceTimer timer;

  LevelController level_controller;
  level_controller.Initialize(sample_rate_hz);

  for (size_t frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) {
    buffers.UpdateInputBuffers();

    timer.StartTimer();
    level_controller.Process(buffers.capture_input_buffer.get());
    timer.StopTimer();
  }
  webrtc::test::PrintResultMeanAndError(
      "level_controller_call_durations",
      "_" + std::to_string(sample_rate_hz) + "Hz_" +
          std::to_string(num_channels) + "_channels",
      "StandaloneLevelControl", FormPerformanceMeasureString(timer), "us",
      false);
}

void RunTogetherWithApm(std::string test_description,
                        int render_input_sample_rate_hz,
                        int render_output_sample_rate_hz,
                        int capture_input_sample_rate_hz,
                        int capture_output_sample_rate_hz,
                        size_t num_channels,
                        bool use_mobile_aec,
                        bool include_default_apm_processing) {
  SimulatorBuffers buffers(
      render_input_sample_rate_hz, capture_input_sample_rate_hz,
      render_output_sample_rate_hz, capture_output_sample_rate_hz, num_channels,
      num_channels, num_channels, num_channels);
  SubmodulePerformanceTimer render_timer;
  SubmodulePerformanceTimer capture_timer;
  SubmodulePerformanceTimer total_timer;

  Config config;
  if (include_default_apm_processing) {
    config.Set<DelayAgnostic>(new DelayAgnostic(true));
    config.Set<ExtendedFilter>(new ExtendedFilter(true));
  }
  config.Set<LevelControl>(new LevelControl(true));

  std::unique_ptr<AudioProcessing> apm;
  apm.reset(AudioProcessing::Create(config));
  ASSERT_TRUE(apm.get());

  ASSERT_EQ(AudioProcessing::kNoError,
            apm->gain_control()->Enable(include_default_apm_processing));
  if (use_mobile_aec) {
    ASSERT_EQ(AudioProcessing::kNoError,
              apm->echo_cancellation()->Enable(false));
    ASSERT_EQ(AudioProcessing::kNoError, apm->echo_control_mobile()->Enable(
                                             include_default_apm_processing));
  } else {
    ASSERT_EQ(AudioProcessing::kNoError,
              apm->echo_cancellation()->Enable(include_default_apm_processing));
    ASSERT_EQ(AudioProcessing::kNoError,
              apm->echo_control_mobile()->Enable(false));
  }
  ASSERT_EQ(AudioProcessing::kNoError,
            apm->high_pass_filter()->Enable(include_default_apm_processing));
  ASSERT_EQ(AudioProcessing::kNoError,
            apm->noise_suppression()->Enable(include_default_apm_processing));
  ASSERT_EQ(AudioProcessing::kNoError,
            apm->voice_detection()->Enable(include_default_apm_processing));
  ASSERT_EQ(AudioProcessing::kNoError,
            apm->level_estimator()->Enable(include_default_apm_processing));

  StreamConfig render_input_config(render_input_sample_rate_hz, num_channels,
                                   false);
  StreamConfig render_output_config(render_output_sample_rate_hz, num_channels,
                                    false);
  StreamConfig capture_input_config(capture_input_sample_rate_hz, num_channels,
                                    false);
  StreamConfig capture_output_config(capture_output_sample_rate_hz,
                                     num_channels, false);

  for (size_t frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) {
    buffers.UpdateInputBuffers();

    total_timer.StartTimer();
    render_timer.StartTimer();
    ASSERT_EQ(AudioProcessing::kNoError,
              apm->ProcessReverseStream(
                  &buffers.render_input[0], render_input_config,
                  render_output_config, &buffers.render_output[0]));

    render_timer.StopTimer();

    capture_timer.StartTimer();
    ASSERT_EQ(AudioProcessing::kNoError, apm->set_stream_delay_ms(0));
    ASSERT_EQ(
        AudioProcessing::kNoError,
        apm->ProcessStream(&buffers.capture_input[0], capture_input_config,
                           capture_output_config, &buffers.capture_output[0]));

    capture_timer.StopTimer();
    total_timer.StopTimer();
  }

  webrtc::test::PrintResultMeanAndError(
      "level_controller_call_durations",
      "_" + std::to_string(render_input_sample_rate_hz) + "_" +
          std::to_string(render_output_sample_rate_hz) + "_" +
          std::to_string(capture_input_sample_rate_hz) + "_" +
          std::to_string(capture_output_sample_rate_hz) + "Hz_" +
          std::to_string(num_channels) + "_channels" + "_render",
      test_description, FormPerformanceMeasureString(render_timer), "us",
      false);
  webrtc::test::PrintResultMeanAndError(
      "level_controller_call_durations",
      "_" + std::to_string(render_input_sample_rate_hz) + "_" +
          std::to_string(render_output_sample_rate_hz) + "_" +
          std::to_string(capture_input_sample_rate_hz) + "_" +
          std::to_string(capture_output_sample_rate_hz) + "Hz_" +
          std::to_string(num_channels) + "_channels" + "_capture",
      test_description, FormPerformanceMeasureString(capture_timer), "us",
      false);
  webrtc::test::PrintResultMeanAndError(
      "level_controller_call_durations",
      "_" + std::to_string(render_input_sample_rate_hz) + "_" +
          std::to_string(render_output_sample_rate_hz) + "_" +
          std::to_string(capture_input_sample_rate_hz) + "_" +
          std::to_string(capture_output_sample_rate_hz) + "Hz_" +
          std::to_string(num_channels) + "_channels" + "_total",
      test_description, FormPerformanceMeasureString(total_timer), "us", false);
}

}  // namespace

TEST(LevelControllerPerformanceTest, StandaloneProcessing) {
  int sample_rates_to_test[] = {
      AudioProcessing::kSampleRate8kHz, AudioProcessing::kSampleRate16kHz,
      AudioProcessing::kSampleRate32kHz, AudioProcessing::kSampleRate48kHz};
  for (auto sample_rate : sample_rates_to_test) {
    for (size_t num_channels = 1; num_channels <= 2; ++num_channels) {
      RunStandaloneSubmodule(sample_rate, num_channels);
    }
  }
}

#if !defined(WEBRTC_ANDROID)
TEST(LevelControllerPerformanceTest, ProcessingViaApm) {
#else
TEST(LevelControllerPerformanceTest, DISABLED_ProcessingViaApm) {
#endif
  int sample_rates_to_test[] = {AudioProcessing::kSampleRate8kHz,
                                AudioProcessing::kSampleRate16kHz,
                                AudioProcessing::kSampleRate32kHz,
                                AudioProcessing::kSampleRate48kHz, 44100};
  for (auto capture_input_sample_rate_hz : sample_rates_to_test) {
    for (auto capture_output_sample_rate_hz : sample_rates_to_test) {
      for (size_t num_channels = 1; num_channels <= 2; ++num_channels) {
        RunTogetherWithApm("SimpleLevelControlViaApm", 48000, 48000,
                           capture_input_sample_rate_hz,
                           capture_output_sample_rate_hz, num_channels, false,
                           false);
      }
    }
  }
}

#if !defined(WEBRTC_ANDROID)
TEST(LevelControllerPerformanceTest, InteractionWithDefaultApm) {
#else
TEST(LevelControllerPerformanceTest, DISABLED_InteractionWithDefaultApm) {
#endif
  int sample_rates_to_test[] = {AudioProcessing::kSampleRate8kHz,
                                AudioProcessing::kSampleRate16kHz,
                                AudioProcessing::kSampleRate32kHz,
                                AudioProcessing::kSampleRate48kHz, 44100};
  for (auto capture_input_sample_rate_hz : sample_rates_to_test) {
    for (auto capture_output_sample_rate_hz : sample_rates_to_test) {
      for (size_t num_channels = 1; num_channels <= 2; ++num_channels) {
        RunTogetherWithApm("LevelControlAndDefaultDesktopApm", 48000, 48000,
                           capture_input_sample_rate_hz,
                           capture_output_sample_rate_hz, num_channels, false,
                           true);
        RunTogetherWithApm("LevelControlAndDefaultMobileApm", 48000, 48000,
                           capture_input_sample_rate_hz,
                           capture_output_sample_rate_hz, num_channels, true,
                           true);
      }
    }
  }
}

}  // namespace webrtc
<|endoftext|>


<commit_before>// NCMLContainer.cc

// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of ncml_module, A C++ module that can be loaded in to
// the OPeNDAP Back-End Server (BES) and is able to handle ncml requests.

// Copyright (c) 2002,2003 OPeNDAP, Inc.
// Author: Patrick West <pwest@ucar.edu>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

// (c) COPYRIGHT URI/MIT 1994-1999
// Please read the full copyright statement in the file COPYRIGHT_URI.
//
// Authors:
//      pcw       Patrick West <pwest@ucar.edu>

#include <fstream>
#include <cerrno>
#include <cstdlib>
#include <cstring>

using std::ofstream ;
using std::endl ;
using std::ios_base ;

#include "NCMLContainer.h"
#include "NCMLContainerStorage.h"

#include <BESSyntaxUserError.h>
#include <BESInternalError.h>
#include <BESDebug.h>

/** @brief Creates an instances of NCMLContainer with the symbolic name
 * and the xml document string.
 *
 * The xml document is contained within the DHI, so must be passed in
 * here.
 *
 * The type of the container is ncml. This way we know to use the ncml
 * handler for this container.
 *
 * @param sym_name symbolic name representing this NCML container
 * @param ncml_doc string of the xml document
 * @see NCMLGatewayUtils
 */
NCMLContainer::NCMLContainer( const string &sym_name, const string &xml_doc )
    : BESContainer( sym_name, "", "ncml" ),
      _xml_doc( xml_doc ),
      _accessed( false )
{
}

NCMLContainer::NCMLContainer( const NCMLContainer &copy_from )
    : BESContainer( copy_from ),
      _xml_doc( copy_from._xml_doc ),
      _accessed( copy_from._accessed )
{
    // we can not make a copy of this container once the NCML document has
    // been written to the temporary file
    if( _accessed )
    {
	string err = (string)"The Container has already been accessed, "
	             + "can not create a copy of this container." ;
	throw BESInternalError( err, __FILE__, __LINE__ ) ;
    }
}

void
NCMLContainer::_duplicate( NCMLContainer &copy_to )
{
    if( copy_to._accessed )
    {
	string err = (string)"The Container has already been accessed, "
	             + "can not duplicate this resource." ;
	throw BESInternalError( err, __FILE__, __LINE__ ) ;
    }
    copy_to._xml_doc = _xml_doc ;
    copy_to._accessed = false ;
    BESContainer::_duplicate( copy_to ) ;
}

BESContainer *
NCMLContainer::ptr_duplicate( )
{
    NCMLContainer *container = new NCMLContainer ;
    _duplicate( *container ) ;
    return container ;
}

NCMLContainer::~NCMLContainer()
{
    if( _accessed )
    {
	release() ;
    }
}

/** @brief access the NCML target response by making the NCML request
 *
 * @return full path to the NCML request response data file
 * @throws BESError if there is a problem making the NCML request
 */
string
NCMLContainer::access()
{
    BESDEBUG( "ncml", "accessing " << _xml_doc << endl );
    if( !_accessed )
    {
	// save the xml document to a temporary file, open it, unlink
	// it. In release, close the file. This will remove the file if
	// it is no longer open.

	string tempfile_template = "ncml_module_XXXXXX" ;
#if defined(WIN32) || defined(TEST_WIN32_TEMPS)
	char *tempfile_c = _mktemp( (char *)tempfile_template.c_str() ) ;
#else
	char *tempfile_c = mktemp( (char *)tempfile_template.c_str() ) ;
#endif
	string tempfile ;
	if( tempfile_c )
	{
	    tempfile = tempfile_c ;
	}
	else
	{
	    string err = (string)"Unable to create temporary ncml document "
			 + _tmp_file_name ;
	    throw BESInternalError( err, __FILE__, __LINE__ ) ;
	}

	_tmp_file_name = NCMLContainerStorage::NCML_TempDir
			 + "/" + tempfile + ".ncml" ;

	ofstream ostrm ;
	int my_errno = 0 ;

	ostrm.open( _tmp_file_name.c_str(), ios_base::out ) ;
	my_errno = errno ;

	if( !ostrm )
	{
	    string err = (string)"Unable to write out the ncml document "
			 + _tmp_file_name ;
	    if( my_errno )
	    {
		char *str = strerror( my_errno ) ;
		if( str ) err += (string)" " + str ;
	    }
	    throw BESInternalError( err, __FILE__, __LINE__ ) ;
	}

	// write out <?xml version="1.0" encoding="UTF-8"?>
	ostrm << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl ;

	// then write out the r_name as the ncml document (no validation)
	ostrm << _xml_doc << endl ;

	ostrm.close() ;

	_accessed = true ;
    }
    return _tmp_file_name ;
}

/** @brief release the NCML cached resources
 *
 * Release the resource
 *
 * @return true if the resource is released successfully and false otherwise
 */
bool
NCMLContainer::release()
{
    if( _accessed && !_tmp_file_name.empty() )
    {
	unlink( _tmp_file_name.c_str() ) ;
	_tmp_file_name = "" ;
    }
    _accessed = false ;
    return true ;
}

/** @brief dumps information about this object
 *
 * Displays the pointer value of this instance along with information about
 * this container.
 *
 * @param strm C++ i/o stream to dump the information to
 */
void
NCMLContainer::dump( ostream &strm ) const
{
    strm << BESIndent::LMarg << "NCMLContainer::dump - ("
			     << (void *)this << ")" << endl ;
    BESIndent::Indent() ;
    if( _accessed )
    {
	strm << BESIndent::LMarg << "temporary file: "
				 << _tmp_file_name << endl ;
    }
    else
    {
	strm << BESIndent::LMarg << "temporary file: not open" << endl ;
    }
    BESContainer::dump( strm ) ;
    BESIndent::UnIndent() ;
}

<commit_msg>Added unistd.h for osx 10.9<commit_after>// NCMLContainer.cc

// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of ncml_module, A C++ module that can be loaded in to
// the OPeNDAP Back-End Server (BES) and is able to handle ncml requests.

// Copyright (c) 2002,2003 OPeNDAP, Inc.
// Author: Patrick West <pwest@ucar.edu>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

// (c) COPYRIGHT URI/MIT 1994-1999
// Please read the full copyright statement in the file COPYRIGHT_URI.
//
// Authors:
//      pcw       Patrick West <pwest@ucar.edu>

#include "config.h"

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#include <fstream>
#include <cerrno>
#include <cstdlib>
#include <cstring>

using std::ofstream ;
using std::endl ;
using std::ios_base ;

#include "NCMLContainer.h"
#include "NCMLContainerStorage.h"

#include <BESSyntaxUserError.h>
#include <BESInternalError.h>
#include <BESDebug.h>

/** @brief Creates an instances of NCMLContainer with the symbolic name
 * and the xml document string.
 *
 * The xml document is contained within the DHI, so must be passed in
 * here.
 *
 * The type of the container is ncml. This way we know to use the ncml
 * handler for this container.
 *
 * @param sym_name symbolic name representing this NCML container
 * @param ncml_doc string of the xml document
 * @see NCMLGatewayUtils
 */
NCMLContainer::NCMLContainer( const string &sym_name, const string &xml_doc )
    : BESContainer( sym_name, "", "ncml" ),
      _xml_doc( xml_doc ),
      _accessed( false )
{
}

NCMLContainer::NCMLContainer( const NCMLContainer &copy_from )
    : BESContainer( copy_from ),
      _xml_doc( copy_from._xml_doc ),
      _accessed( copy_from._accessed )
{
    // we can not make a copy of this container once the NCML document has
    // been written to the temporary file
    if( _accessed )
    {
	string err = (string)"The Container has already been accessed, "
	             + "can not create a copy of this container." ;
	throw BESInternalError( err, __FILE__, __LINE__ ) ;
    }
}

void
NCMLContainer::_duplicate( NCMLContainer &copy_to )
{
    if( copy_to._accessed )
    {
	string err = (string)"The Container has already been accessed, "
	             + "can not duplicate this resource." ;
	throw BESInternalError( err, __FILE__, __LINE__ ) ;
    }
    copy_to._xml_doc = _xml_doc ;
    copy_to._accessed = false ;
    BESContainer::_duplicate( copy_to ) ;
}

BESContainer *
NCMLContainer::ptr_duplicate( )
{
    NCMLContainer *container = new NCMLContainer ;
    _duplicate( *container ) ;
    return container ;
}

NCMLContainer::~NCMLContainer()
{
    if( _accessed )
    {
	release() ;
    }
}

/** @brief access the NCML target response by making the NCML request
 *
 * @return full path to the NCML request response data file
 * @throws BESError if there is a problem making the NCML request
 */
string
NCMLContainer::access()
{
    BESDEBUG( "ncml", "accessing " << _xml_doc << endl );
    if( !_accessed )
    {
	// save the xml document to a temporary file, open it, unlink
	// it. In release, close the file. This will remove the file if
	// it is no longer open.

	string tempfile_template = "ncml_module_XXXXXX" ;
#if defined(WIN32) || defined(TEST_WIN32_TEMPS)
	char *tempfile_c = _mktemp( (char *)tempfile_template.c_str() ) ;
#else
	char *tempfile_c = mktemp( (char *)tempfile_template.c_str() ) ;
#endif
	string tempfile ;
	if( tempfile_c )
	{
	    tempfile = tempfile_c ;
	}
	else
	{
	    string err = (string)"Unable to create temporary ncml document "
			 + _tmp_file_name ;
	    throw BESInternalError( err, __FILE__, __LINE__ ) ;
	}

	_tmp_file_name = NCMLContainerStorage::NCML_TempDir
			 + "/" + tempfile + ".ncml" ;

	ofstream ostrm ;
	int my_errno = 0 ;

	ostrm.open( _tmp_file_name.c_str(), ios_base::out ) ;
	my_errno = errno ;

	if( !ostrm )
	{
	    string err = (string)"Unable to write out the ncml document "
			 + _tmp_file_name ;
	    if( my_errno )
	    {
		char *str = strerror( my_errno ) ;
		if( str ) err += (string)" " + str ;
	    }
	    throw BESInternalError( err, __FILE__, __LINE__ ) ;
	}

	// write out <?xml version="1.0" encoding="UTF-8"?>
	ostrm << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl ;

	// then write out the r_name as the ncml document (no validation)
	ostrm << _xml_doc << endl ;

	ostrm.close() ;

	_accessed = true ;
    }
    return _tmp_file_name ;
}

/** @brief release the NCML cached resources
 *
 * Release the resource
 *
 * @return true if the resource is released successfully and false otherwise
 */
bool
NCMLContainer::release()
{
    if( _accessed && !_tmp_file_name.empty() )
    {
	unlink( _tmp_file_name.c_str() ) ;
	_tmp_file_name = "" ;
    }
    _accessed = false ;
    return true ;
}

/** @brief dumps information about this object
 *
 * Displays the pointer value of this instance along with information about
 * this container.
 *
 * @param strm C++ i/o stream to dump the information to
 */
void
NCMLContainer::dump( ostream &strm ) const
{
    strm << BESIndent::LMarg << "NCMLContainer::dump - ("
			     << (void *)this << ")" << endl ;
    BESIndent::Indent() ;
    if( _accessed )
    {
	strm << BESIndent::LMarg << "temporary file: "
				 << _tmp_file_name << endl ;
    }
    else
    {
	strm << BESIndent::LMarg << "temporary file: not open" << endl ;
    }
    BESContainer::dump( strm ) ;
    BESIndent::UnIndent() ;
}

<|endoftext|>