<commit_before>//=============================================================================================================
/**
* @file     main.cpp
* @author   Ruben Dörfel <ruben.doerfel@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     12, 2019
*
* @section  LICENSE
*
* Copyright (C) 2019, Ruben Dörfel and Matti Hamalainen. 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 the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* 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 COPYRIGHT OWNER 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.
*
*
* @brief     test for filterData function that calls rtproceesing and utils library.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <iostream>
#include <vector>
#include <math.h>

#include <fiff/fiff.h>
#include <utils/filterTools/filterdata.h>
#include <rtprocessing/rtfilter.h>

#include <utils/ioutils.h>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtCore/QCoreApplication>
#include <QFile>
#include <QCommandLineParser>
#include <QtTest>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FIFFLIB;
using namespace UTILSLIB;
using namespace RTPROCESSINGLIB;

//=============================================================================================================
/**
* DECLARE CLASS TestFiffRFR
*
* @brief The TestFiffRFR class provides read filter read fiff verification tests
*
*/
class TestFiffRFR: public QObject
{
    Q_OBJECT

public:
    TestFiffRFR();

private slots:
    void initTestCase();
    void compareData();
    void compareTimes();
    void compareInfo();
    void cleanupTestCase();

private:
    double epsilon;

    FiffRawData first_in_raw;

    MatrixXd first_in_data;
    MatrixXd first_in_times;
    MatrixXd dataFiltered;
    MatrixXd refDataFiltered;

    FiffRawData ref_in_raw;

    MatrixXd ref_in_data;
    MatrixXd ref_in_times;
};

//*************************************************************************************************************

TestFiffRFR::TestFiffRFR()
: epsilon(0.000001)
{
}

//*************************************************************************************************************

void TestFiffRFR::initTestCase()
{
    qDebug() << "Epsilon" << epsilon;

    QFile t_fileIn(QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/MEG/sample/sample_audvis_short_raw.fif");
    QFile t_fileRef(QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/MEG/sample/ref_rtfilter_filterdata_raw.fif");
    QFile t_fileOut(QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/MEG/sample/sample_audvis_raw_short_test_rwr_out.fif");

    //
    //   Make sure test folder exists
    //

    QFileInfo t_fileOutInfo(t_fileOut);
    QDir().mkdir(t_fileOutInfo.path());

    //*********************************************************************************************************
    // First Read, Filter & Write
    //*********************************************************************************************************

    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Read, Filter & Write >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    //
    //   Setup for reading the raw data
    //
    first_in_raw = FiffRawData(t_fileIn);

    //
    //   Set up pick list: MEG + STI 014 - bad channels
    //
    //
    bool want_meg   = true;
    bool want_eeg   = false;
    bool want_stim  = false;
    QStringList include;
    include << "STI 014";

    MatrixXi picks = first_in_raw.info.pick_types(want_meg, want_eeg, want_stim, include, first_in_raw.info.bads); // prefer member function
    if(picks.cols() == 0)
    {
        include.clear();
        include << "STI101" << "STI201" << "STI301";
        picks = first_in_raw.info.pick_types(want_meg, want_eeg, want_stim, include, first_in_raw.info.bads);// prefer member function
        if(picks.cols() == 0)
        {
            printf("channel list may need modification\n");
        }
    }
    //
    RowVectorXd cals;

    FiffStream::SPtr outfid = FiffStream::start_writing_raw(t_fileOut,first_in_raw.info, cals/*, picks*/);

    //
    //   Set up the reading parameters
    //   To read the whole file at once set
    //

    fiff_int_t from = first_in_raw.first_samp;
    fiff_int_t to = first_in_raw.last_samp;
    fiff_int_t quantum = to-from+1;
    RtFilter rtFilter;                                                      // filter object
    MatrixXd dataFiltered;                                                  // filter output

    // channel selection - in this case use every channel
    // size = number of channels; value = index channel number
    QVector<int> channelList(first_in_raw.info.nchan);
    for (int i = 0; i < first_in_raw.info.nchan; i++){
        channelList[i] = i;
    }

    // initialize filter settings
    QString filter_name =  "example_cosine";
    FilterData::FilterType type = FilterData::BPF;
    double sFreq = first_in_raw.info.sfreq;                                          // get Sample freq from Data
    double centerfreq = 10/(sFreq/2.0);                                     // normed nyquist freq.
    double bandwidth = 10/(sFreq/2.0);
    double parkswidth = 1/(sFreq/2.0);

    //
    //
    //   Read and write all the data
    //
    bool first_buffer = true;

    fiff_int_t first, last;
    MatrixXd data;
    MatrixXd times;

    for(first = from; first < to; first+=quantum)
    {
        last = first+quantum-1;
        if (last > to)
        {
            last = to;
        }

        if (!first_in_raw.read_raw_segment(first_in_data,first_in_times,first,last/*,picks*/))
        {
                printf("error during read_raw_segment\n");
        }

        //Filtering
        printf("Filtering...");
        dataFiltered = rtFilter.filterData(data,type,centerfreq,bandwidth,parkswidth,sFreq,channelList);
        printf("[done]\n");

        printf("Writing...");
        if (first_buffer)
        {
           if (first > 0)
               outfid->write_int(FIFF_FIRST_SAMPLE,&first);
           first_buffer = false;
        }
        outfid->write_raw_buffer(dataFiltered,cals);
        printf("[done]\n");
    }

    outfid->finish_writing_raw();

    printf("<<<<<<<<<<<<<<<<<<<<<<<<< Read, Filter & Write Finished <<<<<<<<<<<<<<<<<<<<<<<<<\n");

    //*********************************************************************************************************
    // Read MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Read MNE-PYTHON Results As Reference >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    ref_in_raw = FiffRawData(t_fileRef);

    //
    //   Set up pick list: MEG + STI 014 - bad channels
    //
    //

    picks = ref_in_raw.info.pick_types(want_meg, want_eeg, want_stim, include, ref_in_raw.info.bads); // prefer member function
    if(picks.cols() == 0)
    {
        include.clear();
        include << "STI101" << "STI201" << "STI301";
        picks = ref_in_raw.info.pick_types(want_meg, want_eeg, want_stim, include, ref_in_raw.info.bads);// prefer member function
        if(picks.cols() == 0)
        {
            printf("channel list may need modification\n");
        }
    }

    for(first = from; first < to; first+=quantum)
    {
        last = first+quantum-1;
        if (last > to)
        {
            last = to;
        }

        if (!ref_in_raw.read_raw_segment(ref_in_data,ref_in_times,first,last/*,picks*/))
        {
                printf("error during read_raw_segment\n");
        }
    }

    printf("<<<<<<<<<<<<<<<<<<<<<<<<< Read MNE-PYTHON Results Finished <<<<<<<<<<<<<<<<<<<<<<<<<\n");
}

//*************************************************************************************************************

void TestFiffRFR::compareData()
{
    MatrixXd data_diff = first_in_data - ref_in_data;
//    std::cout << "\tCompare data:\n";
//    std::cout << "\tFirst data\n" << first_in_data.block(0,0,4,4) << "\n";
//    std::cout << "\tSecond data\n" << second_in_data.block(0,0,4,4) << "\n";

    QVERIFY( data_diff.sum() < epsilon );
}

//*************************************************************************************************************

void TestFiffRFR::compareTimes()
{
    MatrixXd times_diff = first_in_times - ref_in_times;
//    std::cout << "\tCompare Times:\n";
//    std::cout << "\tFirst times\n" << first_in_times.block(0,0,1,4) << "\n";
//    std::cout << "\tSecond times\n" << second_in_times.block(0,0,1,4) << "\n";

    QVERIFY( times_diff.sum() < epsilon );
}

//*************************************************************************************************************

void TestFiffRFR::compareInfo()
{
    //Sampling frequency
    std::cout << "[1] Sampling Frequency Check\n";
    QVERIFY( first_in_raw.info.sfreq == ref_in_raw.info.sfreq );

    //Projection
    std::cout << "[2] Projection Check\n";
    QVERIFY( first_in_raw.info.projs.size() == ref_in_raw.info.projs.size() );

    for( qint32 i = 0; i < first_in_raw.info.projs.size(); ++i )
    {
        std::cout << "Projector " << i << std::endl;
        MatrixXd tmp = first_in_raw.info.projs[i].data->data - ref_in_raw.info.projs[i].data->data;
        QVERIFY( tmp.sum() < epsilon );
    }

    //Compensators
    std::cout << "[3] Compensator Check\n";
    QVERIFY( first_in_raw.info.comps.size() == ref_in_raw.info.comps.size() );

    for( qint32 i = 0; i < first_in_raw.info.comps.size(); ++i )
    {
        std::cout << "Compensator " << i << std::endl;
        MatrixXd tmp = first_in_raw.info.comps[i].data->data - ref_in_raw.info.comps[i].data->data;
        QVERIFY( tmp.sum() < epsilon );
    }
}

//*************************************************************************************************************

void TestFiffRFR::cleanupTestCase()
{
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_GUILESS_MAIN(TestFiffRFR)
#include "test_rtfilter_filterdata.moc"
<commit_msg>test_rtfilter: working test; open: still have to get short file working<commit_after>//=============================================================================================================
/**
* @file     main.cpp
* @author   Ruben Dörfel <ruben.doerfel@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     12, 2019
*
* @section  LICENSE
*
* Copyright (C) 2019, Ruben Dörfel and Matti Hamalainen. 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 the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* 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 COPYRIGHT OWNER 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.
*
*
* @brief     test for filterData function that calls rtproceesing and utils library.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <iostream>
#include <vector>
#include <math.h>

#include <fiff/fiff.h>
#include <utils/filterTools/filterdata.h>
#include <rtprocessing/rtfilter.h>

#include <utils/ioutils.h>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtCore/QCoreApplication>
#include <QFile>
#include <QCommandLineParser>
#include <QtTest>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FIFFLIB;
using namespace UTILSLIB;
using namespace RTPROCESSINGLIB;

//=============================================================================================================
/**
* DECLARE CLASS TestFiffRFR
*
* @brief The TestFiffRFR class provides read filter read fiff verification tests
*
*/
class TestFiffRFR: public QObject
{
    Q_OBJECT

public:
    TestFiffRFR();

private slots:
    void initTestCase();
    void compareData();
    void compareTimes();
    void compareInfo();
    void cleanupTestCase();

private:
    double epsilon;

    FiffRawData first_in_raw;

    MatrixXd first_in_data;
    MatrixXd first_in_times;
    MatrixXd first_filtered;

    FiffRawData ref_in_raw;

    MatrixXd ref_in_data;
    MatrixXd ref_in_times;
    MatrixXd ref_filtered;
};

//*************************************************************************************************************

TestFiffRFR::TestFiffRFR()
: epsilon(0.000001)
{
}

//*************************************************************************************************************

void TestFiffRFR::initTestCase()
{
    qDebug() << "Epsilon" << epsilon;

    QFile t_fileIn(QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/MEG/sample/sample_audvis_raw_short.fif");
    QFile t_fileRef(QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/MEG/sample/ref_rtfilter_filterdata_raw.fif");      //Einlesen mne-cpp, schreiben mne-python
    QFile t_fileOut(QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/MEG/sample/rtfilter_filterdata_out_raw.fif");      //schreiben mne-cpp, einlesen mne-python

    //
    //   Make sure test folder exists
    //

    QFileInfo t_fileOutInfo(t_fileOut);
    QDir().mkdir(t_fileOutInfo.path());

    //*********************************************************************************************************
    // First Read, Filter & Write
    //*********************************************************************************************************

    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Read, Filter & Write >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    //
    //   Setup for reading the raw data
    //
    first_in_raw = FiffRawData(t_fileIn);

    //
    //   Set up pick list: MEG + STI 014 - bad channels
    //

    bool want_meg   = true;
    bool want_eeg   = false;
    bool want_stim  = false;
    QStringList include;
    include << "STI 014";

    MatrixXi picks = first_in_raw.info.pick_types(want_meg, want_eeg, want_stim, include, first_in_raw.info.bads); // prefer member function
    if(picks.cols() == 0)
    {
        include.clear();
        include << "STI101" << "STI201" << "STI301";
        picks = first_in_raw.info.pick_types(want_meg, want_eeg, want_stim, include, first_in_raw.info.bads);// prefer member function
        if(picks.cols() == 0)
        {
            printf("channel list may need modification\n");
        }
    }
    //
    RowVectorXd cals;

    FiffStream::SPtr outfid = FiffStream::start_writing_raw(t_fileOut,first_in_raw.info, cals/*, picks*/);

    //
    //   Set up the reading parameters
    //   To read the whole file at once set
    //

    fiff_int_t from = first_in_raw.first_samp;
    fiff_int_t to = first_in_raw.last_samp;
    fiff_int_t quantum = to-from+1;
    RtFilter rtFilter;                                                      // filter object

    // channel selection - in this case use every channel
    // size = number of channels; value = index channel number
    QVector<int> channelList(first_in_raw.info.nchan);
    for (int i = 0; i < first_in_raw.info.nchan; i++){
        channelList[i] = i;
    }

    // initialize filter settings
    QString filter_name = "example_cosine";
    FilterData::FilterType type = FilterData::BPF;
    double sFreq = first_in_raw.info.sfreq;                                 // get Sample freq from Data
    double centerfreq = 10/(sFreq/2.0);                                     // normed to nyquist freq.
    double bandwidth = 10/(sFreq/2.0);
    double parkswidth = 1/(sFreq/2.0);
    int order = 8192;
    int fftlength = 16384;
    //
    //   Read and write all the data
    //
    bool first_buffer = true;

    fiff_int_t first, last;

    for(first = from; first < to; first+=quantum)
    {
        last = first+quantum-1;
        if (last > to)
        {
            last = to;
        }

        if (!first_in_raw.read_raw_segment(first_in_data,first_in_times,first,last/*,picks*/))
        {
                printf("error during read_raw_segment\n");
        }

        //Filtering
        printf("Filtering...");
        first_filtered = rtFilter.filterData(first_in_data,type,centerfreq,bandwidth,parkswidth,sFreq,channelList,order, fftlength);
        printf("[done]\n");

        printf("Writing...");
        if (first_buffer)
        {
           if (first > 0)
               outfid->write_int(FIFF_FIRST_SAMPLE,&first);
           first_buffer = false;
        }
        outfid->write_raw_buffer(first_filtered,cals);
        printf("[done]\n");
    }

    outfid->finish_writing_raw();

    printf("<<<<<<<<<<<<<<<<<<<<<<<<< Read, Filter & Write Finished <<<<<<<<<<<<<<<<<<<<<<<<<\n");

    //*********************************************************************************************************
    // Read MNE-PYTHON Results As Reference
    //*********************************************************************************************************

    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Read MNE-PYTHON Results As Reference >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    ref_in_raw = FiffRawData(t_fileRef);

    //
    //   Set up pick list: MEG + STI 014 - bad channels
    //
    //

    picks = ref_in_raw.info.pick_types(want_meg, want_eeg, want_stim, include, ref_in_raw.info.bads); // prefer member function
    if(picks.cols() == 0)
    {
        include.clear();
        include << "STI101" << "STI201" << "STI301";
        picks = ref_in_raw.info.pick_types(want_meg, want_eeg, want_stim, include, ref_in_raw.info.bads);// prefer member function
        if(picks.cols() == 0)
        {
            printf("channel list may need modification\n");
        }
    }

    for(first = from; first < to; first+=quantum)
    {
        last = first+quantum-1;
        if (last > to)
        {
            last = to;
        }

        if (!ref_in_raw.read_raw_segment(ref_filtered,ref_in_times,first,last/*,picks*/))
        {
                printf("error during read_raw_segment\n");
        }
    }

//    QString refFileName(QCoreApplication::applicationDirPath() + "/MNE-sample-data/MEG/sample/ref_rtfilter_filterdata_raw.txt");
//    IOUtils::read_eigen_matrix(ref_filtered, refFileName);

    printf("<<<<<<<<<<<<<<<<<<<<<<<<< Read MNE-PYTHON Results Finished <<<<<<<<<<<<<<<<<<<<<<<<<\n");
}

//*************************************************************************************************************

void TestFiffRFR::compareData()
{
    MatrixXd data_diff = first_filtered - ref_filtered;
//    std::cout << "\tCompare data:\n";
//    std::cout << "\tFirst data\n" << first_in_data.block(0,0,4,4) << "\n";
//    std::cout << "\tSecond data\n" << second_in_data.block(0,0,4,4) << "\n";

    printf("diff: ..%f",data_diff.sum());
    QVERIFY( data_diff.sum() < epsilon );
}

//*************************************************************************************************************

void TestFiffRFR::compareTimes()
{
    MatrixXd times_diff = first_in_times - ref_in_times;
//    std::cout << "\tCompare Times:\n";
//    std::cout << "\tFirst times\n" << first_in_times.block(0,0,1,4) << "\n";
//    std::cout << "\tSecond times\n" << second_in_times.block(0,0,1,4) << "\n";

    QVERIFY( times_diff.sum() < epsilon );
}

//*************************************************************************************************************

void TestFiffRFR::compareInfo()
{
    //Sampling frequency
    std::cout << "[1] Sampling Frequency Check\n";
    QVERIFY( first_in_raw.info.sfreq == ref_in_raw.info.sfreq );

    //Projection
    std::cout << "[2] Projection Check\n";
    QVERIFY( first_in_raw.info.projs.size() == ref_in_raw.info.projs.size() );

    for( qint32 i = 0; i < first_in_raw.info.projs.size(); ++i )
    {
        std::cout << "Projector " << i << std::endl;
        MatrixXd tmp = first_in_raw.info.projs[i].data->data - ref_in_raw.info.projs[i].data->data;
        QVERIFY( tmp.sum() < epsilon );
    }

    //Compensators
    std::cout << "[3] Compensator Check\n";
    QVERIFY( first_in_raw.info.comps.size() == ref_in_raw.info.comps.size() );

    for( qint32 i = 0; i < first_in_raw.info.comps.size(); ++i )
    {
        std::cout << "Compensator " << i << std::endl;
        MatrixXd tmp = first_in_raw.info.comps[i].data->data - ref_in_raw.info.comps[i].data->data;
        QVERIFY( tmp.sum() < epsilon );
    }
}

//*************************************************************************************************************

void TestFiffRFR::cleanupTestCase()
{
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_GUILESS_MAIN(TestFiffRFR)
#include "test_rtfilter_filterdata.moc"
<|endoftext|>


<commit_before>/** feature-selection.cc ---
 *
 * Copyright (C) 2011 OpenCog Foundation
 *
 * Author: Nil Geisweiller
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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 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, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

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

#include <boost/assign/std/vector.hpp> // for 'operator+=()'
#include <boost/range/algorithm/find.hpp>
#include <boost/range/irange.hpp>

#include <opencog/util/Logger.h>

#include <opencog/comboreduct/table/table.h>
#include <opencog/comboreduct/table/table_io.h>
#include <opencog/learning/moses/optimization/hill-climbing.h> // for hc_params

#include "feature-selection.h"
#include "../algo/deme_optimize.h"
#include "../algo/incremental.h"
#include "../algo/random.h"
#include "../algo/simple.h"
#include "../algo/stochastic_max_dependency.h"

namespace opencog {

using namespace combo;
using namespace std;
using namespace boost::assign; // bring 'operator+=()' into scope

void err_empty_features(const string& outfile)
{
    // If the dataset is degenerate, it can happen that feature
    // selection will fail to find any features.  Rather than just
    // crashing as a result, write out an empty file, which at least
    // allows downstream processes to infer what happened (i.e. to tell
    // apart this case from an outright crash.)
    logger().warn() << "No features have been selected.";
    cerr << "No features have been selected." << endl;
    if (!outfile.empty()) {
        ofstream out(outfile.c_str());
        out << "# No features have been selected." << endl;
    }
    exit(0);
}

// Score all individual features of Table
vector<double> score_individual_features(const Table& table,
                                         const feature_selection_parameters& fs_params)
{
    typedef set<arity_t> FS;
    CTable ctable = table.compressed();
    fs_scorer<FS> fs_sc(ctable, fs_params);
    vector<double> res;
    boost::transform(boost::irange(0, table.get_arity()), back_inserter(res),
                     [&](arity_t idx) { FS fs = {idx}; return fs_sc(fs); });
    return res;
}

// log the set of features and its number
void log_selected_features(arity_t old_arity, const Table& ftable,
                           const feature_selection_parameters& fs_params)
{
    // log the number selected features
    logger().info("%d out of %d features have been selected",
                  ftable.get_arity(), old_arity);

    // log set of selected feature set
    const string_seq& labs = ftable.itable.get_labels();
    const vector<double>& sco = score_individual_features(ftable, fs_params);
    for (unsigned i=0; i<labs.size(); i++)
    {
        logger().info() << "log_selected_features(): " << labs[i] << " " << sco[i];
    }
}

/**
 * Get indices (aka positions or offsets) of a list of labels given a header
 */
vector<unsigned> get_indices(const vector<string>& labels,
                             const vector<string>& header)
{
    vector<unsigned> res;
    for (unsigned i = 0; i < header.size(); ++i)
        if (boost::find(labels, header[i]) != labels.end())
            res.push_back(i);
    return res;
}

unsigned get_index(const string& label, const vector<string>& header)
{
    return distance(header.begin(), boost::find(header, label));
}

void write_results(const Table& selected_table,
                   const feature_selection_parameters& fs_params)
{
    Table table_wff = selected_table;
    if (fs_params.output_file.empty())
        ostreamTable(cout, table_wff);
    else
        saveTable(fs_params.output_file, table_wff);
}

feature_set initial_features(const vector<string>& ilabels,
                             const feature_selection_parameters& fs_params)
{
    vector<string> vif; // valid initial features, used for logging
    feature_set res;

    for (const string& f : fs_params.initial_features) {
        size_t idx = distance(ilabels.begin(), boost::find(ilabels, f));
        if(idx < ilabels.size()) { // feature found
            res.insert(idx);
            // for logging
            vif += f;
        }
        else // feature not found
            logger().warn("No such a feature %s in file %s. It will be ignored as initial feature.", f.c_str(), fs_params.input_file.c_str());
    }
    // Logger
    if(vif.empty())
        logger().info("The search will start with the empty feature set");
    else {
        stringstream ss;
        ss << "The search will start with the following feature set: ";
        ostreamContainer(ss, vif, ",");
        logger().info(ss.str());
    }
    // ~Logger
    return res;
}

feature_set_pop select_feature_sets(const CTable& ctable,
                                    const feature_selection_parameters& fs_params)
{
    if (fs_params.algorithm == moses::hc) {
        // setting moses optimization parameters
        double pop_size_ratio = 20;
        size_t max_dist = 4;
        score_t min_score_improv = 0.0;
        optim_parameters op_params;
        op_params.opt_algo = moses::hc;
        op_params.pop_size_ratio = pop_size_ratio;
        op_params.terminate_if_gte = fs_params.hc_max_score;
        op_params.max_dist = max_dist;
        op_params.set_min_score_improv(min_score_improv);
        hc_parameters hc_params;
        hc_params.widen_search = fs_params.hc_widen_search;
        hc_params.single_step = false;
        hc_params.crossover = fs_params.hc_crossover;
        hc_params.crossover_pop_size = fs_params.hc_crossover_pop_size;
        hc_params.crossover_min_neighbors = fs_params.hc_crossover_min_neighbors;
        hc_params.prefix_stat_deme = "FSDemes";
        hill_climbing hc(op_params, hc_params);
        return moses_select_feature_sets(ctable, hc, fs_params);
    } else if (fs_params.algorithm == "inc") {
        return incremental_select_feature_sets(ctable, fs_params);
    } else if (fs_params.algorithm == "smd") {
        return smd_select_feature_sets(ctable, fs_params);
    } else if (fs_params.algorithm == "random") {
        return random_select_feature_sets(ctable, fs_params);
    } else if (fs_params.algorithm == "simple") {
        return simple_select_feature_sets(ctable, fs_params);
    } else {
        cerr << "Fatal Error: Algorithm '" << fs_params.algorithm
             << "' is unknown, please consult the help for the "
             << "list of algorithms." << endl;
        exit(1);
        return feature_set_pop(); // to please Mr compiler
    }
}

feature_set select_features(const CTable& ctable,
                            const feature_selection_parameters& fs_params)
{
    feature_set_pop fs_pop = select_feature_sets(ctable, fs_params);
    OC_ASSERT(!fs_pop.empty(), "There might a bug");
    return fs_pop.begin()->second;
}

feature_set select_features(const Table& table,
                            const feature_selection_parameters& fs_params)
{
    CTable ctable = table.compressed();
    return select_features(ctable, fs_params);
}

void feature_selection(const Table& table,
                       const feature_selection_parameters& fs_params)
{
    // Select the best features
    feature_set selected_features = select_features(table, fs_params);

    // Add the enforced features
    if (!fs_params.force_features_str.empty()) {
        vector<unsigned> force_idxs =
            get_indices(fs_params.force_features_str, table.itable.get_labels());
        select_features.insert(force_idxs.begin(), force_idxs.end());
    }

    // Write the features (in log and output)
    if (selected_features.empty())
        err_empty_features(fs_params.output_file);
    else {
        Table filt_table = table.filtered(selected_features);
        log_selected_features(table.get_arity(), filt_table, fs_params);
        write_results(filt_table, fs_params);
    }
}

} // ~namespace opencog
<commit_msg>Fix force feature in feature selection<commit_after>/** feature-selection.cc ---
 *
 * Copyright (C) 2011 OpenCog Foundation
 *
 * Author: Nil Geisweiller
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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 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, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

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

#include <boost/assign/std/vector.hpp> // for 'operator+=()'
#include <boost/range/algorithm/find.hpp>
#include <boost/range/irange.hpp>

#include <opencog/util/Logger.h>

#include <opencog/comboreduct/table/table.h>
#include <opencog/comboreduct/table/table_io.h>
#include <opencog/learning/moses/optimization/hill-climbing.h> // for hc_params

#include "feature-selection.h"
#include "../algo/deme_optimize.h"
#include "../algo/incremental.h"
#include "../algo/random.h"
#include "../algo/simple.h"
#include "../algo/stochastic_max_dependency.h"

namespace opencog {

using namespace combo;
using namespace std;
using namespace boost::assign; // bring 'operator+=()' into scope

void err_empty_features(const string& outfile)
{
    // If the dataset is degenerate, it can happen that feature
    // selection will fail to find any features.  Rather than just
    // crashing as a result, write out an empty file, which at least
    // allows downstream processes to infer what happened (i.e. to tell
    // apart this case from an outright crash.)
    logger().warn() << "No features have been selected.";
    cerr << "No features have been selected." << endl;
    if (!outfile.empty()) {
        ofstream out(outfile.c_str());
        out << "# No features have been selected." << endl;
    }
    exit(0);
}

// Score all individual features of Table
vector<double> score_individual_features(const Table& table,
                                         const feature_selection_parameters& fs_params)
{
    typedef set<arity_t> FS;
    CTable ctable = table.compressed();
    fs_scorer<FS> fs_sc(ctable, fs_params);
    vector<double> res;
    boost::transform(boost::irange(0, table.get_arity()), back_inserter(res),
                     [&](arity_t idx) { FS fs = {idx}; return fs_sc(fs); });
    return res;
}

// log the set of features and its number
void log_selected_features(arity_t old_arity, const Table& ftable,
                           const feature_selection_parameters& fs_params)
{
    // log the number selected features
    logger().info("%d out of %d features have been selected",
                  ftable.get_arity(), old_arity);

    // log set of selected feature set
    const string_seq& labs = ftable.itable.get_labels();
    const vector<double>& sco = score_individual_features(ftable, fs_params);
    for (unsigned i=0; i<labs.size(); i++)
    {
        logger().info() << "log_selected_features(): " << labs[i] << " " << sco[i];
    }
}

void write_results(const Table& selected_table,
                   const feature_selection_parameters& fs_params)
{
    Table table_wff = selected_table;
    if (fs_params.output_file.empty())
        ostreamTable(cout, table_wff);
    else
        saveTable(fs_params.output_file, table_wff);
}

feature_set initial_features(const vector<string>& ilabels,
                             const feature_selection_parameters& fs_params)
{
    vector<string> vif; // valid initial features, used for logging
    feature_set res;

    for (const string& f : fs_params.initial_features) {
        size_t idx = distance(ilabels.begin(), boost::find(ilabels, f));
        if(idx < ilabels.size()) { // feature found
            res.insert(idx);
            // for logging
            vif += f;
        }
        else // feature not found
            logger().warn("No such a feature %s in file %s. It will be ignored as initial feature.", f.c_str(), fs_params.input_file.c_str());
    }
    // Logger
    if(vif.empty())
        logger().info("The search will start with the empty feature set");
    else {
        stringstream ss;
        ss << "The search will start with the following feature set: ";
        ostreamContainer(ss, vif, ",");
        logger().info(ss.str());
    }
    // ~Logger
    return res;
}

feature_set_pop select_feature_sets(const CTable& ctable,
                                    const feature_selection_parameters& fs_params)
{
    if (fs_params.algorithm == moses::hc) {
        // setting moses optimization parameters
        double pop_size_ratio = 20;
        size_t max_dist = 4;
        score_t min_score_improv = 0.0;
        optim_parameters op_params;
        op_params.opt_algo = moses::hc;
        op_params.pop_size_ratio = pop_size_ratio;
        op_params.terminate_if_gte = fs_params.hc_max_score;
        op_params.max_dist = max_dist;
        op_params.set_min_score_improv(min_score_improv);
        hc_parameters hc_params;
        hc_params.widen_search = fs_params.hc_widen_search;
        hc_params.single_step = false;
        hc_params.crossover = fs_params.hc_crossover;
        hc_params.crossover_pop_size = fs_params.hc_crossover_pop_size;
        hc_params.crossover_min_neighbors = fs_params.hc_crossover_min_neighbors;
        hc_params.prefix_stat_deme = "FSDemes";
        hill_climbing hc(op_params, hc_params);
        return moses_select_feature_sets(ctable, hc, fs_params);
    } else if (fs_params.algorithm == "inc") {
        return incremental_select_feature_sets(ctable, fs_params);
    } else if (fs_params.algorithm == "smd") {
        return smd_select_feature_sets(ctable, fs_params);
    } else if (fs_params.algorithm == "random") {
        return random_select_feature_sets(ctable, fs_params);
    } else if (fs_params.algorithm == "simple") {
        return simple_select_feature_sets(ctable, fs_params);
    } else {
        cerr << "Fatal Error: Algorithm '" << fs_params.algorithm
             << "' is unknown, please consult the help for the "
             << "list of algorithms." << endl;
        exit(1);
        return feature_set_pop(); // to please Mr compiler
    }
}

feature_set select_features(const CTable& ctable,
                            const feature_selection_parameters& fs_params)
{
    feature_set_pop fs_pop = select_feature_sets(ctable, fs_params);
    OC_ASSERT(!fs_pop.empty(), "There might a bug");
    return fs_pop.begin()->second;
}

feature_set select_features(const Table& table,
                            const feature_selection_parameters& fs_params)
{
    CTable ctable = table.compressed();
    return select_features(ctable, fs_params);
}

void feature_selection(const Table& table,
                       const feature_selection_parameters& fs_params)
{
    // Select the best features
    feature_set selected_features = select_features(table, fs_params);

    // Add the enforced features
    if (!fs_params.force_features_str.empty()) {
        vector<unsigned> force_idxs =
            get_indices(fs_params.force_features_str, table.itable.get_labels());
        selected_features.insert(force_idxs.begin(), force_idxs.end());
    }

    // Write the features (in log and output)
    if (selected_features.empty())
        err_empty_features(fs_params.output_file);
    else {
        Table filt_table = table.filtered(selected_features);
        log_selected_features(table.get_arity(), filt_table, fs_params);
        write_results(filt_table, fs_params);
    }
}

} // ~namespace opencog
<|endoftext|>


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

#include "itkNormalDistributionImageSource.h"
#include "itkNormalVariateGenerator.h"

#include "itkImageScanlineIterator.h"
#include "itkProgressReporter.h"

namespace itk
{

template< typename TImage >
NormalDistributionImageSource< TImage >
::NormalDistributionImageSource()
{
}

template< typename TImage >
void
NormalDistributionImageSource< TImage >
::PrintSelf( std::ostream& os, Indent indent ) const
{
  Superclass::PrintSelf( os, indent );
}

template< typename TImage >
void
NormalDistributionImageSource< TImage >
::DynamicThreadedGenerateData( const OutputRegionType & outputRegion )
{
  ImageType * output = this->GetOutput();

  typedef itk::Statistics::NormalVariateGenerator NormalGeneratorType;
  NormalGeneratorType::Pointer normalGenerator = NormalGeneratorType::New();
  normalGenerator->Initialize( 101 );

  const SizeValueType size0 = outputRegion.GetSize( 0 );
  if( size0 == 0 )
    {
    return;
    }
  const SizeValueType numberOfLinesToProcess = outputRegion.GetNumberOfPixels() / size0;

  typedef ImageScanlineIterator< ImageType > IteratorType;
  IteratorType it( output, outputRegion );
  ProgressReporter progress( this, 0, numberOfLinesToProcess );

  while( !it.IsAtEnd() )
    {
    while( !it.IsAtEndOfLine() )
      {
      it.Set( normalGenerator->GetVariate() );
      ++it;
      }
    it.NextLine();
    progress.CompletedPixel();
    }
}

} // end namespace itk

#endif // itkNormalDistributionImageSource_hxx
<commit_msg>ENH: Remove pixelwise progress report<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef itkNormalDistributionImageSource_hxx
#define itkNormalDistributionImageSource_hxx

#include "itkNormalDistributionImageSource.h"
#include "itkNormalVariateGenerator.h"

#include "itkImageScanlineIterator.h"

namespace itk
{

template< typename TImage >
NormalDistributionImageSource< TImage >
::NormalDistributionImageSource()
{
}

template< typename TImage >
void
NormalDistributionImageSource< TImage >
::PrintSelf( std::ostream& os, Indent indent ) const
{
  Superclass::PrintSelf( os, indent );
}

template< typename TImage >
void
NormalDistributionImageSource< TImage >
::DynamicThreadedGenerateData( const OutputRegionType & outputRegion )
{
  ImageType * output = this->GetOutput();

  typedef itk::Statistics::NormalVariateGenerator NormalGeneratorType;
  NormalGeneratorType::Pointer normalGenerator = NormalGeneratorType::New();
  normalGenerator->Initialize( 101 );

  const SizeValueType size0 = outputRegion.GetSize( 0 );
  if( size0 == 0 )
    {
    return;
    }
  const SizeValueType numberOfLinesToProcess = outputRegion.GetNumberOfPixels() / size0;

  typedef ImageScanlineIterator< ImageType > IteratorType;
  IteratorType it( output, outputRegion );

  while( !it.IsAtEnd() )
    {
    while( !it.IsAtEndOfLine() )
      {
      it.Set( normalGenerator->GetVariate() );
      ++it;
      }
    it.NextLine();
    }
}

} // end namespace itk

#endif // itkNormalDistributionImageSource_hxx
<|endoftext|>


<commit_before>#include <fhe/FHEContext.h>
#include <fhe/FHE.h>
#include <fhe/NumbTh.h>
#include <fhe/EncryptedArray.h>
#include <fhe/replicate.h>

#include <utils/FileUtils.hpp>
#include <utils/timer.hpp>
#include <utils/encoding.hpp>

#include <protocol/Gt.hpp>

#include <thread>
#include <atomic>
#ifdef FHE_THREADS
long WORKER_NR = 8;
#else // ifdef FHE_THREADS
long WORKER_NR = 1;
#endif // ifdef FHE_THREADS

MDL::EncVector sum_ctxts(const std::vector<MDL::EncVector>& ctxts)
{
    std::vector<std::thread>    workers;
    std::vector<MDL::EncVector> partials(WORKER_NR, ctxts[0].getPubKey());
    std::atomic<size_t> counter(WORKER_NR);
    MDL::Timer timer;

    timer.start();

    for (long i = 0; i < WORKER_NR; i++) {
        partials[i] = ctxts[i];
        workers.push_back(std::move(std::thread([&counter, &ctxts]
                                                    (MDL::EncVector& ct) {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ct += ctxts[next];
            }
        }, std::ref(partials[i]))));
    }

    for (auto && wr : workers) wr.join();

    for (long i = 1; i < WORKER_NR; i++) {
        partials[0] += partials[i];
    }
    timer.end();
    printf("Sum %zd ctxts with %ld workers costed %f sec\n", ctxts.size(),
           WORKER_NR, timer.second());
    return partials[0];
}

std::pair<MDL::EncVector, long>load_file(const EncryptedArray& ea,
                                         const FHEPubKey     & pk)
{
    auto data = load_csv("adult.data", 11);
    std::vector<MDL::EncVector> ctxts(data.rows(), pk);
    std::atomic<size_t> counter(0);
    std::vector<std::thread> workers;
    MDL::Timer timer;

    timer.start();

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&counter, &ea,
                                                 &ctxts, &data]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < data.rows()) {
                auto indicator = MDL::encoding::staircase(data[next][0], ea);
                ctxts[next].pack(indicator, ea);
            }
        })));
    }
    timer.end();
    printf("Encrypt %ld records with %ld workers costed %f sec.\n",
           data.rows(), WORKER_NR, timer.second());

    for (auto && wr : workers) wr.join();

    return { sum_ctxts(ctxts), data.rows() };
}

std::vector<MDL::GTResult>k_percentile(const MDL::EncVector& ctxt,
                                       const FHEPubKey& pk,
                                       const EncryptedArray& ea,
                                       long N, long k)
{
    MDL::Timer timer;
    MDL::EncVector oth(pk);
    long kpercentile =  k * N / 100;
    MDL::Vector<long> percentile(ea.size(), kpercentile);
    long plainSpace  = ea.getContext().alMod.getPPowR();
    long domain = N;
    std::vector<MDL::GTResult> gtresults(domain);
    std::atomic<size_t> counter(0);
    std::vector<std::thread> workers;

    oth.pack(percentile, ea);
    timer.start();

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::thread([&ctxt, &ea, &counter, &oth,
                                       &domain, &plainSpace, &gtresults]() {
            size_t d;

            while ((d = counter.fetch_add(1)) < domain) {
                auto tmp(ctxt);
                replicate(ea, tmp, d);
                MDL::GTInput input = { oth, tmp, domain, plainSpace };
                gtresults[d] = MDL::GT(input, ea);
            }
        }));
    }

    for (auto& wr : workers) wr.join();
    timer.end();
    printf("call GT on Domain %ld used %ld workers costed %f second\n",
           domain, WORKER_NR, timer.second());
    return gtresults;
}

int main(int argc, char *argv[]) {
    long m, p, r, L;
    ArgMapping argmap;

    argmap.arg("m", m, "m");
    argmap.arg("L", L, "L");
    argmap.arg("p", p, "p");
    argmap.arg("r", r, "r");
    argmap.parse(argc, argv);

    FHEcontext context(m, p, r);
    buildModChain(context, L);
    FHESecKey sk(context);
    sk.GenSecKey(64);
    addSome1DMatrices(sk);
    FHEPubKey pk = sk;

    auto G = context.alMod.getFactorsOverZZ()[0];
    EncryptedArray ea(context, G);

    auto data      = load_file(ea, pk);
    long kpercent  = 50;
    auto gtresults = k_percentile(data.first, pk, ea,
                                  data.second, kpercent);
    bool prev      = true;

    for (int d = 0; d < gtresults.size(); d++) {
        bool current = MDL::decrypt_gt_result(gtresults[d], sk, ea);

        if (prev && !current) {
            printf("%ld-percentile is %d\n", kpercent, d);
            break;
        }
        prev = current;
    }
    return 0;
}
<commit_msg>bug fix<commit_after>#include <fhe/FHEContext.h>
#include <fhe/FHE.h>
#include <fhe/NumbTh.h>
#include <fhe/EncryptedArray.h>
#include <fhe/replicate.h>

#include <utils/FileUtils.hpp>
#include <utils/timer.hpp>
#include <utils/encoding.hpp>

#include <protocol/Gt.hpp>

#include <thread>
#include <atomic>
#ifdef FHE_THREADS
long WORKER_NR = 8;
#else // ifdef FHE_THREADS
long WORKER_NR = 1;
#endif // ifdef FHE_THREADS

MDL::EncVector sum_ctxts(const std::vector<MDL::EncVector>& ctxts)
{
    std::vector<std::thread>    workers;
    std::vector<MDL::EncVector> partials(WORKER_NR, ctxts[0].getPubKey());
    std::atomic<size_t> counter(WORKER_NR);
    MDL::Timer timer;

    timer.start();

    for (long i = 0; i < WORKER_NR; i++) {
        partials[i] = ctxts[i];
        workers.push_back(std::move(std::thread([&counter, &ctxts]
                                                    (MDL::EncVector& ct) {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ct += ctxts[next];
            }
        }, std::ref(partials[i]))));
    }

    for (auto && wr : workers) wr.join();

    for (long i = 1; i < WORKER_NR; i++) {
        partials[0] += partials[i];
    }
    timer.end();
    printf("Sum %zd ctxts with %ld workers costed %f sec\n", ctxts.size(),
           WORKER_NR, timer.second());
    return partials[0];
}

std::pair<MDL::EncVector, long>load_file(const EncryptedArray& ea,
                                         const FHEPubKey     & pk)
{
    auto data = load_csv("adult.data", 2000);
    std::vector<MDL::EncVector> ctxts(data.rows(), pk);
    std::atomic<size_t> counter(0);
    std::vector<std::thread> workers;
    MDL::Timer timer;

    timer.start();

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&counter, &ea,
                                                 &ctxts, &data]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < data.rows()) {
                auto indicator = MDL::encoding::staircase(data[next][0], ea);
                ctxts[next].pack(indicator, ea);
            }
        })));
    }
    timer.end();

    for (auto && wr : workers) wr.join();
    printf("Encrypt %ld records with %ld workers costed %f sec.\n",
           data.rows(), WORKER_NR, timer.second());
    return { sum_ctxts(ctxts), data.rows() };
}

std::vector<MDL::GTResult>k_percentile(const MDL::EncVector& ctxt,
                                       const FHEPubKey     & pk,
                                       const EncryptedArray& ea,
                                       long                  records_nr,
                                       long                  domain,
                                       long                  k)
{
    MDL::Timer timer;
    MDL::EncVector oth(pk);
    long kpercentile =  k * records_nr / 100;
    MDL::Vector<long> percentile(ea.size(), kpercentile);
    long plainSpace  = ea.getContext().alMod.getPPowR();
    std::vector<MDL::GTResult> gtresults(domain);
    std::atomic<size_t> counter(0);
    std::vector<std::thread> workers;

    oth.pack(percentile, ea);
    timer.start();

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::thread([&ctxt, &ea, &counter, &oth, &records_nr,
                                       &domain, &plainSpace, &gtresults]() {
            size_t d;

            while ((d = counter.fetch_add(1)) < domain) {
                auto tmp(ctxt);
                replicate(ea, tmp, d);
                MDL::GTInput input = { oth, tmp, records_nr, plainSpace };
                gtresults[d] = MDL::GT(input, ea);
            }
        }));
    }

    for (auto& wr : workers) wr.join();
    timer.end();
    printf("call GT on Domain %ld used %ld workers costed %f second\n",
           records_nr, WORKER_NR, timer.second());
    return gtresults;
}

int main(int argc, char *argv[]) {
    long m, p, r, L;
    ArgMapping argmap;

    argmap.arg("m", m, "m");
    argmap.arg("L", L, "L");
    argmap.arg("p", p, "p");
    argmap.arg("r", r, "r");
    argmap.parse(argc, argv);

    FHEcontext context(m, p, r);
    buildModChain(context, L);
    FHESecKey sk(context);
    sk.GenSecKey(64);
    addSome1DMatrices(sk);
    FHEPubKey pk = sk;

    auto G = context.alMod.getFactorsOverZZ()[0];
    EncryptedArray ea(context, G);

    auto data      = load_file(ea, pk);
    long kpercent  = 50;
    auto gtresults = k_percentile(data.first,
                                  pk, ea,
                                  data.second,
                                  100,
                                  kpercent);
    bool prev = true;

    for (int d = 0; d < gtresults.size(); d++) {
        bool current = MDL::decrypt_gt_result(gtresults[d], sk, ea);

        if (prev && !current) {
            printf("%ld-percentile is %d\n", kpercent, d);
            break;
        }
        prev = current;
    }
    return 0;
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// This software module was originally developed by
//
// University of California Santa Barbara, Kapil Chhabra, Yining Deng.
// Mitsubishi Electric ITE-VIL, Leszek Cieplinski.
// (contributing organizations names)
//
// in the course of development of the MPEG-7 Experimentation Model.
//
// This software module is an implementation of a part of one or more MPEG-7
// Experimentation Model tools as specified by the MPEG-7 Requirements.
//
// ISO/IEC gives users of MPEG-7 free license to this software module or
// modifications thereof for use in hardware or software products claiming
// conformance to MPEG-7.
//
// Those intending to use this software module in hardware or software products
// are advised that its use may infringe existing patents. The original
// developer of this software module and his/her company, the subsequent
// editors and their companies, and ISO/IEC have no liability for use of this
// software module or modifications thereof in an implementation.
//
// Copyright is not released for non MPEG-7 conforming products. The
// organizations named above retain full right to use the code for their own
// purpose, assign or donate the code to a third party and inhibit third parties
// from using the code for non MPEG-7 conforming products.
//
// Copyright (c) 1998-2000.
//
// This notice must be included in all copies or derivative works.
//
// Applicable File Name:  DominantColor.cpp
//
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <iostream>

#include "DominantColor.h"

using namespace XM;

DominantColorDescriptor::DominantColorDescriptor():
m_DominantColorsNumber(0),
m_ColorSpacePresent(0),
m_ColorQuantizationPresent(0),
m_VariancePresent(1),
m_SpatialCoherency(0),
m_dc(0),
m_ColorSpace(0),
m_Quantizer(0)
{
    m_ColorSpace = new ColorSpaceDescriptor();;
    m_Quantizer = new ColorQuantizerDescriptor();

}

//----------------------------------------------------------------------------
DominantColorDescriptor::~DominantColorDescriptor()
{
  // will be released by the clients!
}

/*
//----------------------------------------------------------------------------
unsigned long DominantColorDescriptor::
ExportDDL(GenericDSInterfaceABC *aParentDescription)
{
  int i, j;
  vector<int> cvi(3);
  vector<int> var(3);
  DOMCOL *DC;

  GenericDS l_DDLDescription;
  GenericDSInterfaceABC *l_DDLDescriptionInterface;
  GenericDS SpatCoher, V, Per, ColValInd, Var;

  if(!aParentDescription) return (unsigned long) -1;

  l_DDLDescription = aParentDescription->CreateChild("Descriptor");
  l_DDLDescription.SetAttribute("xsi:type","DominantColorType");
  int dc_number = GetDominantColorsNumber();
  //l_DDLDescription.SetAttribute("size", dc_number);

  l_DDLDescriptionInterface = l_DDLDescription.GetInterface();

  bool colspcpres = GetColorSpacePresent();
  if(colspcpres) m_ColorSpace->ExportDDL(l_DDLDescriptionInterface);

  bool colquantpres = GetColorQuantizationPresent();
  if(colquantpres) m_Quantizer->ExportDDL(l_DDLDescriptionInterface);

  bool varpres = GetVariancePresent();

  SpatCoher = l_DDLDescription.CreateChild("SpatialCoherency");
  int spatcoher = GetSpatialCoherency();
  SpatCoher.SetValue(spatcoher);

  DC = GetDominantColors();

  for(i=0; i<dc_number; i++) {
    V = l_DDLDescription.CreateChild("Value");

    Per = V.CreateChild("Percentage");
    Per.SetValue(DC[i].m_Percentage);

    ColValInd = V.CreateChild("Index");
    for(j=0; j<3; j++) cvi[j] = DC[i].m_ColorValue[j];
    ColValInd.SetValue(cvi);

    if(varpres==true) {
      Var = V.CreateChild("ColorVariance");
      for(j=0; j<3; j++) var[j] = DC[i].m_ColorVariance[j];
      Var.SetValue(var);
    }
  }

  return 0;
}

//----------------------------------------------------------------------------
unsigned long DominantColorDescriptor::
ImportDDL(GenericDSInterfaceABC *aDescription)
{
  int i, j, dc_number, spatcoher, per;
  string xsitype, colspcpres, colquantpres, varpres;

  GenericDS l_DDLDescription;
  GenericDSInterfaceABC *l_DDLDescriptionInterface = NULL;

  GenericDS V, Per, ColValInd, Var;
  int *percents, **colors, **variances;

  if(!aDescription) return (unsigned long) -1;

  // if aDescription is of correct type
  if(aDescription->GetDSName() == "Descriptor") {
    aDescription->GetTextAttribute("xsi:type", xsitype);
    if(xsitype == "DominantColorType") {
      l_DDLDescriptionInterface = aDescription;
    }
  }

  // else search for DominantColorType as a child
  if(!l_DDLDescriptionInterface) {
    l_DDLDescription = aDescription->GetDescription("Descriptor");

    // search for correct xsi type
    while(!l_DDLDescription.isNull()) {
      l_DDLDescription.GetTextAttribute("xsi:type", xsitype);
      if(xsitype == "DominantColorType") break;
      l_DDLDescription.GetNextSibling("Descriptor");
    }

    // DominantColorType not found
    if(!l_DDLDescription.isNull()) return (unsigned long) -1;
    // DominantColorType found
    l_DDLDescriptionInterface = l_DDLDescription.GetInterface();
  }

  l_DDLDescriptionInterface->GetIntAttribute("size",dc_number);
  SetDominantColorsNumber(dc_number);

  GenericDS ColSpc = l_DDLDescriptionInterface->GetDescription("ColorSpace");
  if(!ColSpc.isNull()) {
    SetColorSpacePresent(true);
    m_ColorSpace->ImportDDL(l_DDLDescriptionInterface);
  }
  else SetColorSpacePresent(false);

  GenericDS ColQuant = l_DDLDescriptionInterface->GetDescription("ColorQuantization");
  if(!ColQuant.isNull()) {
    SetColorQuantizationPresent(true);
    m_Quantizer->ImportDDL(l_DDLDescriptionInterface);
  }
  else SetColorQuantizationPresent(false);

  GenericDS VarPres = l_DDLDescriptionInterface->GetDescription("VariancePresent");
  VarPres.GetTextValue(varpres);
  if(varpres=="true") SetVariancePresent(true);
  else SetVariancePresent(false);

  GenericDS SpatCoher = l_DDLDescriptionInterface->GetDescription("SpatialCoherency");
  SpatCoher.GetIntValue(spatcoher);
  SetSpatialCoherency(spatcoher);

  // dominant colors
  percents = new int[dc_number];
  colors = new int*[dc_number];
  for(i=0;i<dc_number;i++) colors[i]= new int[3];
  variances = new int*[dc_number];
  for(i=0;i<dc_number;i++) variances[i]= new int[3];

  for(i=0; i<dc_number; i++) {
    vector<int> cvi, var;

    V = l_DDLDescriptionInterface->GetDescription("Values");

    Per = V.GetDescription("Percentage");
    Per.GetIntValue(per);
    percents[i] = per;

    ColValInd = V.GetDescription("ColorValueIndex");
    ColValInd.GetIntVector(cvi);
    for(j=0; j<3; j++) colors[i][j] = cvi[j];

    Var = V.GetDescription("ColorVariance");
    if(!Var.isNull()) {
      SetVariancePresent(true);
      Var.GetIntVector(var);
      for(j=0; j<3; j++) variances[i][j] = var[j];
    }
    else SetVariancePresent(false);

    l_DDLDescriptionInterface->RemoveChild(V);
  }

  SetDominantColors(percents, colors, variances);

  delete [] percents;
  for(i=0;i<dc_number;i++) delete [] colors[i];
  delete [] colors;
  for(i=0;i<dc_number;i++) delete [] variances[i];
  delete [] variances;

  return 0;
}
*/

//----------------------------------------------------------------------------
ColorQuantizerDescriptor * DominantColorDescriptor::
GetColorQuantizerDescriptor(void)
{
  return m_Quantizer;
}

//----------------------------------------------------------------------------
unsigned long DominantColorDescriptor::SetColorQuantizerDescriptor
        (ColorQuantizerDescriptor *quantizer)
{
  if (!quantizer) return (unsigned long) -1;
  if (m_Quantizer == quantizer) return 0;
  if (m_Quantizer) delete m_Quantizer;
  m_Quantizer = quantizer;

  return 0;
}

//----------------------------------------------------------------------------
ColorSpaceDescriptor* DominantColorDescriptor::GetColorSpaceDescriptor()
{
  return m_ColorSpace;
}

//----------------------------------------------------------------------------
unsigned long DominantColorDescriptor::
SetColorSpaceDescriptor(ColorSpaceDescriptor *colorspace)
{
  if (m_ColorSpace == colorspace) return 0;
  if (m_ColorSpace) delete m_ColorSpace;
  m_ColorSpace = colorspace;

  return 0;
}

//----------------------------------------------------------------------------
int DominantColorDescriptor::GetDominantColorsNumber()
{
  return (m_DominantColorsNumber);
}

//----------------------------------------------------------------------------
int DominantColorDescriptor::GetSpatialCoherency()
{
  return (m_SpatialCoherency);
}

//----------------------------------------------------------------------------
DOMCOL* DominantColorDescriptor::GetDominantColors()
{
  return (m_dc);
}

//----------------------------------------------------------------------------
void DominantColorDescriptor::SetDominantColorsNumber(int dc_number)
{
  if (dc_number != m_DominantColorsNumber) {
    if (m_dc)
      delete [] m_dc;
    m_dc = new DOMCOL[dc_number];

	// set values to zero - by mb - may not be crucial here since they are assigned in SetDominantColors() below (no aggregation, etc)
	this->resetDescriptor();

	m_DominantColorsNumber = dc_number;
  }
}

//----------------------------------------------------------------------------
void DominantColorDescriptor::SetSpatialCoherency(int sc)
{
  m_SpatialCoherency = sc;
}
#include <iostream>
//----------------------------------------------------------------------------
void DominantColorDescriptor::SetDominantColors(int *percents, int **colors, int **variances)
{
    int j;

    // count the colors with nonzero weight
    // to cancel the DCs with zero weight
    int index = 0;
    for( int i = 0; i < m_DominantColorsNumber; i++ )
    {
        if(percents[i] > 0)
        {
            m_dc[index].m_Percentage = percents[i];

            for(j=0;j<3;j++)
              m_dc[index].m_ColorValue[j] = colors[i][j];

            if( m_VariancePresent )
                for(j=0;j<3;j++)
                    m_dc[index].m_ColorVariance[j] = variances[i][j];
            index++;
        }
    }

    if(index < m_DominantColorsNumber)
    {
        //std::cerr << "index < mdc" << std::endl;
        m_DominantColorsNumber = index;
    }
}

void DominantColorDescriptor::resetDescriptor()
{
	for( int i = 0; i < m_DominantColorsNumber; i++ ){

		this->m_dc[i].m_Percentage = 0;
		memset( this->m_dc[i].m_ColorValue, 0, 3*sizeof(int) );
		memset( this->m_dc[i].m_ColorVariance, 0, 3*sizeof(int) );
	}

}

//----------------------------------------------------------------------------
void DominantColorDescriptor::Print()
{
  int i;

  std::cerr << "size:        " << m_DominantColorsNumber << " (m_DominantColorsNumber)" << std::endl;
  std::cerr << "sc:          " << m_SpatialCoherency << " (m_SpatialCoherency)" <<std::endl;
  std::cerr << "percentage   |||  color values  |||  color variances" << std::endl;
  for(i=0; i<m_DominantColorsNumber; i++)
    std::cerr << "value: " << m_dc[i].m_Percentage << "  |||  "
         << m_dc[i].m_ColorValue[0] << " "
         << m_dc[i].m_ColorValue[1] << " "
         << m_dc[i].m_ColorValue[2] << "   |||   "
		 << m_dc[i].m_ColorVariance[0] << " "
         << m_dc[i].m_ColorVariance[1] << " "
         << m_dc[i].m_ColorVariance[2] << std::endl;

}
<commit_msg>Update DominantColor.cpp<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// This software module was originally developed by
//
// University of California Santa Barbara, Kapil Chhabra, Yining Deng.
// Mitsubishi Electric ITE-VIL, Leszek Cieplinski.
// (contributing organizations names)
//
// in the course of development of the MPEG-7 Experimentation Model.
//
// This software module is an implementation of a part of one or more MPEG-7
// Experimentation Model tools as specified by the MPEG-7 Requirements.
//
// ISO/IEC gives users of MPEG-7 free license to this software module or
// modifications thereof for use in hardware or software products claiming
// conformance to MPEG-7.
//
// Those intending to use this software module in hardware or software products
// are advised that its use may infringe existing patents. The original
// developer of this software module and his/her company, the subsequent
// editors and their companies, and ISO/IEC have no liability for use of this
// software module or modifications thereof in an implementation.
//
// Copyright is not released for non MPEG-7 conforming products. The
// organizations named above retain full right to use the code for their own
// purpose, assign or donate the code to a third party and inhibit third parties
// from using the code for non MPEG-7 conforming products.
//
// Copyright (c) 1998-2000.
//
// This notice must be included in all copies or derivative works.
//
// Applicable File Name:  DominantColor.cpp
//
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <iostream>

#include "DominantColor.h"

using namespace XM;

DominantColorDescriptor::DominantColorDescriptor():
m_DominantColorsNumber(0),
m_ColorSpacePresent(0),
m_ColorQuantizationPresent(0),
m_VariancePresent(1),
m_SpatialCoherency(0),
m_dc(0),
m_ColorSpace(0),
m_Quantizer(0)
{
    m_ColorSpace = new ColorSpaceDescriptor();;
    m_Quantizer = new ColorQuantizerDescriptor();

}

//----------------------------------------------------------------------------
DominantColorDescriptor::~DominantColorDescriptor()
{
   delete m_dc;
   delete m_ColorSpace;
   delete m_Quantizer;
}

/*
//----------------------------------------------------------------------------
unsigned long DominantColorDescriptor::
ExportDDL(GenericDSInterfaceABC *aParentDescription)
{
  int i, j;
  vector<int> cvi(3);
  vector<int> var(3);
  DOMCOL *DC;

  GenericDS l_DDLDescription;
  GenericDSInterfaceABC *l_DDLDescriptionInterface;
  GenericDS SpatCoher, V, Per, ColValInd, Var;

  if(!aParentDescription) return (unsigned long) -1;

  l_DDLDescription = aParentDescription->CreateChild("Descriptor");
  l_DDLDescription.SetAttribute("xsi:type","DominantColorType");
  int dc_number = GetDominantColorsNumber();
  //l_DDLDescription.SetAttribute("size", dc_number);

  l_DDLDescriptionInterface = l_DDLDescription.GetInterface();

  bool colspcpres = GetColorSpacePresent();
  if(colspcpres) m_ColorSpace->ExportDDL(l_DDLDescriptionInterface);

  bool colquantpres = GetColorQuantizationPresent();
  if(colquantpres) m_Quantizer->ExportDDL(l_DDLDescriptionInterface);

  bool varpres = GetVariancePresent();

  SpatCoher = l_DDLDescription.CreateChild("SpatialCoherency");
  int spatcoher = GetSpatialCoherency();
  SpatCoher.SetValue(spatcoher);

  DC = GetDominantColors();

  for(i=0; i<dc_number; i++) {
    V = l_DDLDescription.CreateChild("Value");

    Per = V.CreateChild("Percentage");
    Per.SetValue(DC[i].m_Percentage);

    ColValInd = V.CreateChild("Index");
    for(j=0; j<3; j++) cvi[j] = DC[i].m_ColorValue[j];
    ColValInd.SetValue(cvi);

    if(varpres==true) {
      Var = V.CreateChild("ColorVariance");
      for(j=0; j<3; j++) var[j] = DC[i].m_ColorVariance[j];
      Var.SetValue(var);
    }
  }

  return 0;
}

//----------------------------------------------------------------------------
unsigned long DominantColorDescriptor::
ImportDDL(GenericDSInterfaceABC *aDescription)
{
  int i, j, dc_number, spatcoher, per;
  string xsitype, colspcpres, colquantpres, varpres;

  GenericDS l_DDLDescription;
  GenericDSInterfaceABC *l_DDLDescriptionInterface = NULL;

  GenericDS V, Per, ColValInd, Var;
  int *percents, **colors, **variances;

  if(!aDescription) return (unsigned long) -1;

  // if aDescription is of correct type
  if(aDescription->GetDSName() == "Descriptor") {
    aDescription->GetTextAttribute("xsi:type", xsitype);
    if(xsitype == "DominantColorType") {
      l_DDLDescriptionInterface = aDescription;
    }
  }

  // else search for DominantColorType as a child
  if(!l_DDLDescriptionInterface) {
    l_DDLDescription = aDescription->GetDescription("Descriptor");

    // search for correct xsi type
    while(!l_DDLDescription.isNull()) {
      l_DDLDescription.GetTextAttribute("xsi:type", xsitype);
      if(xsitype == "DominantColorType") break;
      l_DDLDescription.GetNextSibling("Descriptor");
    }

    // DominantColorType not found
    if(!l_DDLDescription.isNull()) return (unsigned long) -1;
    // DominantColorType found
    l_DDLDescriptionInterface = l_DDLDescription.GetInterface();
  }

  l_DDLDescriptionInterface->GetIntAttribute("size",dc_number);
  SetDominantColorsNumber(dc_number);

  GenericDS ColSpc = l_DDLDescriptionInterface->GetDescription("ColorSpace");
  if(!ColSpc.isNull()) {
    SetColorSpacePresent(true);
    m_ColorSpace->ImportDDL(l_DDLDescriptionInterface);
  }
  else SetColorSpacePresent(false);

  GenericDS ColQuant = l_DDLDescriptionInterface->GetDescription("ColorQuantization");
  if(!ColQuant.isNull()) {
    SetColorQuantizationPresent(true);
    m_Quantizer->ImportDDL(l_DDLDescriptionInterface);
  }
  else SetColorQuantizationPresent(false);

  GenericDS VarPres = l_DDLDescriptionInterface->GetDescription("VariancePresent");
  VarPres.GetTextValue(varpres);
  if(varpres=="true") SetVariancePresent(true);
  else SetVariancePresent(false);

  GenericDS SpatCoher = l_DDLDescriptionInterface->GetDescription("SpatialCoherency");
  SpatCoher.GetIntValue(spatcoher);
  SetSpatialCoherency(spatcoher);

  // dominant colors
  percents = new int[dc_number];
  colors = new int*[dc_number];
  for(i=0;i<dc_number;i++) colors[i]= new int[3];
  variances = new int*[dc_number];
  for(i=0;i<dc_number;i++) variances[i]= new int[3];

  for(i=0; i<dc_number; i++) {
    vector<int> cvi, var;

    V = l_DDLDescriptionInterface->GetDescription("Values");

    Per = V.GetDescription("Percentage");
    Per.GetIntValue(per);
    percents[i] = per;

    ColValInd = V.GetDescription("ColorValueIndex");
    ColValInd.GetIntVector(cvi);
    for(j=0; j<3; j++) colors[i][j] = cvi[j];

    Var = V.GetDescription("ColorVariance");
    if(!Var.isNull()) {
      SetVariancePresent(true);
      Var.GetIntVector(var);
      for(j=0; j<3; j++) variances[i][j] = var[j];
    }
    else SetVariancePresent(false);

    l_DDLDescriptionInterface->RemoveChild(V);
  }

  SetDominantColors(percents, colors, variances);

  delete [] percents;
  for(i=0;i<dc_number;i++) delete [] colors[i];
  delete [] colors;
  for(i=0;i<dc_number;i++) delete [] variances[i];
  delete [] variances;

  return 0;
}
*/

//----------------------------------------------------------------------------
ColorQuantizerDescriptor * DominantColorDescriptor::
GetColorQuantizerDescriptor(void)
{
  return m_Quantizer;
}

//----------------------------------------------------------------------------
unsigned long DominantColorDescriptor::SetColorQuantizerDescriptor
        (ColorQuantizerDescriptor *quantizer)
{
  if (!quantizer) return (unsigned long) -1;
  if (m_Quantizer == quantizer) return 0;
  if (m_Quantizer) delete m_Quantizer;
  m_Quantizer = quantizer;

  return 0;
}

//----------------------------------------------------------------------------
ColorSpaceDescriptor* DominantColorDescriptor::GetColorSpaceDescriptor()
{
  return m_ColorSpace;
}

//----------------------------------------------------------------------------
unsigned long DominantColorDescriptor::
SetColorSpaceDescriptor(ColorSpaceDescriptor *colorspace)
{
  if (m_ColorSpace == colorspace) return 0;
  if (m_ColorSpace) delete m_ColorSpace;
  m_ColorSpace = colorspace;

  return 0;
}

//----------------------------------------------------------------------------
int DominantColorDescriptor::GetDominantColorsNumber()
{
  return (m_DominantColorsNumber);
}

//----------------------------------------------------------------------------
int DominantColorDescriptor::GetSpatialCoherency()
{
  return (m_SpatialCoherency);
}

//----------------------------------------------------------------------------
DOMCOL* DominantColorDescriptor::GetDominantColors()
{
  return (m_dc);
}

//----------------------------------------------------------------------------
void DominantColorDescriptor::SetDominantColorsNumber(int dc_number)
{
  if (dc_number != m_DominantColorsNumber) {
    if (m_dc)
      delete [] m_dc;
    m_dc = new DOMCOL[dc_number];

	// set values to zero - by mb - may not be crucial here since they are assigned in SetDominantColors() below (no aggregation, etc)
	this->resetDescriptor();

	m_DominantColorsNumber = dc_number;
  }
}

//----------------------------------------------------------------------------
void DominantColorDescriptor::SetSpatialCoherency(int sc)
{
  m_SpatialCoherency = sc;
}
#include <iostream>
//----------------------------------------------------------------------------
void DominantColorDescriptor::SetDominantColors(int *percents, int **colors, int **variances)
{
    int j;

    // count the colors with nonzero weight
    // to cancel the DCs with zero weight
    int index = 0;
    for( int i = 0; i < m_DominantColorsNumber; i++ )
    {
        if(percents[i] > 0)
        {
            m_dc[index].m_Percentage = percents[i];

            for(j=0;j<3;j++)
              m_dc[index].m_ColorValue[j] = colors[i][j];

            if( m_VariancePresent )
                for(j=0;j<3;j++)
                    m_dc[index].m_ColorVariance[j] = variances[i][j];
            index++;
        }
    }

    if(index < m_DominantColorsNumber)
    {
        //std::cerr << "index < mdc" << std::endl;
        m_DominantColorsNumber = index;
    }
}

void DominantColorDescriptor::resetDescriptor()
{
	for( int i = 0; i < m_DominantColorsNumber; i++ ){

		this->m_dc[i].m_Percentage = 0;
		memset( this->m_dc[i].m_ColorValue, 0, 3*sizeof(int) );
		memset( this->m_dc[i].m_ColorVariance, 0, 3*sizeof(int) );
	}

}

//----------------------------------------------------------------------------
void DominantColorDescriptor::Print()
{
  int i;

  std::cerr << "size:        " << m_DominantColorsNumber << " (m_DominantColorsNumber)" << std::endl;
  std::cerr << "sc:          " << m_SpatialCoherency << " (m_SpatialCoherency)" <<std::endl;
  std::cerr << "percentage   |||  color values  |||  color variances" << std::endl;
  for(i=0; i<m_DominantColorsNumber; i++)
    std::cerr << "value: " << m_dc[i].m_Percentage << "  |||  "
         << m_dc[i].m_ColorValue[0] << " "
         << m_dc[i].m_ColorValue[1] << " "
         << m_dc[i].m_ColorValue[2] << "   |||   "
		 << m_dc[i].m_ColorVariance[0] << " "
         << m_dc[i].m_ColorVariance[1] << " "
         << m_dc[i].m_ColorVariance[2] << std::endl;

}
<|endoftext|>


<commit_before>/*********************************************************************************
* Copyright (c) 2013 David D. Marshall <ddmarsha@calpoly.edu>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    David D. Marshall - initial code and implementation
********************************************************************************/

#ifndef eli_geom_intersect_minimum_distance_curve_hpp
#define eli_geom_intersect_minimum_distance_curve_hpp

#include <cmath>
#include <vector>
#include <list>

#ifdef Success  // X11 #define collides with Eigen
#undef Success
#endif

#include "Eigen/Eigen"

#include "eli/mutil/nls/newton_raphson_constrained_method.hpp"

#include "eli/geom/point/distance.hpp"

namespace eli
{
  namespace geom
  {
    namespace intersect
    {
      namespace internal
      {
        template <typename curve__>
        struct curve_g_functor
        {
          const curve__ *pc;
          typename curve__::point_type pt;

          typename curve__::data_type operator()(const typename curve__::data_type &t) const
          {
            typename curve__::data_type tt(t);

            assert((tt>=0) && (tt<=1));

            return (pc->f(tt)-pt).dot(pc->fp(tt));
          }
        };

        template <typename curve__>
        struct curve_gp_functor
        {
          const curve__ *pc;
          typename curve__::point_type pt;

          typename curve__::data_type operator()(const typename curve__::data_type &t) const
          {
            typename curve__::data_type tt(t);

            assert((tt>=0) && (tt<=1));

            typename curve__::point_type fp(pc->fp(tt));
            typename curve__::data_type rtn(fp.dot(fp)+pc->fpp(tt).dot(pc->f(tt)-pt));
            typename curve__::tolerance_type tol;

            if (tol.approximately_equal(rtn, 0))
            {
              curve_g_functor<curve__> g;

              g.pc=pc;
              g.pt=pt;
              if (t>=1)
              {
                rtn=(g(1)-g(static_cast<typename curve__::data_type>(0.99)))/static_cast<typename curve__::data_type>(0.01);
              }
              else if (t<=0)
              {
                rtn=(g(static_cast<typename curve__::data_type>(0.01))-g(0))/static_cast<typename curve__::data_type>(0.01);
              }
              else
              {
                rtn=(g(t+static_cast<typename curve__::data_type>(0.01))-g(t))/static_cast<typename curve__::data_type>(0.01);
              }
            }

            return rtn;
          }
        };
      }

      template<typename curve__>
      typename curve__::data_type minimum_distance(typename curve__::data_type &t, const curve__ &c, const typename curve__::point_type &pt, const typename curve__::data_type &t0)
      {
        eli::mutil::nls::newton_raphson_constrained_method<typename curve__::data_type> nrm;
        int stat;
        internal::curve_g_functor<curve__> g;
        internal::curve_gp_functor<curve__> gp;
        typename curve__::data_type dist0, dist;
        typename curve__::tolerance_type tol;

        // setup the functors
        g.pc=&c;
        g.pt=pt;
        gp.pc=&c;
        gp.pt=pt;

        // setup the solver
        nrm.set_absolute_tolerance(tol.get_absolute_tolerance());
        nrm.set_max_iteration(10);
        if (c.open())
        {
          nrm.set_lower_condition(0, eli::mutil::nls::newton_raphson_constrained_method<typename curve__::data_type>::NRC_EXCLUSIVE);
          nrm.set_upper_condition(1, eli::mutil::nls::newton_raphson_constrained_method<typename curve__::data_type>::NRC_EXCLUSIVE);
        }
        else
        {
          nrm.set_periodic_condition(0, 1);
        }

        // set the initial guess
        nrm.set_initial_guess(t0);
        dist0=eli::geom::point::distance(c.f(t0), pt);

        // find the root
        stat = nrm.find_root(t, g, gp, 0);

        // if found root and it is within bounds and is closer than initial guess
        if (stat==eli::mutil::nls::newton_raphson_method<typename curve__::data_type>::converged)
        {
          assert((t>=0) && (t<=1));

          dist = eli::geom::point::distance(c.f(t), pt);
          if  (dist<=dist0)
          {
            return dist;
          }
        }
        else
        {
//             std::cout << "# not converged!" << std::endl;
        }

        // couldn't find better answer so return initial guess
        t=t0;
        return dist0;
      }

      template<typename curve__>
      typename curve__::data_type minimum_distance(typename curve__::data_type &t, const curve__ &c, const typename curve__::point_type &pt)
      {
        typename curve__::tolerance_type tol;
        std::list<std::pair<typename curve__::data_type, typename curve__::data_type>> tinit;
        typename std::list<std::pair<typename curve__::data_type, typename curve__::data_type>>::iterator it;
        std::pair<typename curve__::data_type, typename curve__::data_type> cand_pair;

        // possible that end points are closest, so start by checking them
        typename curve__::data_type dist, tt, dd;

        // first check is start, middle and (if needed) end points
        {
          t=0;
          dist=eli::geom::point::distance(c.f(t), pt);
          tt=0.5;
          dd=eli::geom::point::distance(c.f(tt), pt);
          if (dd<dist)
          {
            t=tt;
            dist=dd;
          }
          if (c.open())
          {
            tt=1;
            dd=eli::geom::point::distance(c.f(tt), pt);
            if (dd<dist)
            {
              t=tt;
              dist=dd;
            }
          }
        }
        cand_pair.first=t;
        cand_pair.second=dist;
        tinit.push_back(cand_pair);

        // need to pick initial guesses
        typename curve__::index_type i, deg(c.degree()), ssize;
        std::vector<typename curve__::data_type> tsample(2*deg+1);
        typename curve__::point_type p0, p1;
        typename curve__::data_type temp, tlen;

        // determine the sample parameters from the control polygon points
        ssize=tsample.size();
        i=0;
        p1=c.get_control_point(i);
        tsample[i]=0;
        for (++i; i<=deg; ++i)
        {
          p0=p1;
          p1=c.get_control_point(i);
          temp=eli::geom::point::distance(p0, p1)/2;
          tsample[2*i-1]=tsample[2*i-2]+temp;
          tsample[2*i]=tsample[2*i-1]+temp;
        }
        tlen=tsample[tsample.size()-1];

        // add points that are minimums
        {
          // find candidate starting locations using distance between sampled points on curve and point
          for (i=0; i<ssize; ++i)
          {
            temp=eli::geom::point::distance(c.f(tsample[i]/tlen), pt);
//             std::cout << "point #=" << i << "\tdist_temp=" << temp << std::endl;
            if (temp<=1.01*dist)
            {
              cand_pair.first=tsample[i]/tlen;
              cand_pair.second=temp;
              tinit.push_back(cand_pair);
              if (temp<dist)
              {
                t=cand_pair.first;
                dist=cand_pair.second;
                it=tinit.begin();
                while (it!=tinit.end())
                {
                  // check to see if distance is beyond new threshold and remove if so
                  if (it->second>1.01*dist)
                  {
                    it=tinit.erase(it);
                  }
                  else
                  {
                    ++it;
                  }
                }
              }
//               std::cout << "% added point #=" << i << "\twith t=" << tsample[i]/tlen << std::endl;
            }
          }
        }

//         std::cout << "# t guesses=" << tinit.size() << std::endl;

        // make sure have some solutions to iterate
//         tinit.push_back(0);
//         if (c.open())
//         {
//           tinit.push_back(1);
//         }

        // cycle through all possible minima to find best
        for (it=tinit.begin(); it!=tinit.end(); ++it)
        {
          dd=minimum_distance(tt, c, pt, it->first);
//           std::cout << "% completed root starting at" << *it << std::endl;

          assert((tt>=0) && (tt<=1));

          dd=eli::geom::point::distance(c.f(tt), pt);

          // check to see if is closer than previous minimum
          if (dd<dist)
          {
            t=tt;
            dist=dd;
          }

//               std::cout << "# dd=" << dd << std::endl;
//               std::cout << "# j=" << j << "\tnj=" << tinit.size() << std::endl;
        }

//         std::cout << "# returning dist=" << dist << std::endl;
        return dist;
      }
    }
  }
}
#endif
<commit_msg>Simplify minimum distance curve with no supplied starting point.<commit_after>/*********************************************************************************
* Copyright (c) 2013 David D. Marshall <ddmarsha@calpoly.edu>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    David D. Marshall - initial code and implementation
********************************************************************************/

#ifndef eli_geom_intersect_minimum_distance_curve_hpp
#define eli_geom_intersect_minimum_distance_curve_hpp

#include <cmath>
#include <vector>
#include <list>

#ifdef Success  // X11 #define collides with Eigen
#undef Success
#endif

#include "Eigen/Eigen"

#include "eli/mutil/nls/newton_raphson_constrained_method.hpp"

#include "eli/geom/point/distance.hpp"

namespace eli
{
  namespace geom
  {
    namespace intersect
    {
      namespace internal
      {
        template <typename curve__>
        struct curve_g_functor
        {
          const curve__ *pc;
          typename curve__::point_type pt;

          typename curve__::data_type operator()(const typename curve__::data_type &t) const
          {
            typename curve__::data_type tt(t);

            assert((tt>=0) && (tt<=1));

            return (pc->f(tt)-pt).dot(pc->fp(tt));
          }
        };

        template <typename curve__>
        struct curve_gp_functor
        {
          const curve__ *pc;
          typename curve__::point_type pt;

          typename curve__::data_type operator()(const typename curve__::data_type &t) const
          {
            typename curve__::data_type tt(t);

            assert((tt>=0) && (tt<=1));

            typename curve__::point_type fp(pc->fp(tt));
            typename curve__::data_type rtn(fp.dot(fp)+pc->fpp(tt).dot(pc->f(tt)-pt));
            typename curve__::tolerance_type tol;

            if (tol.approximately_equal(rtn, 0))
            {
              curve_g_functor<curve__> g;

              g.pc=pc;
              g.pt=pt;
              if (t>=1)
              {
                rtn=(g(1)-g(static_cast<typename curve__::data_type>(0.99)))/static_cast<typename curve__::data_type>(0.01);
              }
              else if (t<=0)
              {
                rtn=(g(static_cast<typename curve__::data_type>(0.01))-g(0))/static_cast<typename curve__::data_type>(0.01);
              }
              else
              {
                rtn=(g(t+static_cast<typename curve__::data_type>(0.01))-g(t))/static_cast<typename curve__::data_type>(0.01);
              }
            }

            return rtn;
          }
        };
      }

      template<typename curve__>
      typename curve__::data_type minimum_distance(typename curve__::data_type &t, const curve__ &c, const typename curve__::point_type &pt, const typename curve__::data_type &t0)
      {
        eli::mutil::nls::newton_raphson_constrained_method<typename curve__::data_type> nrm;
        int stat;
        internal::curve_g_functor<curve__> g;
        internal::curve_gp_functor<curve__> gp;
        typename curve__::data_type dist0, dist;
        typename curve__::tolerance_type tol;

        // setup the functors
        g.pc=&c;
        g.pt=pt;
        gp.pc=&c;
        gp.pt=pt;

        // setup the solver
        nrm.set_absolute_tolerance(tol.get_absolute_tolerance());
        nrm.set_max_iteration(10);
        if (c.open())
        {
          nrm.set_lower_condition(0, eli::mutil::nls::newton_raphson_constrained_method<typename curve__::data_type>::NRC_EXCLUSIVE);
          nrm.set_upper_condition(1, eli::mutil::nls::newton_raphson_constrained_method<typename curve__::data_type>::NRC_EXCLUSIVE);
        }
        else
        {
          nrm.set_periodic_condition(0, 1);
        }

        // set the initial guess
        nrm.set_initial_guess(t0);
        dist0=eli::geom::point::distance(c.f(t0), pt);

        // find the root
        stat = nrm.find_root(t, g, gp, 0);

        // if found root and it is within bounds and is closer than initial guess
        if (stat==eli::mutil::nls::newton_raphson_method<typename curve__::data_type>::converged)
        {
          assert((t>=0) && (t<=1));

          dist = eli::geom::point::distance(c.f(t), pt);
          if  (dist<=dist0)
          {
            return dist;
          }
        }
        else
        {
//             std::cout << "# not converged!" << std::endl;
        }

        // couldn't find better answer so return initial guess
        t=t0;
        return dist0;
      }

      template<typename curve__>
      typename curve__::data_type minimum_distance(typename curve__::data_type &t, const curve__ &c, const typename curve__::point_type &pt)
      {
        typename curve__::tolerance_type tol;
        std::list<std::pair<typename curve__::data_type, typename curve__::data_type>> tinit;
        typename std::list<std::pair<typename curve__::data_type, typename curve__::data_type>>::iterator it;
        std::pair<typename curve__::data_type, typename curve__::data_type> cand_pair;

        // possible that end points are closest, so start by checking them
        typename curve__::data_type dist, tt, dd;

        typename curve__::index_type i, n;

        // Just a guess
        n=2*c.degree()+1;

        // Evenly spaced in parameter, don't repeat 0/1 if closed curve.
        typename curve__::data_type dt;
        if (c.open())
        {
          dt = 1.0/(n-1);
        }
        else
        {
          dt = 1.0/n;
        }

        // Find closest of evenly spaced points.
        tt = 0;
        dist = std::numeric_limits<typename curve__::data_type>::max();
        for (i = 0; i < n; i++)
        {
          dd=eli::geom::point::distance(c.f(tt), pt);

          if( dd < dist )
          {
            t=tt;
            dist=dd;
          }
          tt+=dt;
          if( tt >= 1 )
          {
            tt=1;
          }
        }

        // Polish best point with Newton's method search.
        typename curve__::data_type t0(t);
        dist=minimum_distance(t, c, pt, t0);

        return dist;
      }
    }
  }
}
#endif
<|endoftext|>