<commit_before>#ifndef ABSTRACT_ALGEBRA_HPP
#define ABSTRACT_ALGEBRA_HPP

#include <algorithm>
#include <forward_list>
#include <iostream>
#include <fstream>
#include <list>
#include <memory>
#include <numeric>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>

// TODO: Rethink how to track remaining elements. Loading a set with all elements could be a space hog with for large permutations.
// TODO: Parity function
// TODO: Add usage and comment functions
namespace Permutation
{

    namespace utility
    {
        size_t gcd( size_t a, size_t b)
        {
            for (;;)
            {
                if ( a == 0)
                {
                    return b;
                }
                b %= a;
                if ( b == 0)
                {
                    return a;
                }
                a %= b;
            }
        }

        size_t lcm( size_t a, size_t b)
        {
            size_t temp = gcd( a, b);
            return temp ? (a / temp * b) : 0;
        }
    }

    typedef std::unordered_map<size_t, size_t> nPermutation;
    typedef std::list<nPermutation> composition;
    typedef std::pair<size_t, size_t> movesToPair;

    inline void printPermutation( nPermutation &permutation)
    {
        for( auto &it : permutation)
        {
            printf( "%zu -> %zu\n", it.first, it.second);
        }
    }

    inline bool isIdentity( nPermutation &permutation)
    {
        for( auto& p : permutation)
        {
            if( p.first != p.second)
            {
                return false;
            }
        }
        return true;
    }

    void printCycleNotation( nPermutation &permutation)
    {
        if( isIdentity(permutation))
        {
            printf( "( 1 ) ");
            return;
        }

        std::set<size_t> remaining;
        for( auto &it : permutation)
        {
            remaining.insert( it.first);
        }

        while( !remaining.empty())
        {
            auto begin = *(remaining.begin());
            remaining.erase( begin);

            auto destination = permutation.at( begin);
            if( destination == begin)
            {
                continue;
            }

            printf( "( %zu", begin);

            while(  destination != begin )
            {
                printf( " %zu", destination);
                remaining.erase( destination);
                destination = permutation.at( destination);
            }

            printf( " ) ");

        }
    }

    void printCOF(composition& permutations)
    {
        composition::iterator it = permutations.begin();
        if( it == permutations.end())
        {
            return;
        }
        printCycleNotation( *(it++));

        while( it != permutations.end())
        {
            if( (*it).empty())
            {
                continue;
            }

            printf(" ∘ ");
            printCycleNotation( *(it++));
        }

    }

    std::unique_ptr<nPermutation> compose( composition& permutations)
    {
        std::unique_ptr<nPermutation> result = std::make_unique<nPermutation>();
        composition::reverse_iterator rit = permutations.rbegin();

        std::unordered_set<size_t> keys;

        for( ; rit != permutations.rend(); ++rit)
        {
            for( auto& p : *rit)
            {
                keys.insert( p.first);
            }
        }

        rit = permutations.rbegin();

        for( auto& element : keys)
        {
            auto destination = element;
            while( rit != permutations.rend())
            {
                if( (*rit).count( destination))
                {
                    destination = (*rit).at( destination);
                }
                ++rit;
            }
            result->insert( movesToPair( element, destination));
            rit = permutations.rbegin();
        }

        return result;
    }

    std::unique_ptr<nPermutation> inverse( nPermutation& permutation)
    {
        std::unique_ptr<nPermutation> inv = std::make_unique<nPermutation>();
        for( auto& pair : permutation)
        {
            inv->insert( movesToPair( pair.second, pair.first));
        }
        return inv;
    }

    size_t order( nPermutation& permutation)
    {
        std::set<size_t> remaining;
        for( auto &it : permutation)
        {
            remaining.insert( it.first);
        }

        std::forward_list<size_t> lengthsOfCycles;
        while( !remaining.empty())
        {
            auto begin = *(remaining.begin());
            remaining.erase( begin);

            auto destination = permutation.at( begin);
            if( destination == begin)
            {
                continue;
            }

            size_t length = 1;
            while(  destination != begin )
            {
                remaining.erase( destination);
                destination = permutation.at( destination);
                ++length;
            }
            lengthsOfCycles.push_front( length);

        }

        return std::accumulate( lengthsOfCycles.begin(), lengthsOfCycles.end(), 1, utility::lcm);
    }

    std::unique_ptr<std::unordered_map<std::string, nPermutation>> readPermutations( const char* filename)
    {
        std::ifstream fin{ filename};

        if( !fin.is_open())
        {
            std::cerr << filename << " was not opened properly. Please check if the filename is correct. The function will return 'nullptr'." << std::endl;
            return nullptr;
        }

        std::unique_ptr<std::unordered_map<std::string,nPermutation>> hash_bag = std::make_unique<std::unordered_map<std::string,nPermutation>>();

        std::string key;
        size_t totalPermutations = 0;

        fin >> totalPermutations;
        if( fin.good())
        {
            size_t first, second;
            for(; totalPermutations > 0; --totalPermutations)
            {
                std::unique_ptr<nPermutation> perm = std::make_unique<nPermutation>();
                fin >> key;
                while( fin >> first >> second)
                {
                    perm->insert( movesToPair( first, second));
                }

                hash_bag->insert( std::make_pair(key, *(perm.release())));
                fin.clear();
            }
        }
        fin.close();
        return hash_bag;
    }

    void printProductOfTrans( nPermutation& permutation)
    {
        std::set<size_t> remaining;
        for( auto&it : permutation)
        {
            remaining.insert( it.first);
        }

        while( !remaining.empty())
        {
            std::stack<size_t> inCycle;

            size_t begin = *remaining.begin();
            remaining.erase( begin);

            auto destination = permutation.at( begin);
            while( destination != begin )
            {
                inCycle.push(destination);
                remaining.erase( destination);
                destination = permutation.at( destination);
            }

            while( !inCycle.empty())
            {
                printf( "( %zu %zu ) ", begin, inCycle.top());
                inCycle.pop();
            }
        }
    }

    bool isEven( nPermutation& permutation)
    {
        std::set<size_t> remaining;
        for( auto&it : permutation)
        {
            remaining.insert( it.first);
        }

        size_t count = 0;
        while( !remaining.empty())
        {
           size_t begin = *remaining.begin();
           remaining.erase( begin);

            auto destination = permutation.at( begin);
            while( destination != begin)
            {
                count = (count+1) % 2;
                remaining.erase( destination);
                destination = permutation.at( destination);
            }
        }
        return count ? 0 : 1;
    }

} // end of namespace Permutation

#endif // SYMMETRIC_HPP
<commit_msg>minor update<commit_after>#ifndef ABSTRACT_ALGEBRA_HPP
#define ABSTRACT_ALGEBRA_HPP

#include <algorithm>
#include <forward_list>
#include <iostream>
#include <fstream>
#include <list>
#include <memory>
#include <numeric>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>

// TODO: Rethink how to track remaining elements. Loading a set with all elements could be a space hog with for large permutations.
// TODO: Add usage and comment functions
namespace Permutation
{

    namespace utility
    {
        size_t gcd( size_t a, size_t b)
        {
            for (;;)
            {
                if ( a == 0)
                {
                    return b;
                }
                b %= a;
                if ( b == 0)
                {
                    return a;
                }
                a %= b;
            }
        }

        size_t lcm( size_t a, size_t b)
        {
            size_t temp = gcd( a, b);
            return temp ? (a / temp * b) : 0;
        }
    }

    typedef std::unordered_map<size_t, size_t> nPermutation;
    typedef std::list<nPermutation> composition;
    typedef std::pair<size_t, size_t> movesToPair;

    inline void printPermutation( nPermutation &permutation)
    {
        for( auto &it : permutation)
        {
            printf( "%zu -> %zu\n", it.first, it.second);
        }
    }

    inline bool isIdentity( nPermutation &permutation)
    {
        for( auto& p : permutation)
        {
            if( p.first != p.second)
            {
                return false;
            }
        }
        return true;
    }

    void printCycleNotation( nPermutation &permutation)
    {
        if( isIdentity(permutation))
        {
            printf( "( 1 ) ");
            return;
        }

        std::set<size_t> remaining;
        for( auto &it : permutation)
        {
            remaining.insert( it.first);
        }

        while( !remaining.empty())
        {
            auto begin = *(remaining.begin());
            remaining.erase( begin);

            auto destination = permutation.at( begin);
            if( destination == begin)
            {
                continue;
            }

            printf( "( %zu", begin);

            while(  destination != begin )
            {
                printf( " %zu", destination);
                remaining.erase( destination);
                destination = permutation.at( destination);
            }

            printf( " ) ");

        }
    }

    void printCOF(composition& permutations)
    {
        composition::iterator it = permutations.begin();
        if( it == permutations.end())
        {
            return;
        }
        printCycleNotation( *(it++));

        while( it != permutations.end())
        {
            if( (*it).empty())
            {
                continue;
            }

            printf(" ∘ ");
            printCycleNotation( *(it++));
        }

    }

    std::unique_ptr<nPermutation> compose( composition& permutations)
    {
        std::unique_ptr<nPermutation> result = std::make_unique<nPermutation>();
        composition::reverse_iterator rit = permutations.rbegin();

        std::unordered_set<size_t> keys;

        for( ; rit != permutations.rend(); ++rit)
        {
            for( auto& p : *rit)
            {
                keys.insert( p.first);
            }
        }

        rit = permutations.rbegin();

        for( auto& element : keys)
        {
            auto destination = element;
            while( rit != permutations.rend())
            {
                if( (*rit).count( destination))
                {
                    destination = (*rit).at( destination);
                }
                ++rit;
            }
            result->insert( movesToPair( element, destination));
            rit = permutations.rbegin();
        }

        return result;
    }

    std::unique_ptr<nPermutation> inverse( nPermutation& permutation)
    {
        std::unique_ptr<nPermutation> inv = std::make_unique<nPermutation>();
        for( auto& pair : permutation)
        {
            inv->insert( movesToPair( pair.second, pair.first));
        }
        return inv;
    }

    size_t order( nPermutation& permutation)
    {
        std::set<size_t> remaining;
        for( auto &it : permutation)
        {
            remaining.insert( it.first);
        }

        std::forward_list<size_t> lengthsOfCycles;
        while( !remaining.empty())
        {
            auto begin = *(remaining.begin());
            remaining.erase( begin);

            auto destination = permutation.at( begin);
            if( destination == begin)
            {
                continue;
            }

            size_t length = 1;
            while(  destination != begin )
            {
                remaining.erase( destination);
                destination = permutation.at( destination);
                ++length;
            }
            lengthsOfCycles.push_front( length);

        }

        return std::accumulate( lengthsOfCycles.begin(), lengthsOfCycles.end(), 1, utility::lcm);
    }

    std::unique_ptr<std::unordered_map<std::string, nPermutation>> readPermutations( const char* filename)
    {
        std::ifstream fin{ filename};

        if( !fin.is_open())
        {
            std::cerr << filename << " was not opened properly. Please check if the filename is correct. The function will return 'nullptr'." << std::endl;
            return nullptr;
        }

        std::unique_ptr<std::unordered_map<std::string,nPermutation>> hash_bag = std::make_unique<std::unordered_map<std::string,nPermutation>>();

        std::string key;
        size_t totalPermutations = 0;

        fin >> totalPermutations;
        if( fin.good())
        {
            size_t first, second;
            for(; totalPermutations > 0; --totalPermutations)
            {
                std::unique_ptr<nPermutation> perm = std::make_unique<nPermutation>();
                fin >> key;
                while( fin >> first >> second)
                {
                    perm->insert( movesToPair( first, second));
                }

                hash_bag->insert( std::make_pair(key, *(perm.release())));
                fin.clear();
            }
        }
        fin.close();
        return hash_bag;
    }

    void printProductOfTrans( nPermutation& permutation)
    {
        std::set<size_t> remaining;
        for( auto&it : permutation)
        {
            remaining.insert( it.first);
        }

        while( !remaining.empty())
        {
            std::stack<size_t> inCycle;

            size_t begin = *remaining.begin();
            remaining.erase( begin);

            auto destination = permutation.at( begin);
            while( destination != begin )
            {
                inCycle.push(destination);
                remaining.erase( destination);
                destination = permutation.at( destination);
            }

            while( !inCycle.empty())
            {
                printf( "( %zu %zu ) ", begin, inCycle.top());
                inCycle.pop();
            }
        }
    }

    bool isEven( nPermutation& permutation)
    {
        std::set<size_t> remaining;
        for( auto&it : permutation)
        {
            remaining.insert( it.first);
        }

        size_t count = 0;
        while( !remaining.empty())
        {
           size_t begin = *remaining.begin();
           remaining.erase( begin);

            auto destination = permutation.at( begin);
            while( destination != begin)
            {
                count = (count+1) % 2;
                remaining.erase( destination);
                destination = permutation.at( destination);
            }
        }
        return count ? 0 : 1;
    }

} // end of namespace Permutation

#endif // SYMMETRIC_HPP
<|endoftext|>


<commit_before>/** \file rss_harvester.cc
 *  \brief Downloads and evaluates RSS updates.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2018 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <iostream>
#include <cstring>
#include "DbConnection.h"
#include "DbResultSet.h"
#include "Downloader.h"
#include "FileUtil.h"
#include "IniFile.h"
#include "SyndicationFormat.h"
#include "util.h"
#include "Zotero.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname
              << " [--verbose] [--proxy=<proxy_host_and_port>] rss_url_list_filename zts_server_url map_directory marc_output\n";
    std::exit(EXIT_FAILURE);
}

unsigned ProcessSyndicationURL(const bool verbose, const std::string &url,
                               const std::shared_ptr<Zotero::HarvestParams> harvest_params,
                               const std::shared_ptr<const Zotero::HarvestMaps> harvest_maps,
                               DbConnection * const db_connection)
{
    unsigned successfully_processed_count(0);

    if (verbose)
        std::cerr << "Processing URL: " << url << '\n';

    Downloader downloader(url);
    if (downloader.anErrorOccurred()) {
        WARNING("Download problem for \"" + url + "\": " + downloader.getLastErrorMessage());
        return successfully_processed_count;
    }

    std::string err_msg;
    std::unique_ptr<SyndicationFormat> syndication_format(SyndicationFormat::Factory(downloader.getMessageBody(), &err_msg));
    if (syndication_format == nullptr) {
        WARNING("Problem parsing XML document for \"" + url + "\": " + err_msg);
        return successfully_processed_count;
    }

    std::cout << url << " (" << syndication_format->getFormatName() << "):\n";
    if (verbose) {
        std::cout << "\tTitle: " << syndication_format->getTitle() << '\n';
        std::cout << "\tLink: " << syndication_format->getLink() << '\n';
        std::cout << "\tDescription: " << syndication_format->getDescription() << '\n';
    }

    for (const auto &item : *syndication_format) {
        db_connection->queryOrDie("SELECT creation_datetime FROM rss WHERE server_url='" + db_connection->escapeString(url)
                                  + "' AND item_id='" + db_connection->escapeString(item.getId()) + "'");
        DbResultSet result_set(db_connection->getLastResultSet());
        if (not result_set.empty()) {
            if (verbose) {
                const DbRow first_row(result_set.getNextRow());
                std::cout << "Previously retrieved item w/ ID \"" << item.getId() + "\" at " << first_row["creation_datetime"]
                          << ".\n";
            }
            continue;
        }

        const std::string title(item.getTitle());
        if (not title.empty() and verbose)
            std::cout << "\t\tTitle: " << title << '\n';
        const std::unordered_map<std::string, std::string> &dc_and_prism_data(item.getDCAndPrismData());
        if (dc_and_prism_data.empty()) {
            const auto record_count_and_previously_downloaded_count(
                Zotero::Harvest(item.getLink(), "", harvest_params, harvest_maps));
            successfully_processed_count += record_count_and_previously_downloaded_count.first;
        } else
            ERROR("create a MARC record from the RSS DC and PRISM metadata!");

        db_connection->queryOrDie("INSERT INTO rss SET server_url='" + db_connection->escapeString(url) + "',item_id='"
                                  + db_connection->escapeString(item.getId()) + "'");

    }

    return successfully_processed_count;
}

void LoadServerURLs(const std::string &path, std::vector<std::string> * const server_urls) {
    std::unique_ptr<File> input(FileUtil::OpenInputFileOrDie(path));
    while (not input->eof()) {
        std::string line;
        input->getline(&line);
        StringUtil::TrimWhite(&line);
        if (not line.empty())
            server_urls->emplace_back(line);
    }
}

std::string GetMarcFormat(const std::string &output_filename) {
    if (StringUtil::EndsWith(output_filename, ".mrc") or StringUtil::EndsWith(output_filename, ".marc"))
        return "marc21";
    if (StringUtil::EndsWith(output_filename, ".xml"))
        return "marcxml";
    ERROR("can't determine output format from MARC output filename \"" + output_filename + "\"!");
}

const std::string CONF_FILE_PATH("/usr/local/var/lib/tuelib/rss_client.conf");

} // unnamed namespace

int main(int argc, char *argv[]) {
    ::progname = argv[0];

    if (argc < 5)
        Usage();

    bool verbose(false);
    if (std::strcmp(argv[1], "--verbose") == 0) {
        verbose = true;
        --argc, ++argv;
    }

    std::string proxy_host_and_port;
    const std::string PROXY_FLAG_PREFIX("--proxy=");
    if (StringUtil::StartsWith(argv[1], PROXY_FLAG_PREFIX)) {
        proxy_host_and_port = argv[1] + PROXY_FLAG_PREFIX.length();
        --argc, ++argv;
    }

    if (argc != 5)
        Usage();

    try {
        std::vector<std::string> server_urls;
        LoadServerURLs(argv[1], &server_urls);

        std::shared_ptr<Zotero::HarvestParams> harvest_params(new Zotero::HarvestParams);
        harvest_params->zts_server_url_ = Url(argv[2]);

        std::string map_directory_path(argv[3]);
        if (not StringUtil::EndsWith(map_directory_path, '/'))
            map_directory_path += '/';

        std::shared_ptr<Zotero::HarvestMaps> harvest_maps(Zotero::LoadMapFilesFromDirectory(map_directory_path));
        const std::shared_ptr<RegexMatcher> supported_urls_regex(Zotero::LoadSupportedURLsRegex(map_directory_path));

        const std::string PREVIOUSLY_DOWNLOADED_HASHES_PATH(map_directory_path + "previously_downloaded.hashes");
        Zotero::PreviouslyDownloadedHashesManager previously_downloaded_hashes_manager(PREVIOUSLY_DOWNLOADED_HASHES_PATH,
                                                                                &harvest_maps->previously_downloaded_);
        const std::string MARC_OUTPUT_FILE(argv[4]);
        harvest_params->format_handler_ = Zotero::FormatHandler::Factory(GetMarcFormat(MARC_OUTPUT_FILE), MARC_OUTPUT_FILE,
                                                                         harvest_maps, harvest_params);

        const IniFile ini_file(CONF_FILE_PATH);
        const std::string sql_database(ini_file.getString("Database", "sql_database"));
        const std::string sql_username(ini_file.getString("Database", "sql_username"));
        const std::string sql_password(ini_file.getString("Database", "sql_password"));
        DbConnection db_connection(sql_database, sql_username, sql_password);

        harvest_params->format_handler_->prepareProcessing();

        unsigned download_count(0);
        for (const auto &server_url : server_urls)
            download_count += ProcessSyndicationURL(verbose, server_url, harvest_params, harvest_maps, &db_connection);

        harvest_params->format_handler_->finishProcessing();

        logger->info("Extracted metadata from " + std::to_string(download_count) + " pages.");
    } catch (const std::exception &x) {
        ERROR("caught exception: " + std::string(x.what()));
    }

}
<commit_msg>Adapted to the new API.<commit_after>/** \file rss_harvester.cc
 *  \brief Downloads and evaluates RSS updates.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2018 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <iostream>
#include <cstring>
#include "DbConnection.h"
#include "DbResultSet.h"
#include "Downloader.h"
#include "FileUtil.h"
#include "IniFile.h"
#include "SyndicationFormat.h"
#include "util.h"
#include "Zotero.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << ::progname
              << " [--verbose] [--proxy=<proxy_host_and_port>] rss_url_list_filename zts_server_url map_directory marc_output\n";
    std::exit(EXIT_FAILURE);
}

unsigned ProcessSyndicationURL(const bool verbose, const std::string &url,
                               const std::shared_ptr<Zotero::HarvestParams> harvest_params,
                               const std::shared_ptr<const Zotero::HarvestMaps> harvest_maps,
                               DbConnection * const db_connection)
{
    unsigned successfully_processed_count(0);

    if (verbose)
        std::cerr << "Processing URL: " << url << '\n';

    Downloader downloader(url);
    if (downloader.anErrorOccurred()) {
        WARNING("Download problem for \"" + url + "\": " + downloader.getLastErrorMessage());
        return successfully_processed_count;
    }

    std::string err_msg;
    std::unique_ptr<SyndicationFormat> syndication_format(SyndicationFormat::Factory(downloader.getMessageBody(), &err_msg));
    if (syndication_format == nullptr) {
        WARNING("Problem parsing XML document for \"" + url + "\": " + err_msg);
        return successfully_processed_count;
    }

    std::cout << url << " (" << syndication_format->getFormatName() << "):\n";
    if (verbose) {
        std::cout << "\tTitle: " << syndication_format->getTitle() << '\n';
        std::cout << "\tLink: " << syndication_format->getLink() << '\n';
        std::cout << "\tDescription: " << syndication_format->getDescription() << '\n';
    }

    for (const auto &item : *syndication_format) {
        db_connection->queryOrDie("SELECT creation_datetime FROM rss WHERE server_url='" + db_connection->escapeString(url)
                                  + "' AND item_id='" + db_connection->escapeString(item.getId()) + "'");
        DbResultSet result_set(db_connection->getLastResultSet());
        if (not result_set.empty()) {
            if (verbose) {
                const DbRow first_row(result_set.getNextRow());
                std::cout << "Previously retrieved item w/ ID \"" << item.getId() + "\" at " << first_row["creation_datetime"]
                          << ".\n";
            }
            continue;
        }

        const std::string title(item.getTitle());
        if (not title.empty() and verbose)
            std::cout << "\t\tTitle: " << title << '\n';
        const std::unordered_map<std::string, std::string> &dc_and_prism_data(item.getDCAndPrismData());
        if (dc_and_prism_data.empty()) {
            const auto record_count_and_previously_downloaded_count(
                Zotero::Harvest(item.getLink(), harvest_params, harvest_maps));
            successfully_processed_count += record_count_and_previously_downloaded_count.first;
        } else
            ERROR("create a MARC record from the RSS DC and PRISM metadata!");

        db_connection->queryOrDie("INSERT INTO rss SET server_url='" + db_connection->escapeString(url) + "',item_id='"
                                  + db_connection->escapeString(item.getId()) + "'");

    }

    return successfully_processed_count;
}

void LoadServerURLs(const std::string &path, std::vector<std::string> * const server_urls) {
    std::unique_ptr<File> input(FileUtil::OpenInputFileOrDie(path));
    while (not input->eof()) {
        std::string line;
        input->getline(&line);
        StringUtil::TrimWhite(&line);
        if (not line.empty())
            server_urls->emplace_back(line);
    }
}

std::string GetMarcFormat(const std::string &output_filename) {
    if (StringUtil::EndsWith(output_filename, ".mrc") or StringUtil::EndsWith(output_filename, ".marc"))
        return "marc21";
    if (StringUtil::EndsWith(output_filename, ".xml"))
        return "marcxml";
    ERROR("can't determine output format from MARC output filename \"" + output_filename + "\"!");
}

const std::string CONF_FILE_PATH("/usr/local/var/lib/tuelib/rss_client.conf");

} // unnamed namespace

int main(int argc, char *argv[]) {
    ::progname = argv[0];

    if (argc < 5)
        Usage();

    bool verbose(false);
    if (std::strcmp(argv[1], "--verbose") == 0) {
        verbose = true;
        --argc, ++argv;
    }

    std::string proxy_host_and_port;
    const std::string PROXY_FLAG_PREFIX("--proxy=");
    if (StringUtil::StartsWith(argv[1], PROXY_FLAG_PREFIX)) {
        proxy_host_and_port = argv[1] + PROXY_FLAG_PREFIX.length();
        --argc, ++argv;
    }

    if (argc != 5)
        Usage();

    try {
        std::vector<std::string> server_urls;
        LoadServerURLs(argv[1], &server_urls);

        std::shared_ptr<Zotero::HarvestParams> harvest_params(new Zotero::HarvestParams);
        harvest_params->zts_server_url_ = Url(argv[2]);

        std::string map_directory_path(argv[3]);
        if (not StringUtil::EndsWith(map_directory_path, '/'))
            map_directory_path += '/';

        std::shared_ptr<Zotero::HarvestMaps> harvest_maps(Zotero::LoadMapFilesFromDirectory(map_directory_path));
        const std::shared_ptr<RegexMatcher> supported_urls_regex(Zotero::LoadSupportedURLsRegex(map_directory_path));

        const std::string PREVIOUSLY_DOWNLOADED_HASHES_PATH(map_directory_path + "previously_downloaded.hashes");
        Zotero::PreviouslyDownloadedHashesManager previously_downloaded_hashes_manager(PREVIOUSLY_DOWNLOADED_HASHES_PATH,
                                                                                &harvest_maps->previously_downloaded_);
        const std::string MARC_OUTPUT_FILE(argv[4]);
        harvest_params->format_handler_ = Zotero::FormatHandler::Factory(GetMarcFormat(MARC_OUTPUT_FILE), MARC_OUTPUT_FILE,
                                                                         harvest_maps, harvest_params);

        const IniFile ini_file(CONF_FILE_PATH);
        const std::string sql_database(ini_file.getString("Database", "sql_database"));
        const std::string sql_username(ini_file.getString("Database", "sql_username"));
        const std::string sql_password(ini_file.getString("Database", "sql_password"));
        DbConnection db_connection(sql_database, sql_username, sql_password);

        harvest_params->format_handler_->prepareProcessing();

        unsigned download_count(0);
        for (const auto &server_url : server_urls)
            download_count += ProcessSyndicationURL(verbose, server_url, harvest_params, harvest_maps, &db_connection);

        harvest_params->format_handler_->finishProcessing();

        logger->info("Extracted metadata from " + std::to_string(download_count) + " pages.");
    } catch (const std::exception &x) {
        ERROR("caught exception: " + std::string(x.what()));
    }

}
<|endoftext|>


<commit_before>#include "fid_math.h"

namespace fid
{

std::vector<std::complex<double>> dsp::fft(const std::vector<double> &wf)
{
  // Grab some useful constants.
  int N = wf.size();
  int n = N / 2 + 1;  // size of rfft
  double Nroot = std::sqrt(N);

  // Instantiate the result vector.
  std::vector<std::complex<double>> fft_vec(n, 0.0);
  auto wf_vec = wf; // copy waveform since fftw destroys it

  // Plan and execute the fft.
  fftw_plan wf_to_fft;
  fftw_complex *fft_ptr = reinterpret_cast<fftw_complex *>(&fft_vec[0]);
  wf_to_fft = fftw_plan_dft_r2c_1d(N, &wf_vec[0], fft_ptr, FFTW_ESTIMATE);
  fftw_execute(wf_to_fft);
  fftw_destroy_plan(wf_to_fft);

  for (auto it = fft_vec.begin(); it != fft_vec.end(); ++it) {
    *it /= Nroot;
  }

  return fft_vec;
}

std::vector<double> dsp::ifft(const std::vector<std::complex<double>>& fft)
{
  // Grab some useful constants.
  int n = fft.size();
  int N = 2 * (n - 1);
  double Nroot = std::sqrt(N);

  // Instantiate the result vector.
  std::vector<double> ifft_vec(N, 0.0);
  fftw_complex *fft_ptr = new fftw_complex[n];
  memcpy(fft_ptr, &fft[0], sizeof(fftw_complex) * n);

  // Plan and execute the fft.
  fftw_plan fft_to_wf;
  fft_to_wf = fftw_plan_dft_c2r_1d(N, fft_ptr, &ifft_vec[0], FFTW_ESTIMATE);
  fftw_execute(fft_to_wf);
  fftw_destroy_plan(fft_to_wf);

  // fftw is unnormalized, so we need to fix that.
  for (auto it = ifft_vec.begin(); it != ifft_vec.end(); ++it) {
  	*it /= Nroot;
  }

  delete[] fft_ptr;

  return ifft_vec;
}

std::vector<double> dsp::hilbert(const std::vector<double>& wf)
{
	// Return the call to the fft version.
	auto fft_vec = dsp::fft(wf);

  // Multiply in the -i.
  for (auto it = fft_vec.begin(); it != fft_vec.end(); ++it) {
    *it = std::complex<double>((*it).imag(), -(*it).real());
  }

  // Reverse the fft.
  return ifft(fft_vec);
}

std::vector<double> dsp::psd(const std::vector<double>& wf)
{
  // Perform fft on the original data.
	auto fft_vec = dsp::fft(wf);

  // Get the norm of the fft as that is the power.
	return dsp::norm(fft_vec);
}

std::vector<double> dsp::norm(const std::vector<double>& wf)
{
  // Allocate the memory
  std::vector<double> res;
  res.reserve(wf.size());

  // Iterate and push back the norm.
  for (auto it = wf.begin(); it < wf.end(); ++it) {
    res.push_back(std::norm(*it));
  }

  return res;
}

std::vector<double> dsp::norm(const std::vector<std::complex<double>>& wf)
{
  // Allocate the memory
  std::vector<double> res;
  res.reserve(wf.size());

  // Iterate and push back the norm.
  for (auto it = wf.begin(); it < wf.end(); ++it) {
    res.push_back(std::norm(*it));
  }

  return res;
}

// Helper function to get frequencies for FFT
std::vector<double> dsp::fftfreq(const std::vector<double>& tm)
{
	int N = tm.size();
	double dt = (tm[N-1] - tm[0]) / (N - 1); // sampling rate

	return dsp::fftfreq(N, dt);
}

std::vector<double> dsp::fftfreq(const int N, const double dt)
{
	// Instantiate return vector.
	std::vector<double> freq;

	// Handle both even and odd cases properly.
	if (N % 2 == 0) {

		freq.resize(N/2 + 1);

		for (int i = 0; i < freq.size(); ++i) {
			freq[i] = i / (dt * N);
		}

	} else {

		freq.resize((N + 1) / 2);

		for (int i = 0; i < freq.size(); ++i){
			freq[i] = i / (dt * N);
		}
	}

	return freq;
}

// Calculates the phase by assuming the real signal is harmonic.
std::vector<double> dsp::phase(const std::vector<double>& wf)
{
	return dsp::phase(wf, dsp::hilbert(wf));
}

std::vector<double> dsp::phase(const std::vector<double>& wf_re,
                               const std::vector<double>& wf_im)
{
  std::vector<double> phase(wf_re.size(), 0.0);

  // Calculate the modulo-ed phase
  std::transform(wf_re.begin(), wf_re.end(), wf_im.begin(), phase.begin(),
                 [](double re, double im) { return std::atan2(im, re); });

  // Now unwrap the phase
  double thresh = params::max_phase_jump;
  double m_avg = 0.0;
  double m_std = 0.0;
  double m = 0.0;
  double a = 0.001;
  bool phase_trend = false;

  int k = 0; // to track the winding number
  for (auto it = phase.begin() + 1; it != phase.end(); ++it) {

    // Add current total
    *it += k * kTau;
    m = *(it) - *(it - 1);

    // Check for large jumps, both positive and negative.
    while (std::abs(m) > thresh) {

      if (-m > thresh) {

        if (m + kTau > thresh) {
          std::cout << "Warning: jump over threshold." << std::endl;
          break;
        }

        k++;
        *it += kTau;

      } else if (m > thresh) {

        if (m - kTau < -thresh) {
          std::cout << "Warning: jump over threshold." << std::endl;
          break;
        }

        k--;
        *it -= kTau;
      }

      m = *(it) - *(it - 1);
    }

    // Recalculate slope.
    m = *(it) - *(it - 1);

    // Check against the slope of the last few points for outliers
    if (phase_trend) {
      if (m > 3.0 * m_avg) {

        k--;
        *it -= kTau;

      } else if (m < -2.0 * m_avg) {

        k++;
        *it += kTau;
      }
    }

    // Compute the exponential moving average
    if (!phase_trend && (std::abs(k) > 5)) {
      m_avg = a * (*it - *(it - 1)) + (1 - a) * m_avg;
      m_std = a * (m - m_avg) + (1 - a) * m_std;

      if (std::abs(m_avg) > 15.0 * std::abs(m_std)) {
        m_avg = *it - *(it - 1);
        phase_trend = true;
      }

    } else {

      m_avg = a * (*it - *(it - 1)) + (1 - a) * m_avg;
    }
  }

  return phase;
}

std::vector<double> dsp::envelope(const std::vector<double>& wf)
{
	return dsp::envelope(wf, dsp::hilbert(wf));
}

std::vector<double> dsp::envelope(const std::vector<double>& wf_re, const std::vector<double>& wf_im)
{
 	// Set the envelope function
	std::vector<double> env(wf_re.size(), 0.0);

	std::transform(wf_re.begin(), wf_re.end(), wf_im.begin(), env.begin(),
    			   [](double r, double i) { return std::sqrt(r*r + i*i); });

	return env;
}

arma::cx_mat dsp::wvd_cx(const std::vector<double>& wf, bool upsample)
{
  int M, N;
  if (upsample) {

    M = 2 * wf.size();
    N = wf.size();

  } else {

    M = wf.size();
    N = wf.size();
  }

  // Initiate the return matrix
  arma::cx_mat res(M, N, arma::fill::zeros);

  // Artificially double the sampling rate by repeating each sample.
  std::vector<double> wf_re(M, 0.0);

  auto it1 = wf_re.begin();
  for (auto it2 = wf.begin(); it2 != wf.end(); ++it2) {
    *(it1++) = *it2;
    if (upsample) {
      *(it1++) = *it2;
    }
  }

  // Make the signal harmonic
  arma::cx_vec v(M);
  arma::vec phase(M);

  auto wf_im = dsp::hilbert(wf_re);

  for (uint i = 0; i < M; ++i) {
    v[i] = arma::cx_double(wf_re[i], wf_im[i]);
    phase[i] = (1.0 * i) / M * M_PI;
  }

  // Now compute the Wigner-Ville Distribution
  for (int idx = 0; idx < N; ++idx) {
    res.col(idx) = arma::fft(dsp::rconvolve(v, idx));
    //    res.col(idx) = res.col(idx) % (arma::cos(phase * idx) + 1j * arma::sin(phase * idx));
  }

  return res;
}

arma::mat dsp::wvd(const std::vector<double>& wf, bool upsample)
{
  int M, N;
  if (upsample) {

    M = 2 * wf.size();
    N = wf.size();

  } else {

    M = wf.size();
    N = wf.size();
  }

  // Instiate the return matrix
  arma::mat res(M, N, arma::fill::zeros);

  // Artificially double the sampling rate by repeating each sample.
  std::vector<double> wf_re(M, 0.0);

  auto it1 = wf_re.begin();
  for (auto it2 = wf.begin(); it2 != wf.end(); ++it2) {
    *(it1++) = *it2;
    if (upsample) {
      *(it1++) = *it2;
    }
  }

  // Make the signal harmonic
  arma::cx_vec v(M);

  auto wf_im = dsp::hilbert(wf_re);

  for (int i = 0; i < M; ++i) {
    v[i] = arma::cx_double(wf_re[i], wf_im[i]);
  }

  // Now compute the Wigner-Ville Distribution
  for (int idx = 0; idx < N; ++idx) {
    res.col(idx) = arma::real(arma::fft(dsp::rconvolve(v, idx))) ;
  }

  return res;
}

std::vector<double> dsp::savgol3(const std::vector<double>& wf)
{
  std::vector<double> res(0, wf.size());
  std::vector<double> filter = {-2.0, 3.0, 6.0, 7.0, 6.0, 3.0, -2.0};
  filter = (1.0 / 21.0) * filter;

  if (dsp::convolve(wf, filter, res) == 0) {

    return res;

  } else {

    return wf;
  }
}

std::vector<double> dsp::savgol5(const std::vector<double>& wf)
{
  std::vector<double> res(0, wf.size());
  std::vector<double> filter = {15.0, -55.0, 30.0, 135.0, 179.0, 135.0, 30.0, -55.0, 15.0};
  filter = (1.0 / 429.0) * filter;

  if (dsp::convolve(wf, filter, res) == 0) {

    return res;

  } else {

    return wf;
  }
}

int dsp::convolve(const std::vector<double>& wf, const std::vector<double>& filter, std::vector<double>& res)
{
  int k = filter.size();
  int N = wf.size();
  res.resize(N);

  // Check to make sure we can do something.
  if (N < k) {
    return -1;
  }

  // First take care of the beginning and end.
  for (int i = 0; i < k + 1; ++i) {
    res[i] = 0.0;
    res[N -1 - i] = 0.0;

    for (int j = i; j < i + k; ++j) {

      res[i] += wf[abs(j - k/2)] * filter[j - i];
      res[N - 1 - i] += wf[N - 1 - abs(k/2 - j)] * filter[j - i];
    }
  }

  // Now the rest of the elements.
  for (auto it = wf.begin(); it != wf.end() - k; ++it) {
    double val = std::inner_product(it, it + k, filter.begin(), 0.0);
    res[std::distance(wf.begin(), it + k/2)] = val;
  }

  return 0;
}

std::vector<double> dsp::convolve(const std::vector<double>& wf, const std::vector<double>& filter)
{
  std::vector<double> res(0.0, wf.size());

  if (dsp::convolve(wf, filter, res) == 0) {

    return res;

  } else {

    return wf;
  }
}

} // ::fid
<commit_msg>Updated phase unwrapping to be simpler.<commit_after>#include "fid_math.h"

namespace fid
{

std::vector<std::complex<double>> dsp::fft(const std::vector<double> &wf)
{
  // Grab some useful constants.
  int N = wf.size();
  int n = N / 2 + 1;  // size of rfft
  double Nroot = std::sqrt(N);

  // Instantiate the result vector.
  std::vector<std::complex<double>> fft_vec(n, 0.0);
  auto wf_vec = wf; // copy waveform since fftw destroys it

  // Plan and execute the fft.
  fftw_plan wf_to_fft;
  fftw_complex *fft_ptr = reinterpret_cast<fftw_complex *>(&fft_vec[0]);
  wf_to_fft = fftw_plan_dft_r2c_1d(N, &wf_vec[0], fft_ptr, FFTW_ESTIMATE);
  fftw_execute(wf_to_fft);
  fftw_destroy_plan(wf_to_fft);

  for (auto it = fft_vec.begin(); it != fft_vec.end(); ++it) {
    *it /= Nroot;
  }

  return fft_vec;
}

std::vector<double> dsp::ifft(const std::vector<std::complex<double>>& fft)
{
  // Grab some useful constants.
  int n = fft.size();
  int N = 2 * (n - 1);
  double Nroot = std::sqrt(N);

  // Instantiate the result vector.
  std::vector<double> ifft_vec(N, 0.0);
  fftw_complex *fft_ptr = new fftw_complex[n];
  memcpy(fft_ptr, &fft[0], sizeof(fftw_complex) * n);

  // Plan and execute the fft.
  fftw_plan fft_to_wf;
  fft_to_wf = fftw_plan_dft_c2r_1d(N, fft_ptr, &ifft_vec[0], FFTW_ESTIMATE);
  fftw_execute(fft_to_wf);
  fftw_destroy_plan(fft_to_wf);

  // fftw is unnormalized, so we need to fix that.
  for (auto it = ifft_vec.begin(); it != ifft_vec.end(); ++it) {
  	*it /= Nroot;
  }

  delete[] fft_ptr;

  return ifft_vec;
}

std::vector<double> dsp::hilbert(const std::vector<double>& wf)
{
	// Return the call to the fft version.
	auto fft_vec = dsp::fft(wf);

  // Multiply in the -i.
  for (auto it = fft_vec.begin(); it != fft_vec.end(); ++it) {
    *it = std::complex<double>((*it).imag(), -(*it).real());
  }

  // Reverse the fft.
  return ifft(fft_vec);
}

std::vector<double> dsp::psd(const std::vector<double>& wf)
{
  // Perform fft on the original data.
	auto fft_vec = dsp::fft(wf);

  // Get the norm of the fft as that is the power.
	return dsp::norm(fft_vec);
}

std::vector<double> dsp::norm(const std::vector<double>& wf)
{
  // Allocate the memory
  std::vector<double> res;
  res.reserve(wf.size());

  // Iterate and push back the norm.
  for (auto it = wf.begin(); it < wf.end(); ++it) {
    res.push_back(std::norm(*it));
  }

  return res;
}

std::vector<double> dsp::norm(const std::vector<std::complex<double>>& wf)
{
  // Allocate the memory
  std::vector<double> res;
  res.reserve(wf.size());

  // Iterate and push back the norm.
  for (auto it = wf.begin(); it < wf.end(); ++it) {
    res.push_back(std::norm(*it));
  }

  return res;
}

// Helper function to get frequencies for FFT
std::vector<double> dsp::fftfreq(const std::vector<double>& tm)
{
	int N = tm.size();
	double dt = (tm[N-1] - tm[0]) / (N - 1); // sampling rate

	return dsp::fftfreq(N, dt);
}

std::vector<double> dsp::fftfreq(const int N, const double dt)
{
	// Instantiate return vector.
	std::vector<double> freq;

	// Handle both even and odd cases properly.
	if (N % 2 == 0) {

		freq.resize(N/2 + 1);

		for (int i = 0; i < freq.size(); ++i) {
			freq[i] = i / (dt * N);
		}

	} else {

		freq.resize((N + 1) / 2);

		for (int i = 0; i < freq.size(); ++i){
			freq[i] = i / (dt * N);
		}
	}

	return freq;
}

// Calculates the phase by assuming the real signal is harmonic.
std::vector<double> dsp::phase(const std::vector<double>& wf)
{
	return dsp::phase(wf, dsp::hilbert(wf));
}

std::vector<double> dsp::phase(const std::vector<double>& wf_re,
                               const std::vector<double>& wf_im)
{
  std::vector<double> phase(wf_re.size(), 0.0);

  // Calculate the modulo-ed phase
  std::transform(wf_re.begin(), wf_re.end(), wf_im.begin(), phase.begin(),
                 [](double re, double im) { return std::atan2(im, re); });

  // Now unwrap the phase
  double thresh = params::max_phase_jump;
  double m_avg = 0.0;
  double m_std = 0.0;
  double m = 0.0;
  double a = 0.001;
  bool phase_trend = false;

  int k = 0; // to track the winding number
  for (auto it = phase.begin() + 1; it != phase.end(); ++it) {

    // Add current total
    *it += k * kTau;
    m = *(it) - *(it - 1);

    // Check for large jumps, both positive and negative.
    while (std::abs(m) > thresh) {

      if (-m > thresh) {

        if (m + kTau > thresh) {
          std::cout << "Warning: jump over threshold." << std::endl;
          break;
        }

        k++;
        *it += kTau;

      } else if (m > thresh) {

        if (m - kTau < -thresh) {
          std::cout << "Warning: jump over threshold." << std::endl;
          break;
        }

        k--;
        *it -= kTau;
      }

      m = *(it) - *(it - 1);
    }

    // // Recalculate slope.
    // m = *(it) - *(it - 1);

    // // Check against the slope of the last few points for outliers
    // if (phase_trend) {
    //   if (m > 3.0 * m_avg) {

    //     k--;
    //     *it -= kTau;

    //   } else if (m < -2.0 * m_avg) {

    //     k++;
    //     *it += kTau;
    //   }
    // }

    // // Compute the exponential moving average
    // if (!phase_trend && (std::abs(k) > 15)) {
    //   m_avg = a * (*it - *(it - 1)) + (1 - a) * m_avg;
    //   m_std = a * (m - m_avg) + (1 - a) * m_std;

    //   if (std::abs(m_avg) > 10.0 * std::abs(m_std)) {
    //     m_avg = *it - *(it - 1);
    //     phase_trend = true;
    //   }

    // } else {

    //   m_avg = a * (*it - *(it - 1)) + (1 - a) * m_avg;
    // }
  }

  return phase;
}

std::vector<double> dsp::envelope(const std::vector<double>& wf)
{
	return dsp::envelope(wf, dsp::hilbert(wf));
}

std::vector<double> dsp::envelope(const std::vector<double>& wf_re, const std::vector<double>& wf_im)
{
 	// Set the envelope function
	std::vector<double> env(wf_re.size(), 0.0);

	std::transform(wf_re.begin(), wf_re.end(), wf_im.begin(), env.begin(),
    			   [](double r, double i) { return std::sqrt(r*r + i*i); });

	return env;
}

arma::cx_mat dsp::wvd_cx(const std::vector<double>& wf, bool upsample)
{
  int M, N;
  if (upsample) {

    M = 2 * wf.size();
    N = wf.size();

  } else {

    M = wf.size();
    N = wf.size();
  }

  // Initiate the return matrix
  arma::cx_mat res(M, N, arma::fill::zeros);

  // Artificially double the sampling rate by repeating each sample.
  std::vector<double> wf_re(M, 0.0);

  auto it1 = wf_re.begin();
  for (auto it2 = wf.begin(); it2 != wf.end(); ++it2) {
    *(it1++) = *it2;
    if (upsample) {
      *(it1++) = *it2;
    }
  }

  // Make the signal harmonic
  arma::cx_vec v(M);
  arma::vec phase(M);

  auto wf_im = dsp::hilbert(wf_re);

  for (uint i = 0; i < M; ++i) {
    v[i] = arma::cx_double(wf_re[i], wf_im[i]);
    phase[i] = (1.0 * i) / M * M_PI;
  }

  // Now compute the Wigner-Ville Distribution
  for (int idx = 0; idx < N; ++idx) {
    res.col(idx) = arma::fft(dsp::rconvolve(v, idx));
    //    res.col(idx) = res.col(idx) % (arma::cos(phase * idx) + 1j * arma::sin(phase * idx));
  }

  return res;
}

arma::mat dsp::wvd(const std::vector<double>& wf, bool upsample)
{
  int M, N;
  if (upsample) {

    M = 2 * wf.size();
    N = wf.size();

  } else {

    M = wf.size();
    N = wf.size();
  }

  // Instiate the return matrix
  arma::mat res(M, N, arma::fill::zeros);

  // Artificially double the sampling rate by repeating each sample.
  std::vector<double> wf_re(M, 0.0);

  auto it1 = wf_re.begin();
  for (auto it2 = wf.begin(); it2 != wf.end(); ++it2) {
    *(it1++) = *it2;
    if (upsample) {
      *(it1++) = *it2;
    }
  }

  // Make the signal harmonic
  arma::cx_vec v(M);

  auto wf_im = dsp::hilbert(wf_re);

  for (int i = 0; i < M; ++i) {
    v[i] = arma::cx_double(wf_re[i], wf_im[i]);
  }

  // Now compute the Wigner-Ville Distribution
  for (int idx = 0; idx < N; ++idx) {
    res.col(idx) = arma::real(arma::fft(dsp::rconvolve(v, idx))) ;
  }

  return res;
}

std::vector<double> dsp::savgol3(const std::vector<double>& wf)
{
  std::vector<double> res(0, wf.size());
  std::vector<double> filter = {-2.0, 3.0, 6.0, 7.0, 6.0, 3.0, -2.0};
  filter = (1.0 / 21.0) * filter;

  if (dsp::convolve(wf, filter, res) == 0) {

    return res;

  } else {

    return wf;
  }
}

std::vector<double> dsp::savgol5(const std::vector<double>& wf)
{
  std::vector<double> res(0, wf.size());
  std::vector<double> filter = {15.0, -55.0, 30.0, 135.0, 179.0, 135.0, 30.0, -55.0, 15.0};
  filter = (1.0 / 429.0) * filter;

  if (dsp::convolve(wf, filter, res) == 0) {

    return res;

  } else {

    return wf;
  }
}

int dsp::convolve(const std::vector<double>& wf, const std::vector<double>& filter, std::vector<double>& res)
{
  int k = filter.size();
  int N = wf.size();
  res.resize(N);

  // Check to make sure we can do something.
  if (N < k) {
    return -1;
  }

  // First take care of the beginning and end.
  for (int i = 0; i < k + 1; ++i) {
    res[i] = 0.0;
    res[N -1 - i] = 0.0;

    for (int j = i; j < i + k; ++j) {

      res[i] += wf[abs(j - k/2)] * filter[j - i];
      res[N - 1 - i] += wf[N - 1 - abs(k/2 - j)] * filter[j - i];
    }
  }

  // Now the rest of the elements.
  for (auto it = wf.begin(); it != wf.end() - k; ++it) {
    double val = std::inner_product(it, it + k, filter.begin(), 0.0);
    res[std::distance(wf.begin(), it + k/2)] = val;
  }

  return 0;
}

std::vector<double> dsp::convolve(const std::vector<double>& wf, const std::vector<double>& filter)
{
  std::vector<double> res(0.0, wf.size());

  if (dsp::convolve(wf, filter, res) == 0) {

    return res;

  } else {

    return wf;
  }
}

} // ::fid
<|endoftext|>


<commit_before>// g++ -Wall -Wextra -std=c++17 -mwindows activity_monitor.cpp -lcomctl32 -lole32 -o activity_monitor.exe

#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <ole2.h>
#include <commctrl.h>
#include <shlwapi.h>
#include <strsafe.h>

constexpr UINT_PTR IDT_TIMER1 = 1;

HINSTANCE g_hinst;                          /* This application's HINSTANCE */
HWND g_hwndChild;                           /* Optional child window */
/*
 *  OnSize
 *      If we have an inner child, resize it to fit.
 */
void
OnSize([[maybe_unused]] HWND hwnd, [[maybe_unused]] UINT state, int cx, int cy)
{
    if (g_hwndChild) {
        MoveWindow(g_hwndChild, 0, 0, cx, cy, TRUE);
    }
}
/*
 *  OnCreate
 *      Applications will typically override this and maybe even
 *      create a child window.
 */
BOOL
OnCreate(HWND hwnd, [[maybe_unused]] LPCREATESTRUCT lpcs)
{
  g_hwndChild = CreateWindow(TEXT("listbox"), NULL,
      LBS_HASSTRINGS | WS_CHILD | WS_VISIBLE | WS_VSCROLL,
      0, 0, 0, 0, hwnd, NULL, g_hinst, 0);

  RAWINPUTDEVICE dev[2];
  dev[0].usUsagePage = 1;
  dev[0].usUsage = 6;
  dev[0].dwFlags = RIDEV_INPUTSINK;
  dev[0].hwndTarget = hwnd;

  dev[1].usUsagePage = 1;
  dev[1].usUsage = 2;
  dev[1].dwFlags = RIDEV_INPUTSINK;
  dev[1].hwndTarget = hwnd;

  RegisterRawInputDevices(dev, sizeof(dev) / sizeof(dev[0]), sizeof(dev[0]));

  SetTimer(hwnd, IDT_TIMER1, 1000, nullptr);

  return TRUE;
}
/*
 *  OnDestroy
 *      Post a quit message because our application is over when the
 *      user closes this window.
 */
void
OnDestroy(HWND hwnd)
{
  RAWINPUTDEVICE dev[2];
  dev[0].usUsagePage = 1;
  dev[0].usUsage = 6;
  dev[0].dwFlags = RIDEV_REMOVE;
  dev[0].hwndTarget = hwnd;

  dev[1].usUsagePage = 1;
  dev[1].usUsage = 2;
  dev[1].dwFlags = RIDEV_REMOVE;
  dev[1].hwndTarget = hwnd;

  RegisterRawInputDevices(dev, sizeof(dev) / sizeof(dev[0]), sizeof(dev[0]));

  KillTimer(hwnd, IDT_TIMER1);

  PostQuitMessage(0);
}

#define HANDLE_WM_INPUT(hwnd, wParam, lParam, fn) \
  ((fn)((hwnd), GET_RAWINPUT_CODE_WPARAM(wParam), \
        (HRAWINPUT)(lParam)), 0)

void OnInput([[maybe_unused]] HWND hwnd, [[maybe_unused]] WPARAM code, HRAWINPUT hRawInput)
{
  UINT dwSize;
  GetRawInputData(hRawInput, RID_INPUT, nullptr,
                  &dwSize, sizeof(RAWINPUTHEADER));
  RAWINPUT *input = (RAWINPUT *)malloc(dwSize);
  GetRawInputData(hRawInput, RID_INPUT, input,
                  &dwSize, sizeof(RAWINPUTHEADER));
  if (input->header.dwType == RIM_TYPEKEYBOARD) {
    TCHAR prefix[80];
    prefix[0] = TEXT('\0');
    if (input->data.keyboard.Flags & RI_KEY_E0) {
        StringCchCat(prefix, ARRAYSIZE(prefix), TEXT("E0 "));
    }
    if (input->data.keyboard.Flags & RI_KEY_E1) {
        StringCchCat(prefix, ARRAYSIZE(prefix), TEXT("E1 "));
    }

    TCHAR buffer[256];
    StringCchPrintf(buffer, ARRAYSIZE(buffer),
        TEXT("%p, msg=%04x, vk=%04x, scanCode=%s%02x, %s"),
        input->header.hDevice,
        input->data.keyboard.Message,
        input->data.keyboard.VKey,
        prefix,
        input->data.keyboard.MakeCode,
        (input->data.keyboard.Flags & RI_KEY_BREAK)
            ? TEXT("release") : TEXT("press"));
    ListBox_AddString(g_hwndChild, buffer);
  } else if (input->header.dwType == RIM_TYPEMOUSE) {
    if (input->data.mouse.usButtonFlags != 0) { // print only transitions of the mouse buttons
        TCHAR buffer[256];
        StringCchPrintf(buffer, ARRAYSIZE(buffer),
          TEXT("MOUSE %p, usFlags 0x%04x, usButtonFlags 0x%04x, usButtonData %d, ulRawButtons 0x%08x, lLastX %d, lLastY &d, ulExtraInformation 0x%08x"),
          input->header.hDevice,
          input->data.mouse.usFlags,
          input->data.mouse.usButtonFlags,
          static_cast<SHORT>(input->data.mouse.usButtonData),
          input->data.mouse.ulRawButtons,
          input->data.mouse.lLastX,
          input->data.mouse.lLastY,
          input->data.mouse.ulExtraInformation
        );
        ListBox_AddString(g_hwndChild, buffer);
    }
  }
  DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER));
  free(input);
}

/*
 *  PaintContent
 *      Interesting things will be painted here eventually.
 */
void
PaintContent([[maybe_unused]] HWND hwnd, [[maybe_unused]] PAINTSTRUCT *pps)
{
}
/*
 *  OnPaint
 *      Paint the content as part of the paint cycle.
 */
void
OnPaint(HWND hwnd)
{
    PAINTSTRUCT ps;
    BeginPaint(hwnd, &ps);
    PaintContent(hwnd, &ps);
    EndPaint(hwnd, &ps);
}
/*
 *  OnPrintClient
 *      Paint the content as requested by USER.
 */
void
OnPrintClient(HWND hwnd, HDC hdc)
{
    PAINTSTRUCT ps;
    ps.hdc = hdc;
    GetClientRect(hwnd, &ps.rcPaint);
    PaintContent(hwnd, &ps);
}
/*
 *  Window procedure
 */
LRESULT CALLBACK
WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uiMsg) {
    HANDLE_MSG(hwnd, WM_CREATE, OnCreate);
    HANDLE_MSG(hwnd, WM_SIZE, OnSize);
    HANDLE_MSG(hwnd, WM_DESTROY, OnDestroy);
    HANDLE_MSG(hwnd, WM_PAINT, OnPaint);
    HANDLE_MSG(hwnd, WM_INPUT, OnInput);
    case WM_PRINTCLIENT: OnPrintClient(hwnd, (HDC)wParam); return 0;

    case WM_TIMER: ListBox_AddString(g_hwndChild, TEXT("TIMER")); return 0;

    }
    return DefWindowProc(hwnd, uiMsg, wParam, lParam);
}
BOOL
InitApp(void)
{
    WNDCLASS wc;
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = g_hinst;
    wc.hIcon = NULL;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = TEXT("Scratch");
    if (!RegisterClass(&wc)) return FALSE;
    InitCommonControls();               /* In case we use a common control */
    return TRUE;
}
int WINAPI WinMain(HINSTANCE hinst, [[maybe_unused]] HINSTANCE hinstPrev,
                   [[maybe_unused]] LPSTR lpCmdLine, int nShowCmd)
{
    MSG msg;
    HWND hwnd;
    g_hinst = hinst;
    if (!InitApp()) return 0;
    if (SUCCEEDED(CoInitialize(NULL))) {/* In case we use COM */
        hwnd = CreateWindow(
            TEXT("Scratch"),                /* Class Name */
            TEXT("Scratch"),                /* Title */
            WS_OVERLAPPEDWINDOW,            /* Style */
            CW_USEDEFAULT, CW_USEDEFAULT,   /* Position */
            CW_USEDEFAULT, CW_USEDEFAULT,   /* Size */
            NULL,                           /* Parent */
            NULL,                           /* No menu */
            hinst,                          /* Instance */
            0);                             /* No special parameters */
        ShowWindow(hwnd, nShowCmd);
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        CoUninitialize();
    }
    return 0;
}
<commit_msg>Print buttons/keys on device<commit_after>// g++ -Wall -Wextra -std=c++17 -mwindows activity_monitor.cpp -lcomctl32 -lole32 -o activity_monitor.exe

#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <ole2.h>
#include <commctrl.h>
#include <shlwapi.h>
#include <strsafe.h>
#include <assert.h>

constexpr UINT_PTR IDT_TIMER1 = 1;

HINSTANCE g_hinst;                          /* This application's HINSTANCE */
HWND g_hwndChild;                           /* Optional child window */
/*
 *  OnSize
 *      If we have an inner child, resize it to fit.
 */
void
OnSize([[maybe_unused]] HWND hwnd, [[maybe_unused]] UINT state, int cx, int cy)
{
    if (g_hwndChild) {
        MoveWindow(g_hwndChild, 0, 0, cx, cy, TRUE);
    }
}
/*
 *  OnCreate
 *      Applications will typically override this and maybe even
 *      create a child window.
 */
BOOL
OnCreate(HWND hwnd, [[maybe_unused]] LPCREATESTRUCT lpcs)
{
  g_hwndChild = CreateWindow(TEXT("listbox"), NULL,
      LBS_HASSTRINGS | WS_CHILD | WS_VISIBLE | WS_VSCROLL,
      0, 0, 0, 0, hwnd, NULL, g_hinst, 0);

  RAWINPUTDEVICE dev[2];
  dev[0].usUsagePage = 1;
  dev[0].usUsage = 6;
  dev[0].dwFlags = RIDEV_INPUTSINK;
  dev[0].hwndTarget = hwnd;

  dev[1].usUsagePage = 1;
  dev[1].usUsage = 2;
  dev[1].dwFlags = RIDEV_INPUTSINK;
  dev[1].hwndTarget = hwnd;

  RegisterRawInputDevices(dev, sizeof(dev) / sizeof(dev[0]), sizeof(dev[0]));

  SetTimer(hwnd, IDT_TIMER1, 1000, nullptr);

  return TRUE;
}
/*
 *  OnDestroy
 *      Post a quit message because our application is over when the
 *      user closes this window.
 */
void
OnDestroy(HWND hwnd)
{
  RAWINPUTDEVICE dev[2];
  dev[0].usUsagePage = 1;
  dev[0].usUsage = 6;
  dev[0].dwFlags = RIDEV_REMOVE;
  dev[0].hwndTarget = hwnd;

  dev[1].usUsagePage = 1;
  dev[1].usUsage = 2;
  dev[1].dwFlags = RIDEV_REMOVE;
  dev[1].hwndTarget = hwnd;

  RegisterRawInputDevices(dev, sizeof(dev) / sizeof(dev[0]), sizeof(dev[0]));

  KillTimer(hwnd, IDT_TIMER1);

  PostQuitMessage(0);
}

#define HANDLE_WM_INPUT(hwnd, wParam, lParam, fn) \
  ((fn)((hwnd), GET_RAWINPUT_CODE_WPARAM(wParam), \
        (HRAWINPUT)(lParam)), 0)

void OnInput([[maybe_unused]] HWND hwnd, [[maybe_unused]] WPARAM code, HRAWINPUT hRawInput)
{
  UINT dwSize;
  GetRawInputData(hRawInput, RID_INPUT, nullptr,
                  &dwSize, sizeof(RAWINPUTHEADER));
  RAWINPUT *input = (RAWINPUT *)malloc(dwSize);
  GetRawInputData(hRawInput, RID_INPUT, input,
                  &dwSize, sizeof(RAWINPUTHEADER));
  if (input->header.dwType == RIM_TYPEKEYBOARD) {
    TCHAR prefix[80];
    prefix[0] = TEXT('\0');
    if (input->data.keyboard.Flags & RI_KEY_E0) {
        StringCchCat(prefix, ARRAYSIZE(prefix), TEXT("E0 "));
    }
    if (input->data.keyboard.Flags & RI_KEY_E1) {
        StringCchCat(prefix, ARRAYSIZE(prefix), TEXT("E1 "));
    }

    RID_DEVICE_INFO device_info{};
    UINT cbSize = sizeof(device_info);
    const UINT ret = GetRawInputDeviceInfoA(input->header.hDevice, RIDI_DEVICEINFO, &device_info, &cbSize);
    if (ret == 0 || ret == static_cast<UINT>(-1)) {
        assert(false);
    }
    if (ret != sizeof(device_info)) {
        assert(false);
    }
    // GetRawInputDeviceInfoA reported success
    if (device_info.cbSize != sizeof(device_info) || device_info.dwType != input->header.dwType) {
        assert(false);
    }

    TCHAR buffer[256];
    StringCchPrintf(buffer, ARRAYSIZE(buffer),
        TEXT("%p, msg=%04x, vk=%04x, scanCode=%s%02x, %s, dwNumberOfFunctionKeys %u, dwNumberOfIndicators %u, dwNumberOfKeysTotal %u"),
        input->header.hDevice,
        input->data.keyboard.Message,
        input->data.keyboard.VKey,
        prefix,
        input->data.keyboard.MakeCode,
        (input->data.keyboard.Flags & RI_KEY_BREAK)
            ? TEXT("release") : TEXT("press"),
        device_info.keyboard.dwNumberOfFunctionKeys,
        device_info.keyboard.dwNumberOfIndicators,
        device_info.keyboard.dwNumberOfKeysTotal);
    ListBox_AddString(g_hwndChild, buffer);
  } else if (input->header.dwType == RIM_TYPEMOUSE) {
    if (input->data.mouse.usButtonFlags != 0) { // print only transitions of the mouse buttons
        RID_DEVICE_INFO device_info{};
        UINT cbSize = sizeof(device_info);
        const UINT ret = GetRawInputDeviceInfoA(input->header.hDevice, RIDI_DEVICEINFO, &device_info, &cbSize);
        if (ret == 0 || ret == static_cast<UINT>(-1)) {
            assert(false);
        }
        if (ret != sizeof(device_info)) {
            assert(false);
        }
        // GetRawInputDeviceInfoA reported success
        if (device_info.cbSize != sizeof(device_info) || device_info.dwType != input->header.dwType) {
            assert(false);
        }

        TCHAR buffer[256];
        StringCchPrintf(buffer, ARRAYSIZE(buffer),
          TEXT("MOUSE %p, usFlags 0x%04x, usButtonFlags 0x%04x, usButtonData %d, ulRawButtons 0x%08x, lLastX %d, lLastY %d, ulExtraInformation 0x%08x, dwNumberOfButtons %u"),
          input->header.hDevice,
          input->data.mouse.usFlags,
          input->data.mouse.usButtonFlags,
          static_cast<SHORT>(input->data.mouse.usButtonData),
          input->data.mouse.ulRawButtons,
          input->data.mouse.lLastX,
          input->data.mouse.lLastY,
          input->data.mouse.ulExtraInformation,
          device_info.mouse.dwNumberOfButtons
        );
        ListBox_AddString(g_hwndChild, buffer);
    }
  }
  DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER));
  free(input);
}

/*
 *  PaintContent
 *      Interesting things will be painted here eventually.
 */
void
PaintContent([[maybe_unused]] HWND hwnd, [[maybe_unused]] PAINTSTRUCT *pps)
{
}
/*
 *  OnPaint
 *      Paint the content as part of the paint cycle.
 */
void
OnPaint(HWND hwnd)
{
    PAINTSTRUCT ps;
    BeginPaint(hwnd, &ps);
    PaintContent(hwnd, &ps);
    EndPaint(hwnd, &ps);
}
/*
 *  OnPrintClient
 *      Paint the content as requested by USER.
 */
void
OnPrintClient(HWND hwnd, HDC hdc)
{
    PAINTSTRUCT ps;
    ps.hdc = hdc;
    GetClientRect(hwnd, &ps.rcPaint);
    PaintContent(hwnd, &ps);
}
/*
 *  Window procedure
 */
LRESULT CALLBACK
WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uiMsg) {
    HANDLE_MSG(hwnd, WM_CREATE, OnCreate);
    HANDLE_MSG(hwnd, WM_SIZE, OnSize);
    HANDLE_MSG(hwnd, WM_DESTROY, OnDestroy);
    HANDLE_MSG(hwnd, WM_PAINT, OnPaint);
    HANDLE_MSG(hwnd, WM_INPUT, OnInput);
    case WM_PRINTCLIENT: OnPrintClient(hwnd, (HDC)wParam); return 0;

    case WM_TIMER: ListBox_AddString(g_hwndChild, TEXT("TIMER")); return 0;

    }
    return DefWindowProc(hwnd, uiMsg, wParam, lParam);
}
BOOL
InitApp(void)
{
    WNDCLASS wc;
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = g_hinst;
    wc.hIcon = NULL;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = TEXT("Scratch");
    if (!RegisterClass(&wc)) return FALSE;
    InitCommonControls();               /* In case we use a common control */
    return TRUE;
}
int WINAPI WinMain(HINSTANCE hinst, [[maybe_unused]] HINSTANCE hinstPrev,
                   [[maybe_unused]] LPSTR lpCmdLine, int nShowCmd)
{
    MSG msg;
    HWND hwnd;
    g_hinst = hinst;
    if (!InitApp()) return 0;
    if (SUCCEEDED(CoInitialize(NULL))) {/* In case we use COM */
        hwnd = CreateWindow(
            TEXT("Scratch"),                /* Class Name */
            TEXT("Scratch"),                /* Title */
            WS_OVERLAPPEDWINDOW,            /* Style */
            CW_USEDEFAULT, CW_USEDEFAULT,   /* Position */
            CW_USEDEFAULT, CW_USEDEFAULT,   /* Size */
            NULL,                           /* Parent */
            NULL,                           /* No menu */
            hinst,                          /* Instance */
            0);                             /* No special parameters */
        ShowWindow(hwnd, nShowCmd);
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        CoUninitialize();
    }
    return 0;
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkHedgeHog.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkHedgeHog.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------
vtkHedgeHog* vtkHedgeHog::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkHedgeHog");
  if(ret)
    {
    return (vtkHedgeHog*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkHedgeHog;
}

vtkHedgeHog::vtkHedgeHog()
{
  this->ScaleFactor = 1.0;
  this->VectorMode = VTK_USE_VECTOR;
}

void vtkHedgeHog::Execute()
{
  vtkDataSet *input= this->GetInput();
  vtkIdType numPts;
  vtkPoints *newPts;
  vtkPointData *pd;
  vtkDataArray *inVectors;
  vtkDataArray *inNormals;
  vtkIdType ptId;
  int i;
  vtkIdType pts[2];
  vtkCellArray *newLines;
  float *x, *v;
  float newX[3];
  vtkPolyData *output = this->GetOutput();
  vtkPointData *outputPD = output->GetPointData();

  // Initialize
  //
  numPts = input->GetNumberOfPoints();
  pd = input->GetPointData();
  inVectors = pd->GetActiveVectors();
  if ( numPts < 1 )
    {
    vtkErrorMacro(<<"No input data");
    return;
    }
  if ( !inVectors && this->VectorMode == VTK_USE_VECTOR)
    {
    vtkErrorMacro(<<"No vectors in input data");
    return;
    }

  inNormals = pd->GetActiveNormals();
  if ( !inNormals && this->VectorMode == VTK_USE_NORMAL)
    {
    vtkErrorMacro(<<"No normals in input data");
    return;
    }
  outputPD->CopyAllocate(pd, 2*numPts);

  newPts = vtkPoints::New(); newPts->SetNumberOfPoints(2*numPts);
  newLines = vtkCellArray::New();
  newLines->Allocate(newLines->EstimateSize(numPts,2));

  // Loop over all points, creating oriented line
  //
  for (ptId=0; ptId < numPts; ptId++)
    {
    if ( ! (ptId % 10000) ) //abort/progress
      {
      this->UpdateProgress ((float)ptId/numPts);
      if (this->GetAbortExecute())
	{
	break;
	}
      }

    x = input->GetPoint(ptId);
    if (this->VectorMode == VTK_USE_VECTOR)
      {
      v = inVectors->GetTuple(ptId);
      }
    else
      {
      v = inNormals->GetTuple(ptId);
      }
    for (i=0; i<3; i++)
      {
      newX[i] = x[i] + this->ScaleFactor * v[i];
      }

    pts[0] = ptId;
    pts[1] = ptId + numPts;;

    newPts->SetPoint(pts[0], x);
    newPts->SetPoint(pts[1], newX);

    newLines->InsertNextCell(2,pts);

    outputPD->CopyData(pd,ptId,pts[0]);
    }

  // Update ourselves and release memory
  //
  output->SetPoints(newPts);
  newPts->Delete();

  output->SetLines(newLines);
  newLines->Delete();
}

void vtkHedgeHog::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToPolyDataFilter::PrintSelf(os,indent);

  os << indent << "Scale Factor: " << this->ScaleFactor << "\n";
  os << indent << "Orient Mode: " << (this->VectorMode == VTK_USE_VECTOR ?
                                       "Orient by vector\n" : "Orient by normal\n");
}
<commit_msg>Oops.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkHedgeHog.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkHedgeHog.h"
#include "vtkObjectFactory.h"

//------------------------------------------------------------------------
vtkHedgeHog* vtkHedgeHog::New()
{
  // First try to create the object from the vtkObjectFactory
  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkHedgeHog");
  if(ret)
    {
    return (vtkHedgeHog*)ret;
    }
  // If the factory was unable to create the object, then create it here.
  return new vtkHedgeHog;
}

vtkHedgeHog::vtkHedgeHog()
{
  this->ScaleFactor = 1.0;
  this->VectorMode = VTK_USE_VECTOR;
}

void vtkHedgeHog::Execute()
{
  vtkDataSet *input= this->GetInput();
  vtkIdType numPts;
  vtkPoints *newPts;
  vtkPointData *pd;
  vtkDataArray *inVectors;
  vtkDataArray *inNormals;
  vtkIdType ptId;
  int i;
  vtkIdType pts[2];
  vtkCellArray *newLines;
  float *x, *v;
  float newX[3];
  vtkPolyData *output = this->GetOutput();
  vtkPointData *outputPD = output->GetPointData();

  // Initialize
  //
  numPts = input->GetNumberOfPoints();
  pd = input->GetPointData();
  inVectors = pd->GetActiveVectors();
  if ( numPts < 1 )
    {
    vtkErrorMacro(<<"No input data");
    return;
    }
  if ( !inVectors && this->VectorMode == VTK_USE_VECTOR)
    {
    vtkErrorMacro(<<"No vectors in input data");
    return;
    }

  inNormals = pd->GetActiveNormals();
  if ( !inNormals && this->VectorMode == VTK_USE_NORMAL)
    {
    vtkErrorMacro(<<"No normals in input data");
    return;
    }
  outputPD->CopyAllocate(pd, 2*numPts);

  newPts = vtkPoints::New(); newPts->SetNumberOfPoints(2*numPts);
  newLines = vtkCellArray::New();
  newLines->Allocate(newLines->EstimateSize(numPts,2));

  // Loop over all points, creating oriented line
  //
  for (ptId=0; ptId < numPts; ptId++)
    {
    if ( ! (ptId % 10000) ) //abort/progress
      {
      this->UpdateProgress ((float)ptId/numPts);
      if (this->GetAbortExecute())
	{
	break;
	}
      }

    x = input->GetPoint(ptId);
    if (this->VectorMode == VTK_USE_VECTOR)
      {
      v = inVectors->GetTuple(ptId);
      }
    else
      {
      v = inNormals->GetTuple(ptId);
      }
    for (i=0; i<3; i++)
      {
      newX[i] = x[i] + this->ScaleFactor * v[i];
      }

    pts[0] = ptId;
    pts[1] = ptId + numPts;;

    newPts->SetPoint(pts[0], x);
    newPts->SetPoint(pts[1], newX);

    newLines->InsertNextCell(2,pts);

    outputPD->CopyData(pd,ptId,pts[0]);
    outputPD->CopyData(pd,ptId,pts[1]);
    }

  // Update ourselves and release memory
  //
  output->SetPoints(newPts);
  newPts->Delete();

  output->SetLines(newLines);
  newLines->Delete();
}

void vtkHedgeHog::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkDataSetToPolyDataFilter::PrintSelf(os,indent);

  os << indent << "Scale Factor: " << this->ScaleFactor << "\n";
  os << indent << "Orient Mode: " << (this->VectorMode == VTK_USE_VECTOR ?
                                       "Orient by vector\n" : "Orient by normal\n");
}
<|endoftext|>


<commit_before>/* -*- mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
// vim:sts=4:sw=4:ts=4:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s

/*
 * Copyright (C) FFLAS-FFPACK
 * Written by David Lucas
 * This file is Free Software and part of FFLAS-FFPACK.
 *
 * ========LICENCE========
 * This file is part of the library FFLAS-FFPACK.
 *
 * FFLAS-FFPACK 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
 * ========LICENCE========
 *.
 */

//--------------------------------------------------------------------------
//                        Test for minpoly
//
//--------------------------------------------------------------------------
// David Lucas
//-------------------------------------------------------------------------

#include <iomanip>
#include <iostream>

#include "fflas-ffpack/fflas-ffpack-config.h"
#include "fflas-ffpack/utils/fflas_randommatrix.h"
#include "fflas-ffpack/ffpack/ffpack.h"
#include "fflas-ffpack/fflas/fflas.h"
#include "fflas-ffpack/utils/args-parser.h"
#include "test-utils.h"
#include <givaro/modular-integer.h>
#include <givaro/modular.h>
#include <givaro/modular-balanced.h>
#include <givaro/givpoly1.h>

using namespace std;
using namespace FFPACK;
using Givaro::Modular;
using Givaro::ModularBalanced;

typedef Givaro::ModularBalanced<double> Field;
typedef vector<Field::Element> Polynomial;

template<typename Field, class RandIter>
bool check_minpoly(const Field &F, size_t n, RandIter& G)
{
	cout<<"Entering check_minpoly";
	cout<<endl;
	typedef typename Field::Element Element;
	size_t lda, ldv;
	Element *A, *V;

	//Default
	lda = n;
	ldv = n;

	/*Create variables used for testing (matrices, vectors and polynomials) */

    A = FFLAS::fflas_new(F, n, n);
    V = FFLAS::fflas_new(F, n+1, n);
    Polynomial minP;

    FFPACK::RandomMatrix (F, n, n, A, lda, G);

	FFPACK::NonZeroRandomMatrix(F, 1, n, V, n, G);

	FFPACK::MatVecMinPoly(F, minP, n, A, lda, V, ldv); //3rd input argument is the matrix order

	/*Check that minP is monic*/

	size_t deg = minP.size() - 1;
	if(!(minP[deg]==F.one))
		return false;

	/*Check that minP(A).V is zero*/

	Element *E, *E_tmp;
    E = FFLAS::fflas_new(F, n+1, n);
	E_tmp = FFLAS::fflas_new(F, n+1, n);

    /* Horner's method for polynomial evaluation */

	FFLAS::finit(F, n, V, n, E, n); //E <- V

    for(long i = deg; i > 0; --i)
    {
		FFLAS::faxpy(F, F.one, n, minP[i-1], V, n, E, n); //E <- minP[i-1] * V + E
		FFLAS::fassign(F, 1, n, E_tmp, n, E, n); //E_tmp <- E
		FFLAS::fgemv(F, FFLAS::FflasNoTrans, n, n, F.one, A, n, E_tmp, n, F.zero, E, n);//E <- E_tmp * A
    }

	FFLAS::fflas_delete(E_tmp);
	FFLAS::fflas_delete(A);
	FFLAS::fflas_delete(V);

    if (!FFLAS::fiszero(F, n, E, n))
	{
		cout<<"NONZERO"<<endl;
		for(long i = 0; i<n; ++i)
			cout<<E[i]<<" ";
		cout<<endl;
		FFLAS::fflas_delete(E);
		return false;
	}

	FFLAS::fflas_delete(E);
	return true;
}

template <class Field>
bool run_with_field (Givaro::Integer q, size_t b, size_t n, size_t iters, uint64_t seed)
{
	bool ok = true;
	int nbiter = iters;

	while (ok && nbiter)
	{
		Field* F = chooseField<Field>(q, b); // F, characteristic q of b bits
		typename Field::RandIter G(*F, 0, seed); //random generator over F

		if(F == nullptr)
			return true; //if F is null, nothing to test, just pass

		cout<<"Checking with "; F->write(cout)<<endl;

		ok = ok && check_minpoly(*F, n, G);

		if(!ok)
			cout<<"FAILED"<<endl;
		else
			cout<<"PASS"<<endl;

		delete F;
		nbiter--;
	}

	return ok;
}

int main(int argc, char** argv)
{
    /* Test parameters */
	Givaro::Integer q = -1;
	size_t b = 0;
    size_t n = 128;
	size_t iters = 1;
	bool loop = false;
    uint64_t seed = time(NULL);

	Argument as[] = {
		{ 'q', "-q Q", "Set the field characteristic (-1 for random).",	TYPE_INTEGER, &q },
		{ 'b', "-b B", "Set the bitsize of the field characteristic.", TYPE_INT, &b },
		{ 'n', "-n N", "Set the order of the matrix.", TYPE_INT, &b },
		{ 'i', "-i, R", "set the number of repetitions.", TYPE_INT, &iters },
		{ 'l', "-loop Y/N", "run the test in an infinite loop.", TYPE_BOOL , &loop },
		{ 's', "-s seed", "set seed for the random generator.", TYPE_INT, &seed },
			END_OF_ARGUMENTS
		};

	FFLAS::parseArguments(argc, argv, as);

	bool ok = true;

	do
	{
		ok &= run_with_field<Modular<double>>(q,b,n,iters,seed);
		//more tests?
	} while(ok && loop);

	return !ok ;
}
<commit_msg>Debugged minP(A)V = 0 check<commit_after>/* -*- mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
// vim:sts=4:sw=4:ts=4:noet:sr:cino=>s,f0,{0,g0,(0,\:0,t0,+0,=s

/*
 * Copyright (C) FFLAS-FFPACK
 * Written by David Lucas
 * This file is Free Software and part of FFLAS-FFPACK.
 *
 * ========LICENCE========
 * This file is part of the library FFLAS-FFPACK.
 *
 * FFLAS-FFPACK 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
 * ========LICENCE========
 *.
 */

//--------------------------------------------------------------------------
//                        Test for minpoly
//
//--------------------------------------------------------------------------
// David Lucas
//-------------------------------------------------------------------------

#include <iomanip>
#include <iostream>

#include "fflas-ffpack/fflas-ffpack-config.h"
#include "fflas-ffpack/fflas/fflas.h"
#include "fflas-ffpack/ffpack/ffpack.h"
#include "fflas-ffpack/utils/args-parser.h"
#include "fflas-ffpack/utils/fflas_randommatrix.h"
#include "test-utils.h"
#include <givaro/modular.h>
#include <givaro/modular-balanced.h>
#include <givaro/modular-integer.h>
#include <givaro/givpoly1factor.h>

using namespace std;
using namespace FFPACK;
using Givaro::Modular;
using Givaro::ModularBalanced;

typedef Givaro::ModularBalanced<double> Field;
typedef vector<Field::Element> Polynomial;

template<typename Field, class RandIter>
bool check_minpoly(const Field &F, size_t n, RandIter& G)
{
	cout<<"Entering check_minpoly"<<endl;
	typedef typename Field::Element Element;
	size_t lda, ldv;
	Element *A, *V, *Vcst;

	//Default
	lda = n;
	ldv = n;

	/*Create variables used for testing (matrices, vectors and polynomials) */

    A = FFLAS::fflas_new(F, n, n);
    V = FFLAS::fflas_new(F, n+1, n);
	Vcst = FFLAS::fflas_new(F, 1, n);
    Polynomial minP;

    FFPACK::RandomMatrix (F, n, n, A, lda, G);

	FFPACK::NonZeroRandomMatrix(F, 1, n, V, n, G);
	FFLAS::fassign(F, n, V, 1, Vcst, 1); //MatVecMinPoly modifies V, we store it in Vcst beforehand

	FFPACK::MatVecMinPoly(F, minP, n, A, lda, V, ldv);
	FFLAS::fflas_delete(V);

	/*Check that minP is monic*/

	size_t deg = minP.size() - 1;
	if(!(minP[deg]==F.one))
		return false;

	/*Check that minP(A).V is zero*/

	Element *E, *E_tmp;
    E = FFLAS::fflas_new(F, 1, n);
	E_tmp = FFLAS::fflas_new(F, 1, n);

    /* Horner's method for polynomial evaluation */

	FFLAS::fassign(F, n, Vcst, 1, E, 1); //E <- V

    for(long i = deg; i > 0; --i)
    {
		FFLAS::fassign(F, n, E, 1, E_tmp, 1); //E_tmp <- E
		FFLAS::fgemv(F, FFLAS::FflasNoTrans, n, n, F.one, A, lda, E_tmp, 1, F.zero, E, 1);//E <- A * E_tmp
		FFLAS::faxpy(F, 1, n, minP[i-1], Vcst, 1, E, 1); //E <- minP[i-1] * V + E
    }
	FFLAS::fflas_delete(E_tmp);

	/* Check minimality of minP */

	//cout<<V[0]<<" "<<V[1]<<" "<<V[2]<<" "<<V[n-1]<<endl;
	// Krylov matrix computation
	//Element *K, *u;
	//size_t ldk = n;
	//K = FFLAS::fflas_new(F, deg+1, ldk);
	//u = FFLAS::fflas_new(F, n, 1);
	//Element *Kptr = K;
	//FFLAS::fassign(F, n, K, 1, V, n);
	//cout<<V[0]<<" "<<K[0]<<" "<<endl;
	//cout<<V[1]<<" "<<K[1]<<" "<<endl;
	//cout<<V[2]<<" "<<K[2]<<" "<<endl;
	//cout<<V[n]<<" "<<K[n]<<" "<<endl;
	//cout<<V[n+1]<<" "<<K[n+1]<<" "<<endl;

	//for(size_t i = 0; i <= deg; ++i, Kptr += ldk)
	//{
	//	FFLAS::fgemv(F, FFLAS::FflasNoTrans, n, n, F.one, A, lda, u, 1, F.zero, Kptr, 1);
	//	FFLAS::fassign(F, n, Kptr, 1, u, 1);
	//}

	//minP factorization

	//factorized minP checks

	FFLAS::fflas_delete(A);
	FFLAS::fflas_delete(Vcst);
	//FFLAS::fflas_delete(K);
	//FFLAS::fflas_delete(u);

    if (!FFLAS::fiszero(F, n, E, 1))
	{
		cout<<"NONZEROERROR"<<endl;
		FFLAS::fflas_delete(E);
		return false;
	}

	FFLAS::fflas_delete(E);
	return true;
}

template <class Field>
bool run_with_field (Givaro::Integer q, size_t b, size_t n, size_t iters, uint64_t seed)
{
	bool ok = true;
	int nbiter = iters;

	while (ok && nbiter)
	{
		Field* F = chooseField<Field>(q, b); // F, characteristic q of b bits
		typename Field::RandIter G(*F, 0, seed); //random generator over F

		if(F == nullptr)
			return true; //if F is null, nothing to test, just pass

		cout<<"Checking with "; F->write(cout)<<endl;

		ok = ok && check_minpoly(*F, n, G);

		if(!ok)
			cout<<"FAILED"<<endl;
		else
			cout<<"PASS"<<endl;

		delete F;
		nbiter--;
	}

	return ok;
}

int main(int argc, char** argv)
{
    /* Test parameters */
	Givaro::Integer q = -1;
	size_t b = 0;
    size_t n = 128;
	size_t iters = 1;
	bool loop = false;
    uint64_t seed = time(NULL);

	Argument as[] = {
		{ 'q', "-q Q", "Set the field characteristic (-1 for random).",	TYPE_INTEGER, &q },
		{ 'b', "-b B", "Set the bitsize of the field characteristic.", TYPE_INT, &b },
		{ 'n', "-n N", "Set the order of the matrix.", TYPE_INT, &b },
		{ 'i', "-i, R", "set the number of repetitions.", TYPE_INT, &iters },
		{ 'l', "-loop Y/N", "run the test in an infinite loop.", TYPE_BOOL , &loop },
		{ 's', "-s seed", "set seed for the random generator.", TYPE_INT, &seed },
			END_OF_ARGUMENTS
		};

	FFLAS::parseArguments(argc, argv, as);

	bool ok = true;

	do
	{
		ok &= run_with_field<Modular<double>>(q,b,n,iters,seed);
		//more tests?
	} while(ok && loop);

	return !ok ;
}
<|endoftext|>


<commit_before>#if !defined(__CINT__) || defined(__MAKECINT__)
#include <TFile.h>
#include <TH1F.h>
#include <TGraph.h>
#include <TGraphErrors.h>
#include <TStyle.h>
#include <TGrid.h>
#include <TCanvas.h>
#include <TSystem.h>
#include <TLatex.h>
#include <TObjArray.h>
#include "AliCDBEntry.h"
#include "AliITSCalibrationSDD.h"
#endif

/*  $Id$    */

// Macro to plot the calibration parameters from the OCDB files
// created from PEDESTAL and PULSER runs vs. Time
// Origin: F. Prino (prino@to.infn.it)

void PlotCalibSDDVsTime(Int_t firstRun=77677, Int_t lastRun=999999999){

  gStyle->SetOptTitle(0);
  gStyle->SetOptStat(0);
  gStyle->SetPadLeftMargin(0.14);
  gStyle->SetTitleOffset(1.4,"Y");

  TGrid::Connect("alien:",0,0,"t");
  gSystem->Exec("gbbox find \"/alice/data/2009/OCDB/ITS/Calib/CalibSDD\" \"Run*.root\" > runCalibAlien.txt");
  FILE* listruns=fopen("runCalibAlien.txt","r");

  TH1F* hbase=new TH1F("hbase","",60,0.5,120.5);
  TH1F* hnoise=new TH1F("hnoise","",100,0.,7.);
  TH1F* hgain=new TH1F("hgain","",100,0.,4.);
  TH1F* hchstatus=new TH1F("hchstatus","",2,-0.5,1.5);
  TGraphErrors* gbasevstim=new TGraphErrors(0);
  TGraphErrors* gnoisevstim=new TGraphErrors(0);
  TGraphErrors* ggainvstim=new TGraphErrors(0);
  TGraphErrors* gstatvstim=new TGraphErrors(0);
  gbasevstim->SetName("gbasevstim");
  gnoisevstim->SetName("gnoisevstim");
  ggainvstim->SetName("ggainvstim");
  gstatvstim->SetName("gstatvstim");
  gbasevstim->SetTitle("Baseline vs. run");
  gnoisevstim->SetTitle("Noise vs. run");
  ggainvstim->SetTitle("Gain vs. run");
  gstatvstim->SetTitle("Good Anodes vs. run");

  Char_t filnam[200],filnamalien[200];
  Int_t iPoint=0;
  Int_t nrun,nrun2,nv,ns;

  while(!feof(listruns)){
    hbase->Reset();
    hnoise->Reset();
    hgain->Reset();
    hchstatus->Reset();
    fscanf(listruns,"%s\n",filnam);
    if(!strstr(filnam,"/alice/data/2009")) continue;
    sscanf(filnam,"/alice/data/2009/OCDB/ITS/Calib/CalibSDD/Run%d_%d_v%d_s%d.root",&nrun,&nrun2,&nv,&ns);
    if(nrun<85639 && nrun2> 85639) continue; // protection for files with swapped ladders 4-5 of layer 3
    if(nrun>100000 && nv< 184) continue; // protection for files with swapped ladder 0-1 of layer 4
    if(nrun<firstRun) continue;
    if(nrun>lastRun) continue;
    sprintf(filnamalien,"alien://%s",filnam);
    printf("Open file: %s\n",filnam);
    TFile *f= TFile::Open(filnamalien);
    AliCDBEntry *ent=(AliCDBEntry*)f->Get("AliCDBEntry");
    TObjArray *calSDD = (TObjArray *)ent->GetObject();
    printf("Run %d Entries in array=%d Entries in Histo=%d\n",nrun,calSDD->GetEntriesFast(),int(hbase->GetEntries()));

    AliITSCalibrationSDD *cal;
    for(Int_t iMod=0; iMod<260;iMod++){
      cal=(AliITSCalibrationSDD*)calSDD->At(iMod);
      if(cal==0) continue;
      for(Int_t iAn=0; iAn<512; iAn++){
	Int_t ic=cal->GetChip(iAn);
	Float_t base=cal->GetBaseline(iAn);
	Float_t noise=cal->GetNoiseAfterElectronics(iAn);
	Float_t gain=cal->GetChannelGain(iAn);
	if(cal->IsBadChannel(iAn)) hchstatus->Fill(0);
	if(!cal->IsBadChannel(iAn) && !cal->IsChipBad(ic) && !cal->IsBad() ){
	  hbase->Fill(base);
	  hchstatus->Fill(1);
	  hnoise->Fill(noise);
	  hgain->Fill(gain);
	}
      }
    }
    printf("Set Point %d run %d Base = %f Noise =%f Entries = %d\n",iPoint,nrun,hbase->GetMean(),hnoise->GetMean(),(Int_t)hbase->GetEntries());
    if((Int_t)hbase->GetEntries()==0) continue;
    gbasevstim->SetPoint(iPoint,(Double_t)nrun,hbase->GetMean());
    gbasevstim->SetPointError(iPoint,0.,hbase->GetRMS());
    gnoisevstim->SetPoint(iPoint,(Double_t)nrun,hnoise->GetMean());
    gnoisevstim->SetPointError(iPoint,0.,hnoise->GetRMS());
    ggainvstim->SetPoint(iPoint,(Double_t)nrun,hgain->GetMean());
    ggainvstim->SetPointError(iPoint,0.,hgain->GetRMS());
    gstatvstim->SetPoint(iPoint,(Double_t)nrun,hchstatus->GetBinContent(2));
    iPoint++;
    f->Close();
  }

  TFile *ofil=new TFile("Calib2009VsTime.root","recreate");
  gbasevstim->Write();
  gnoisevstim->Write();
  ggainvstim->Write();
  gstatvstim->Write();
  ofil->Close();

  TCanvas* cbase=new TCanvas("cbase","Baselines");
  gbasevstim->SetFillColor(kOrange-2);
  gbasevstim->SetMarkerStyle(20);
  gbasevstim->Draw("AP3");
  gbasevstim->Draw("PLXSAME");
  gbasevstim->SetMinimum(0.);
  gbasevstim->SetMaximum(70.);
  gbasevstim->GetXaxis()->SetTitle("Run number");
  gbasevstim->GetYaxis()->SetTitle("<Baseline> (ADC counts)");
  cbase->SaveAs("BaseRun09.gif");

  TCanvas* cnoise=new TCanvas("cnoise","Noise");
  gnoisevstim->SetFillColor(kOrange-2);
  gnoisevstim->SetMarkerStyle(20);
  gnoisevstim->Draw("AP3");
  gnoisevstim->Draw("PLXSAME");
  gnoisevstim->SetMinimum(0.);
  gnoisevstim->SetMaximum(4.);
  gnoisevstim->GetXaxis()->SetTitle("Run number");
  gnoisevstim->GetYaxis()->SetTitle("<Noise> (ADC counts)");
  cnoise->SaveAs("NoiseRun09.gif");

  TCanvas* cgain=new TCanvas("cgain","Gain");
  ggainvstim->SetFillColor(kOrange-2);
  ggainvstim->SetMarkerStyle(20);
  ggainvstim->Draw("AP3");
  ggainvstim->Draw("PLXSAME");
  ggainvstim->SetMinimum(0.);
  ggainvstim->SetMaximum(4.);
  ggainvstim->GetXaxis()->SetTitle("Run number");
  ggainvstim->GetYaxis()->SetTitle("<Gain> (ADC/DAC)");
  cgain->SaveAs("GainRun09.gif");

  TCanvas* cfrac=new TCanvas("cfrac","Good channels");
  gstatvstim->SetFillColor(kOrange-2);
  gstatvstim->SetMarkerStyle(20);
  gstatvstim->Draw("AP3");
  gstatvstim->Draw("PLXSAME");
  gstatvstim->SetMinimum(100000.);
  gstatvstim->SetMaximum(133000.);
  gstatvstim->GetXaxis()->SetTitle("Run number");
  gstatvstim->GetYaxis()->SetTitle("Number of good anodes in acquisition");
  cfrac->SaveAs("GoodAnodesRun09.gif");

}
<commit_msg>Macro to visualize SDD calibration parameters updated for 2010 runs<commit_after>#if !defined(__CINT__) || defined(__MAKECINT__)
#include <TFile.h>
#include <TH1F.h>
#include <TGraph.h>
#include <TGraphErrors.h>
#include <TStyle.h>
#include <TGrid.h>
#include <TCanvas.h>
#include <TSystem.h>
#include <TLatex.h>
#include <TObjArray.h>
#include "AliCDBEntry.h"
#include "AliITSCalibrationSDD.h"
#endif

/*  $Id$    */

// Macro to plot the calibration parameters from the OCDB files
// created from PEDESTAL and PULSER runs vs. Time
// Origin: F. Prino (prino@to.infn.it)

void PlotCalibSDDVsTime(Int_t year=2010, Int_t firstRun=77677,
			Int_t lastRun=999999999){

  gStyle->SetOptTitle(0);
  gStyle->SetOptStat(0);
  gStyle->SetPadLeftMargin(0.14);
  gStyle->SetTitleOffset(1.4,"Y");

  TGrid::Connect("alien:",0,0,"t");
  gSystem->Exec(Form("gbbox find \"/alice/data/%d/OCDB/ITS/Calib/CalibSDD\" \"Run*.root\" > runCalibAlien.txt",year));
  FILE* listruns=fopen("runCalibAlien.txt","r");

  TH1F* hbase=new TH1F("hbase","",60,0.5,120.5);
  TH1F* hnoise=new TH1F("hnoise","",100,0.,7.);
  TH1F* hgain=new TH1F("hgain","",100,0.,4.);
  TH1F* hchstatus=new TH1F("hchstatus","",2,-0.5,1.5);
  TGraphErrors* gbasevstim=new TGraphErrors(0);
  TGraphErrors* gnoisevstim=new TGraphErrors(0);
  TGraphErrors* ggainvstim=new TGraphErrors(0);
  TGraphErrors* gstatvstim=new TGraphErrors(0);
  gbasevstim->SetName("gbasevstim");
  gnoisevstim->SetName("gnoisevstim");
  ggainvstim->SetName("ggainvstim");
  gstatvstim->SetName("gstatvstim");
  gbasevstim->SetTitle("Baseline vs. run");
  gnoisevstim->SetTitle("Noise vs. run");
  ggainvstim->SetTitle("Gain vs. run");
  gstatvstim->SetTitle("Good Anodes vs. run");

  Char_t filnam[200],filnamalien[200];
  Int_t iPoint=0;
  Int_t nrun,nrun2,nv,ns;

  while(!feof(listruns)){
    hbase->Reset();
    hnoise->Reset();
    hgain->Reset();
    hchstatus->Reset();
    fscanf(listruns,"%s\n",filnam);
    Char_t directory[100];
    sprintf(directory,"/alice/data/%d",year);
    if(!strstr(filnam,directory)) continue;
    sscanf(filnam,"/alice/data/%d/OCDB/ITS/Calib/CalibSDD/Run%d_%d_v%d_s%d.root",&year,&nrun,&nrun2,&nv,&ns);
    if(year==2009 && (nrun<85639 && nrun2> 85639)) continue; // protection for files with swapped ladders 4-5 of layer 3
    if(year==2009 && (nrun>100000 && nv< 184)) continue; // protection for files with swapped ladder 0-1 of layer 4
    if(nrun<firstRun) continue;
    if(nrun>lastRun) continue;
    sprintf(filnamalien,"alien://%s",filnam);
    printf("Open file: %s\n",filnam);
    TFile *f= TFile::Open(filnamalien);
    AliCDBEntry *ent=(AliCDBEntry*)f->Get("AliCDBEntry");
    TObjArray *calSDD = (TObjArray *)ent->GetObject();
    printf("Run %d Entries in array=%d \n",nrun,calSDD->GetEntriesFast());

    AliITSCalibrationSDD *cal;
    for(Int_t iMod=0; iMod<260;iMod++){
      cal=(AliITSCalibrationSDD*)calSDD->At(iMod);
      if(cal==0) continue;
      for(Int_t iAn=0; iAn<512; iAn++){
	Int_t ic=cal->GetChip(iAn);
	Float_t base=cal->GetBaseline(iAn);
	Float_t noise=cal->GetNoiseAfterElectronics(iAn);
	Float_t gain=cal->GetChannelGain(iAn);
	if(cal->IsBadChannel(iAn)) hchstatus->Fill(0);
	if(!cal->IsBadChannel(iAn) && !cal->IsChipBad(ic) && !cal->IsBad() ){
	  hbase->Fill(base);
	  hchstatus->Fill(1);
	  hnoise->Fill(noise);
	  hgain->Fill(gain);
	}
      }
    }
    printf("Run %d <Base> = %f <Noise> =%f Entries = %d\n",nrun,hbase->GetMean(),hnoise->GetMean(),(Int_t)hbase->GetEntries());
    if((Int_t)hbase->GetEntries()==0) continue;
    gbasevstim->SetPoint(iPoint,(Double_t)nrun,hbase->GetMean());
    gbasevstim->SetPointError(iPoint,0.,hbase->GetRMS());
    gnoisevstim->SetPoint(iPoint,(Double_t)nrun,hnoise->GetMean());
    gnoisevstim->SetPointError(iPoint,0.,hnoise->GetRMS());
    ggainvstim->SetPoint(iPoint,(Double_t)nrun,hgain->GetMean());
    ggainvstim->SetPointError(iPoint,0.,hgain->GetRMS());
    gstatvstim->SetPoint(iPoint,(Double_t)nrun,hchstatus->GetBinContent(2));
    iPoint++;
    f->Close();
  }

  TFile *ofil=new TFile(Form("Calib%dVsTime.root",year),"recreate");
  gbasevstim->Write();
  gnoisevstim->Write();
  ggainvstim->Write();
  gstatvstim->Write();
  ofil->Close();

  TCanvas* cbase=new TCanvas("cbase","Baselines");
  gbasevstim->SetFillColor(kOrange-2);
  gbasevstim->SetMarkerStyle(20);
  gbasevstim->Draw("AP3");
  gbasevstim->Draw("PLXSAME");
  gbasevstim->SetMinimum(0.);
  gbasevstim->SetMaximum(70.);
  gbasevstim->GetXaxis()->SetTitle("Run number");
  gbasevstim->GetYaxis()->SetTitle("<Baseline> (ADC counts)");
  cbase->SaveAs("BaseRun09.gif");

  TCanvas* cnoise=new TCanvas("cnoise","Noise");
  gnoisevstim->SetFillColor(kOrange-2);
  gnoisevstim->SetMarkerStyle(20);
  gnoisevstim->Draw("AP3");
  gnoisevstim->Draw("PLXSAME");
  gnoisevstim->SetMinimum(0.);
  gnoisevstim->SetMaximum(4.);
  gnoisevstim->GetXaxis()->SetTitle("Run number");
  gnoisevstim->GetYaxis()->SetTitle("<Noise> (ADC counts)");
  cnoise->SaveAs("NoiseRun09.gif");

  TCanvas* cgain=new TCanvas("cgain","Gain");
  ggainvstim->SetFillColor(kOrange-2);
  ggainvstim->SetMarkerStyle(20);
  ggainvstim->Draw("AP3");
  ggainvstim->Draw("PLXSAME");
  ggainvstim->SetMinimum(0.);
  ggainvstim->SetMaximum(4.);
  ggainvstim->GetXaxis()->SetTitle("Run number");
  ggainvstim->GetYaxis()->SetTitle("<Gain> (ADC/DAC)");
  cgain->SaveAs("GainRun09.gif");

  TCanvas* cfrac=new TCanvas("cfrac","Good channels");
  gstatvstim->SetFillColor(kOrange-2);
  gstatvstim->SetMarkerStyle(20);
  gstatvstim->Draw("AP3");
  gstatvstim->Draw("PLXSAME");
  gstatvstim->SetMinimum(100000.);
  gstatvstim->SetMaximum(133000.);
  gstatvstim->GetXaxis()->SetTitle("Run number");
  gstatvstim->GetYaxis()->SetTitle("Number of good anodes in acquisition");
  cfrac->SaveAs("GoodAnodesRun09.gif");

}
<|endoftext|>