<commit_before>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
 *
 * Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
 *
 * This program 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 program 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 program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "Parser.h"

#include <algorithm>

#include "IMedia.h"

Parser::Parser(DBConnection dbConnection , IMediaLibraryCb* cb)
    : m_stopParser( false )
    , m_dbConnection( dbConnection )
    , m_callback( cb )
    , m_nbParsed( 0 )
    , m_nbToParse( 0 )
    , m_paused( false )
{
}

Parser::~Parser()
{
    if ( m_thread.joinable() )
    {
        {
            std::lock_guard<std::mutex> lock( m_lock );
            if ( m_tasks.empty() == true )
                m_cond.notify_all();
            m_stopParser = true;
        }
        m_thread.join();
    }
    while ( m_tasks.empty() == false )
    {
        delete m_tasks.front();
        m_tasks.pop();
    }
}

void Parser::addService(std::unique_ptr<IMetadataService> service)
{
    m_services.emplace_back( std::move( service ) );
    std::push_heap( m_services.begin(), m_services.end(), []( const ServicePtr& a, const ServicePtr& b )
    {
        // We want higher priority first
        return a->priority() < b->priority();
    });
}

void Parser::parse( std::shared_ptr<Media> file )
{
    std::lock_guard<std::mutex> lock( m_lock );

    if ( m_services.size() == 0 )
        return;
    m_tasks.push( new Task( file, m_services, m_callback ) );
    updateStats( false, true );
    if ( m_paused == false )
        m_cond.notify_all();
}

void Parser::start()
{
    // Ensure we don't start multiple times.
    assert( m_thread.joinable() == false );

    m_thread = std::thread{ &Parser::run, this };
}

void Parser::pause()
{
    std::lock_guard<std::mutex> lock( m_lock );
    m_paused = true;
}

void Parser::resume()
{
    std::lock_guard<std::mutex> lock( m_lock );
    m_paused = false;
    m_cond.notify_all();
}

void Parser::run()
{
    LOG_INFO("Starting Parser thread");
    restore();

    while ( m_stopParser == false )
    {
        Task* task = nullptr;
        {
            std::unique_lock<std::mutex> lock( m_lock );
            if ( m_tasks.empty() == true || m_paused == true )
            {
                m_cond.wait( lock, [this]() {
                    return ( m_tasks.empty() == false && m_paused == false )
                            || m_stopParser == true;
                });
                // We might have been woken up because the parser is being destroyed
                if ( m_stopParser  == true )
                    break;
            }
            // Otherwise it's safe to assume we have at least one element.
            task = m_tasks.front();
            m_tasks.pop();
        }
        try
        {
            (*task->it)->run( task->file, task );
        }
        catch (const std::exception& ex)
        {
            LOG_ERROR( "Caught an exception during ", task->file->mrl(), " parsing: ", ex.what() );
            done( task->file, IMetadataService::Status::Fatal, task );
        }
    }
    LOG_INFO("Exiting Parser thread");
}

void Parser::restore()
{
    if ( m_services.empty() == true )
        return;

    static const std::string req = "SELECT * FROM " + policy::MediaTable::Name
            + " WHERE parsed = 0";
    auto media = Media::fetchAll<Media>( m_dbConnection, req );

    std::lock_guard<std::mutex> lock( m_lock );
    for ( auto& m : media )
    {
        m_tasks.push( new Task( m, m_services, m_callback ) );
    }
}

void Parser::updateStats( bool newMediaParsed, bool newMediaQueued )
{
    if ( m_callback == nullptr )
        return;

    if ( newMediaParsed == true )
        m_nbParsed++;
    else if ( newMediaQueued == true )
        m_nbToParse++;
    else
        assert(false);

    if ( m_nbParsed == m_nbToParse )
    {
        m_callback->onParsingStatsUpdated( m_nbParsed, m_nbToParse );
        m_nbParsed = 0;
        m_nbToParse = 0;
        return;
    }
    // Only send an update every X new elem
    const uint32_t NbElems = 3;
    if ( ( newMediaParsed == true && m_nbParsed % NbElems == 0 ) ||
         ( newMediaQueued == true && m_nbToParse % NbElems == 0 ) )
    {
        m_callback->onParsingStatsUpdated( m_nbParsed, m_nbToParse );
    }
}

Parser::Task::Task(std::shared_ptr<Media> file, Parser::ServiceList& serviceList, IMediaLibraryCb* metadataCb )
    : file(file)
    , it( serviceList.begin() )
    , end( serviceList.end() )
    , cb( metadataCb )
{
}

void Parser::done(std::shared_ptr<Media> file, IMetadataService::Status status, void* data )
{
    Task *t = reinterpret_cast<Task*>( data );
    if ( status == IMetadataService::Status::TemporaryUnavailable ||
         status == IMetadataService::Status::Fatal )
    {
        updateStats( true, false );
        delete t;
        return;
    }
    else if ( status == IMetadataService::Status::Success )
    {
        if ( t->cb != nullptr )
            t->cb->onFileUpdated( file );
    }

    ++t->it;
    if (t->it == t->end)
    {
        updateStats( true, false );
        file->markParsed();
        delete t;
        return;
    }
    std::lock_guard<std::mutex> lock( m_lock );
    m_tasks.push( t );
    m_cond.notify_all();
}
<commit_msg>Parser: Add comment about objects lifetime<commit_after>/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
 *
 * Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
 *
 * This program 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 program 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 program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "Parser.h"

#include <algorithm>

#include "IMedia.h"

Parser::Parser(DBConnection dbConnection , IMediaLibraryCb* cb)
    : m_stopParser( false )
    , m_dbConnection( dbConnection )
    , m_callback( cb )
    , m_nbParsed( 0 )
    , m_nbToParse( 0 )
    , m_paused( false )
{
}

Parser::~Parser()
{
    if ( m_thread.joinable() )
    {
        {
            std::lock_guard<std::mutex> lock( m_lock );
            if ( m_tasks.empty() == true )
                m_cond.notify_all();
            m_stopParser = true;
        }
        m_thread.join();
    }
    while ( m_tasks.empty() == false )
    {
        delete m_tasks.front();
        m_tasks.pop();
    }
}

void Parser::addService(std::unique_ptr<IMetadataService> service)
{
    m_services.emplace_back( std::move( service ) );
    std::push_heap( m_services.begin(), m_services.end(), []( const ServicePtr& a, const ServicePtr& b )
    {
        // We want higher priority first
        return a->priority() < b->priority();
    });
}

void Parser::parse( std::shared_ptr<Media> file )
{
    std::lock_guard<std::mutex> lock( m_lock );

    if ( m_services.size() == 0 )
        return;
    m_tasks.push( new Task( file, m_services, m_callback ) );
    updateStats( false, true );
    if ( m_paused == false )
        m_cond.notify_all();
}

void Parser::start()
{
    // Ensure we don't start multiple times.
    assert( m_thread.joinable() == false );

    m_thread = std::thread{ &Parser::run, this };
}

void Parser::pause()
{
    std::lock_guard<std::mutex> lock( m_lock );
    m_paused = true;
}

void Parser::resume()
{
    std::lock_guard<std::mutex> lock( m_lock );
    m_paused = false;
    m_cond.notify_all();
}

void Parser::run()
{
    LOG_INFO("Starting Parser thread");
    restore();

    while ( m_stopParser == false )
    {
        Task* task = nullptr;
        {
            std::unique_lock<std::mutex> lock( m_lock );
            if ( m_tasks.empty() == true || m_paused == true )
            {
                m_cond.wait( lock, [this]() {
                    return ( m_tasks.empty() == false && m_paused == false )
                            || m_stopParser == true;
                });
                // We might have been woken up because the parser is being destroyed
                if ( m_stopParser  == true )
                    break;
            }
            // Otherwise it's safe to assume we have at least one element.
            task = m_tasks.front();
            m_tasks.pop();
        }
        try
        {
            (*task->it)->run( task->file, task );
            // Consider the task invalid starting from this point. If it completed
            // it cleared itself afterward.
        }
        catch (const std::exception& ex)
        {
            LOG_ERROR( "Caught an exception during ", task->file->mrl(), " parsing: ", ex.what() );
            done( task->file, IMetadataService::Status::Fatal, task );
        }
    }
    LOG_INFO("Exiting Parser thread");
}

void Parser::restore()
{
    if ( m_services.empty() == true )
        return;

    static const std::string req = "SELECT * FROM " + policy::MediaTable::Name
            + " WHERE parsed = 0";
    auto media = Media::fetchAll<Media>( m_dbConnection, req );

    std::lock_guard<std::mutex> lock( m_lock );
    for ( auto& m : media )
    {
        m_tasks.push( new Task( m, m_services, m_callback ) );
    }
}

void Parser::updateStats( bool newMediaParsed, bool newMediaQueued )
{
    if ( m_callback == nullptr )
        return;

    if ( newMediaParsed == true )
        m_nbParsed++;
    else if ( newMediaQueued == true )
        m_nbToParse++;
    else
        assert(false);

    if ( m_nbParsed == m_nbToParse )
    {
        m_callback->onParsingStatsUpdated( m_nbParsed, m_nbToParse );
        m_nbParsed = 0;
        m_nbToParse = 0;
        return;
    }
    // Only send an update every X new elem
    const uint32_t NbElems = 3;
    if ( ( newMediaParsed == true && m_nbParsed % NbElems == 0 ) ||
         ( newMediaQueued == true && m_nbToParse % NbElems == 0 ) )
    {
        m_callback->onParsingStatsUpdated( m_nbParsed, m_nbToParse );
    }
}

Parser::Task::Task(std::shared_ptr<Media> file, Parser::ServiceList& serviceList, IMediaLibraryCb* metadataCb )
    : file(file)
    , it( serviceList.begin() )
    , end( serviceList.end() )
    , cb( metadataCb )
{
}

void Parser::done(std::shared_ptr<Media> file, IMetadataService::Status status, void* data )
{
    Task *t = reinterpret_cast<Task*>( data );
    if ( status == IMetadataService::Status::TemporaryUnavailable ||
         status == IMetadataService::Status::Fatal )
    {
        updateStats( true, false );
        delete t;
        return;
    }
    else if ( status == IMetadataService::Status::Success )
    {
        if ( t->cb != nullptr )
            t->cb->onFileUpdated( file );
    }

    ++t->it;
    if (t->it == t->end)
    {
        updateStats( true, false );
        file->markParsed();
        delete t;
        return;
    }
    std::lock_guard<std::mutex> lock( m_lock );
    m_tasks.push( t );
    m_cond.notify_all();
}
<|endoftext|>


<commit_before>/*-----------------------------------------------------------------------------

 Copyright 2017 Hopsan Group

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

 The full license is available in the file LICENSE.
 For details about the 'Hopsan Group' or information about Authors and
 Contributors see the HOPSANGROUP and AUTHORS files that are located in
 the Hopsan source code root directory.

-----------------------------------------------------------------------------*/

//!
//! @file   HopsanCLI/CliUtilities.cpp
//! @author peter.nordin@liu.se
//! @date   2014-12-09
//!
//! @brief Contains helpfunctions for CLI
//!
//$Id$

#include "CliUtilities.h"

#include <iostream>
#include <sstream>
#include <fstream>
#include <cmath>

#ifndef _WIN32
#include <unistd.h>
#include <limits.h>
#else
#include <windows.h>
#endif

using namespace std;

//! @brief Prints a message with red color (resets color to defaul after)
//! @param[in] rError The error message
void printErrorMessage(const std::string &rError, bool silent)
{
    if(silent) return;

    setTerminalColor(Red);
    cout << "Error: " << rError << endl;
    setTerminalColor(Reset);
}

//! @brief Prints a message with yellow color (resets color to defaul after)
//! @param[in] rWarning The warning message
void printWarningMessage(const std::string &rWarning, bool silent)
{
    if(silent) return;

    setTerminalColor(Yellow);
    cout << "Warning: " << rWarning << endl;
    setTerminalColor(Reset);
}

//! @brief Prints a message with green color (resets color to defaul after)
//! @param[in] color The text color for the message
//! @param[in] rMessage The message
void printColorMessage(const ColorsEnumT color, const std::string &rMessage, bool silent)
{
    if(silent) return;

    setTerminalColor(color);
    cout << rMessage << endl;
    setTerminalColor(Reset);
}

//! @brief Changes color on console output
//! @param color Color number (0-15)
//! @todo Need yellow color also
void setTerminalColor(const ColorsEnumT color)
{
#ifdef _WIN32
    WORD c;
    switch (color)
    {
    case Red:
        c = FOREGROUND_INTENSITY | FOREGROUND_RED;
        break;
    case Green:
        c = FOREGROUND_INTENSITY | FOREGROUND_GREEN;
        break;
    case Yellow:
        c = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED;
        break;
    case Blue:
        c = FOREGROUND_INTENSITY | FOREGROUND_BLUE;
        break;
    case White:
    default:
        c = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
    }

    HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hcon,c);
#else
    string c;
    switch (color)
    {
    case Red:
        c = "\e[0;91m";
        break;
    case Green:
        c = "\e[0;92m";
        break;
    case Yellow:
        c = "\e[0;93m";
        break;
    case Blue:
        c = "\e[0;94m";
        break;
    case White:
    default:
        c = "\e[0m";
    }

    cout << c;
#endif
}

//! @brief Helpfunction that splits a filename into basename and extesion
void splitFileName(const std::string fileName, std::string &rBaseName, std::string &rExt)
{
    size_t pos = fileName.rfind('.');
    if (pos != std::string::npos)
    {
        rBaseName = fileName.substr(0, pos) ;
        rExt = fileName.substr(pos+1);
    }
    else
    {
        rExt = "";
        rBaseName = fileName;
    }
}

//! @brief Convert the fullpath into a path relative to basepath, both paths must be relative the same directoryo (or absolute)
std::string relativePath(std::string basePath, std::string fullPath)
{
    std::string result;

    if ( (basePath.size()>0) && basePath[basePath.size()-1] != '/')
    {
        basePath.push_back('/');
    }

    // First chew up the initial common part of the string
    size_t pe = basePath.find('/');
    while (pe != std::string::npos)
    {
        //cout << "basePath: " << basePath << endl;
        //cout << "fullPath: " << fullPath << endl;
        string sub = basePath.substr(0, pe+1);

        size_t fe = fullPath.find(sub);
        if (fe == 0)
        {
            basePath.erase(0, pe+1);
            fullPath.erase(0, sub.size());
            pe = basePath.find('/');
        }
        else
        {
            break;
        }
    }

    // Now determine the number of levels to "go up" based on remaning '/' in basePath
    pe = basePath.find('/');
    while (pe != std::string::npos)
    {
        result += "../";
        basePath.erase(0, pe+1);
        pe = basePath.find('/');
    }
    // Append what is remaning of base path
    result += fullPath;

    //cout << "Result: " << result << endl;

    return result;
}

void splitStringOnDelimiter(const std::string &rString, const char delim, std::vector<std::string> &rSplitVector)
{
    rSplitVector.clear();
    string item;
    stringstream ss(rString);
    while(getline(ss, item, delim))
    {
        rSplitVector.push_back(item);
    }
}

//! @brief Helpfunction that splits a full path into basepath and filename
//! @note Assumes that dir separator is forward slash /
void splitFilePath(const std::string fullPath, std::string &rBasePath, std::string &rFileName)
{
    size_t pos = fullPath.rfind('/');
    // If not found try a windows backslash instead
    if (pos == std::string::npos)
    {
        pos = fullPath.rfind('\\');
    }
    if (pos != std::string::npos)
    {
        rBasePath = fullPath.substr(0, pos+1) ;
        rFileName = fullPath.substr(pos+1);
    }
    else
    {
        rBasePath = "";
        rFileName = fullPath;
    }
}

//! @brief Helper function that returns the number of availible cores
size_t getNumAvailibleCores()
{
    size_t nCores = 1; // If non-Windows system, make sure there is at least one thread
#ifdef _WIN32
    // Obtain number of processor cores from environment variable
    if(getenv("NUMBER_OF_PROCESSORS") != 0)
    {
        string temp = getenv("NUMBER_OF_PROCESSORS");
        nCores = atoi(temp.c_str());
    }
#else
    nCores = max((long)1, sysconf(_SC_NPROCESSORS_ONLN));
#endif
    return nCores;
}

//! @brief Compares a vector with a reference vector
//! @param rVec Vector to compare
//! @param rRef Reference vector
//! @param tol (%) for acceptance
bool compareVectors(const std::vector<double> &rVec, const std::vector<double> &rRef, const double tol)
{
    if(rVec.size() != rRef.size())
    {
        printErrorMessage("compareVectors() Size mismatch!");
        return false;
    }

    for(size_t i=0; i<rVec.size(); ++i)
    {
        if( (fabs(1-rVec[i]/rRef[i]) > tol) && !(fabs(rVec[i])<1e-100) && !(fabs(rRef[i])<1e-10) )
        {
            //cout << "Test failed, Tol: " << tol << " comparing: " << rVec.at(i) << " with " << rRef.at(i) << " at index " << i << endl;
            return false;
        }
    }
    return true;
}

//! @brief Read the paths of external liubs from a text file
//! @param[in] filePath The file to read from
//! @param[out] rExtLibFileNames A vector with paths to the external libs to load
void readExternalLibsFromTxtFile(const std::string filePath, std::vector<std::string> &rExtLibFileNames)
{
    rExtLibFileNames.clear();
    std::string line;
    std::ifstream file;
    file.open(filePath.c_str());
    if ( file.is_open() )
    {
        while ( file.good() )
        {
            getline(file, line);
            if (*line.begin() != '#')
            {
                rExtLibFileNames.push_back(line);
            }
        }
        file.close();
    }
    else
    {
        printErrorMessage(string("Could not open externalLibsToLoadFile: ") + filePath );
    }
}

//! @brief Return the path to the current executable (HopsanCLI most likely)
//! @returns The path or empty string if path can not be found
string getCurrentExecPath()
{
#ifdef _WIN32
    char result[ MAX_PATH ];
    size_t count = GetModuleFileNameA( NULL, result, MAX_PATH );
#else
    char result[ PATH_MAX ];
    ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
#endif

    if (count > 0)
    {
        string base, file;
        splitFilePath(string(result, count), base, file);
        cout << "base, file: " << base << " " << file << endl;
        return base;
    }

    return "";
}
<commit_msg>Remove left-over debug message<commit_after>/*-----------------------------------------------------------------------------

 Copyright 2017 Hopsan Group

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

 The full license is available in the file LICENSE.
 For details about the 'Hopsan Group' or information about Authors and
 Contributors see the HOPSANGROUP and AUTHORS files that are located in
 the Hopsan source code root directory.

-----------------------------------------------------------------------------*/

//!
//! @file   HopsanCLI/CliUtilities.cpp
//! @author peter.nordin@liu.se
//! @date   2014-12-09
//!
//! @brief Contains helpfunctions for CLI
//!
//$Id$

#include "CliUtilities.h"

#include <iostream>
#include <sstream>
#include <fstream>
#include <cmath>

#ifndef _WIN32
#include <unistd.h>
#include <limits.h>
#else
#include <windows.h>
#endif

using namespace std;

//! @brief Prints a message with red color (resets color to defaul after)
//! @param[in] rError The error message
void printErrorMessage(const std::string &rError, bool silent)
{
    if(silent) return;

    setTerminalColor(Red);
    cout << "Error: " << rError << endl;
    setTerminalColor(Reset);
}

//! @brief Prints a message with yellow color (resets color to defaul after)
//! @param[in] rWarning The warning message
void printWarningMessage(const std::string &rWarning, bool silent)
{
    if(silent) return;

    setTerminalColor(Yellow);
    cout << "Warning: " << rWarning << endl;
    setTerminalColor(Reset);
}

//! @brief Prints a message with green color (resets color to defaul after)
//! @param[in] color The text color for the message
//! @param[in] rMessage The message
void printColorMessage(const ColorsEnumT color, const std::string &rMessage, bool silent)
{
    if(silent) return;

    setTerminalColor(color);
    cout << rMessage << endl;
    setTerminalColor(Reset);
}

//! @brief Changes color on console output
//! @param color Color number (0-15)
//! @todo Need yellow color also
void setTerminalColor(const ColorsEnumT color)
{
#ifdef _WIN32
    WORD c;
    switch (color)
    {
    case Red:
        c = FOREGROUND_INTENSITY | FOREGROUND_RED;
        break;
    case Green:
        c = FOREGROUND_INTENSITY | FOREGROUND_GREEN;
        break;
    case Yellow:
        c = FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED;
        break;
    case Blue:
        c = FOREGROUND_INTENSITY | FOREGROUND_BLUE;
        break;
    case White:
    default:
        c = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
    }

    HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hcon,c);
#else
    string c;
    switch (color)
    {
    case Red:
        c = "\e[0;91m";
        break;
    case Green:
        c = "\e[0;92m";
        break;
    case Yellow:
        c = "\e[0;93m";
        break;
    case Blue:
        c = "\e[0;94m";
        break;
    case White:
    default:
        c = "\e[0m";
    }

    cout << c;
#endif
}

//! @brief Helpfunction that splits a filename into basename and extesion
void splitFileName(const std::string fileName, std::string &rBaseName, std::string &rExt)
{
    size_t pos = fileName.rfind('.');
    if (pos != std::string::npos)
    {
        rBaseName = fileName.substr(0, pos) ;
        rExt = fileName.substr(pos+1);
    }
    else
    {
        rExt = "";
        rBaseName = fileName;
    }
}

//! @brief Convert the fullpath into a path relative to basepath, both paths must be relative the same directoryo (or absolute)
std::string relativePath(std::string basePath, std::string fullPath)
{
    std::string result;

    if ( (basePath.size()>0) && basePath[basePath.size()-1] != '/')
    {
        basePath.push_back('/');
    }

    // First chew up the initial common part of the string
    size_t pe = basePath.find('/');
    while (pe != std::string::npos)
    {
        //cout << "basePath: " << basePath << endl;
        //cout << "fullPath: " << fullPath << endl;
        string sub = basePath.substr(0, pe+1);

        size_t fe = fullPath.find(sub);
        if (fe == 0)
        {
            basePath.erase(0, pe+1);
            fullPath.erase(0, sub.size());
            pe = basePath.find('/');
        }
        else
        {
            break;
        }
    }

    // Now determine the number of levels to "go up" based on remaning '/' in basePath
    pe = basePath.find('/');
    while (pe != std::string::npos)
    {
        result += "../";
        basePath.erase(0, pe+1);
        pe = basePath.find('/');
    }
    // Append what is remaning of base path
    result += fullPath;

    //cout << "Result: " << result << endl;

    return result;
}

void splitStringOnDelimiter(const std::string &rString, const char delim, std::vector<std::string> &rSplitVector)
{
    rSplitVector.clear();
    string item;
    stringstream ss(rString);
    while(getline(ss, item, delim))
    {
        rSplitVector.push_back(item);
    }
}

//! @brief Helpfunction that splits a full path into basepath and filename
//! @note Assumes that dir separator is forward slash /
void splitFilePath(const std::string fullPath, std::string &rBasePath, std::string &rFileName)
{
    size_t pos = fullPath.rfind('/');
    // If not found try a windows backslash instead
    if (pos == std::string::npos)
    {
        pos = fullPath.rfind('\\');
    }
    if (pos != std::string::npos)
    {
        rBasePath = fullPath.substr(0, pos+1) ;
        rFileName = fullPath.substr(pos+1);
    }
    else
    {
        rBasePath = "";
        rFileName = fullPath;
    }
}

//! @brief Helper function that returns the number of availible cores
size_t getNumAvailibleCores()
{
    size_t nCores = 1; // If non-Windows system, make sure there is at least one thread
#ifdef _WIN32
    // Obtain number of processor cores from environment variable
    if(getenv("NUMBER_OF_PROCESSORS") != 0)
    {
        string temp = getenv("NUMBER_OF_PROCESSORS");
        nCores = atoi(temp.c_str());
    }
#else
    nCores = max((long)1, sysconf(_SC_NPROCESSORS_ONLN));
#endif
    return nCores;
}

//! @brief Compares a vector with a reference vector
//! @param rVec Vector to compare
//! @param rRef Reference vector
//! @param tol (%) for acceptance
bool compareVectors(const std::vector<double> &rVec, const std::vector<double> &rRef, const double tol)
{
    if(rVec.size() != rRef.size())
    {
        printErrorMessage("compareVectors() Size mismatch!");
        return false;
    }

    for(size_t i=0; i<rVec.size(); ++i)
    {
        if( (fabs(1-rVec[i]/rRef[i]) > tol) && !(fabs(rVec[i])<1e-100) && !(fabs(rRef[i])<1e-10) )
        {
            //cout << "Test failed, Tol: " << tol << " comparing: " << rVec.at(i) << " with " << rRef.at(i) << " at index " << i << endl;
            return false;
        }
    }
    return true;
}

//! @brief Read the paths of external liubs from a text file
//! @param[in] filePath The file to read from
//! @param[out] rExtLibFileNames A vector with paths to the external libs to load
void readExternalLibsFromTxtFile(const std::string filePath, std::vector<std::string> &rExtLibFileNames)
{
    rExtLibFileNames.clear();
    std::string line;
    std::ifstream file;
    file.open(filePath.c_str());
    if ( file.is_open() )
    {
        while ( file.good() )
        {
            getline(file, line);
            if (*line.begin() != '#')
            {
                rExtLibFileNames.push_back(line);
            }
        }
        file.close();
    }
    else
    {
        printErrorMessage(string("Could not open externalLibsToLoadFile: ") + filePath );
    }
}

//! @brief Return the path to the current executable (HopsanCLI most likely)
//! @returns The path or empty string if path can not be found
string getCurrentExecPath()
{
#ifdef _WIN32
    char result[ MAX_PATH ];
    size_t count = GetModuleFileNameA( NULL, result, MAX_PATH );
#else
    char result[ PATH_MAX ];
    ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
#endif

    if (count > 0)
    {
        string base, file;
        splitFilePath(string(result, count), base, file);
        //cout << "base, file: " << base << " " << file << endl;
        return base;
    }

    return "";
}
<|endoftext|>


<commit_before>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/client/lib/approx_topk.h"

#include <string>

#include "absl/numeric/bits.h"
#include "absl/strings/str_format.h"
#include "tensorflow/compiler/xla/client/xla_builder.h"
#include "tensorflow/compiler/xla/client/xla_computation.h"
#include "tensorflow/compiler/xla/shape.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/util.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"

// Used by rank 2+ operands
const uint64_t kTpuLaneTiling = 128;
// Used by rank 1 operands.
const uint64_t kTpuChunkTiling = 1024;

namespace xla {

// Converts a comparator to a combiner computation that can be fed to reduce or
// partial reduce ops.
XlaComputation BuildReductionComputation(
    XlaBuilder* builder, absl::Span<const PrimitiveType> op_types,
    const XlaComputation& comparator) {
  auto num_operands = op_types.size();
  std::vector<XlaOp> lhs_params;
  std::vector<XlaOp> rhs_params;
  int64_t param_number = 0;
  lhs_params.reserve(num_operands);
  rhs_params.reserve(num_operands);
  auto reduction_builder = builder->CreateSubBuilder("ReductionFn");
  for (const auto& op_type : op_types) {
    lhs_params.push_back(Parameter(reduction_builder.get(), param_number,
                                   ShapeUtil::MakeScalarShape(op_type),
                                   absl::StrFormat("lhs.%d", param_number)));
    param_number++;
  }
  for (const auto& op_type : op_types) {
    rhs_params.push_back(Parameter(reduction_builder.get(), param_number,
                                   ShapeUtil::MakeScalarShape(op_type),
                                   absl::StrFormat("rhs.%d", param_number)));
    param_number++;
  }

  std::vector<XlaOp> comparator_args;
  comparator_args.reserve(num_operands * 2);
  for (int i = 0; i < num_operands; ++i) {
    comparator_args.push_back(lhs_params[i]);
    comparator_args.push_back(rhs_params[i]);
  }
  auto pred = Call(reduction_builder.get(), comparator, comparator_args);
  std::vector<XlaOp> results;
  results.reserve(num_operands);
  for (int i = 0; i < num_operands; ++i) {
    results.push_back(Select(pred, lhs_params[i], rhs_params[i]));
  }
  Tuple(reduction_builder.get(), results);
  return reduction_builder->BuildAndNoteError();
}

XlaOp SortAndSliceBuilder(XlaBuilder* builder, absl::Span<const XlaOp> operands,
                          int64_t top_k, int64_t reduction_dim,
                          const XlaComputation& comparator) {
  auto operands_shapes = builder->GetOperandShapes(operands).ValueOrDie();
  int64_t rank = operands_shapes[0].rank();
  int64_t num_operands = operands.size();

  auto sorted_results = Sort(operands, comparator, reduction_dim);
  std::vector<int64_t> slice_start_indices(rank, 0);
  std::vector<int64_t> slice_limit_indices;
  std::vector<int64_t> slice_strides(rank, 1);
  slice_limit_indices.insert(slice_limit_indices.begin(),
                             operands_shapes[0].dimensions().begin(),
                             operands_shapes[0].dimensions().end());

  std::vector<XlaOp> sliced_results;
  sliced_results.reserve(num_operands);
  for (int i = 0; i < num_operands; ++i) {
    sliced_results.push_back(Slice(GetTupleElement(sorted_results, i),
                                   slice_start_indices, slice_limit_indices,
                                   slice_strides));
  }
  return Tuple(builder, sliced_results);
}

XlaOp ApproxTopK(XlaBuilder* builder, absl::Span<const XlaOp> operands,
                 absl::Span<const XlaOp> init_values, int64_t top_k,
                 int64_t reduction_dim, const XlaComputation& comparator,
                 float recall_target, bool aggregate_to_topk) {
  // Validates shapes and ranks
  if (operands.size() != init_values.size()) {
    return builder->ReportError(
        InvalidArgument("operands and init_values size mismatch: %d vs %d",
                        operands.size(), init_values.size()));
  }
  auto num_operands = operands.size();
  auto operands_shapes = builder->GetOperandShapes(operands).ValueOrDie();
  auto init_values_shapes = builder->GetOperandShapes(init_values).ValueOrDie();
  std::vector<PrimitiveType> op_types;
  for (int i = 0; i < num_operands; ++i) {
    const auto& op_shape = operands_shapes[i];
    const auto& init_shape = init_values_shapes[i];
    if (op_shape.rank() == 0) {
      return builder->ReportError(
          InvalidArgument("ApproxTopK operands must have rank 1+."));
    }
    if (!ShapeUtil::CompatibleIgnoringElementType(operands_shapes[0],
                                                  op_shape)) {
      return builder->ReportError(InvalidArgument(
          "operands shape mismatch: %s vs %s", operands_shapes[0].DebugString(),
          op_shape.DebugString()));
    }
    if (op_shape.element_type() != init_shape.element_type()) {
      return builder->ReportError(
          InvalidArgument("operands type mismatch: %s vs %s",
                          op_shape.DebugString(), init_shape.DebugString()));
    }

    op_types.push_back(op_shape.element_type());
  }
  int64_t rank = operands_shapes[0].rank();
  if (reduction_dim < 0 || reduction_dim >= rank) {
    return builder->ReportError(
        InvalidArgument("reduction_dim should range in [0,%d)", rank));
  }

  auto reduction_computation =
      BuildReductionComputation(builder, op_types, comparator);

  // Fallback to variadic reduce when top_k == 1.
  // TODO(fchern): Approx-topk followed by variadic reduce might run faster
  // than running variadic reduce directly.
  if (top_k == 1) {
    return Reduce(builder, operands, init_values, reduction_computation,
                  {reduction_dim});
  }

  uint64_t tpu_tiling = rank == 1 ? kTpuChunkTiling : kTpuLaneTiling;
  uint64_t n = operands_shapes[0].dimensions(reduction_dim);
  // ApproxTopK can only reduce elements larger than the tiling.
  if (n <= tpu_tiling) {
    if (aggregate_to_topk) {
      return SortAndSliceBuilder(builder, operands, top_k, reduction_dim,
                                 comparator);
    }
    return Tuple(builder, operands);
  }

  // Given number of data points N, K for top-k elements, and W for the size of
  // the reduce window, let M = Ceil(N / W) be the number of windows. The
  // expected number of top-k elements that doesn't collide in windows is
  //
  //   K * ((M - 1) / M)^{K - 1}
  //
  // The recall of is the expected number of top-k elements divided by K
  //
  //   recall = ((M - 1) / M)^{K - 1}
  //          = (1 - 1/M)^{K - 1}
  //          = (1 - 1/M)^{-M * (K - 1)/(-M)}
  //          ~= EXP((1 - K) / M)    for large M
  //
  //   => M = (1 - K)/LOG(recall)
  if (recall_target <= 0. || recall_target > 1.0) {
    return builder->ReportError(
        InvalidArgument("recall_target should range in (0,1]"));
  }
  uint64_t m = std::min(
      std::max(static_cast<uint64_t>((1.0 - top_k) / std::log(recall_target)),
               tpu_tiling),
      n);
  uint32_t log2_reduction = absl::bit_width(n / m) - 1;  // floor(n / m)
  if (log2_reduction == 0) {
    if (aggregate_to_topk) {
      return SortAndSliceBuilder(builder, operands, top_k, reduction_dim,
                                 comparator);
    }
    return Tuple(builder, operands);
  }

  std::vector<XlaOp> partial_reduce_args;
  for (const auto& op : operands) {
    partial_reduce_args.push_back(op);
  }
  for (const auto& op : init_values) {
    partial_reduce_args.push_back(op);
  }
  int64_t output_reduction_size =
      CeilOfRatio<int64_t>(CeilOfRatio(n, tpu_tiling), (1 << log2_reduction)) *
      tpu_tiling;
  std::vector<Shape> approx_output_shapes;
  for (auto op_shape : operands_shapes) {
    op_shape.mutable_dimensions()[reduction_dim] = output_reduction_size;
    approx_output_shapes.push_back(op_shape);
  }
  auto approx_output_shape = ShapeUtil::MakeTupleShape(approx_output_shapes);
  // PartialReduce option in JSON form
  std::string partial_reduce_option =
      absl::StrFormat("{\"log2_reduction\": %d, \"reduction_dim\": %d}",
                      log2_reduction, reduction_dim);

  auto approx_topk = CustomCallWithComputation(
      builder, "PartialReduce", partial_reduce_args, reduction_computation,
      approx_output_shape, partial_reduce_option);

  if (aggregate_to_topk) {
    std::vector<XlaOp> approx_topk_results;
    approx_topk_results.reserve(num_operands);
    for (int i = 0; i < num_operands; ++i) {
      approx_topk_results.push_back(GetTupleElement(approx_topk, i));
    }
    return SortAndSliceBuilder(builder, approx_topk_results, top_k,
                               reduction_dim, comparator);
  }
  return approx_topk;
}

}  // namespace xla
<commit_msg>[XLA:TPU] Update ApproxTopK to use native comparator.<commit_after>/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/compiler/xla/client/lib/approx_topk.h"

#include <string>

#include "absl/numeric/bits.h"
#include "absl/strings/str_format.h"
#include "tensorflow/compiler/xla/client/xla_builder.h"
#include "tensorflow/compiler/xla/client/xla_computation.h"
#include "tensorflow/compiler/xla/shape.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/util.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"

// Used by rank 2+ operands
const uint64_t kTpuLaneTiling = 128;
// Used by rank 1 operands.
const uint64_t kTpuChunkTiling = 1024;

namespace xla {

// Converts a comparator to a combiner computation that can be fed to reduce or
// partial reduce ops.
XlaComputation BuildReductionComputation(
    XlaBuilder* builder, absl::Span<const PrimitiveType> op_types,
    const XlaComputation& comparator) {
  auto num_operands = op_types.size();
  std::vector<XlaOp> lhs_params;
  std::vector<XlaOp> rhs_params;
  int64_t param_number = 0;
  lhs_params.reserve(num_operands);
  rhs_params.reserve(num_operands);
  auto reduction_builder = builder->CreateSubBuilder("ReductionFn");
  for (const auto& op_type : op_types) {
    lhs_params.push_back(Parameter(reduction_builder.get(), param_number,
                                   ShapeUtil::MakeScalarShape(op_type),
                                   absl::StrFormat("lhs.%d", param_number)));
    param_number++;
  }
  for (const auto& op_type : op_types) {
    rhs_params.push_back(Parameter(reduction_builder.get(), param_number,
                                   ShapeUtil::MakeScalarShape(op_type),
                                   absl::StrFormat("rhs.%d", param_number)));
    param_number++;
  }

  std::vector<XlaOp> comparator_args;
  comparator_args.reserve(num_operands * 2);
  for (int i = 0; i < num_operands; ++i) {
    comparator_args.push_back(lhs_params[i]);
    comparator_args.push_back(rhs_params[i]);
  }
  auto pred = Call(reduction_builder.get(), comparator, comparator_args);
  std::vector<XlaOp> results;
  results.reserve(num_operands);
  for (int i = 0; i < num_operands; ++i) {
    results.push_back(Select(pred, lhs_params[i], rhs_params[i]));
  }
  Tuple(reduction_builder.get(), results);
  return reduction_builder->BuildAndNoteError();
}

XlaOp SortAndSliceBuilder(XlaBuilder* builder, absl::Span<const XlaOp> operands,
                          int64_t top_k, int64_t reduction_dim,
                          const XlaComputation& comparator) {
  auto operands_shapes = builder->GetOperandShapes(operands).ValueOrDie();
  int64_t rank = operands_shapes[0].rank();
  int64_t num_operands = operands.size();

  auto sorted_results = Sort(operands, comparator, reduction_dim);
  std::vector<int64_t> slice_start_indices(rank, 0);
  std::vector<int64_t> slice_limit_indices;
  std::vector<int64_t> slice_strides(rank, 1);
  slice_limit_indices.insert(slice_limit_indices.begin(),
                             operands_shapes[0].dimensions().begin(),
                             operands_shapes[0].dimensions().end());

  std::vector<XlaOp> sliced_results;
  sliced_results.reserve(num_operands);
  for (int i = 0; i < num_operands; ++i) {
    sliced_results.push_back(Slice(GetTupleElement(sorted_results, i),
                                   slice_start_indices, slice_limit_indices,
                                   slice_strides));
  }
  return Tuple(builder, sliced_results);
}

XlaOp ApproxTopK(XlaBuilder* builder, absl::Span<const XlaOp> operands,
                 absl::Span<const XlaOp> init_values, int64_t top_k,
                 int64_t reduction_dim, const XlaComputation& comparator,
                 float recall_target, bool aggregate_to_topk) {
  // Validates shapes and ranks
  if (operands.size() != init_values.size()) {
    return builder->ReportError(
        InvalidArgument("operands and init_values size mismatch: %d vs %d",
                        operands.size(), init_values.size()));
  }
  auto num_operands = operands.size();
  auto operands_shapes = builder->GetOperandShapes(operands).ValueOrDie();
  auto init_values_shapes = builder->GetOperandShapes(init_values).ValueOrDie();
  std::vector<PrimitiveType> op_types;
  for (int i = 0; i < num_operands; ++i) {
    const auto& op_shape = operands_shapes[i];
    const auto& init_shape = init_values_shapes[i];
    if (op_shape.rank() == 0) {
      return builder->ReportError(
          InvalidArgument("ApproxTopK operands must have rank 1+."));
    }
    if (!ShapeUtil::CompatibleIgnoringElementType(operands_shapes[0],
                                                  op_shape)) {
      return builder->ReportError(InvalidArgument(
          "operands shape mismatch: %s vs %s", operands_shapes[0].DebugString(),
          op_shape.DebugString()));
    }
    if (op_shape.element_type() != init_shape.element_type()) {
      return builder->ReportError(
          InvalidArgument("operands type mismatch: %s vs %s",
                          op_shape.DebugString(), init_shape.DebugString()));
    }

    op_types.push_back(op_shape.element_type());
  }
  int64_t rank = operands_shapes[0].rank();
  if (reduction_dim < 0 || reduction_dim >= rank) {
    return builder->ReportError(
        InvalidArgument("reduction_dim should range in [0,%d)", rank));
  }

  auto reduction_computation =
      BuildReductionComputation(builder, op_types, comparator);

  // Fallback to variadic reduce when top_k == 1.
  // TODO(fchern): Approx-topk followed by variadic reduce might run faster
  // than running variadic reduce directly.
  if (top_k == 1) {
    return Reduce(builder, operands, init_values, reduction_computation,
                  {reduction_dim});
  }

  uint64_t tpu_tiling = rank == 1 ? kTpuChunkTiling : kTpuLaneTiling;
  uint64_t n = operands_shapes[0].dimensions(reduction_dim);
  // ApproxTopK can only reduce elements larger than the tiling.
  if (n <= tpu_tiling) {
    if (aggregate_to_topk) {
      return SortAndSliceBuilder(builder, operands, top_k, reduction_dim,
                                 comparator);
    }
    return Tuple(builder, operands);
  }

  // Given number of data points N, K for top-k elements, and W for the size of
  // the reduce window, let M = Ceil(N / W) be the number of windows. The
  // expected number of top-k elements that doesn't collide in windows is
  //
  //   K * ((M - 1) / M)^{K - 1}
  //
  // The recall of is the expected number of top-k elements divided by K
  //
  //   recall = ((M - 1) / M)^{K - 1}
  //          = (1 - 1/M)^{K - 1}
  //          = (1 - 1/M)^{-M * (K - 1)/(-M)}
  //          ~= EXP((1 - K) / M)    for large M
  //
  //   => M = (1 - K)/LOG(recall)
  if (recall_target <= 0. || recall_target > 1.0) {
    return builder->ReportError(
        InvalidArgument("recall_target should range in (0,1]"));
  }
  uint64_t m = std::min(
      std::max(static_cast<uint64_t>((1.0 - top_k) / std::log(recall_target)),
               tpu_tiling),
      n);
  uint32_t log2_reduction = absl::bit_width(n / m) - 1;  // floor(n / m)
  if (log2_reduction == 0) {
    if (aggregate_to_topk) {
      return SortAndSliceBuilder(builder, operands, top_k, reduction_dim,
                                 comparator);
    }
    return Tuple(builder, operands);
  }

  std::vector<XlaOp> partial_reduce_args;
  for (const auto& op : operands) {
    partial_reduce_args.push_back(op);
  }
  for (const auto& op : init_values) {
    partial_reduce_args.push_back(op);
  }
  int64_t output_reduction_size =
      CeilOfRatio<int64_t>(CeilOfRatio(n, tpu_tiling), (1 << log2_reduction)) *
      tpu_tiling;
  std::vector<Shape> approx_output_shapes;
  for (auto op_shape : operands_shapes) {
    op_shape.mutable_dimensions()[reduction_dim] = output_reduction_size;
    approx_output_shapes.push_back(op_shape);
  }
  auto approx_output_shape = ShapeUtil::MakeTupleShape(approx_output_shapes);
  // PartialReduce option in JSON form
  std::string partial_reduce_option = absl::StrFormat(
      "{\"log2_reduction\": %d, \"reduction_dim\": %d, \"to_apply_type\": "
      "\"comparator\"}",
      log2_reduction, reduction_dim);

  auto approx_topk = CustomCallWithComputation(
      builder, "PartialReduce", partial_reduce_args, comparator,
      approx_output_shape, partial_reduce_option);

  if (aggregate_to_topk) {
    std::vector<XlaOp> approx_topk_results;
    approx_topk_results.reserve(num_operands);
    for (int i = 0; i < num_operands; ++i) {
      approx_topk_results.push_back(GetTupleElement(approx_topk, i));
    }
    return SortAndSliceBuilder(builder, approx_topk_results, top_k,
                               reduction_dim, comparator);
  }
  return approx_topk;
}

}  // namespace xla
<|endoftext|>


<commit_before>// REQUIRES: x86-registered-target,x86-64-registered-target
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -S %s -o %t-64.s
// RUN: FileCheck -check-prefix CHECK-LP64 --input-file=%t-64.s %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -S %s -o %t-32.s
// RUN: FileCheck -check-prefix CHECK-LP32 --input-file=%t-32.s %s

struct A { A(const A&, int i1 = 1); };

struct B : A { };

A f(const B &b) {
  return b;
}

// CHECK-LP64: callq    __ZN1AC1ERKS_i

// CHECK-LP32: calll     L__ZN1AC1ERKS_i

<commit_msg>Check IR instead of assembly in this test.<commit_after>// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | \
// RUN: FileCheck %s
// RUN: %clang_cc1 -triple i386-apple-darwin -std=c++11 -emit-llvm %s -o - | \
// RUN: FileCheck %s

struct A { A(const A&, int i1 = 1); };

struct B : A { };

A f(const B &b) {
  return b;
}

// CHECK: call void @_ZN1AC1ERKS_i
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    RibbonF.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkMath.hh"
#include "RibbonF.hh"
#include "FPoints.hh"
#include "FNormals.hh"
#include "PolyLine.hh"

// Description:
// Construct ribbon so that width is 0.1, no normal rotation, the width does
// not vary with scalar values, and the width factor is 2.0.
vtkRibbonFilter::vtkRibbonFilter()
{
  this->Width = 0.5;
  this->Angle = 0.0;
  this->VaryWidth = 0;
  this->WidthFactor = 2.0;
}

void vtkRibbonFilter::Execute()
{
  int i, j, k;
  vtkPoints *inPts;
  vtkNormals *inNormals;
  vtkPointData *pd;
  vtkCellArray *inLines;
  int numNewPts;
  vtkFloatPoints *newPts;
  vtkFloatNormals *newNormals;
  vtkCellArray *newStrips;
  int npts, *pts;
  float p[3], pNext[3];
  float *n;
  float s[3], sNext[3], sPrev[3], w[3];
  double BevelAngle;
  vtkMath math;
  float theta;
  int deleteNormals=0, ptId;
  vtkPolyData *input=(vtkPolyData *)this->Input;
  vtkScalars *inScalars=NULL;
  float sFactor=1.0, range[2];
  int ptOffset=0;
//
// Initialize
//
  vtkDebugMacro(<<"Creating ribbon");
  this->Initialize();

  if ( !(inPts=input->GetPoints()) ||
  (numNewPts=inPts->GetNumberOfPoints()*2) < 1 ||
  !(inLines = input->GetLines()) || inLines->GetNumberOfCells() < 1 )
    {
    vtkErrorMacro(<< ": No input data!\n");
    return;
    }

  // copy scalars, vectors, tcoords. Normals may be computed here.
  pd = input->GetPointData();
  this->PointData.CopyNormalsOff();
  this->PointData.CopyAllocate(pd,numNewPts);

  if ( !(inNormals=pd->GetNormals()) )
    {
    vtkPolyLine lineNormalGenerator;
    deleteNormals = 1;
    inNormals = new vtkFloatNormals(numNewPts);
    if ( !lineNormalGenerator.GenerateSlidingNormals(inPts,inLines,(vtkFloatNormals*)inNormals) )
      {
      vtkErrorMacro(<< "No normals for line!\n");
      inNormals->Delete();
      return;
      }
    }
//
// If varying width, get appropriate info.
//
  if ( this->VaryWidth && (inScalars=pd->GetScalars()) )
    {
    inScalars->GetRange(range);
    }

  newPts = new vtkFloatPoints(numNewPts);
  newNormals = new vtkFloatNormals(numNewPts);
  newStrips = new vtkCellArray;
  newStrips->Allocate(newStrips->EstimateSize(1,numNewPts));
//
//  Create pairs of points along the line that are later connected into a
//  triangle strip.
//
  theta = this->Angle * math.DegreesToRadians();
  for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); )
    {
//
// Use "averaged" segment to create beveled effect. Watch out for first and
// last points.
//
    for (j=0; j < npts; j++)
      {

      if ( j == 0 ) //first point
        {
        inPts->GetPoint(pts[0],p);
        inPts->GetPoint(pts[1],pNext);
        for (i=0; i<3; i++)
          {
          sNext[i] = pNext[i] - p[i];
          sPrev[i] = sNext[i];
          }
        }

      else if ( j == (npts-1) ) //last point
        {
        for (i=0; i<3; i++)
          {
          sPrev[i] = sNext[i];
          p[i] = pNext[i];
          }
        }

      else
        {
        for (i=0; i<3; i++) p[i] = pNext[i];
        inPts->GetPoint(pts[j+1],pNext);
        for (i=0; i<3; i++)
          {
          sPrev[i] = sNext[i];
          sNext[i] = pNext[i] - p[i];
          }
        }

      n = inNormals->GetNormal(pts[j]);

      if ( math.Normalize(sNext) == 0.0 )
        {
        vtkErrorMacro(<<"Coincident points!");
        return;
        }

      for (i=0; i<3; i++) s[i] = (sPrev[i] + sNext[i]) / 2.0; //average vector
      math.Normalize(s);

      if ( (BevelAngle = math.Dot(sNext,sPrev)) > 1.0 ) BevelAngle = 1.0;
      if ( BevelAngle < -1.0 ) BevelAngle = -1.0;
      BevelAngle = acos((double)BevelAngle) / 2.0; //(0->90 degrees)
      if ( (BevelAngle = cos(BevelAngle)) == 0.0 ) BevelAngle = 1.0;

      BevelAngle = this->Width / BevelAngle;

      math.Cross(s,n,w);
      if ( math.Normalize(w) == 0.0)
        {
        vtkErrorMacro(<<"Bad normal!");
        return;
        }

      if ( inScalars )
        sFactor = 1.0 + ((this->WidthFactor - 1.0) *
                  (inScalars->GetScalar(j) - range[0]) / (range[1]-range[0]));

      for (i=0; i<3; i++) s[i] = p[i] + w[i] * BevelAngle * sFactor;
      ptId = newPts->InsertNextPoint(s);
      newNormals->InsertNormal(ptId,n);
      this->PointData.CopyData(pd,pts[j],ptId);

      for (i=0; i<3; i++) s[i] = p[i] - w[i] * BevelAngle * sFactor;
      ptId = newPts->InsertNextPoint(s);
      newNormals->InsertNormal(ptId,n);
      this->PointData.CopyData(pd,pts[j],ptId);
      }
//
// Generate the strip topology
//
    newStrips->InsertNextCell(npts*2);
    for (i=0; i < npts; i++)
      {
      newStrips->InsertCellPoint(ptOffset+2*i);
      newStrips->InsertCellPoint(ptOffset+2*i+1);
      }

    ptOffset += npts*2;
    } //for this line
//
// Update ourselves
//
  if ( deleteNormals ) inNormals->Delete();

  this->SetPoints(newPts);
  newPts->Delete();

  this->SetStrips(newStrips);
  newStrips->Delete();

  this->PointData.SetNormals(newNormals);
  newNormals->Delete();

  this->Squeeze();
}

void vtkRibbonFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolyToPolyFilter::PrintSelf(os,indent);

  os << indent << "Width: " << this->Width << "\n";
  os << indent << "Angle: " << this->Angle << "\n";
  os << indent << "VaryWidth: " << (this->VaryWidth ? "On\n" : "Off\n");
  os << indent << "Width Factor: " << this->WidthFactor << "\n";
}

<commit_msg>removed unused variable<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    RibbonF.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkMath.hh"
#include "RibbonF.hh"
#include "FPoints.hh"
#include "FNormals.hh"
#include "PolyLine.hh"

// Description:
// Construct ribbon so that width is 0.1, no normal rotation, the width does
// not vary with scalar values, and the width factor is 2.0.
vtkRibbonFilter::vtkRibbonFilter()
{
  this->Width = 0.5;
  this->Angle = 0.0;
  this->VaryWidth = 0;
  this->WidthFactor = 2.0;
}

void vtkRibbonFilter::Execute()
{
  int i, j;
  vtkPoints *inPts;
  vtkNormals *inNormals;
  vtkPointData *pd;
  vtkCellArray *inLines;
  int numNewPts;
  vtkFloatPoints *newPts;
  vtkFloatNormals *newNormals;
  vtkCellArray *newStrips;
  int npts, *pts;
  float p[3], pNext[3];
  float *n;
  float s[3], sNext[3], sPrev[3], w[3];
  double BevelAngle;
  vtkMath math;
  float theta;
  int deleteNormals=0, ptId;
  vtkPolyData *input=(vtkPolyData *)this->Input;
  vtkScalars *inScalars=NULL;
  float sFactor=1.0, range[2];
  int ptOffset=0;
//
// Initialize
//
  vtkDebugMacro(<<"Creating ribbon");
  this->Initialize();

  if ( !(inPts=input->GetPoints()) ||
  (numNewPts=inPts->GetNumberOfPoints()*2) < 1 ||
  !(inLines = input->GetLines()) || inLines->GetNumberOfCells() < 1 )
    {
    vtkErrorMacro(<< ": No input data!\n");
    return;
    }

  // copy scalars, vectors, tcoords. Normals may be computed here.
  pd = input->GetPointData();
  this->PointData.CopyNormalsOff();
  this->PointData.CopyAllocate(pd,numNewPts);

  if ( !(inNormals=pd->GetNormals()) )
    {
    vtkPolyLine lineNormalGenerator;
    deleteNormals = 1;
    inNormals = new vtkFloatNormals(numNewPts);
    if ( !lineNormalGenerator.GenerateSlidingNormals(inPts,inLines,(vtkFloatNormals*)inNormals) )
      {
      vtkErrorMacro(<< "No normals for line!\n");
      inNormals->Delete();
      return;
      }
    }
//
// If varying width, get appropriate info.
//
  if ( this->VaryWidth && (inScalars=pd->GetScalars()) )
    {
    inScalars->GetRange(range);
    }

  newPts = new vtkFloatPoints(numNewPts);
  newNormals = new vtkFloatNormals(numNewPts);
  newStrips = new vtkCellArray;
  newStrips->Allocate(newStrips->EstimateSize(1,numNewPts));
//
//  Create pairs of points along the line that are later connected into a
//  triangle strip.
//
  theta = this->Angle * math.DegreesToRadians();
  for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); )
    {
//
// Use "averaged" segment to create beveled effect. Watch out for first and
// last points.
//
    for (j=0; j < npts; j++)
      {

      if ( j == 0 ) //first point
        {
        inPts->GetPoint(pts[0],p);
        inPts->GetPoint(pts[1],pNext);
        for (i=0; i<3; i++)
          {
          sNext[i] = pNext[i] - p[i];
          sPrev[i] = sNext[i];
          }
        }

      else if ( j == (npts-1) ) //last point
        {
        for (i=0; i<3; i++)
          {
          sPrev[i] = sNext[i];
          p[i] = pNext[i];
          }
        }

      else
        {
        for (i=0; i<3; i++) p[i] = pNext[i];
        inPts->GetPoint(pts[j+1],pNext);
        for (i=0; i<3; i++)
          {
          sPrev[i] = sNext[i];
          sNext[i] = pNext[i] - p[i];
          }
        }

      n = inNormals->GetNormal(pts[j]);

      if ( math.Normalize(sNext) == 0.0 )
        {
        vtkErrorMacro(<<"Coincident points!");
        return;
        }

      for (i=0; i<3; i++) s[i] = (sPrev[i] + sNext[i]) / 2.0; //average vector
      math.Normalize(s);

      if ( (BevelAngle = math.Dot(sNext,sPrev)) > 1.0 ) BevelAngle = 1.0;
      if ( BevelAngle < -1.0 ) BevelAngle = -1.0;
      BevelAngle = acos((double)BevelAngle) / 2.0; //(0->90 degrees)
      if ( (BevelAngle = cos(BevelAngle)) == 0.0 ) BevelAngle = 1.0;

      BevelAngle = this->Width / BevelAngle;

      math.Cross(s,n,w);
      if ( math.Normalize(w) == 0.0)
        {
        vtkErrorMacro(<<"Bad normal!");
        return;
        }

      if ( inScalars )
        sFactor = 1.0 + ((this->WidthFactor - 1.0) *
                  (inScalars->GetScalar(j) - range[0]) / (range[1]-range[0]));

      for (i=0; i<3; i++) s[i] = p[i] + w[i] * BevelAngle * sFactor;
      ptId = newPts->InsertNextPoint(s);
      newNormals->InsertNormal(ptId,n);
      this->PointData.CopyData(pd,pts[j],ptId);

      for (i=0; i<3; i++) s[i] = p[i] - w[i] * BevelAngle * sFactor;
      ptId = newPts->InsertNextPoint(s);
      newNormals->InsertNormal(ptId,n);
      this->PointData.CopyData(pd,pts[j],ptId);
      }
//
// Generate the strip topology
//
    newStrips->InsertNextCell(npts*2);
    for (i=0; i < npts; i++)
      {
      newStrips->InsertCellPoint(ptOffset+2*i);
      newStrips->InsertCellPoint(ptOffset+2*i+1);
      }

    ptOffset += npts*2;
    } //for this line
//
// Update ourselves
//
  if ( deleteNormals ) inNormals->Delete();

  this->SetPoints(newPts);
  newPts->Delete();

  this->SetStrips(newStrips);
  newStrips->Delete();

  this->PointData.SetNormals(newNormals);
  newNormals->Delete();

  this->Squeeze();
}

void vtkRibbonFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkPolyToPolyFilter::PrintSelf(os,indent);

  os << indent << "Width: " << this->Width << "\n";
  os << indent << "Angle: " << this->Angle << "\n";
  os << indent << "VaryWidth: " << (this->VaryWidth ? "On\n" : "Off\n");
  os << indent << "Width Factor: " << this->WidthFactor << "\n";
}

<|endoftext|>


<commit_before>AliAnalysisTaskElectronEfficiencyV2* AddTask_rbailhac_ElectronEfficiencyV2_PbPb(Bool_t getFromAlien = kFALSE,
										TString cFileName ="Config_rbailhac_ElectronEfficiencyV2_PbPb.C",
										UInt_t trigger = AliVEvent::kINT7,
										Bool_t rejpileup = kTRUE,
										const Int_t CenMin =  0,
										const Int_t CenMax = 10,
										const Float_t PtMin =  0.2,
										const Float_t PtMax = 10.0,
										const Float_t EtaMin = -0.8,
										const Float_t EtaMax = +0.8,
										const Bool_t UsePtVec = kTRUE,
										const Bool_t DoULSLS = kTRUE,
										const TString generators = "pizero_0;eta_1;etaprime_2;rho_3;omega_4;phi_5;jpsi_6;Pythia CC_0;Pythia BB_0;Pythia B_0;",
										const Bool_t isLHC19f2 = kTRUE,
										const std::string resolutionFilename ="",
										const std::string cocktailFilename   ="",
										const std::string centralityFilename ="",
										const TString outname = "LMEE.root")
{

  //get the current analysis manager
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTask_rbailhac_test", "No analysis manager found.");
    return 0;
  }

  //Base Directory for GRID / LEGO Train
  TString configBasePath= "$ALICE_PHYSICS/PWGDQ/dielectron/macrosLMEE/";
  if(getFromAlien && (!gSystem->Exec(Form("alien_cp alien:///alice/cern.ch/user/r/rbailhac/PWGDQ/dielectron/macrosLMEE/%s .",cFileName.Data()))) ){
    configBasePath=Form("%s/",gSystem->pwd());
  }

  TString configFilePath(configBasePath+cFileName);

  std::cout << "Configpath:  " << configFilePath << std::endl;

  if (!gROOT->GetListOfGlobalFunctions()->FindObject("Config_rbailhac_ElectronEfficiencyV2_PbPb")) {
    printf("Load macro now\n");
    gROOT->LoadMacro(configFilePath.Data());
  }

  // trigger
  TString triggername = "NULL";
  if(trigger == (UInt_t)AliVEvent::kINT7)             triggername = "kINT7";
  else if(trigger == (UInt_t)AliVEvent::kCentral)     triggername = "kCentral";
  else if(trigger == (UInt_t)AliVEvent::kSemiCentral) triggername = "kSemiCentral";
  else if(trigger == (UInt_t)(AliVEvent::kINT7 | AliVEvent::kCentral | AliVEvent::kSemiCentral)) triggername = "kCombinedCentralityTriggers";
  else if(trigger == (UInt_t)(AliVEvent::kINT7 | AliVEvent::kCentral))                           triggername = "kCombinedCentral";
  else if(trigger == (UInt_t)(AliVEvent::kINT7 | AliVEvent::kSemiCentral))                       triggername = "kCombinedSemiCentral";

  // generators
  TString suffixgen = "";
  if(generators.Contains("Pythia CC") && (generators.Contains("Pythia BB") || generators.Contains("Pythia B"))) suffixgen = "_CC_BB";
  else if(generators.Contains("Pythia CC")) suffixgen = "_CC";
  else if(generators.Contains("Pythia BB") || generators.Contains("Pythia B")) suffixgen = "_BB";
  else if(generators.Contains("pizero_0")) suffixgen = "_LF";
  else suffixgen = "";

  //create task and add it to the manager (MB)
  TString appendix;
  appendix += TString::Format("Cen%d_%d_%s_%s",CenMin,CenMax,triggername.Data(),suffixgen.Data());
  printf("appendix %s\n", appendix.Data());

  //##########################################################
  //############################################################
  // Creating an instance of the task
  AliAnalysisTaskElectronEfficiencyV2* task = new AliAnalysisTaskElectronEfficiencyV2(Form("TaskElectronEfficiencyV2_%s",appendix.Data()));
  gROOT->GetListOfSpecials()->Add(task);//this is only for ProcessLine(AddMCSignal);

  // #########################################################
  // #########################################################
  // Set TOF correction
  // if(tofcor){
  //  SetEtaCorrectionTOFRMS(task, AliDielectronVarManager::kP, AliDielectronVarManager::kEta);
  //  SetEtaCorrectionTOFMean(task, AliDielectronVarManager::kP, AliDielectronVarManager::kEta);
  //}

  // #########################################################
  // #########################################################
  // Event selection. Is the same for all the different cutsettings
  task->SetEnablePhysicsSelection(kTRUE);//always ON in Run2 analyses for both data and MC.
  task->SetTriggerMask(trigger);
  task->SetEventFilter((reinterpret_cast<AliDielectronEventCuts*>(gROOT->ProcessLine(Form("GetEventCuts(%f,%f,%d,\"%s\")",(Float_t)CenMin,(Float_t)CenMax,rejpileup,"V0M")))));

  // #########################################################
  // #########################################################
  // Set minimum and maximum values of generated tracks. Only used to save computing power.
  // Do not set here your analysis pt-cuts
  task->SetMinPtGen(0.1);
  task->SetMaxPtGen(1e+10);
  task->SetMinEtaGen(-1.5);
  task->SetMaxEtaGen(+1.5);

  // #########################################################
  // #########################################################
  // Set minimum and maximum values for pairing
  task->SetKinematicCuts(PtMin, PtMax, EtaMin, EtaMax);

  // #########################################################
  // #########################################################
  // Set Binning single variables
  if (UsePtVector == true) {
    std::vector<double> ptBinsVec;
     const Int_t nBinsPt = (Int_t)gROOT->ProcessLine("GetnBinsPt()");
    for (unsigned int i = 0; i < nBinsPt+1; ++i){
      ptBinsVec.push_back(reinterpret_cast<Double_t>(gROOT->ProcessLine(Form("GetptBins(%d)",i))));
    }
    task->SetPtBins(ptBinsVec);
  }
  else task->SetPtBinsLinear   (0,  10, 100);
  task->SetEtaBinsLinear (-1.,1.,20); // 40 before
  task->SetPhiBinsLinear  (0, TMath::TwoPi(), 36); // 90 before
  task->SetThetaBinsLinear(0, TMath::TwoPi(), 60);

  // pair variables
  const Int_t Nmee = 150;
  Double_t mee[Nmee] = {};
  for(Int_t i=0  ;i<110 ;i++) mee[i] = 0.01 * (i-  0) +  0.0;//from 0 to 1.1 GeV/c2, every 0.01 GeV/c2
  for(Int_t i=110;i<Nmee;i++) mee[i] = 0.1  * (i-110) +  1.1;//from 1.1 to 5 GeV/c2, evety 0.1 GeV/c2
  std::vector<double> v_mee(mee,std::end(mee));

  const Int_t NpTee = 121;
  Double_t pTee[NpTee] = {};
  for(Int_t i=0  ;i<10   ;i++) pTee[i] = 0.01 * (i-  0) +  0.0;//from 0 to 0.09 GeV/c, every 0.01 GeV/c
  for(Int_t i=10 ;i<110  ;i++) pTee[i] = 0.1  * (i- 10) +  0.1;//from 0.1 to 10 GeV/c, evety 0.1 GeV/c
  for(Int_t i=110;i<NpTee;i++) pTee[i] = 1.0  * (i-110) + 10.0;//from 10 to 20 GeV/c, evety 1.0 GeV/c
  std::vector<double> v_pTee(pTee,std::end(pTee));
  task->SetMassBins(v_mee);
  task->SetPairPtBins(v_pTee);
  //task->SetPhiVBinsLinear(0, TMath::Pi(), 100);
  //task->SetFillPhiV(kTRUE);

  // #########################################################
  // #########################################################
  //task->SetSmearGenerated(kFALSE); // cross check smearing the MC at single level and filling resolution maps
 // Resolution File, If resoFilename = "" no correction is applied
  task->SetResolutionFile(resolutionFilename);
  task->SetResolutionFileFromAlien("/alice/cern.ch/user/r/rbailhac/supportFiles/" + resolutionFilename);
  task->SetResolutionDeltaPtBinsLinear   (-10., 2., (Int_t)gROOT->ProcessLine("GetNbinsDeltaMom()"));
  task->SetResolutionRelPtBinsLinear   (0., 2.,  (Int_t)gROOT->ProcessLine("GetNbinsRelMom()"));
  task->SetResolutionEtaBinsLinear  (-0.4, 0.4, (Int_t)gROOT->ProcessLine("GetNbinsDeltaEta()"));
  task->SetResolutionPhiBinsLinear  (-0.4, 0.4, (Int_t)gROOT->ProcessLine("GetNbinsDeltaPhi()"));
  task->SetResolutionThetaBinsLinear(-0.4, 0.4, (Int_t)gROOT->ProcessLine("GetNbinsDeltaTheta()"));

  //###########################################################
  //############################################################
  // Set MCSignal and Cutsetting to fill the support histograms
  task->SetSupportHistoMCSignalAndCutsetting(0,0);//fill support histograms for first MCsignal and first cutsetting

  // #########################################################
  // #########################################################
  // Set centrality correction. If resoFilename = "" no correction is applied
  task->SetCentralityFile(centralityFilename);

  // #########################################################
  // #########################################################
  // Pairing related config
  task->SetDoPairing(kTRUE);
  task->SetULSandLS(DoULSLS);

  //#####################################################
  //######################################################
  // Generators
  cout<<"Efficiency based on MC generators: " << generators <<endl;
  TString generatorsPair=generators;
  task->SetGeneratorMCSignalName(generatorsPair);
  task->SetGeneratorULSSignalName(generators);
  task->SetLHC19f2MC(isLHC19f2);

  //###############################################
  //##############################################
  task->SetCocktailWeighting(cocktailFilename);
  task->SetCocktailWeightingFromAlien("/alice/cern.ch/user/r/rbailhac/supportFiles/" + cocktailFilename);

  // #########################################################
  // #########################################################
  // Add MCSignals. Can be set to see differences of:
  // e.g. secondaries and primaries. or primaries from charm and resonances
  gROOT->ProcessLine(Form("AddSingleLegMCSignal(%s)",task->GetName()));//not task itself, task name
  gROOT->ProcessLine(Form("AddPairMCSignal(%s)"     ,task->GetName()));//not task itself, task name

  // #########################################################
  // #########################################################
  // Adding cutsettings
 // Cuts
  // Number of cuts
  const Int_t nDie = (Int_t)gROOT->ProcessLine("GetN()");
  //add dielectron analysis with different cuts to the task
  for (Int_t i=0; i<nDie; ++i){ //nDie defined in config file
    AliAnalysisFilter *filter = reinterpret_cast<AliAnalysisFilter*>(gROOT->ProcessLine(Form("Config_rbailhac_ElectronEfficiencyV2_PbPb(%d)",i)));
    task->AddTrackCuts(filter);
  }

  //########################################
  //########################################
  TString outlistname = Form("efficiency_%s",appendix.Data());
  const TString fileName = outname;
  mgr->AddTask(task);
  mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, mgr->CreateContainer(outlistname, TList::Class(), AliAnalysisManager::kOutputContainer, Form("%s",fileName.Data()));

  return task;
}
<commit_msg>Update macro<commit_after>AliAnalysisTaskElectronEfficiencyV2* AddTask_rbailhac_ElectronEfficiencyV2_PbPb(Bool_t getFromAlien = kFALSE,
										TString cFileName ="Config_rbailhac_ElectronEfficiencyV2_PbPb.C",
										UInt_t trigger = AliVEvent::kINT7,
										Bool_t rejpileup = kTRUE,
										const Int_t CenMin =  0,
										const Int_t CenMax = 10,
										const Float_t PtMin =  0.2,
										const Float_t PtMax = 10.0,
										const Float_t EtaMin = -0.8,
										const Float_t EtaMax = +0.8,
										const Bool_t UsePtVec = kTRUE,
										const Bool_t DoULSLS = kTRUE,
										const TString generators = "pizero_0;eta_1;etaprime_2;rho_3;omega_4;phi_5;jpsi_6;Pythia CC_0;Pythia BB_0;Pythia B_0;",
										const std::string resolutionFilename ="",
										const std::string cocktailFilename   ="",
										const std::string centralityFilename ="",
										const TString outname = "LMEE.root")
{

  //get the current analysis manager
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTask_rbailhac_test", "No analysis manager found.");
    return 0;
  }

  //Base Directory for GRID / LEGO Train
  TString configBasePath= "$ALICE_PHYSICS/PWGDQ/dielectron/macrosLMEE/";
  if(getFromAlien && (!gSystem->Exec(Form("alien_cp alien:///alice/cern.ch/user/r/rbailhac/PWGDQ/dielectron/macrosLMEE/%s .",cFileName.Data()))) ){
    configBasePath=Form("%s/",gSystem->pwd());
  }

  TString configFilePath(configBasePath+cFileName);

  std::cout << "Configpath:  " << configFilePath << std::endl;

  if (!gROOT->GetListOfGlobalFunctions()->FindObject("Config_rbailhac_ElectronEfficiencyV2_PbPb")) {
    printf("Load macro now\n");
    gROOT->LoadMacro(configFilePath.Data());
  }

  // trigger
  TString triggername = "NULL";
  if(trigger == (UInt_t)AliVEvent::kINT7)             triggername = "kINT7";
  else if(trigger == (UInt_t)AliVEvent::kCentral)     triggername = "kCentral";
  else if(trigger == (UInt_t)AliVEvent::kSemiCentral) triggername = "kSemiCentral";
  else if(trigger == (UInt_t)(AliVEvent::kINT7 | AliVEvent::kCentral | AliVEvent::kSemiCentral)) triggername = "kCombinedCentralityTriggers";
  else if(trigger == (UInt_t)(AliVEvent::kINT7 | AliVEvent::kCentral))                           triggername = "kCombinedCentral";
  else if(trigger == (UInt_t)(AliVEvent::kINT7 | AliVEvent::kSemiCentral))                       triggername = "kCombinedSemiCentral";

  // generators
  TString suffixgen = "";
  if(generators.Contains("Pythia CC") && (generators.Contains("Pythia BB") || generators.Contains("Pythia B"))) suffixgen = "_CC_BB";
  else if(generators.Contains("Pythia CC")) suffixgen = "_CC";
  else if(generators.Contains("Pythia BB") || generators.Contains("Pythia B")) suffixgen = "_BB";
  else if(generators.Contains("pizero_0")) suffixgen = "_LF";
  else suffixgen = "";

  // generator index
  TString suffixgenID = "";
  std::vector<UInt_t> genID;
  const Int_t ngenID = (Int_t)gROOT->ProcessLine("GetGenID()");
  if(ngenID > 0) {
    for (unsigned int i = 0; i < ngenID+1; ++i){
      genID.push_back(reinterpret_cast<UInt_t>(gROOT->ProcessLine(Form("GetGenID(%d)",i))));
      suffixgenID += reinterpret_cast<UInt_t>(gROOT->ProcessLine(Form("GetGenID(%d)",i)));
    }
  }

  //create task and add it to the manager (MB)
  TString appendix;
  appendix += TString::Format("Cen%d_%d_%s_%s_%s",CenMin,CenMax,triggername.Data(),suffixgen.Data(),suffixgenID.Data());
  printf("appendix %s\n", appendix.Data());

  //##########################################################
  //############################################################
  // Creating an instance of the task
  AliAnalysisTaskElectronEfficiencyV2* task = new AliAnalysisTaskElectronEfficiencyV2(Form("TaskElectronEfficiencyV2_%s",appendix.Data()));
  gROOT->GetListOfSpecials()->Add(task);//this is only for ProcessLine(AddMCSignal);

  // #########################################################
  // #########################################################
  // Set TOF correction
  // if(tofcor){
  //  SetEtaCorrectionTOFRMS(task, AliDielectronVarManager::kP, AliDielectronVarManager::kEta);
  //  SetEtaCorrectionTOFMean(task, AliDielectronVarManager::kP, AliDielectronVarManager::kEta);
  //}

  // #########################################################
  // #########################################################
  // Event selection. Is the same for all the different cutsettings
  task->SetEnablePhysicsSelection(kTRUE);//always ON in Run2 analyses for both data and MC.
  task->SetTriggerMask(trigger);
  task->SetEventFilter((reinterpret_cast<AliDielectronEventCuts*>(gROOT->ProcessLine(Form("GetEventCuts(%f,%f,%d,\"%s\")",(Float_t)CenMin,(Float_t)CenMax,rejpileup,"V0M")))));

  // #########################################################
  // #########################################################
  // Set minimum and maximum values of generated tracks. Only used to save computing power.
  // Do not set here your analysis pt-cuts
  task->SetMinPtGen(0.1);
  task->SetMaxPtGen(1e+10);
  task->SetMinEtaGen(-1.5);
  task->SetMaxEtaGen(+1.5);

  // #########################################################
  // #########################################################
  // Set minimum and maximum values for pairing
  task->SetKinematicCuts(PtMin, PtMax, EtaMin, EtaMax);

  // #########################################################
  // #########################################################
  // Set Binning single variables
  if (UsePtVector == true) {
    std::vector<double> ptBinsVec;
     const Int_t nBinsPt = (Int_t)gROOT->ProcessLine("GetnBinsPt()");
    for (unsigned int i = 0; i < nBinsPt+1; ++i){
      ptBinsVec.push_back(reinterpret_cast<Double_t>(gROOT->ProcessLine(Form("GetptBins(%d)",i))));
    }
    task->SetPtBins(ptBinsVec);
  }
  else task->SetPtBinsLinear   (0,  10, 100);
  task->SetEtaBinsLinear (-1.,1.,20); // 40 before
  task->SetPhiBinsLinear  (0, TMath::TwoPi(), 36); // 90 before
  task->SetThetaBinsLinear(0, TMath::TwoPi(), 60);

  // pair variables
  const Int_t Nmee = 150;
  Double_t mee[Nmee] = {};
  for(Int_t i=0  ;i<110 ;i++) mee[i] = 0.01 * (i-  0) +  0.0;//from 0 to 1.1 GeV/c2, every 0.01 GeV/c2
  for(Int_t i=110;i<Nmee;i++) mee[i] = 0.1  * (i-110) +  1.1;//from 1.1 to 5 GeV/c2, evety 0.1 GeV/c2
  std::vector<double> v_mee(mee,std::end(mee));

  const Int_t NpTee = 121;
  Double_t pTee[NpTee] = {};
  for(Int_t i=0  ;i<10   ;i++) pTee[i] = 0.01 * (i-  0) +  0.0;//from 0 to 0.09 GeV/c, every 0.01 GeV/c
  for(Int_t i=10 ;i<110  ;i++) pTee[i] = 0.1  * (i- 10) +  0.1;//from 0.1 to 10 GeV/c, evety 0.1 GeV/c
  for(Int_t i=110;i<NpTee;i++) pTee[i] = 1.0  * (i-110) + 10.0;//from 10 to 20 GeV/c, evety 1.0 GeV/c
  std::vector<double> v_pTee(pTee,std::end(pTee));
  task->SetMassBins(v_mee);
  task->SetPairPtBins(v_pTee);
  //task->SetPhiVBinsLinear(0, TMath::Pi(), 100);
  //task->SetFillPhiV(kTRUE);

  // #########################################################
  // #########################################################
  //task->SetSmearGenerated(kFALSE); // cross check smearing the MC at single level and filling resolution maps
 // Resolution File, If resoFilename = "" no correction is applied
  task->SetResolutionFile(resolutionFilename);
  task->SetResolutionFileFromAlien("/alice/cern.ch/user/r/rbailhac/supportFiles/" + resolutionFilename);
  task->SetResolutionDeltaPtBinsLinear   (-10., 2., (Int_t)gROOT->ProcessLine("GetNbinsDeltaMom()"));
  task->SetResolutionRelPtBinsLinear   (0., 2.,  (Int_t)gROOT->ProcessLine("GetNbinsRelMom()"));
  task->SetResolutionEtaBinsLinear  (-0.4, 0.4, (Int_t)gROOT->ProcessLine("GetNbinsDeltaEta()"));
  task->SetResolutionPhiBinsLinear  (-0.4, 0.4, (Int_t)gROOT->ProcessLine("GetNbinsDeltaPhi()"));
  task->SetResolutionThetaBinsLinear(-0.4, 0.4, (Int_t)gROOT->ProcessLine("GetNbinsDeltaTheta()"));

  //###########################################################
  //############################################################
  // Set MCSignal and Cutsetting to fill the support histograms
  task->SetSupportHistoMCSignalAndCutsetting(0,0);//fill support histograms for first MCsignal and first cutsetting

  // #########################################################
  // #########################################################
  // Set centrality correction. If resoFilename = "" no correction is applied
  task->SetCentralityFile(centralityFilename);

  // #########################################################
  // #########################################################
  // Pairing related config
  task->SetDoPairing(kTRUE);
  task->SetULSandLS(DoULSLS);

  //#####################################################
  //######################################################
  // Generators
  cout<<"Efficiency based on MC generators: " << generators <<endl;
  TString generatorsPair=generators;
  task->SetGeneratorMCSignalName(generatorsPair);
  task->SetGeneratorULSSignalName(generators);

  //#################################################
  //#################################################
  // generator ID to select pile-up or not
  if(ngenID > 0) {
    task->SetGeneratorMCSignalIndex(genID);
    task->SetGeneratorULSSignalIndex(genID);
    task->SetCheckGenID(kTRUE);
  }

  //###############################################
  //##############################################
  task->SetCocktailWeighting(cocktailFilename);
  task->SetCocktailWeightingFromAlien("/alice/cern.ch/user/r/rbailhac/supportFiles/" + cocktailFilename);

  // #########################################################
  // #########################################################
  // Add MCSignals. Can be set to see differences of:
  // e.g. secondaries and primaries. or primaries from charm and resonances
  gROOT->ProcessLine(Form("AddSingleLegMCSignal(%s)",task->GetName()));//not task itself, task name
  gROOT->ProcessLine(Form("AddPairMCSignal(%s)"     ,task->GetName()));//not task itself, task name

  // #########################################################
  // #########################################################
  // Adding cutsettings
 // Cuts
  // Number of cuts
  const Int_t nDie = (Int_t)gROOT->ProcessLine("GetN()");
  //add dielectron analysis with different cuts to the task
  for (Int_t i=0; i<nDie; ++i){ //nDie defined in config file
    AliAnalysisFilter *filter = reinterpret_cast<AliAnalysisFilter*>(gROOT->ProcessLine(Form("Config_rbailhac_ElectronEfficiencyV2_PbPb(%d)",i)));
    task->AddTrackCuts(filter);
  }

  //########################################
  //########################################
  TString outlistname = Form("efficiency_%s",appendix.Data());
  const TString fileName = outname;
  mgr->AddTask(task);
  mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, mgr->CreateContainer(outlistname, TList::Class(), AliAnalysisManager::kOutputContainer, Form("%s",fileName.Data()));

  return task;
}
<|endoftext|>


<commit_before>#include "Screen.hpp"

#include <sstream>
#include <fstream>
#include <cmath>

Screen::Screen(const string& name, double width, double height, unsigned int dots_per_meter) :
	Device(name, width, height, 0),
	m_dots_per_meter(dots_per_meter),
	m_pixel(ceil(dots_per_meter*dots_per_meter*width*height)),
	m_missed(0)
{ }

Screen::~Screen()
{ }

string
Screen::toString(unsigned int indent) const
{
	string indention = "";
	for( unsigned int i=0; i<indent; i++ ){
		indention = indention + "\t";
	}

	stringstream ss;
	ss << indention << toLine() << " ("
	   << "width = " << m_width << " m, "
	   << "height = " << m_height << " m, "
	   << "dots_per_meter = " << m_dots_per_meter << ", "
	   << "missed = " << m_missed
	   << ") {\n";

	unsigned int cells_hor = m_dots_per_meter * m_width;
	unsigned int cells_ver = m_dots_per_meter * m_height;

	for( unsigned int y=0; y<cells_ver; y++ ){
		ss << indention << "\t";
		for( unsigned int x=0; x<cells_hor; x++ ){
			ss << m_pixel[cells_hor * y + x] << " ";
		}
		ss << "\n";
	}
	ss << indention << "}";
	return ss.str();
}

string
Screen::toLine(void) const
{
	return m_name==""?"Screen":m_name;
}

ostream&
operator<<(ostream& os, const Screen& screen)
{
	return os << screen.toLine();
}

void
Screen::transport(Ion& ion)
{
	fillHistogram(ion.x(),ion.y());
	if( m_next != NULL ){
		m_next->transport(ion);
	}
}

void
Screen::reset(void)
{
	fill(m_pixel.begin(), m_pixel.end(), 0);
	m_missed = 0;
}

void
Screen::exportHistogram(const string& filename) const
{
	ofstream outfile;
	outfile.open(filename, ios::out | ios::trunc );

	unsigned int cells_hor = m_dots_per_meter * m_width;
	unsigned int x = 0;
	unsigned int y = 0;
	outfile << cells_hor << "\n";
	for( auto it = m_pixel.begin(); it<m_pixel.end(); it++ ){
		outfile << x << "," << y << "," << *it << "\n";
		x++;
		if( x == cells_hor ){
			x = 0;
			y++;
		}
	}

	outfile.close();
}

void
Screen::exportHistogram(void) const
{
	exportHistogram(m_name + ".dat");
}

// @TODO optimize
void
Screen::fillHistogram(double x, double y)
{
	double half_width  = 0.5*m_width;
	double half_height = 0.5*m_height;
	unsigned int dots_hor = m_dots_per_meter * m_width;
	unsigned int dots_ver = m_dots_per_meter * m_height;

	if ( x < half_width and
		 x > -half_width and
		 y < half_height and
		 y > -half_height){

		double x_ = floor((x*m_dots_per_meter) + 0.5*dots_hor);
		double y_ = floor((y*m_dots_per_meter) + 0.5*dots_ver);
		unsigned int pos = dots_hor * y_ + x_;

		m_pixel[pos] += 1;
	} else {
		m_missed += 1;
	}
}

<commit_msg>histogram is now filled correctly<commit_after>#include "Screen.hpp"

#include <sstream>
#include <fstream>
#include <cmath>

Screen::Screen(const string& name, double width, double height, unsigned int dots_per_meter) :
	Device(name, width, height, 0),
	m_dots_per_meter(dots_per_meter),
	m_pixel(ceil(dots_per_meter*dots_per_meter*width*height)),
	m_missed(0)
{ }

Screen::~Screen()
{ }

string
Screen::toString(unsigned int indent) const
{
	string indention = "";
	for( unsigned int i=0; i<indent; i++ ){
		indention = indention + "\t";
	}

	stringstream ss;
	ss << indention << toLine() << " ("
	   << "width = " << m_width << " m, "
	   << "height = " << m_height << " m, "
	   << "dots_per_meter = " << m_dots_per_meter << ", "
	   << "missed = " << m_missed
	   << ") {\n";

	unsigned int cells_hor = m_dots_per_meter * m_width;
	unsigned int cells_ver = m_dots_per_meter * m_height;

	for( unsigned int y=0; y<cells_ver; y++ ){
		ss << indention << "\t";
		for( unsigned int x=0; x<cells_hor; x++ ){
			ss << m_pixel[cells_hor * y + x] << " ";
		}
		ss << "\n";
	}
	ss << indention << "}";
	return ss.str();
}

string
Screen::toLine(void) const
{
	return m_name==""?"Screen":m_name;
}

ostream&
operator<<(ostream& os, const Screen& screen)
{
	return os << screen.toLine();
}

void
Screen::transport(Ion& ion)
{
	fillHistogram(ion.x(),ion.y());
	if( m_next != NULL ){
		m_next->transport(ion);
	}
}

void
Screen::reset(void)
{
	fill(m_pixel.begin(), m_pixel.end(), 0);
	m_missed = 0;
}

void
Screen::exportHistogram(const string& filename) const
{
	ofstream outfile;
	outfile.open(filename, ios::out | ios::trunc );

	unsigned int dots_hor = m_dots_per_meter * m_width;
	unsigned int dots_ver = m_dots_per_meter * m_height;
	unsigned int x = 0;
	unsigned int y = 0;

	outfile << dots_hor << "\n";
	outfile << dots_ver << "\n";

	for( auto it = m_pixel.begin(); it<m_pixel.end(); it++ ){
		outfile << x << "," << y << "," << *it << "\n";
		x++;
		if( x == dots_hor ){
			x = 0;
			y++;
		}
	}

	outfile.close();
}

void
Screen::exportHistogram(void) const
{
	exportHistogram(m_name + ".dat");
}

void
Screen::fillHistogram(double x, double y)
{
	double half_width  = 0.5 * m_width;
	double half_height = 0.5 * m_height;
	unsigned int dots_hor = m_dots_per_meter * m_width;
	unsigned int dots_ver = m_dots_per_meter * m_height;

	if ( x < half_width and
		 x > -half_width and
		 y < half_height and
		 y > -half_height){

		double x_ = round((x * m_dots_per_meter) + 0.5 * dots_hor);
		double y_ = round((y * m_dots_per_meter) + 0.5 * dots_ver);

		unsigned int pos = dots_hor * y_ + x_;

		m_pixel[pos] += 1;
	} else {
		m_missed += 1;
	}
}

<|endoftext|>