<commit_before>/*
 *  qigroups.cpp
 *
 *  Copyright (c) 2016 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>

#include "itkTileImageFilter.h"
#include "itkSubtractImageFilter.h"
#include "itkDivideImageFilter.h"
#include "Filters/MeanImageFilter.h"

#include "QI/Types.h"
#include "QI/Util.h"
#include "QI/Option.h"

const std::string usage{
"Usage is: qigroups [options] output_file\n\
\n\
A utility for setting up merged 4D files for use with FSL randomise etc.\n\
The list of files to be merged is read from stdin, one per line.\n\
A list of groups must be passed in with the --groups option. This\n\
file should contain a single number per line, indicating the group each\n\
matching line of stdin corresponds to. Group 0 is ignore.\n"
};

int main(int argc, char **argv) {
    Eigen::initParallel();
    QI::OptionList opts(usage);
    QI::Switch sort('s',"sort","Sort merged file (and design matrix) in ascending group order", opts);
    QI::Switch pdiffs('F',"fracdiffs","Output fractional group mean diffs", opts);
    QI::Switch diffs('D',"diffs","Output group mean diffs", opts);
    QI::Switch means('m',"means","Output group means", opts);
    QI::Option<std::string> covars_path("",'C',"covars","Path to covariates file (added to design matrix)", opts);
    QI::Option<std::string> ftests_path("",'f',"ftests","Generate and save F-tests", opts);
    QI::Option<std::string> contrasts_path("",'c',"contrasts","Generate and save contrasts", opts);
    QI::Option<std::string> design_path("",'d',"design","Path to save design matrix", opts);
    QI::Option<std::string> output_path("",'o',"out","Path for output merged file", opts);
    QI::Option<std::string> group_path("",'g',"groups","File to read group numbers from", opts);
    QI::Switch verbose('v',"verbose","Print more information", opts);
    QI::Help help(opts);
    std::vector<std::string> file_paths = opts.parse(argc, argv);
    if (!group_path.set()) {
        std::cerr << opts << std::endl;
        std::cerr << "Group file must be set with --groups option" << std::endl;
        return EXIT_FAILURE;
    }

    std::ifstream group_file(*group_path);
    if (!group_file) {
        std::cerr << "Group file: " << *group_path << " does not exist" << std::endl;
        return EXIT_FAILURE;
    }
    if (*verbose) std::cout << "Reading group file" << std::endl;
    std::vector<int> group_list;
    int temp;
    while (group_file >> temp) {
        group_list.push_back(temp);
    }
    int n_groups = *std::max_element(group_list.begin(), group_list.end());
    int n_images = std::count_if(group_list.begin(), group_list.end(), [](int i){return i > 0;}); // Count non-zero elements

    if (file_paths.size() != group_list.size()) {
        std::cerr << "Group list size and number of files do not match." << std::endl;
        return EXIT_FAILURE;
    }

    std::vector<std::vector<QI::VolumeF::Pointer>> groups(n_groups);
    if (*verbose) std::cout << "Number of groups: " << n_groups << std::endl;
    if (*verbose) std::cout << "Number of images: " << n_images << std::endl;
    itk::FixedArray<unsigned int, 4> layout;
    layout[0] = layout[1] = layout[2] = 1;
    layout[3] = n_images;
    auto tiler = itk::TileImageFilter<QI::VolumeF, QI::SeriesF>::New();
    tiler->SetLayout(layout);

    std::ofstream design_file;
    if (design_path.set()) {
        if (*verbose) std::cout << "Design matrix will be saved to: " << *design_path << std::endl;
        design_file = std::ofstream(*design_path);
    }
    std::vector<std::vector<std::vector<double>>> covars(n_groups);
    std::ifstream covars_file;
    if (covars_path.set()) {
        covars_file = std::ifstream(*covars_path);
    }
    int out_index = 0;
    for (int i = 0; i < group_list.size(); i++) {
        const int group = group_list.at(i);
        if (group > 0) { // Ignore entries with a 0
            if (*verbose) std::cout << "File: " << file_paths.at(i) << " Group: " << group << std::flush;
            QI::VolumeF::Pointer ptr = QI::ReadImage(file_paths.at(i));
            groups.at(group - 1).push_back(ptr);
            std::vector<double> covar;
            if (covars_path.set()) {
                std::string covar_line;
                std::getline(covars_file, covar_line);
                std::stringstream css(covar_line);
                double c;
                while (css >> c) {
                    covar.push_back(c);
                }
                covars.at(group - 1).push_back(covar);
                if (*verbose) std::cout << ", read covariates.";
            }
            if (*verbose) std::cout << std::endl;
            if (!*sort) {
                tiler->SetInput(out_index, ptr);
                out_index++;
                if (design_path.set()) {
                    for (int g = 1; g <= n_groups; g++) {
                        if (g == group) {
                            design_file << "1\t";
                        } else {
                            design_file << "0\t";
                        }
                    }
                    if (covars_path.set()) {
                        for (auto& c : covar) {
                            design_file << c << "\t";
                        }
                    }
                    design_file << std::endl;
                }
            }
        } else {
            if (*verbose) std::cout << "Ignoring file: " << file_paths.at(i) << std::endl;
        }
    }
    if (*sort) {
        if (*verbose) std::cout << "Sorting." << std::endl;
        for (int g = 0; g < n_groups; g++) {
            for (int i = 0; i < groups.at(g).size(); i++) {
                tiler->SetInput(out_index, groups.at(g).at(i));
                out_index++;
                if (design_path.set()) {
                    for (int g2 = 0; g2 < n_groups; g2++) {
                        if (g2 == g) {
                            design_file << "1\t";
                        } else {
                            design_file << "0\t";
                        }
                    }
                    if (covars_path.set()) {
                        for (auto& c : covars.at(g).at(i)) {
                            design_file << c << "\t";
                        }
                    }
                    design_file << std::endl;
                }
            }
        }
    }
    int n_covars = covars_path.set() ? covars.front().front().size() : 0;
    if (contrasts_path.set()) {
        if (*verbose) std::cout << "Generating contrasts" << std::endl;
        std::ofstream con_file(*contrasts_path);
        for (int g = 0; g < n_groups; g++) {
            for (int g2 = 0; g2 < n_groups; g2++) {
                if (g2 == g) {
                    con_file << "1\t";
                } else if (g2 == ((g+1) % (n_groups))) {
                    con_file << "-1\t";
                } else {
                    con_file << "0\t";
                }
            }
            for (int c = 0; c < n_covars; c++) {
                con_file << "0\t";
            }
            con_file << std::endl;
        }
        for (int c = 0; c < 2*n_covars; c++) {
            for (int g = 0; g < n_groups; g++) {
                con_file << "0\t";
            }
            for (int c2 = 0; c2 < n_covars; c2++) {
                if ((c/2) == c2) {
                    con_file << ((c % 2 == 0) ? "1\t" : "-1\t");
                } else {
                    con_file << "0\t";
                }
            }
            con_file << std::endl;
        }
    }
    if (ftests_path.set()) {
        if (*verbose) std::cout << "Generating F-tests" << std::endl;
        std::ofstream fts_file(*ftests_path);
        for (int g = 0; g < n_groups; g++) { // Individual group comparisons
            for (int g2 = 0; g2 < n_groups; g2++) {
                fts_file << ((g2 == g) ? "1\t" : "0\t");
            }
            for (int c = 0; c < 2*n_covars; c++) {
                fts_file << "0\t";
            }
            fts_file << std::endl;
        }
        if (n_groups > 2) { // Main effect
            for (int g = 0; g < (n_groups - 1); g++) {
                fts_file << "1\t";
            }
            fts_file << "0\t";
            for (int c = 0; c < 2*n_covars; c++) {
                fts_file << "0\t";
            }
            fts_file << std::endl;
        }
    }
    if (*means | *diffs | *pdiffs) {
        std::vector<QI::VolumeF::Pointer> mean_imgs(n_groups, ITK_NULLPTR);
        for (int g = 0; g < n_groups; g++) {
            auto mean = itk::MeanImageFilter<QI::VolumeF>::New();
            for (int i = 0; i < groups.at(g).size(); i++) {
                mean->SetInput(i, groups.at(g).at(i));
            }
            mean->Update();
            mean_imgs.at(g) = mean->GetOutput();
            mean_imgs.at(g)->DisconnectPipeline();
            if (*means) {
                if (*verbose) std::cout << "Writing mean " << std::to_string(g+1) << std::endl;
                QI::WriteImage(mean_imgs.at(g), QI::StripExt(*output_path) + "_mean" + std::to_string(g+1) + ".nii");
            }
            if ((*diffs || *pdiffs) && g > 0) {
                auto diff = itk::SubtractImageFilter<QI::VolumeF, QI::VolumeF>::New();
                diff->SetInput1(mean_imgs.at(g));
                for (int g2 = 0; g2 < g; g2++) {
                    diff->SetInput2(mean_imgs.at(g2));
                    diff->Update();
                    if (*diffs) {
                        if (*verbose) std::cout << "Writing difference " << std::to_string(g+1) << " - " << std::to_string(g2+1) << std::endl;
                        QI::WriteImage(diff->GetOutput(), QI::StripExt(*output_path) + "_diff" + std::to_string(g+1) + "_" + std::to_string(g2+1) + ".nii");
                    }
                    if (*pdiffs) {
                        auto frac = itk::DivideImageFilter<QI::VolumeF, QI::VolumeF, QI::VolumeF>::New();
                        frac->SetInput1(diff->GetOutput());
                        frac->SetInput2(mean_imgs.at(g));
                        frac->Update();
                        if (*verbose) std::cout << "Writing fractional difference " << std::to_string(g+1) << " - " << std::to_string(g2+1) << std::endl;
                        QI::WriteImage(frac->GetOutput(), QI::StripExt(*output_path) + "_fdiff" + std::to_string(g+1) + "_" + std::to_string(g2 + 1) + ".nii");
                    }
                }
            }
        }
    }
    if (*verbose) std::cout << "Writing merged file: " << *output_path << std::endl;
    tiler->UpdateLargestPossibleRegion();
    // Reset space information because tiler messes it up
    QI::SeriesF::Pointer output = tiler->GetOutput();
    output->DisconnectPipeline();
    auto spacing    = output->GetSpacing();
    auto origin     = output->GetOrigin();
    auto direction  = output->GetDirection();
    spacing.Fill(1);
    origin.Fill(0);
    direction.SetIdentity();
    for (int i = 0; i < 3; i++) {
        spacing[i] = groups.at(0).at(0)->GetSpacing()[i];
        origin[i] =  groups.at(0).at(0)->GetOrigin()[i];
        for (int j = 0; j < 3; j++) {
            direction[i][j] = groups.at(0).at(0)->GetDirection()[i][j];
        }
    }
    output->SetSpacing(spacing);
    output->SetOrigin(origin);
    output->SetDirection(direction);
    QI::WriteImage<QI::SeriesF>(output, *output_path);
    return EXIT_SUCCESS;
}

<commit_msg>BUG: Covariates were not being ignore when groups were<commit_after>/*
 *  qigroups.cpp
 *
 *  Copyright (c) 2016 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>

#include "itkTileImageFilter.h"
#include "itkSubtractImageFilter.h"
#include "itkDivideImageFilter.h"
#include "Filters/MeanImageFilter.h"

#include "QI/Types.h"
#include "QI/Util.h"
#include "QI/Option.h"

const std::string usage{
"Usage is: qigroups [options] output_file\n\
\n\
A utility for setting up merged 4D files for use with FSL randomise etc.\n\
The list of files to be merged is read from stdin, one per line.\n\
A list of groups must be passed in with the --groups option. This\n\
file should contain a single number per line, indicating the group each\n\
matching line of stdin corresponds to. Group 0 is ignore.\n"
};

int main(int argc, char **argv) {
    Eigen::initParallel();
    QI::OptionList opts(usage);
    QI::Switch sort('s',"sort","Sort merged file (and design matrix) in ascending group order", opts);
    QI::Switch pdiffs('F',"fracdiffs","Output fractional group mean diffs", opts);
    QI::Switch diffs('D',"diffs","Output group mean diffs", opts);
    QI::Switch means('m',"means","Output group means", opts);
    QI::Option<std::string> covars_path("",'C',"covars","Path to covariates file (added to design matrix)", opts);
    QI::Option<std::string> ftests_path("",'f',"ftests","Generate and save F-tests", opts);
    QI::Option<std::string> contrasts_path("",'c',"contrasts","Generate and save contrasts", opts);
    QI::Option<std::string> design_path("",'d',"design","Path to save design matrix", opts);
    QI::Option<std::string> output_path("",'o',"out","Path for output merged file", opts);
    QI::Option<std::string> group_path("",'g',"groups","File to read group numbers from", opts);
    QI::Switch verbose('v',"verbose","Print more information", opts);
    QI::Help help(opts);
    std::vector<std::string> file_paths = opts.parse(argc, argv);
    if (!group_path.set()) {
        std::cerr << opts << std::endl;
        std::cerr << "Group file must be set with --groups option" << std::endl;
        return EXIT_FAILURE;
    }

    std::ifstream group_file(*group_path);
    if (!group_file) {
        std::cerr << "Group file: " << *group_path << " does not exist" << std::endl;
        return EXIT_FAILURE;
    }
    if (*verbose) std::cout << "Reading group file" << std::endl;
    std::vector<int> group_list;
    int temp;
    while (group_file >> temp) {
        group_list.push_back(temp);
    }
    int n_groups = *std::max_element(group_list.begin(), group_list.end());
    int n_images = std::count_if(group_list.begin(), group_list.end(), [](int i){return i > 0;}); // Count non-zero elements

    if (file_paths.size() != group_list.size()) {
        std::cerr << "Group list size and number of files do not match." << std::endl;
        return EXIT_FAILURE;
    }

    std::vector<std::vector<QI::VolumeF::Pointer>> groups(n_groups);
    if (*verbose) std::cout << "Number of groups: " << n_groups << std::endl;
    if (*verbose) std::cout << "Number of images: " << n_images << std::endl;
    itk::FixedArray<unsigned int, 4> layout;
    layout[0] = layout[1] = layout[2] = 1;
    layout[3] = n_images;
    auto tiler = itk::TileImageFilter<QI::VolumeF, QI::SeriesF>::New();
    tiler->SetLayout(layout);

    std::ofstream design_file;
    if (design_path.set()) {
        if (*verbose) std::cout << "Design matrix will be saved to: " << *design_path << std::endl;
        design_file = std::ofstream(*design_path);
    }
    std::vector<std::vector<std::vector<double>>> covars(n_groups);
    std::ifstream covars_file;
    if (covars_path.set()) {
        covars_file = std::ifstream(*covars_path);
    }
    int out_index = 0;
    for (int i = 0; i < group_list.size(); i++) {
        const int group = group_list.at(i);
        if (group > 0) { // Ignore entries with a 0
            if (*verbose) std::cout << "File: " << file_paths.at(i) << " Group: " << group << std::flush;
            QI::VolumeF::Pointer ptr = QI::ReadImage(file_paths.at(i));
            groups.at(group - 1).push_back(ptr);
            std::vector<double> covar;
            if (covars_path.set()) {
                std::string covar_line;
                std::getline(covars_file, covar_line);
                std::stringstream css(covar_line);
                double c;
                while (css >> c) {
                    covar.push_back(c);
                }
                covars.at(group - 1).push_back(covar);
                if (*verbose) std::cout << ", read covariates.";
            }
            if (*verbose) std::cout << std::endl;
            if (!*sort) {
                tiler->SetInput(out_index, ptr);
                out_index++;
                if (design_path.set()) {
                    for (int g = 1; g <= n_groups; g++) {
                        if (g == group) {
                            design_file << "1\t";
                        } else {
                            design_file << "0\t";
                        }
                    }
                    if (covars_path.set()) {
                        for (auto& c : covar) {
                            design_file << c << "\t";
                        }
                    }
                    design_file << std::endl;
                }
            }
        } else {
            if (*verbose) std::cout << "Ignoring file: " << file_paths.at(i) << std::endl;
            // Eat a line in the covariates file as well
            if (covars_path.set()) {
                std::string covar_line;
                std::getline(covars_file, covar_line);
            }
        }
    }
    if (*sort) {
        if (*verbose) std::cout << "Sorting." << std::endl;
        for (int g = 0; g < n_groups; g++) {
            for (int i = 0; i < groups.at(g).size(); i++) {
                tiler->SetInput(out_index, groups.at(g).at(i));
                out_index++;
                if (design_path.set()) {
                    for (int g2 = 0; g2 < n_groups; g2++) {
                        if (g2 == g) {
                            design_file << "1\t";
                        } else {
                            design_file << "0\t";
                        }
                    }
                    if (covars_path.set()) {
                        for (auto& c : covars.at(g).at(i)) {
                            design_file << c << "\t";
                        }
                    }
                    design_file << std::endl;
                }
            }
        }
    }
    int n_covars = covars_path.set() ? covars.front().front().size() : 0;
    if (contrasts_path.set()) {
        if (*verbose) std::cout << "Generating contrasts" << std::endl;
        std::ofstream con_file(*contrasts_path);
        for (int g = 0; g < n_groups; g++) {
            for (int g2 = 0; g2 < n_groups; g2++) {
                if (g2 == g) {
                    con_file << "1\t";
                } else if (g2 == ((g+1) % (n_groups))) {
                    con_file << "-1\t";
                } else {
                    con_file << "0\t";
                }
            }
            for (int c = 0; c < n_covars; c++) {
                con_file << "0\t";
            }
            con_file << std::endl;
        }
        for (int c = 0; c < 2*n_covars; c++) {
            for (int g = 0; g < n_groups; g++) {
                con_file << "0\t";
            }
            for (int c2 = 0; c2 < n_covars; c2++) {
                if ((c/2) == c2) {
                    con_file << ((c % 2 == 0) ? "1\t" : "-1\t");
                } else {
                    con_file << "0\t";
                }
            }
            con_file << std::endl;
        }
    }
    if (ftests_path.set()) {
        if (*verbose) std::cout << "Generating F-tests" << std::endl;
        std::ofstream fts_file(*ftests_path);
        for (int g = 0; g < n_groups; g++) { // Individual group comparisons
            for (int g2 = 0; g2 < n_groups; g2++) {
                fts_file << ((g2 == g) ? "1\t" : "0\t");
            }
            for (int c = 0; c < 2*n_covars; c++) {
                fts_file << "0\t";
            }
            fts_file << std::endl;
        }
        if (n_groups > 2) { // Main effect
            for (int g = 0; g < (n_groups - 1); g++) {
                fts_file << "1\t";
            }
            fts_file << "0\t";
            for (int c = 0; c < 2*n_covars; c++) {
                fts_file << "0\t";
            }
            fts_file << std::endl;
        }
    }
    if (*means | *diffs | *pdiffs) {
        std::vector<QI::VolumeF::Pointer> mean_imgs(n_groups, ITK_NULLPTR);
        for (int g = 0; g < n_groups; g++) {
            auto mean = itk::MeanImageFilter<QI::VolumeF>::New();
            for (int i = 0; i < groups.at(g).size(); i++) {
                mean->SetInput(i, groups.at(g).at(i));
            }
            mean->Update();
            mean_imgs.at(g) = mean->GetOutput();
            mean_imgs.at(g)->DisconnectPipeline();
            if (*means) {
                if (*verbose) std::cout << "Writing mean " << std::to_string(g+1) << std::endl;
                QI::WriteImage(mean_imgs.at(g), QI::StripExt(*output_path) + "_mean" + std::to_string(g+1) + ".nii");
            }
            if ((*diffs || *pdiffs) && g > 0) {
                auto diff = itk::SubtractImageFilter<QI::VolumeF, QI::VolumeF>::New();
                diff->SetInput1(mean_imgs.at(g));
                for (int g2 = 0; g2 < g; g2++) {
                    diff->SetInput2(mean_imgs.at(g2));
                    diff->Update();
                    if (*diffs) {
                        if (*verbose) std::cout << "Writing difference " << std::to_string(g+1) << " - " << std::to_string(g2+1) << std::endl;
                        QI::WriteImage(diff->GetOutput(), QI::StripExt(*output_path) + "_diff" + std::to_string(g+1) + "_" + std::to_string(g2+1) + ".nii");
                    }
                    if (*pdiffs) {
                        auto frac = itk::DivideImageFilter<QI::VolumeF, QI::VolumeF, QI::VolumeF>::New();
                        frac->SetInput1(diff->GetOutput());
                        frac->SetInput2(mean_imgs.at(g));
                        frac->Update();
                        if (*verbose) std::cout << "Writing fractional difference " << std::to_string(g+1) << " - " << std::to_string(g2+1) << std::endl;
                        QI::WriteImage(frac->GetOutput(), QI::StripExt(*output_path) + "_fdiff" + std::to_string(g+1) + "_" + std::to_string(g2 + 1) + ".nii");
                    }
                }
            }
        }
    }
    if (*verbose) std::cout << "Writing merged file: " << *output_path << std::endl;
    tiler->UpdateLargestPossibleRegion();
    // Reset space information because tiler messes it up
    QI::SeriesF::Pointer output = tiler->GetOutput();
    output->DisconnectPipeline();
    auto spacing    = output->GetSpacing();
    auto origin     = output->GetOrigin();
    auto direction  = output->GetDirection();
    spacing.Fill(1);
    origin.Fill(0);
    direction.SetIdentity();
    for (int i = 0; i < 3; i++) {
        spacing[i] = groups.at(0).at(0)->GetSpacing()[i];
        origin[i] =  groups.at(0).at(0)->GetOrigin()[i];
        for (int j = 0; j < 3; j++) {
            direction[i][j] = groups.at(0).at(0)->GetDirection()[i][j];
        }
    }
    output->SetSpacing(spacing);
    output->SetOrigin(origin);
    output->SetDirection(direction);
    QI::WriteImage<QI::SeriesF>(output, *output_path);
    return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>/*
 *  qiunwrap.cpp
 *
 *  Created by Tobias Wood on 11/06/2015.
 *  Copyright (c) 2015 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <time.h>
#include <getopt.h>
#include <iostream>
#include <atomic>
#include "Eigen/Dense"

#include "itkImageSource.h"
#include "itkConstNeighborhoodIterator.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkMultiplyImageFilter.h"
#include "itkForwardFFTImageFilter.h"
#include "itkInverseFFTImageFilter.h"
#include "itkFFTPadImageFilter.h"
#include "itkMaskImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkBinaryCrossStructuringElement.h"
#include "itkBinaryBallStructuringElement.h"
#include "itkBinaryErodeImageFilter.h"
#include "Types.h"
#include "Util.h"

using namespace std;
using namespace Eigen;

namespace itk {

class DiscreteLaplacePhaseFilter : public ImageToImageFilter<QI::ImageF, QI::ImageF> {
protected:

public:
	/** Standard class typedefs. */
    typedef QI::ImageF     TImage;

	typedef DiscreteLaplacePhaseFilter         Self;
	typedef ImageToImageFilter<TImage, TImage> Superclass;
	typedef SmartPointer<Self>                 Pointer;
	typedef typename TImage::RegionType        RegionType;

	itkNewMacro(Self);
	itkTypeMacro(DiscreteLaplacePhaseFilter, DiscreteLaplacePhaseFilter);

    void SetInput(const TImage *img) override      { this->SetNthInput(0, const_cast<TImage*>(img)); }
	typename TImage::ConstPointer GetInput() const { return static_cast<const TImage *>(this->ProcessObject::GetInput(0)); }

	virtual void GenerateOutputInformation() override {
		Superclass::GenerateOutputInformation();
		auto op = this->GetOutput();
		op->SetRegions(this->GetInput()->GetLargestPossibleRegion());
		op->Allocate();
	}

protected:
	DiscreteLaplacePhaseFilter() {
		this->SetNumberOfRequiredInputs(1);
		this->SetNumberOfRequiredOutputs(1);
		this->SetNthOutput(0, this->MakeOutput(0));
	}
	~DiscreteLaplacePhaseFilter() {}

	DataObject::Pointer MakeOutput(unsigned int idx) {
		//std::cout <<  __PRETTY_FUNCTION__ << endl;
		if (idx == 0) {
			DataObject::Pointer output = (TImage::New()).GetPointer();
			return output.GetPointer();
		} else {
			std::cerr << "No output " << idx << std::endl;
			return NULL;
		}
	}

    virtual void ThreadedGenerateData(const RegionType &region, ThreadIdType threadId) override {
		//std::cout <<  __PRETTY_FUNCTION__ << endl;
		ConstNeighborhoodIterator<TImage>::RadiusType radius;
		radius.Fill(1);
		ConstNeighborhoodIterator<TImage> inputIter(radius, this->GetInput(), region);
		ImageRegionIterator<TImage> outputIter(this->GetOutput(), region);

		vector<ConstNeighborhoodIterator<TImage>::OffsetType> back, fwrd;
		back.push_back({{-1, 0, 0}});
		fwrd.push_back({{ 1, 0, 0}});
		back.push_back({{ 0,-1, 0}});
		fwrd.push_back({{ 0, 1, 0}});
		back.push_back({{ 0, 0,-1}});
		fwrd.push_back({{ 0, 0, 1}});

		TImage::SpacingType spacing = this->GetInput()->GetSpacing();
		TImage::SpacingType s_sqr = spacing * spacing;
		while(!inputIter.IsAtEnd()) {
			double sum = 0;
            double cphase = inputIter.GetCenterPixel();
            complex<double> c = std::polar(1., cphase);
            for (int i = 0; i < fwrd.size(); ++i) {
                double bphase = inputIter.GetPixel(back[i]);
                double fphase = inputIter.GetPixel(fwrd[i]);
                complex<double> b = std::polar(1., bphase);
                complex<double> f = std::polar(1., fphase);
                sum += std::arg((f*b)/(c*c)) / s_sqr[i];
            }
            outputIter.Set(sum / 7.);
			++inputIter;
			++outputIter;
		}
	}

private:
	DiscreteLaplacePhaseFilter(const Self &); //purposely not implemented
	void operator=(const Self &);  //purposely not implemented
};

class DiscreteInverseLaplace : public ImageSource<QI::ImageF> {
public:
    typedef QI::ImageF             TImage;
	typedef DiscreteInverseLaplace Self;
	typedef ImageSource<TImage>    Superclass;
	typedef SmartPointer<Self>     Pointer;

	itkNewMacro(Self);
	itkTypeMacro(DiscreteInverseLaplace, ImageSource);

    void SetImageProperties(const TImage *img) {
        m_region = img->GetLargestPossibleRegion();
		m_spacing = img->GetSpacing();
		m_direction = img->GetDirection();
		m_origin = img->GetOrigin();
	}

protected:
    typename TImage::RegionType    m_region;
	typename TImage::SpacingType   m_spacing;
	typename TImage::DirectionType m_direction;
	typename TImage::PointType     m_origin;

	DiscreteInverseLaplace(){}
	~DiscreteInverseLaplace(){}
    virtual void GenerateData() override {
		typename TImage::Pointer output = this->GetOutput();
        output->SetRegions(m_region);
		output->Allocate();
		output->SetSpacing(m_spacing);
		output->SetDirection(m_direction);
		output->SetOrigin(m_origin);
		itk::ImageRegionIteratorWithIndex<TImage> imageIt(output,output->GetLargestPossibleRegion());
		imageIt.GoToBegin();
		imageIt.Set(0.); // There is a pole here
		++imageIt;
		while(!imageIt.IsAtEnd()) {
            auto index = imageIt.GetIndex() - m_region.GetIndex(); // Might be padded to a negative start
			double val = 0;
			for (int i = 0; i < 3; i++) {
                val += 2. - 2. * cos(index[i] * 2. * M_PI / m_region.GetSize()[i]);
            }
            val /= 7.;
			imageIt.Set(1./val);
			++imageIt;
		}
	}

private:
	DiscreteInverseLaplace(const Self &);
	void operator=(const Self &);
};

} // End namespace itk

//******************************************************************************
// Arguments / Usage
//******************************************************************************
const string usage {
"Usage is: qiunwrap [options] input \n\
\n\
Input is a single wrapped phase volume\n\
\n\
Options:\n\
	--help, -h        : Print this message.\n\
	--verbose, -v     : Print more information.\n\
	--out, -o path    : Specify an output filename (default image base).\n\
	--mask, -m file   : Mask input with specified file.\n\
    --erode, -e N     : Erode mask by N voxels (Default 1).\n\
    --savelap, -l     : Save the Laplace filtered phase.\n\
    --threads, -T N   : Use N threads (default=hardware limit).\n"
};

const struct option long_options[] = {
	{"help", no_argument, 0, 'h'},
	{"verbose", no_argument, 0, 'v'},
	{"out", required_argument, 0, 'o'},
	{"mask", required_argument, 0, 'm'},
    {"erode", required_argument, 0, 'e'},
    {"savelap", no_argument, 0, 'l'},
	{"threads", required_argument, 0, 'T'},
	{0, 0, 0, 0}
};
const char *short_options = "hvo:m:e:lT:";

//******************************************************************************
// Main
//******************************************************************************
int main(int argc, char **argv) {
	Eigen::initParallel();

    bool verbose = false, savelap = false;
    int erodeRadius = 1;
	string prefix;
    QI::MaskImage::Pointer mask = ITK_NULLPTR;
	int indexptr = 0, c;
	while ((c = getopt_long(argc, argv, short_options, long_options, &indexptr)) != -1) {
		switch (c) {
			case 'v': verbose = true; break;
            case 'm': {
                if (verbose) cout << "Reading mask file " << optarg << endl;
                auto maskFile = QI::ReadImageF::New();
                auto maskThresh = itk::BinaryThresholdImageFilter<QI::ImageF, QI::MaskImage>::New();
                maskFile->SetFileName(optarg);
                maskThresh->SetInput(maskFile->GetOutput());
                maskThresh->SetLowerThreshold(1.0);
                maskThresh->SetInsideValue(1);
                maskThresh->Update();
                mask = maskThresh->GetOutput();
                mask->DisconnectPipeline();
            } break;
            case 'e': erodeRadius = atoi(optarg); break;
			case 'o':
				prefix = optarg;
				cout << "Output prefix will be: " << prefix << endl;
				break;
            case 'l': savelap = true; break;
			case 'T': itk::MultiThreader::SetGlobalMaximumNumberOfThreads(atoi(optarg)); break;
			case 'h':
				cout << usage << endl;
				return EXIT_SUCCESS;
			case '?': // getopt will print an error message
				return EXIT_FAILURE;
			default:
				cout << "Unhandled option " << string(1, c) << endl;
				return EXIT_FAILURE;
		}
	}
	if ((argc - optind) != 1) {
		cout << "Incorrect number of arguments." << endl << usage << endl;
		return EXIT_FAILURE;
	}
	if (verbose) cout << "Opening input file: " << argv[optind] << endl;
	string fname(argv[optind++]);
	if (prefix == "")
		prefix = fname.substr(0, fname.find(".nii"));
	string outname = prefix + "_unwrap" + QI::OutExt();
	if (verbose) cout << "Output filename: " << outname << endl;

    auto inFile = QI::ReadImageF::New();
	auto calcLaplace = itk::DiscreteLaplacePhaseFilter::New();
	inFile->SetFileName(fname);
	inFile->Update(); // Need the size info
	calcLaplace->SetInput(inFile->GetOutput());
    calcLaplace->Update();
    if (savelap) {
        auto outLap = QI::WriteImageF::New();
        outLap->SetInput(calcLaplace->GetOutput());
        outLap->SetFileName(prefix + "_laplace" + QI::OutExt());
        outLap->Update();
    }

    QI::ImageF::Pointer lap = calcLaplace->GetOutput();
    if (mask) {
        auto masker = itk::MaskImageFilter<QI::ImageF, QI::MaskImage>::New();
        masker->SetInput(calcLaplace->GetOutput());
        masker->SetMaskImage(mask);
        if (erodeRadius > 0) {
            if (verbose) cout << "Eroding mask by " << erodeRadius << " voxels" << endl;
            typedef itk::BinaryBallStructuringElement<QI::MaskImage::PixelType, 3> StructuringElementType;
            StructuringElementType structuringElement;
            structuringElement.SetRadius(erodeRadius);
            structuringElement.CreateStructuringElement();

            typedef itk::BinaryErodeImageFilter <QI::MaskImage, QI::MaskImage, StructuringElementType> BinaryErodeImageFilterType;
            BinaryErodeImageFilterType::Pointer erodeFilter = BinaryErodeImageFilterType::New();
            erodeFilter->SetInput(mask);
            erodeFilter->SetErodeValue(1);
            erodeFilter->SetKernel(structuringElement);
            erodeFilter->Update();
            auto checkMask = itk::ImageFileWriter<QI::MaskImage>::New();
            checkMask->SetInput(erodeFilter->GetOutput());
            checkMask->SetFileName(prefix + "_ero_mask" + QI::OutExt());
            checkMask->Update();
            masker->SetMaskImage(erodeFilter->GetOutput());
        }
        if (verbose) cout << "Applying mask" << endl;
        masker->Update();
        lap = masker->GetOutput();
        lap->DisconnectPipeline();
    }

    if (verbose) cout << "Padding image to valid FFT size." << endl;
    typedef itk::FFTPadImageFilter<QI::ImageF> PadFFTType;
    auto padFFT = PadFFTType::New();
    padFFT->SetInput(lap);
    padFFT->Update();

    if (verbose) {
        cout << "Padded image size: " << padFFT->GetOutput()->GetLargestPossibleRegion().GetSize() << endl;
        cout << "Calculating Forward FFT." << endl;
    }
    typedef itk::ForwardFFTImageFilter<QI::ImageF> FFFTType;
	auto forwardFFT = FFFTType::New();
    forwardFFT->SetInput(padFFT->GetOutput());
    forwardFFT->Update();

	if (verbose) cout << "Generating Inverse Laplace Kernel." << endl;
	auto inverseLaplace = itk::DiscreteInverseLaplace::New();
    inverseLaplace->SetImageProperties(padFFT->GetOutput());
    inverseLaplace->Update();

    if (verbose) cout << "Multiplying." << endl;
    auto mult = itk::MultiplyImageFilter<QI::ImageXF, QI::ImageF, QI::ImageXF>::New();
	mult->SetInput1(forwardFFT->GetOutput());
	mult->SetInput2(inverseLaplace->GetOutput());

	if (verbose) cout << "Inverse FFT." << endl;
    auto inverseFFT = itk::InverseFFTImageFilter<QI::ImageXF, QI::ImageF>::New();
	inverseFFT->SetInput(mult->GetOutput());
    inverseFFT->Update();

    if (verbose) cout << "Extracting original size image" << endl;
    auto extract = itk::ExtractImageFilter<QI::ImageF, QI::ImageF>::New();
    extract->SetInput(inverseFFT->GetOutput());
    extract->SetDirectionCollapseToSubmatrix();
    extract->SetExtractionRegion(calcLaplace->GetOutput()->GetLargestPossibleRegion());
    extract->Update();

    auto outFile = QI::WriteImageF::New();
    if (mask) {
        if (verbose) cout << "Re-applying mask" << endl;
        auto masker = itk::MaskImageFilter<QI::ImageF, QI::MaskImage>::New();
        masker->SetMaskImage(mask);
        masker->SetInput(extract->GetOutput());
        masker->Update();
        outFile->SetInput(masker->GetOutput());
    } else {
        outFile->SetInput(extract->GetOutput());
    }
	outFile->SetFileName(outname);
    if (verbose) cout << "Writing output." << endl;
	outFile->Update();
	if (verbose) cout << "Finished." << endl;
	return EXIT_SUCCESS;
}
<commit_msg>Changed the save Laplacian flag to a generalised debug flag.<commit_after>/*
 *  qiunwrap.cpp
 *
 *  Created by Tobias Wood on 11/06/2015.
 *  Copyright (c) 2015 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <time.h>
#include <getopt.h>
#include <iostream>
#include <atomic>
#include "Eigen/Dense"

#include "itkImageSource.h"
#include "itkConstNeighborhoodIterator.h"
#include "itkImageRegionIteratorWithIndex.h"
#include "itkMultiplyImageFilter.h"
#include "itkForwardFFTImageFilter.h"
#include "itkInverseFFTImageFilter.h"
#include "itkFFTPadImageFilter.h"
#include "itkMaskImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkBinaryCrossStructuringElement.h"
#include "itkBinaryBallStructuringElement.h"
#include "itkBinaryErodeImageFilter.h"
#include "Types.h"
#include "Util.h"

using namespace std;
using namespace Eigen;

namespace itk {

class DiscreteLaplacePhaseFilter : public ImageToImageFilter<QI::ImageF, QI::ImageF> {
protected:

public:
	/** Standard class typedefs. */
    typedef QI::ImageF     TImage;

	typedef DiscreteLaplacePhaseFilter         Self;
	typedef ImageToImageFilter<TImage, TImage> Superclass;
	typedef SmartPointer<Self>                 Pointer;
	typedef typename TImage::RegionType        RegionType;

	itkNewMacro(Self);
	itkTypeMacro(DiscreteLaplacePhaseFilter, DiscreteLaplacePhaseFilter);

    void SetInput(const TImage *img) override      { this->SetNthInput(0, const_cast<TImage*>(img)); }
	typename TImage::ConstPointer GetInput() const { return static_cast<const TImage *>(this->ProcessObject::GetInput(0)); }

	virtual void GenerateOutputInformation() override {
		Superclass::GenerateOutputInformation();
		auto op = this->GetOutput();
		op->SetRegions(this->GetInput()->GetLargestPossibleRegion());
		op->Allocate();
	}

protected:
	DiscreteLaplacePhaseFilter() {
		this->SetNumberOfRequiredInputs(1);
		this->SetNumberOfRequiredOutputs(1);
		this->SetNthOutput(0, this->MakeOutput(0));
	}
	~DiscreteLaplacePhaseFilter() {}

	DataObject::Pointer MakeOutput(unsigned int idx) {
		//std::cout <<  __PRETTY_FUNCTION__ << endl;
		if (idx == 0) {
			DataObject::Pointer output = (TImage::New()).GetPointer();
			return output.GetPointer();
		} else {
			std::cerr << "No output " << idx << std::endl;
			return NULL;
		}
	}

    virtual void ThreadedGenerateData(const RegionType &region, ThreadIdType threadId) override {
		//std::cout <<  __PRETTY_FUNCTION__ << endl;
		ConstNeighborhoodIterator<TImage>::RadiusType radius;
		radius.Fill(1);
		ConstNeighborhoodIterator<TImage> inputIter(radius, this->GetInput(), region);
		ImageRegionIterator<TImage> outputIter(this->GetOutput(), region);

		vector<ConstNeighborhoodIterator<TImage>::OffsetType> back, fwrd;
		back.push_back({{-1, 0, 0}});
		fwrd.push_back({{ 1, 0, 0}});
		back.push_back({{ 0,-1, 0}});
		fwrd.push_back({{ 0, 1, 0}});
		back.push_back({{ 0, 0,-1}});
		fwrd.push_back({{ 0, 0, 1}});

		TImage::SpacingType spacing = this->GetInput()->GetSpacing();
		TImage::SpacingType s_sqr = spacing * spacing;
		while(!inputIter.IsAtEnd()) {
			double sum = 0;
            double cphase = inputIter.GetCenterPixel();
            complex<double> c = std::polar(1., cphase);
            for (int i = 0; i < fwrd.size(); ++i) {
                double bphase = inputIter.GetPixel(back[i]);
                double fphase = inputIter.GetPixel(fwrd[i]);
                complex<double> b = std::polar(1., bphase);
                complex<double> f = std::polar(1., fphase);
                sum += std::arg((f*b)/(c*c)) / s_sqr[i];
            }
            outputIter.Set(sum / 7.);
			++inputIter;
			++outputIter;
		}
	}

private:
	DiscreteLaplacePhaseFilter(const Self &); //purposely not implemented
	void operator=(const Self &);  //purposely not implemented
};

class DiscreteInverseLaplace : public ImageSource<QI::ImageF> {
public:
    typedef QI::ImageF             TImage;
	typedef DiscreteInverseLaplace Self;
	typedef ImageSource<TImage>    Superclass;
	typedef SmartPointer<Self>     Pointer;

	itkNewMacro(Self);
	itkTypeMacro(DiscreteInverseLaplace, ImageSource);

    void SetImageProperties(const TImage *img) {
        m_region = img->GetLargestPossibleRegion();
		m_spacing = img->GetSpacing();
		m_direction = img->GetDirection();
		m_origin = img->GetOrigin();
	}

protected:
    typename TImage::RegionType    m_region;
	typename TImage::SpacingType   m_spacing;
	typename TImage::DirectionType m_direction;
	typename TImage::PointType     m_origin;

	DiscreteInverseLaplace(){}
	~DiscreteInverseLaplace(){}
    virtual void GenerateData() override {
		typename TImage::Pointer output = this->GetOutput();
        output->SetRegions(m_region);
		output->Allocate();
		output->SetSpacing(m_spacing);
		output->SetDirection(m_direction);
		output->SetOrigin(m_origin);
		itk::ImageRegionIteratorWithIndex<TImage> imageIt(output,output->GetLargestPossibleRegion());
		imageIt.GoToBegin();
		imageIt.Set(0.); // There is a pole here
		++imageIt;
		while(!imageIt.IsAtEnd()) {
            auto index = imageIt.GetIndex() - m_region.GetIndex(); // Might be padded to a negative start
			double val = 0;
			for (int i = 0; i < 3; i++) {
                val += 2. - 2. * cos(index[i] * 2. * M_PI / m_region.GetSize()[i]);
            }
            val /= 7.;
			imageIt.Set(1./val);
			++imageIt;
		}
	}

private:
	DiscreteInverseLaplace(const Self &);
	void operator=(const Self &);
};

} // End namespace itk

//******************************************************************************
// Arguments / Usage
//******************************************************************************
const string usage {
"Usage is: qiunwrap [options] input \n\
\n\
Input is a single wrapped phase volume\n\
\n\
Options:\n\
	--help, -h        : Print this message.\n\
	--verbose, -v     : Print more information.\n\
	--out, -o path    : Specify an output filename (default image base).\n\
	--mask, -m file   : Mask input with specified file.\n\
    --erode, -e N     : Erode mask by N voxels (Default 1).\n\
    --debug, -d       : Save all pipeline steps.\n\
    --threads, -T N   : Use N threads (default=hardware limit).\n"
};

const struct option long_options[] = {
	{"help", no_argument, 0, 'h'},
	{"verbose", no_argument, 0, 'v'},
	{"out", required_argument, 0, 'o'},
	{"mask", required_argument, 0, 'm'},
    {"erode", required_argument, 0, 'e'},
    {"debug", no_argument, 0, 'd'},
	{"threads", required_argument, 0, 'T'},
	{0, 0, 0, 0}
};
const char *short_options = "hvo:m:e:dT:";

//******************************************************************************
// Main
//******************************************************************************
int main(int argc, char **argv) {
	Eigen::initParallel();

    bool verbose = false, debug = false;
    int erodeRadius = 1;
	string prefix;
    QI::MaskImage::Pointer mask = ITK_NULLPTR;
	int indexptr = 0, c;
	while ((c = getopt_long(argc, argv, short_options, long_options, &indexptr)) != -1) {
		switch (c) {
			case 'v': verbose = true; break;
            case 'm': {
                if (verbose) cout << "Reading mask file " << optarg << endl;
                auto maskFile = QI::ReadImageF::New();
                auto maskThresh = itk::BinaryThresholdImageFilter<QI::ImageF, QI::MaskImage>::New();
                maskFile->SetFileName(optarg);
                maskThresh->SetInput(maskFile->GetOutput());
                maskThresh->SetLowerThreshold(1.0);
                maskThresh->SetInsideValue(1);
                maskThresh->Update();
                mask = maskThresh->GetOutput();
                mask->DisconnectPipeline();
            } break;
            case 'e': erodeRadius = atoi(optarg); break;
			case 'o':
				prefix = optarg;
				cout << "Output prefix will be: " << prefix << endl;
				break;
            case 'd': debug = true; break;
			case 'T': itk::MultiThreader::SetGlobalMaximumNumberOfThreads(atoi(optarg)); break;
			case 'h':
				cout << usage << endl;
				return EXIT_SUCCESS;
			case '?': // getopt will print an error message
				return EXIT_FAILURE;
			default:
				cout << "Unhandled option " << string(1, c) << endl;
				return EXIT_FAILURE;
		}
	}
	if ((argc - optind) != 1) {
		cout << "Incorrect number of arguments." << endl << usage << endl;
		return EXIT_FAILURE;
	}
	if (verbose) cout << "Opening input file: " << argv[optind] << endl;
	string fname(argv[optind++]);
	if (prefix == "")
		prefix = fname.substr(0, fname.find(".nii"));
	string outname = prefix + "_unwrap" + QI::OutExt();
	if (verbose) cout << "Output filename: " << outname << endl;

    auto inFile = QI::ReadImageF::New();
	auto calcLaplace = itk::DiscreteLaplacePhaseFilter::New();
	inFile->SetFileName(fname);
	inFile->Update(); // Need the size info
	calcLaplace->SetInput(inFile->GetOutput());
    calcLaplace->Update();
    if (debug) QI::writeResult(calcLaplace->GetOutput(), prefix + "_step1_laplace" + QI::OutExt());

    QI::ImageF::Pointer lap = calcLaplace->GetOutput();
    if (mask) {
        auto masker = itk::MaskImageFilter<QI::ImageF, QI::MaskImage>::New();
        masker->SetInput(calcLaplace->GetOutput());
        masker->SetMaskImage(mask);
        if (erodeRadius > 0) {
            if (verbose) cout << "Eroding mask by " << erodeRadius << " voxels" << endl;
            typedef itk::BinaryBallStructuringElement<QI::MaskImage::PixelType, 3> StructuringElementType;
            StructuringElementType structuringElement;
            structuringElement.SetRadius(erodeRadius);
            structuringElement.CreateStructuringElement();

            typedef itk::BinaryErodeImageFilter <QI::MaskImage, QI::MaskImage, StructuringElementType> BinaryErodeImageFilterType;
            BinaryErodeImageFilterType::Pointer erodeFilter = BinaryErodeImageFilterType::New();
            erodeFilter->SetInput(mask);
            erodeFilter->SetErodeValue(1);
            erodeFilter->SetKernel(structuringElement);
            erodeFilter->Update();
            masker->SetMaskImage(erodeFilter->GetOutput());
            if (debug) QI::writeResult<QI::MaskImage>(erodeFilter->GetOutput(), prefix + "_eroded_mask" + QI::OutExt());
        }
        if (verbose) cout << "Applying mask" << endl;
        masker->Update();
        lap = masker->GetOutput();
        lap->DisconnectPipeline();
        if (debug) QI::writeResult(lap, prefix + "_step1_laplace_masked" + QI::OutExt());
    }

    if (verbose) cout << "Padding image to valid FFT size." << endl;
    typedef itk::FFTPadImageFilter<QI::ImageF> PadFFTType;
    auto padFFT = PadFFTType::New();
    padFFT->SetInput(lap);
    padFFT->Update();
    if (debug) QI::writeResult(padFFT->GetOutput(), prefix + "_step2_padFFT" + QI::OutExt());
    if (verbose) {
        cout << "Padded image size: " << padFFT->GetOutput()->GetLargestPossibleRegion().GetSize() << endl;
        cout << "Calculating Forward FFT." << endl;
    }
    typedef itk::ForwardFFTImageFilter<QI::ImageF> FFFTType;
	auto forwardFFT = FFFTType::New();
    forwardFFT->SetInput(padFFT->GetOutput());
    forwardFFT->Update();
    if (debug) QI::writeResult<QI::ImageXF>(forwardFFT->GetOutput(), prefix + "_step3_forwardFFT" + QI::OutExt());
	if (verbose) cout << "Generating Inverse Laplace Kernel." << endl;
	auto inverseLaplace = itk::DiscreteInverseLaplace::New();
    inverseLaplace->SetImageProperties(padFFT->GetOutput());
    inverseLaplace->Update();
    if (debug) QI::writeResult(inverseLaplace->GetOutput(), prefix + "_inverse_laplace_filter" + QI::OutExt());
    if (verbose) cout << "Multiplying." << endl;
    auto mult = itk::MultiplyImageFilter<QI::ImageXF, QI::ImageF, QI::ImageXF>::New();
	mult->SetInput1(forwardFFT->GetOutput());
	mult->SetInput2(inverseLaplace->GetOutput());
    if (debug) QI::writeResult<QI::ImageXF>(mult->GetOutput(), prefix + "_step3_multFFT" + QI::OutExt());
	if (verbose) cout << "Inverse FFT." << endl;
    auto inverseFFT = itk::InverseFFTImageFilter<QI::ImageXF, QI::ImageF>::New();
	inverseFFT->SetInput(mult->GetOutput());
    inverseFFT->Update();
    if (debug) QI::writeResult(inverseFFT->GetOutput(), prefix + "_step4_inverseFFT" + QI::OutExt());
    if (verbose) cout << "Extracting original size image" << endl;
    auto extract = itk::ExtractImageFilter<QI::ImageF, QI::ImageF>::New();
    extract->SetInput(inverseFFT->GetOutput());
    extract->SetDirectionCollapseToSubmatrix();
    extract->SetExtractionRegion(calcLaplace->GetOutput()->GetLargestPossibleRegion());
    extract->Update();
    if (debug) QI::writeResult(extract->GetOutput(), prefix + "_step5_extract" + QI::OutExt());
    auto outFile = QI::WriteImageF::New();
    if (mask) {
        if (verbose) cout << "Re-applying mask" << endl;
        auto masker = itk::MaskImageFilter<QI::ImageF, QI::MaskImage>::New();
        masker->SetMaskImage(mask);
        masker->SetInput(extract->GetOutput());
        masker->Update();
        outFile->SetInput(masker->GetOutput());
    } else {
        outFile->SetInput(extract->GetOutput());
    }
	outFile->SetFileName(outname);
    if (verbose) cout << "Writing output." << endl;
	outFile->Update();
	if (verbose) cout << "Finished." << endl;
	return EXIT_SUCCESS;
}
<|endoftext|>


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

#include "condor_common.h"
#include "condor_classad.h"
#include "condor_debug.h"
#include "condor_daemon_core.h"
#include "condor_attributes.h"
#include "condor_syscall_mode.h"
#include "exit.h"
#include "vanilla_proc.h"
#include "starter.h"
#include "syscall_numbers.h"
#include "dynuser.h"
#include "condor_config.h"
#include "domain_tools.h"

#ifdef WIN32
#include "executable_scripts.WINDOWS.h"
extern dynuser* myDynuser;
#endif

extern CStarter *Starter;

int
VanillaProc::StartJob()
{
	dprintf(D_FULLDEBUG,"in VanillaProc::StartJob()\n");

	// vanilla jobs, unlike standard jobs, are allowed to run
	// shell scripts (or as is the case on NT, batch files).  so
	// edit the ad so we start up a shell, pass the executable as
	// an argument to the shell, if we are asked to run a .bat file.
#ifdef WIN32

	CHAR		interpreter[MAX_PATH+1],
				systemshell[MAX_PATH+1];
	const char* jobtmp				= Starter->jic->origJobName();
	int			joblen				= strlen(jobtmp);
	const char	*extension			= joblen > 0 ? &(jobtmp[joblen-4]) : NULL;
	bool		binary_executable	= ( extension &&
										( MATCH == strcasecmp ( ".exe", extension ) ||
										  MATCH == strcasecmp ( ".com", extension ) ) ),
				java_universe		= ( CONDOR_UNIVERSE_JAVA == job_universe );
	ArgList		arguments;
	MyString	filename,
				jobname,
				error;

	if ( extension && !java_universe && !binary_executable ) {

		/** since we do not actually know how long the extension of
			the file is, we'll need to hunt down the '.' in the path,
			if it exists */
		extension = strrchr ( jobtmp, '.' );

		if ( !extension ) {

			dprintf (
				D_ALWAYS,
				"VanillaProc::StartJob(): Failed to extract "
				"the file's extension.\n" );

			/** don't fail here, since we want executables to run
				as usual.  That is, some condor jobs submit
				executables that do not have the '.exe' extension,
				but are, nonetheless, executable binaries.  For
				instance, a submit script may contain:

				executable = executable$(OPSYS) */

		} else {

			/** pull out the path to the executable */
			if ( !JobAd->LookupString (
				ATTR_JOB_CMD,
				jobname ) ) {

				/** fall back on Starter->jic->origJobName() */
				jobname = jobtmp;

			}

			/** If we transferred the job, it may have been
				renamed to condor_exec.exe even though it is
				not an executable. Here we rename it back to
				a the correct extension before it will run. */
			if ( MATCH == strcasecmp (
					CONDOR_EXEC,
					condor_basename ( jobname.Value () ) ) ) {
				filename.sprintf ( "condor_exec%s", extension );
				rename ( CONDOR_EXEC, filename.Value () );
			} else {
				filename = jobname;
			}

			/** Since we've renamed our executable, we need to
				update the job ad to reflect this change. */
			if ( !JobAd->Assign (
				ATTR_JOB_CMD,
				filename ) ) {

				dprintf (
					D_ALWAYS,
					"VanillaProc::StartJob(): ERROR: failed to "
					"set new executable name.\n" );

				return FALSE;

			}

			/** We've moved the script to argv[1], so we need to
				add	the remaining arguments to positions argv[2]..
				argv[/n/]. */
			if ( !arguments.AppendArgsFromClassAd ( JobAd, &error ) ||
				 !arguments.InsertArgsIntoClassAd ( JobAd, NULL,
				&error ) ) {

				dprintf (
					D_ALWAYS,
					"VanillaProc::StartJob(): ERROR: failed to "
					"get arguments from job ad: %s\n",
					error.Value () );

				return FALSE;

			}

			/** Since we know already we don't want this file returned
				to us, we explicitly add it to an exception list which
				will stop the file transfer mechanism from considering
				it for transfer back to its submitter */
			Starter->jic->removeFromOutputFiles (
				filename.Value () );

		}

	}
#endif

	// set up a FamilyInfo structure to tell OsProc to register a family
	// with the ProcD in its call to DaemonCore::Create_Process
	//
	FamilyInfo fi;

	// take snapshots at no more than 15 seconds in between, by default
	//
	fi.max_snapshot_interval = param_integer("PID_SNAPSHOT_INTERVAL", 15);

	char const *dedicated_account = Starter->jic->getExecuteAccountIsDedicated();
	if( ThisProcRunsAlongsideMainProc() ) {
			// If we track a secondary proc's family tree (such as
			// sshd) using the same dedicated account as the job's
			// family tree, we could end up killing the job when we
			// clean up the secondary family.
		dedicated_account = NULL;
	}
	if (dedicated_account) {
			// using login-based family tracking
		fi.login = dedicated_account;
			// The following message is documented in the manual as the
			// way to tell whether the dedicated execution account
			// configuration is being used.
		dprintf(D_ALWAYS,
		        "Tracking process family by login \"%s\"\n",
		        fi.login);
	}

#if defined(LINUX)
	// on Linux, we also have the ability to track processes via
	// a phony supplementary group ID
	//
	gid_t tracking_gid;
	if (param_boolean("USE_GID_PROCESS_TRACKING", false)) {
		if (!can_switch_ids() &&
		    (Starter->condorPrivSepHelper() == NULL))
		{
			EXCEPT("USE_GID_PROCESS_TRACKING enabled, but can't modify "
			           "the group list of our children unless running as "
			           "root or using PrivSep");
		}
		fi.group_ptr = &tracking_gid;
	}
#endif

	// have OsProc start the job
	//
	return OsProc::StartJob(&fi);
}

bool
VanillaProc::PublishUpdateAd( ClassAd* ad )
{
	dprintf( D_FULLDEBUG, "In VanillaProc::PublishUpdateAd()\n" );

	ProcFamilyUsage* usage;
	ProcFamilyUsage cur_usage;
	if (m_proc_exited) {
		usage = &m_final_usage;
	}
	else {
		if (daemonCore->Get_Family_Usage(JobPid, cur_usage) == FALSE) {
			dprintf(D_ALWAYS, "error getting family usage in "
					"VanillaProc::PublishUpdateAd() for pid %d\n", JobPid);
			return false;
		}
		usage = &cur_usage;
	}

		// Publish the info we care about into the ad.
	char buf[200];
	sprintf( buf, "%s=%lu", ATTR_JOB_REMOTE_SYS_CPU, usage->sys_cpu_time );
	ad->InsertOrUpdate( buf );
	sprintf( buf, "%s=%lu", ATTR_JOB_REMOTE_USER_CPU, usage->user_cpu_time );
	ad->InsertOrUpdate( buf );
	sprintf( buf, "%s=%lu", ATTR_IMAGE_SIZE, usage->max_image_size );
	ad->InsertOrUpdate( buf );

		// Update our knowledge of how many processes the job has
	num_pids = usage->num_procs;

		// Now, call our parent class's version
	return OsProc::PublishUpdateAd( ad );
}

bool
VanillaProc::JobReaper(int pid, int status)
{
	dprintf(D_FULLDEBUG,"Inside VanillaProc::JobReaper()\n");

	if (pid == JobPid) {
			// Make sure that nothing was left behind.
		daemonCore->Kill_Family(JobPid);

			// Record final usage stats for this process family, since
			// once the reaper returns, the family is no longer
			// registered with DaemonCore and we'll never be able to
			// get this information again.
		if (daemonCore->Get_Family_Usage(JobPid, m_final_usage) == FALSE) {
			dprintf(D_ALWAYS, "error getting family usage for pid %d in "
					"VanillaProc::JobReaper()\n", JobPid);
		}
	}

		// This will reset num_pids for us, too.
	return OsProc::JobReaper( pid, status );
}

void
VanillaProc::Suspend()
{
	dprintf(D_FULLDEBUG,"in VanillaProc::Suspend()\n");

	// suspend the user job
	if (JobPid != -1) {
		if (daemonCore->Suspend_Family(JobPid) == FALSE) {
			dprintf(D_ALWAYS,
			        "error suspending family in VanillaProc::Suspend()\n");
		}
	}

	// set our flag
	is_suspended = true;
}

void
VanillaProc::Continue()
{
	dprintf(D_FULLDEBUG,"in VanillaProc::Continue()\n");

	// resume user job
	if (JobPid != -1) {
		if (daemonCore->Continue_Family(JobPid) == FALSE) {
			dprintf(D_ALWAYS,
			        "error continuing family in VanillaProc::Continue()\n");
		}
	}

	// set our flag
	is_suspended = false;
}

bool
VanillaProc::ShutdownGraceful()
{
	dprintf(D_FULLDEBUG,"in VanillaProc::ShutdownGraceful()\n");

	if ( JobPid == -1 ) {
		// there is no process family yet, probably because we are still
		// transferring files.  just return true to say we're all done,
		// and that way the starter class will simply delete us and the
		// FileTransfer destructor will clean up.
		return true;
	}

	// WE USED TO.....
	//
	// take a snapshot before we softkill the parent job process.
	// this helps ensure that if the parent exits without killing
	// the kids, our JobExit() handler will get em all.
	//
	// TODO: should we make an explicit call to the procd here to tell
	// it to take a snapshot???

	// now softkill the parent job process.  this is exactly what
	// OsProc::ShutdownGraceful does, so call it.
	//
	OsProc::ShutdownGraceful();
	startEscalationTimer();
	return false; // shutdown is pending (same as OsProc::ShutdownGraceful()
}

bool
VanillaProc::ShutdownFast()
{
	dprintf(D_FULLDEBUG,"in VanillaProc::ShutdownFast()\n");

	if ( JobPid == -1 ) {
		// there is no process family yet, probably because we are still
		// transferring files.  just return true to say we're all done,
		// and that way the starter class will simply delete us and the
		// FileTransfer destructor will clean up.
		return true;
	}

	// We purposely do not do a SIGCONT here, since there is no sense
	// in potentially swapping the job back into memory if our next
	// step is to hard kill it.
	requested_exit = true;

	// this used to be the only place where we would clean up the process
	// family. this, however, wouldn't properly clean up local universe jobs
	// so a call to Kill_Family has been added to JobReaper(). i'm not sure
	// that this call is still needed, but am unwilling to remove it on the
	// eve of Condor 7
	//   -gquinn, 2007-11-14
	daemonCore->Kill_Family(JobPid);

	return false;	// shutdown is pending, so return false
}
<commit_msg>startEscalationTimer is only in 7.5, 7.4 will have to live without this fix for #1392<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_classad.h"
#include "condor_debug.h"
#include "condor_daemon_core.h"
#include "condor_attributes.h"
#include "condor_syscall_mode.h"
#include "exit.h"
#include "vanilla_proc.h"
#include "starter.h"
#include "syscall_numbers.h"
#include "dynuser.h"
#include "condor_config.h"
#include "domain_tools.h"

#ifdef WIN32
#include "executable_scripts.WINDOWS.h"
extern dynuser* myDynuser;
#endif

extern CStarter *Starter;

int
VanillaProc::StartJob()
{
	dprintf(D_FULLDEBUG,"in VanillaProc::StartJob()\n");

	// vanilla jobs, unlike standard jobs, are allowed to run
	// shell scripts (or as is the case on NT, batch files).  so
	// edit the ad so we start up a shell, pass the executable as
	// an argument to the shell, if we are asked to run a .bat file.
#ifdef WIN32

	CHAR		interpreter[MAX_PATH+1],
				systemshell[MAX_PATH+1];
	const char* jobtmp				= Starter->jic->origJobName();
	int			joblen				= strlen(jobtmp);
	const char	*extension			= joblen > 0 ? &(jobtmp[joblen-4]) : NULL;
	bool		binary_executable	= ( extension &&
										( MATCH == strcasecmp ( ".exe", extension ) ||
										  MATCH == strcasecmp ( ".com", extension ) ) ),
				java_universe		= ( CONDOR_UNIVERSE_JAVA == job_universe );
	ArgList		arguments;
	MyString	filename,
				jobname,
				error;

	if ( extension && !java_universe && !binary_executable ) {

		/** since we do not actually know how long the extension of
			the file is, we'll need to hunt down the '.' in the path,
			if it exists */
		extension = strrchr ( jobtmp, '.' );

		if ( !extension ) {

			dprintf (
				D_ALWAYS,
				"VanillaProc::StartJob(): Failed to extract "
				"the file's extension.\n" );

			/** don't fail here, since we want executables to run
				as usual.  That is, some condor jobs submit
				executables that do not have the '.exe' extension,
				but are, nonetheless, executable binaries.  For
				instance, a submit script may contain:

				executable = executable$(OPSYS) */

		} else {

			/** pull out the path to the executable */
			if ( !JobAd->LookupString (
				ATTR_JOB_CMD,
				jobname ) ) {

				/** fall back on Starter->jic->origJobName() */
				jobname = jobtmp;

			}

			/** If we transferred the job, it may have been
				renamed to condor_exec.exe even though it is
				not an executable. Here we rename it back to
				a the correct extension before it will run. */
			if ( MATCH == strcasecmp (
					CONDOR_EXEC,
					condor_basename ( jobname.Value () ) ) ) {
				filename.sprintf ( "condor_exec%s", extension );
				rename ( CONDOR_EXEC, filename.Value () );
			} else {
				filename = jobname;
			}

			/** Since we've renamed our executable, we need to
				update the job ad to reflect this change. */
			if ( !JobAd->Assign (
				ATTR_JOB_CMD,
				filename ) ) {

				dprintf (
					D_ALWAYS,
					"VanillaProc::StartJob(): ERROR: failed to "
					"set new executable name.\n" );

				return FALSE;

			}

			/** We've moved the script to argv[1], so we need to
				add	the remaining arguments to positions argv[2]..
				argv[/n/]. */
			if ( !arguments.AppendArgsFromClassAd ( JobAd, &error ) ||
				 !arguments.InsertArgsIntoClassAd ( JobAd, NULL,
				&error ) ) {

				dprintf (
					D_ALWAYS,
					"VanillaProc::StartJob(): ERROR: failed to "
					"get arguments from job ad: %s\n",
					error.Value () );

				return FALSE;

			}

			/** Since we know already we don't want this file returned
				to us, we explicitly add it to an exception list which
				will stop the file transfer mechanism from considering
				it for transfer back to its submitter */
			Starter->jic->removeFromOutputFiles (
				filename.Value () );

		}

	}
#endif

	// set up a FamilyInfo structure to tell OsProc to register a family
	// with the ProcD in its call to DaemonCore::Create_Process
	//
	FamilyInfo fi;

	// take snapshots at no more than 15 seconds in between, by default
	//
	fi.max_snapshot_interval = param_integer("PID_SNAPSHOT_INTERVAL", 15);

	char const *dedicated_account = Starter->jic->getExecuteAccountIsDedicated();
	if( ThisProcRunsAlongsideMainProc() ) {
			// If we track a secondary proc's family tree (such as
			// sshd) using the same dedicated account as the job's
			// family tree, we could end up killing the job when we
			// clean up the secondary family.
		dedicated_account = NULL;
	}
	if (dedicated_account) {
			// using login-based family tracking
		fi.login = dedicated_account;
			// The following message is documented in the manual as the
			// way to tell whether the dedicated execution account
			// configuration is being used.
		dprintf(D_ALWAYS,
		        "Tracking process family by login \"%s\"\n",
		        fi.login);
	}

#if defined(LINUX)
	// on Linux, we also have the ability to track processes via
	// a phony supplementary group ID
	//
	gid_t tracking_gid;
	if (param_boolean("USE_GID_PROCESS_TRACKING", false)) {
		if (!can_switch_ids() &&
		    (Starter->condorPrivSepHelper() == NULL))
		{
			EXCEPT("USE_GID_PROCESS_TRACKING enabled, but can't modify "
			           "the group list of our children unless running as "
			           "root or using PrivSep");
		}
		fi.group_ptr = &tracking_gid;
	}
#endif

	// have OsProc start the job
	//
	return OsProc::StartJob(&fi);
}

bool
VanillaProc::PublishUpdateAd( ClassAd* ad )
{
	dprintf( D_FULLDEBUG, "In VanillaProc::PublishUpdateAd()\n" );

	ProcFamilyUsage* usage;
	ProcFamilyUsage cur_usage;
	if (m_proc_exited) {
		usage = &m_final_usage;
	}
	else {
		if (daemonCore->Get_Family_Usage(JobPid, cur_usage) == FALSE) {
			dprintf(D_ALWAYS, "error getting family usage in "
					"VanillaProc::PublishUpdateAd() for pid %d\n", JobPid);
			return false;
		}
		usage = &cur_usage;
	}

		// Publish the info we care about into the ad.
	char buf[200];
	sprintf( buf, "%s=%lu", ATTR_JOB_REMOTE_SYS_CPU, usage->sys_cpu_time );
	ad->InsertOrUpdate( buf );
	sprintf( buf, "%s=%lu", ATTR_JOB_REMOTE_USER_CPU, usage->user_cpu_time );
	ad->InsertOrUpdate( buf );
	sprintf( buf, "%s=%lu", ATTR_IMAGE_SIZE, usage->max_image_size );
	ad->InsertOrUpdate( buf );

		// Update our knowledge of how many processes the job has
	num_pids = usage->num_procs;

		// Now, call our parent class's version
	return OsProc::PublishUpdateAd( ad );
}

bool
VanillaProc::JobReaper(int pid, int status)
{
	dprintf(D_FULLDEBUG,"Inside VanillaProc::JobReaper()\n");

	if (pid == JobPid) {
			// Make sure that nothing was left behind.
		daemonCore->Kill_Family(JobPid);

			// Record final usage stats for this process family, since
			// once the reaper returns, the family is no longer
			// registered with DaemonCore and we'll never be able to
			// get this information again.
		if (daemonCore->Get_Family_Usage(JobPid, m_final_usage) == FALSE) {
			dprintf(D_ALWAYS, "error getting family usage for pid %d in "
					"VanillaProc::JobReaper()\n", JobPid);
		}
	}

		// This will reset num_pids for us, too.
	return OsProc::JobReaper( pid, status );
}

void
VanillaProc::Suspend()
{
	dprintf(D_FULLDEBUG,"in VanillaProc::Suspend()\n");

	// suspend the user job
	if (JobPid != -1) {
		if (daemonCore->Suspend_Family(JobPid) == FALSE) {
			dprintf(D_ALWAYS,
			        "error suspending family in VanillaProc::Suspend()\n");
		}
	}

	// set our flag
	is_suspended = true;
}

void
VanillaProc::Continue()
{
	dprintf(D_FULLDEBUG,"in VanillaProc::Continue()\n");

	// resume user job
	if (JobPid != -1) {
		if (daemonCore->Continue_Family(JobPid) == FALSE) {
			dprintf(D_ALWAYS,
			        "error continuing family in VanillaProc::Continue()\n");
		}
	}

	// set our flag
	is_suspended = false;
}

bool
VanillaProc::ShutdownGraceful()
{
	dprintf(D_FULLDEBUG,"in VanillaProc::ShutdownGraceful()\n");

	if ( JobPid == -1 ) {
		// there is no process family yet, probably because we are still
		// transferring files.  just return true to say we're all done,
		// and that way the starter class will simply delete us and the
		// FileTransfer destructor will clean up.
		return true;
	}

	// WE USED TO.....
	//
	// take a snapshot before we softkill the parent job process.
	// this helps ensure that if the parent exits without killing
	// the kids, our JobExit() handler will get em all.
	//
	// TODO: should we make an explicit call to the procd here to tell
	// it to take a snapshot???

	// now softkill the parent job process.  this is exactly what
	// OsProc::ShutdownGraceful does, so call it.
	//
	return OsProc::ShutdownGraceful();
}

bool
VanillaProc::ShutdownFast()
{
	dprintf(D_FULLDEBUG,"in VanillaProc::ShutdownFast()\n");

	if ( JobPid == -1 ) {
		// there is no process family yet, probably because we are still
		// transferring files.  just return true to say we're all done,
		// and that way the starter class will simply delete us and the
		// FileTransfer destructor will clean up.
		return true;
	}

	// We purposely do not do a SIGCONT here, since there is no sense
	// in potentially swapping the job back into memory if our next
	// step is to hard kill it.
	requested_exit = true;

	// this used to be the only place where we would clean up the process
	// family. this, however, wouldn't properly clean up local universe jobs
	// so a call to Kill_Family has been added to JobReaper(). i'm not sure
	// that this call is still needed, but am unwilling to remove it on the
	// eve of Condor 7
	//   -gquinn, 2007-11-14
	daemonCore->Kill_Family(JobPid);

	return false;	// shutdown is pending, so return false
}
<|endoftext|>


<commit_before>class Solution {
public:
    /**
     * @param n the nth
     * @return the nth sequence
     */
    std::vector<string> countAndSaySeqs;
    typedef pair<int,char> PAIR_TIMES_CHAR;
    string countAndSay(int n) {
        // Write your code here
        string s1(""),s2;
        countAndSaySeqs.push_back(s1);
        s1="1";
        countAndSaySeqs.push_back(s1);
        if (n<=1) return countAndSaySeqs[n];

        int i,j,k,m;
        i=2;
        while (i<=n){
        	countAndSaySeqs.push_back(genNext(countAndSaySeqs[i-1]));
        	i++;
        }
        return countAndSaySeqs[n];
    }

    string genNext(string s_prev){
    	//pair  base times ->char
    	pair<int,char> p1,p2;
    	int i=0,j,k;
    	string rt_next;

    	if (s_prev.size()<1) return rt_next;
    	char c_prev='&';// impossible char

    	for (auto const s1:s_prev){
    		if (s1==c_prev){
    			i++;
    		}
    		else{
    			stringstream ss_n;
    			ss_n<<i<<c_prev;
    			rt_next.push_back(ss_n.str());

    			i=1;
    			c_prev=s1;
    		}

    	}

    	return rt_next;
    }
};<commit_msg>tested 420<commit_after>class Solution {
public:
    /**
     * @param n the nth
     * @return the nth sequence
     */
    std::vector<string> countAndSaySeqs;
    typedef pair<int,char> PAIR_TIMES_CHAR;
    string countAndSay(int n) {
        // Write your code here
        string s1(""),s2;
        countAndSaySeqs.push_back(s1);
        s1="1";
        countAndSaySeqs.push_back(s1);
        if (n<=1) return countAndSaySeqs[n];

        int i,j,k,m;
        i=2;
        while (i<=n){
            countAndSaySeqs.push_back(genNext(countAndSaySeqs[i-1]));
            i++;
        }
        return countAndSaySeqs[n];
    }

    string genNext(string s_prev){
        //pair  base times ->char
        pair<int,char> p1,p2;
        int i=0,j,k;
        string rt_next;

        if (s_prev.size()<1) return rt_next;
        char c_prev=s_prev[0];// impossible char

        for (auto const s1:s_prev){
            if (s1==c_prev){
                i++;
            }
            else{
                stringstream ss_n;
                ss_n<<i<<c_prev;
                rt_next += ss_n.str();

                i=1;
                c_prev=s1;
            }

        }

        stringstream ss_n;
        ss_n<<i<<c_prev;
        rt_next += ss_n.str();

        return rt_next;
    }
};<|endoftext|>


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

#include <grpc/support/port_platform.h>

#include "src/core/lib/iomgr/port.h"

#include <inttypes.h>

#ifdef GRPC_WINSOCK_SOCKET

#include "src/core/lib/iomgr/sockaddr_windows.h"

#include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/log_windows.h>

#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/iocp_windows.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/socket_windows.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/iomgr/tcp_windows.h"
#include "src/core/lib/iomgr/timer.h"

typedef struct {
  grpc_closure* on_done;
  gpr_mu mu;
  grpc_winsocket* socket;
  grpc_timer alarm;
  grpc_closure on_alarm;
  char* addr_name;
  int refs;
  grpc_closure on_connect;
  grpc_endpoint** endpoint;
  grpc_channel_args* channel_args;
} async_connect;

static void async_connect_unlock_and_cleanup(async_connect* ac,
                                             grpc_winsocket* socket) {
  int done = (--ac->refs == 0);
  gpr_mu_unlock(&ac->mu);
  if (done) {
    grpc_channel_args_destroy(ac->channel_args);
    gpr_mu_destroy(&ac->mu);
    gpr_free(ac->addr_name);
    gpr_free(ac);
  }
  if (socket != NULL) grpc_winsocket_destroy(socket);
}

static void on_alarm(void* acp, grpc_error* error) {
  async_connect* ac = (async_connect*)acp;
  gpr_mu_lock(&ac->mu);
  grpc_winsocket* socket = ac->socket;
  ac->socket = NULL;
  if (socket != NULL) {
    grpc_winsocket_shutdown(socket);
  }
  async_connect_unlock_and_cleanup(ac, socket);
}

static void on_connect(void* acp, grpc_error* error) {
  async_connect* ac = (async_connect*)acp;
  grpc_endpoint** ep = ac->endpoint;
  GPR_ASSERT(*ep == NULL);
  grpc_closure* on_done = ac->on_done;

  GRPC_ERROR_REF(error);

  gpr_mu_lock(&ac->mu);
  grpc_winsocket* socket = ac->socket;
  ac->socket = NULL;
  gpr_mu_unlock(&ac->mu);

  grpc_timer_cancel(&ac->alarm);

  gpr_mu_lock(&ac->mu);

  if (error == GRPC_ERROR_NONE) {
    if (socket != NULL) {
      DWORD transfered_bytes = 0;
      DWORD flags;
      BOOL wsa_success =
          WSAGetOverlappedResult(socket->socket, &socket->write_info.overlapped,
                                 &transfered_bytes, FALSE, &flags);
      GPR_ASSERT(transfered_bytes == 0);
      if (!wsa_success) {
        error = GRPC_WSA_ERROR(WSAGetLastError(), "ConnectEx");
        closesocket(socket->socket);
      } else {
        *ep = grpc_tcp_create(socket, ac->channel_args, ac->addr_name);
        socket = NULL;
      }
    } else {
      error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("socket is null");
    }
  }

  async_connect_unlock_and_cleanup(ac, socket);
  /* If the connection was aborted, the callback was already called when
     the deadline was met. */
  GRPC_CLOSURE_SCHED(on_done, error);
}

/* Tries to issue one async connection, then schedules both an IOCP
   notification request for the connection, and one timeout alert. */
static void tcp_connect(grpc_closure* on_done, grpc_endpoint** endpoint,
                        grpc_pollset_set* interested_parties,
                        const grpc_channel_args* channel_args,
                        const grpc_resolved_address* addr,
                        grpc_millis deadline) {
  SOCKET sock = INVALID_SOCKET;
  BOOL success;
  int status;
  grpc_resolved_address addr6_v4mapped;
  grpc_resolved_address local_address;
  async_connect* ac;
  grpc_winsocket* socket = NULL;
  LPFN_CONNECTEX ConnectEx;
  GUID guid = WSAID_CONNECTEX;
  DWORD ioctl_num_bytes;
  grpc_winsocket_callback_info* info;
  grpc_error* error = GRPC_ERROR_NONE;

  *endpoint = NULL;

  /* Use dualstack sockets where available. */
  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
    addr = &addr6_v4mapped;
  }

  sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
                   WSA_FLAG_OVERLAPPED);
  if (sock == INVALID_SOCKET) {
    error = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket");
    goto failure;
  }

  error = grpc_tcp_prepare_socket(sock);
  if (error != GRPC_ERROR_NONE) {
    goto failure;
  }

  /* Grab the function pointer for ConnectEx for that specific socket.
     It may change depending on the interface. */
  status =
      WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
               &ConnectEx, sizeof(ConnectEx), &ioctl_num_bytes, NULL, NULL);

  if (status != 0) {
    error = GRPC_WSA_ERROR(WSAGetLastError(),
                           "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER)");
    goto failure;
  }

  grpc_sockaddr_make_wildcard6(0, &local_address);

  status =
      bind(sock, (grpc_sockaddr*)&local_address.addr, (int)local_address.len);
  if (status != 0) {
    error = GRPC_WSA_ERROR(WSAGetLastError(), "bind");
    goto failure;
  }

  socket = grpc_winsocket_create(sock, "client");
  info = &socket->write_info;
  success = ConnectEx(sock, (grpc_sockaddr*)&addr->addr, (int)addr->len, NULL,
                      0, NULL, &info->overlapped);

  /* It wouldn't be unusual to get a success immediately. But we'll still get
     an IOCP notification, so let's ignore it. */
  if (!success) {
    int last_error = WSAGetLastError();
    if (last_error != ERROR_IO_PENDING) {
      error = GRPC_WSA_ERROR(last_error, "ConnectEx");
      goto failure;
    }
  }

  ac = (async_connect*)gpr_malloc(sizeof(async_connect));
  ac->on_done = on_done;
  ac->socket = socket;
  gpr_mu_init(&ac->mu);
  ac->refs = 2;
  ac->addr_name = grpc_sockaddr_to_uri(addr);
  ac->endpoint = endpoint;
  ac->channel_args = grpc_channel_args_copy(channel_args);
  GRPC_CLOSURE_INIT(&ac->on_connect, on_connect, ac, grpc_schedule_on_exec_ctx);

  GRPC_CLOSURE_INIT(&ac->on_alarm, on_alarm, ac, grpc_schedule_on_exec_ctx);
  grpc_timer_init(&ac->alarm, deadline, &ac->on_alarm);
  grpc_socket_notify_on_write(socket, &ac->on_connect);
  return;

failure:
  GPR_ASSERT(error != GRPC_ERROR_NONE);
  char* target_uri = grpc_sockaddr_to_uri(addr);
  grpc_error* final_error = grpc_error_set_str(
      GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Failed to connect",
                                                       &error, 1),
      GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(target_uri));
  GRPC_ERROR_UNREF(error);
  if (socket != NULL) {
    grpc_winsocket_destroy(socket);
  } else if (sock != INVALID_SOCKET) {
    closesocket(sock);
  }
  GRPC_CLOSURE_SCHED(on_done, final_error);
}

grpc_tcp_client_vtable grpc_windows_tcp_client_vtable = {tcp_connect};

#endif /* GRPC_WINSOCK_SOCKET */
<commit_msg>Fix a NULL deref in tcp_client_windows.cc<commit_after>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include "src/core/lib/iomgr/port.h"

#include <inttypes.h>

#ifdef GRPC_WINSOCK_SOCKET

#include "src/core/lib/iomgr/sockaddr_windows.h"

#include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/log_windows.h>

#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/iocp_windows.h"
#include "src/core/lib/iomgr/sockaddr.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/socket_windows.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/iomgr/tcp_windows.h"
#include "src/core/lib/iomgr/timer.h"

typedef struct {
  grpc_closure* on_done;
  gpr_mu mu;
  grpc_winsocket* socket;
  grpc_timer alarm;
  grpc_closure on_alarm;
  char* addr_name;
  int refs;
  grpc_closure on_connect;
  grpc_endpoint** endpoint;
  grpc_channel_args* channel_args;
} async_connect;

static void async_connect_unlock_and_cleanup(async_connect* ac,
                                             grpc_winsocket* socket) {
  int done = (--ac->refs == 0);
  gpr_mu_unlock(&ac->mu);
  if (done) {
    grpc_channel_args_destroy(ac->channel_args);
    gpr_mu_destroy(&ac->mu);
    gpr_free(ac->addr_name);
    gpr_free(ac);
  }
  if (socket != NULL) grpc_winsocket_destroy(socket);
}

static void on_alarm(void* acp, grpc_error* error) {
  async_connect* ac = (async_connect*)acp;
  gpr_mu_lock(&ac->mu);
  grpc_winsocket* socket = ac->socket;
  ac->socket = NULL;
  if (socket != NULL) {
    grpc_winsocket_shutdown(socket);
  }
  async_connect_unlock_and_cleanup(ac, socket);
}

static void on_connect(void* acp, grpc_error* error) {
  async_connect* ac = (async_connect*)acp;
  grpc_endpoint** ep = ac->endpoint;
  GPR_ASSERT(*ep == NULL);
  grpc_closure* on_done = ac->on_done;

  GRPC_ERROR_REF(error);

  gpr_mu_lock(&ac->mu);
  grpc_winsocket* socket = ac->socket;
  ac->socket = NULL;
  gpr_mu_unlock(&ac->mu);

  grpc_timer_cancel(&ac->alarm);

  gpr_mu_lock(&ac->mu);

  if (error == GRPC_ERROR_NONE) {
    if (socket != NULL) {
      DWORD transfered_bytes = 0;
      DWORD flags;
      BOOL wsa_success =
          WSAGetOverlappedResult(socket->socket, &socket->write_info.overlapped,
                                 &transfered_bytes, FALSE, &flags);
      GPR_ASSERT(transfered_bytes == 0);
      if (!wsa_success) {
        error = GRPC_WSA_ERROR(WSAGetLastError(), "ConnectEx");
        closesocket(socket->socket);
      } else {
        *ep = grpc_tcp_create(socket, ac->channel_args, ac->addr_name);
        socket = NULL;
      }
    } else {
      error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("socket is null");
    }
  }

  async_connect_unlock_and_cleanup(ac, socket);
  /* If the connection was aborted, the callback was already called when
     the deadline was met. */
  GRPC_CLOSURE_SCHED(on_done, error);
}

/* Tries to issue one async connection, then schedules both an IOCP
   notification request for the connection, and one timeout alert. */
static void tcp_connect(grpc_closure* on_done, grpc_endpoint** endpoint,
                        grpc_pollset_set* interested_parties,
                        const grpc_channel_args* channel_args,
                        const grpc_resolved_address* addr,
                        grpc_millis deadline) {
  SOCKET sock = INVALID_SOCKET;
  BOOL success;
  int status;
  grpc_resolved_address addr6_v4mapped;
  grpc_resolved_address local_address;
  async_connect* ac;
  grpc_winsocket* socket = NULL;
  LPFN_CONNECTEX ConnectEx;
  GUID guid = WSAID_CONNECTEX;
  DWORD ioctl_num_bytes;
  grpc_winsocket_callback_info* info;
  grpc_error* error = GRPC_ERROR_NONE;

  *endpoint = NULL;

  /* Use dualstack sockets where available. */
  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
    addr = &addr6_v4mapped;
  }

  sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
                   WSA_FLAG_OVERLAPPED);
  if (sock == INVALID_SOCKET) {
    error = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket");
    goto failure;
  }

  error = grpc_tcp_prepare_socket(sock);
  if (error != GRPC_ERROR_NONE) {
    goto failure;
  }

  /* Grab the function pointer for ConnectEx for that specific socket.
     It may change depending on the interface. */
  status =
      WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
               &ConnectEx, sizeof(ConnectEx), &ioctl_num_bytes, NULL, NULL);

  if (status != 0) {
    error = GRPC_WSA_ERROR(WSAGetLastError(),
                           "WSAIoctl(SIO_GET_EXTENSION_FUNCTION_POINTER)");
    goto failure;
  }

  grpc_sockaddr_make_wildcard6(0, &local_address);

  status =
      bind(sock, (grpc_sockaddr*)&local_address.addr, (int)local_address.len);
  if (status != 0) {
    error = GRPC_WSA_ERROR(WSAGetLastError(), "bind");
    goto failure;
  }

  socket = grpc_winsocket_create(sock, "client");
  info = &socket->write_info;
  success = ConnectEx(sock, (grpc_sockaddr*)&addr->addr, (int)addr->len, NULL,
                      0, NULL, &info->overlapped);

  /* It wouldn't be unusual to get a success immediately. But we'll still get
     an IOCP notification, so let's ignore it. */
  if (!success) {
    int last_error = WSAGetLastError();
    if (last_error != ERROR_IO_PENDING) {
      error = GRPC_WSA_ERROR(last_error, "ConnectEx");
      goto failure;
    }
  }

  ac = (async_connect*)gpr_malloc(sizeof(async_connect));
  ac->on_done = on_done;
  ac->socket = socket;
  gpr_mu_init(&ac->mu);
  ac->refs = 2;
  ac->addr_name = grpc_sockaddr_to_uri(addr);
  ac->endpoint = endpoint;
  ac->channel_args = grpc_channel_args_copy(channel_args);
  GRPC_CLOSURE_INIT(&ac->on_connect, on_connect, ac, grpc_schedule_on_exec_ctx);

  GRPC_CLOSURE_INIT(&ac->on_alarm, on_alarm, ac, grpc_schedule_on_exec_ctx);
  grpc_timer_init(&ac->alarm, deadline, &ac->on_alarm);
  grpc_socket_notify_on_write(socket, &ac->on_connect);
  return;

failure:
  GPR_ASSERT(error != GRPC_ERROR_NONE);
  char* target_uri = grpc_sockaddr_to_uri(addr);
  grpc_error* final_error =
      grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
                             "Failed to connect", &error, 1),
                         GRPC_ERROR_STR_TARGET_ADDRESS,
                         grpc_slice_from_copied_string(
                             target_uri == nullptr ? "NULL" : target_uri));
  GRPC_ERROR_UNREF(error);
  if (socket != NULL) {
    grpc_winsocket_destroy(socket);
  } else if (sock != INVALID_SOCKET) {
    closesocket(sock);
  }
  GRPC_CLOSURE_SCHED(on_done, final_error);
}

grpc_tcp_client_vtable grpc_windows_tcp_client_vtable = {tcp_connect};

#endif /* GRPC_WINSOCK_SOCKET */
<|endoftext|>


<commit_before>#include "Accelerator.hpp"

#include <sstream>
#include <exception>

Accelerator::Accelerator() :
	m_ion_source(),
	m_devices()
{ }

Accelerator::~Accelerator()
{
	for( auto it=m_devices.begin(); it<m_devices.end(); it++ ){
		if( (*it) != NULL ){
			delete (*it);
			(*it) = NULL;
		}
	}
}

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

	stringstream ss;
	ss << indention << toLine() << " {\n";
	for( auto it_device=m_devices.begin(); it_device<m_devices.end(); it_device++ ){
		ss << indention << (*it_device)->toString(indent+1) << "\n";
	}
	ss << indention << "}";
	return ss.str();
}

string
Accelerator::toLine(void) const
{
	stringstream ss;
	ss << "Accelerator ( ion_source = " << m_ion_source.toString() << " )";
	return ss.str();
}

ostream&
operator<<(ostream& os, const Accelerator& accelerator)
{
	return os << accelerator.toLine();
}

void
Accelerator::appendDevice(Device* device)
{
	m_devices.push_back(device);
	m_ion_source.appendDevice(device);
}

Device*
Accelerator::getDeviceByName(const string& name)
{
	for( auto it=m_devices.begin(); it<m_devices.end(); it++ ){
		if( name == (*it)->getName() ){
			return *it;
		}
	}
	return NULL;
}

void
Accelerator::startSimulation(unsigned int nof_ions, bool threaded, unsigned int nof_threads)
{
	for( auto it_device=m_devices.begin(); it_device<m_devices.end(); it_device++ ){
		(*it_device)->reset();
	}

	if( threaded ){

		unsigned int ions_per_core = nof_ions/nof_threads;

		thread* threadlist = new thread[nof_threads];

		for( unsigned int i=0; i<nof_threads; i++ ){
			try{
				threadlist[i] = thread(&IonSource::run, m_ion_source, ions_per_core);
			} catch(exception &e) {
				cout << "Error in " << __FILE__ << " line " << __LINE__ << " " << e.what() << endl;
				exit(0);
			}
		}

		for( unsigned int i=0; i<nof_threads; i++ ){
			threadlist[i].join();
		}

		delete[] threadlist;
	} else {
		m_ion_source.run(nof_ions);
	}
}

void
Accelerator::setNormValues(vector<double> values)
{
	int i = 0;
	for( auto it=m_devices.begin(); it<m_devices.end(); it++ ){
		if( (*it)->settingSize() == 1 ){
			(*it)->setNormValue(values.at(i));
			i++;
		}
	}
}

int
Accelerator::settingSize(void)
{
	int settingSize = 0;
	for( auto it=m_devices.begin(); it<m_devices.end(); it++ ){
		settingSize += (*it)->settingSize();
	}
	return settingSize;
}

void
Accelerator::setScreenIgnore(bool ignore)
{
	for( auto it=m_devices.begin(); it<m_devices.end(); it++ ){
		if( (*it)->getClassName() == "Screen" ){
			(*it)->setIgnore(ignore);
		}
	}
}

<commit_msg>return of a null pointer avoided<commit_after>#include "Accelerator.hpp"

#include <sstream>
#include <exception>

Accelerator::Accelerator() :
	m_ion_source(),
	m_devices()
{ }

Accelerator::~Accelerator()
{
	for( auto it=m_devices.begin(); it<m_devices.end(); it++ ){
		if( (*it) != NULL ){
			delete (*it);
			(*it) = NULL;
		}
	}
}

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

	stringstream ss;
	ss << indention << toLine() << " {\n";
	for( auto it_device=m_devices.begin(); it_device<m_devices.end(); it_device++ ){
		ss << indention << (*it_device)->toString(indent+1) << "\n";
	}
	ss << indention << "}";
	return ss.str();
}

string
Accelerator::toLine(void) const
{
	stringstream ss;
	ss << "Accelerator ( ion_source = " << m_ion_source.toString() << " )";
	return ss.str();
}

ostream&
operator<<(ostream& os, const Accelerator& accelerator)
{
	return os << accelerator.toLine();
}

void
Accelerator::appendDevice(Device* device)
{
	m_devices.push_back(device);
	m_ion_source.appendDevice(device);
}

Device*
Accelerator::getDeviceByName(const string& name)
{
	for( auto it=m_devices.begin(); it<m_devices.end(); it++ ){
		if( name == (*it)->getName() ){
			return *it;
		}
	}
	cout << "Error in " << __FILE__ << " line " << __LINE__ << " no device with name " << name << " found" << endl;
	exit(0);
}

void
Accelerator::startSimulation(unsigned int nof_ions, bool threaded, unsigned int nof_threads)
{
	for( auto it_device=m_devices.begin(); it_device<m_devices.end(); it_device++ ){
		(*it_device)->reset();
	}

	if( threaded ){

		unsigned int ions_per_core = nof_ions/nof_threads;

		thread* threadlist = new thread[nof_threads];

		for( unsigned int i=0; i<nof_threads; i++ ){
			try{
				threadlist[i] = thread(&IonSource::run, m_ion_source, ions_per_core);
			} catch(exception &e) {
				cout << "Error in " << __FILE__ << " line " << __LINE__ << " " << e.what() << endl;
				exit(0);
			}
		}

		for( unsigned int i=0; i<nof_threads; i++ ){
			threadlist[i].join();
		}

		delete[] threadlist;
	} else {
		m_ion_source.run(nof_ions);
	}
}

void
Accelerator::setNormValues(vector<double> values)
{
	int i = 0;
	for( auto it=m_devices.begin(); it<m_devices.end(); it++ ){
		if( (*it)->settingSize() == 1 ){
			(*it)->setNormValue(values.at(i));
			i++;
		}
	}
}

int
Accelerator::settingSize(void)
{
	int settingSize = 0;
	for( auto it=m_devices.begin(); it<m_devices.end(); it++ ){
		settingSize += (*it)->settingSize();
	}
	return settingSize;
}

void
Accelerator::setScreenIgnore(bool ignore)
{
	for( auto it=m_devices.begin(); it<m_devices.end(); it++ ){
		if( (*it)->getClassName() == "Screen" ){
			(*it)->setIgnore(ignore);
		}
	}
}

<|endoftext|>