<commit_before>#include "ImportMatchers.h"
#include "clang/Basic/SourceManager.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>

using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace import_tidy;

namespace clang {
namespace ast_matchers {
  static const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr> message;
  static const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl> interface;
  static const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl> method;
  static const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCProtocolExpr> protocol;

  AST_MATCHER(ObjCInterfaceDecl, isImplementationInMainFile) {
    if (auto *ImpDecl = Node.getImplementation()) {
      auto &SourceManager = Finder->getASTContext().getSourceManager();
      return SourceManager.isInMainFile(SourceManager.getExpansionLoc(ImpDecl->getLocStart()));
    } else {
      return false;
    }
  }

  AST_MATCHER(ObjCMethodDecl, isDefinedInHeader) {
    auto *ID = Node.getClassInterface();
    if (!ID || !ID->getImplementation())
      return false;

    auto &SM = Finder->getASTContext().getSourceManager();
    if (SM.isInMainFile(SM.getExpansionLoc(Node.getLocStart())))
      return false;

    auto ImpLoc = SM.getExpansionLoc(ID->getImplementation()->getLocStart());
    return SM.isInMainFile(ImpLoc);
  }
} // end namespace ast_matchers
} // end namespace clang

namespace {

  static Import importForFileLoc(const SourceLocation L, const SourceManager &SM) {
    if (SM.isLoadedSourceLocation(L)) {
      return Import(ImportType::Module, SM.getModuleImportLoc(L).second);
    }

    auto Path = SM.getFilename(L);
    if (SM.isInSystemHeader(L)) {
      return Import(ImportType::Library, Path);
    }

    auto Filename = Path.drop_front(Path.find_last_of('/') + 1);
    return Import(ImportType::File, Filename);
  }

  static const clang::FileEntry*
  fileIncludingFile(std::map<const FileEntry*,
                    std::set<const FileEntry*>> &Map,
                    const FileEntry *F) {
    for (auto I : Map) {
      if (I.second.count(F)) {
        return I.first;
      }
    }
    return F;
  }

  static FileID
  topFileIncludingFile(std::map<const FileEntry*,
                       std::set<const FileEntry*>> &Map,
                       FileID File,
                       const SourceManager &SM) {
    auto *FE = SM.getFileEntryForID(File);
    const FileEntry *PE;
    do {
      PE = FE;
      FE = fileIncludingFile(Map, PE);
    } while (PE != FE);

    return SM.translateFile(FE);
  }

  // TODO: strip out forward declares too
  class ImportCallbacks : public clang::PPCallbacks {
  public:
    ImportCallbacks(const SourceManager &SM, ImportMatcher &M) :
      SM(SM), Matcher(M) { };

    void InclusionDirective(SourceLocation HashLoc,
                            const Token &IncludeTok,
                            StringRef FileName,
                            bool IsAngled,
                            CharSourceRange FilenameRange,
                            const FileEntry *File,
                            StringRef SearchPath,
                            StringRef RelativePath,
                            const Module *Imported) override {
      // TODO: use the imported module

      if (SM.isInSystemHeader(HashLoc)) {
        Matcher.addLibraryInclude(SM.getFileEntryForID(SM.getFileID(HashLoc)), File);
      } else {
        Matcher.removeImport(HashLoc, SM);
      }
    }
  private:
    const SourceManager &SM;
    ImportMatcher &Matcher;
  };

} // end anonymous namespace

namespace import_tidy {
  static const StringRef nodeKey = "key";

  bool FileCallbacks::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
    auto &SM = CI.getSourceManager();
    auto &PP = CI.getPreprocessor();
    PP.addPPCallbacks(std::unique_ptr<ImportCallbacks>(new ImportCallbacks(SM, Matcher)));
    SourceMgr = &SM;

    return true;
  }

  void FileCallbacks::handleEndSource() {
    Matcher.flush(*SourceMgr);
  }

  void CallExprCallback::run(const MatchFinder::MatchResult &Result) {
    if (auto *FD = Result.Nodes.getNodeAs<CallExpr>(nodeKey)->getDirectCallee()) {
      auto &SM = *Result.SourceManager;
      Matcher.addImport(SM.getMainFileID(), FD->getLocation(), SM);
    }
  }

  void InterfaceCallback::run(const MatchFinder::MatchResult &Result) {
    if (auto *ID = Result.Nodes.getNodeAs<ObjCInterfaceDecl>(nodeKey)) {
      auto &SM = *Result.SourceManager;
      auto InFile = SM.getFileID(ID->getLocation());

      if (auto *SC = ID->getSuperClass()) {
        Matcher.addImport(InFile, SC->getLocation(), SM);
      }

      if (InFile != SM.getMainFileID()) {
        Matcher.addImport(SM.getMainFileID(), ID->getLocation(), SM);
      }

      for (auto *P : ID->protocols()) {
        Matcher.addImport(InFile, P->getLocation(), SM);
      }

      for (auto *C : ID->visible_categories()) {
        auto CategoryFile = SM.getFileID(C->getLocation());

        for (auto *P : C->protocols()) {
          Matcher.addImport(CategoryFile, P->getLocation(), SM);
        }
      }
    }
  }

  void MessageExprCallback::run(const MatchFinder::MatchResult &Result) {
    if (auto *E = Result.Nodes.getNodeAs<ObjCMessageExpr>(nodeKey)) {
      auto &SM = *Result.SourceManager;

      if (auto *ID = E->getReceiverInterface()) {
        Matcher.addImport(SM.getMainFileID(), ID->getLocation(), SM);
      } else if (auto *Ptr = E->getReceiverType()->getAs<ObjCObjectPointerType>()) {
        assert(Ptr->isObjCQualifiedIdType());
        for (auto i = Ptr->qual_begin(); i != Ptr->qual_end(); i++) {
          Matcher.addImport(SM.getMainFileID(), (*i)->getLocation(), SM);
        }
      } else {
        llvm::outs() << "failed to unpack expr of kind " << E->getReceiverKind();
        assert(0);
      }
    }
  }

  void MethodCallback::run(const MatchFinder::MatchResult &Result) {
    if (auto *M = Result.Nodes.getNodeAs<ObjCMethodDecl>(nodeKey)) {
      auto FID = Result.SourceManager->getFileID(M->getLocation());
      addType(FID, M->getReturnType(), *Result.SourceManager);

      for (auto i = M->param_begin(); i != M->param_end(); i++) {
        addType(FID, (*i)->getType(), *Result.SourceManager);
      }
    }
  }

  void MethodCallback::addType(const FileID InFile, QualType T, const SourceManager &SM) {
    if (auto *PT = T->getAs<ObjCObjectPointerType>()) {
      if (auto *ID = PT->getInterfaceDecl()) {
        // TODO: forward declare if it is a system library too
        // but check first if it is already imported
        if (SM.isInSystemHeader(ID->getLocation())) {
          Matcher.addImport(InFile, ID->getLocation(), SM);
        } else {
          Matcher.addForwardDeclare(InFile, ID->getName());
        }
      }
    }
  }

  void ProtocolCallback::run(const MatchFinder::MatchResult &Result) {
    if (auto *PD = Result.Nodes.getNodeAs<ObjCProtocolExpr>(nodeKey)->getProtocol()) {
      auto &SM = *Result.SourceManager;
      Matcher.addImport(SM.getMainFileID(), PD->getLocation(), SM);
    }
  }

  std::unique_ptr<FrontendActionFactory>
  ImportMatcher::getActionFactory(MatchFinder& Finder) {
    auto CallMatcher = callExpr(isExpansionInMainFile()).bind(nodeKey);
    auto InterfaceMatcher = interface(isImplementationInMainFile()).bind(nodeKey);
    auto MsgMatcher = message(isExpansionInMainFile()).bind(nodeKey);
    auto MtdMatcher = method(isDefinedInHeader()).bind(nodeKey);
    auto ProtoMatcher = protocol(isExpansionInMainFile()).bind(nodeKey);
    Finder.addMatcher(CallMatcher, &CallCallback);
    Finder.addMatcher(InterfaceMatcher, &InterfaceCallback);
    Finder.addMatcher(MsgMatcher, &MsgCallback);
    Finder.addMatcher(MtdMatcher, &MtdCallback);
    Finder.addMatcher(ProtoMatcher, &ProtoCallback);

    return newFrontendActionFactory(&Finder, &FileCallbacks);
  }

  void ImportMatcher::addLibraryInclude(const FileEntry *HE, const FileEntry *FE) {
    // don't allow circular includes
    // TODO: only map files belonging to the same library
    if (LibraryImportMap[FE].count(HE) == 0) {
      LibraryImportMap[HE].insert(FE);
    }
  }

  void ImportMatcher::addForwardDeclare(const FileID InFile, llvm::StringRef Name) {
    ImportMap[InFile].insert(Import(ImportType::ForwardDeclare, Name));
  }

  void ImportMatcher::addImport(const FileID InFile,
                                const SourceLocation Loc,
                                const SourceManager &SM) {
    auto OfFile = SM.getFileID(Loc);
    auto ImportedFile = topFileIncludingFile(LibraryImportMap, OfFile, SM);
    auto ImportedLoc = SM.getLocForStartOfFile(ImportedFile);
    ImportMap[InFile].insert(importForFileLoc(ImportedLoc, SM));
  }

  void ImportMatcher::removeImport(const SourceLocation Loc, const SourceManager &SM) {
    auto fid = SM.getFileID(Loc);
    auto *fileStart = SM.getBuffer(fid)->getBufferStart();
    unsigned start = SM.getFileOffset(Loc);
    unsigned end = strchr(fileStart + start, '\n') - fileStart + 1;

    // TODO: this is a dangerous assumption, should be modelled as a set of ranges
    ImportOffset[fid] = std::max(ImportOffset[fid], end);
  }

  void ImportMatcher::flush(const SourceManager &SM) {
    auto &out = llvm::outs();

    for (auto &Pair : ImportMap) {
      std::string import;
      llvm::raw_string_ostream ImportStr(import);
      for (auto &Import : Pair.second) {
        ImportStr << Import << '\n';
      }

      auto fid = Pair.first;
      auto start = SM.getLocForStartOfFile(fid);
      auto replacementLength = ImportOffset[fid];
      if (replacementLength == 0) {
        // make sure there is at least a line of whitespace after the new imports
        ImportStr << '\n';
      }

      Replacements.insert(Replacement(SM, start, replacementLength, ImportStr.str()));
      out << "File ID: " << fid.getHashValue() << "\n" << ImportStr.str() << "\n";
    }
    ImportMap.clear();
    ImportOffset.clear();
  }

} // end namespace import_tidy
<commit_msg>fix circular framework imports, don't follow dependencies across frameworks<commit_after>#include "ImportMatchers.h"
#include "clang/Basic/SourceManager.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>

using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace import_tidy;

namespace clang {
namespace ast_matchers {
  static const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr> message;
  static const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl> interface;
  static const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl> method;
  static const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCProtocolExpr> protocol;

  AST_MATCHER(ObjCInterfaceDecl, isImplementationInMainFile) {
    if (auto *ImpDecl = Node.getImplementation()) {
      auto &SourceManager = Finder->getASTContext().getSourceManager();
      return SourceManager.isInMainFile(SourceManager.getExpansionLoc(ImpDecl->getLocStart()));
    } else {
      return false;
    }
  }

  AST_MATCHER(ObjCMethodDecl, isDefinedInHeader) {
    auto *ID = Node.getClassInterface();
    if (!ID || !ID->getImplementation())
      return false;

    auto &SM = Finder->getASTContext().getSourceManager();
    if (SM.isInMainFile(SM.getExpansionLoc(Node.getLocStart())))
      return false;

    auto ImpLoc = SM.getExpansionLoc(ID->getImplementation()->getLocStart());
    return SM.isInMainFile(ImpLoc);
  }
} // end namespace ast_matchers
} // end namespace clang

namespace {

  static Import importForFileLoc(const SourceLocation L, const SourceManager &SM) {
    if (SM.isLoadedSourceLocation(L)) {
      return Import(ImportType::Module, SM.getModuleImportLoc(L).second);
    }

    auto Path = SM.getFilename(L);
    if (SM.isInSystemHeader(L)) {
      return Import(ImportType::Library, Path);
    }

    auto Filename = Path.drop_front(Path.find_last_of('/') + 1);
    return Import(ImportType::File, Filename);
  }

  static const clang::FileEntry*
  fileIncludingFile(std::map<const FileEntry*,
                    std::set<const FileEntry*>> &Map,
                    const FileEntry *F) {
    for (auto I : Map) {
      if (I.second.count(F)) {
        return I.first;
      }
    }
    return F;
  }

  static FileID
  topFileIncludingFile(std::map<const FileEntry*,
                       std::set<const FileEntry*>> &Map,
                       FileID File,
                       const SourceManager &SM) {
    auto *FE = SM.getFileEntryForID(File);
    const FileEntry *PE;
    do {
      PE = FE;
      FE = fileIncludingFile(Map, PE);
    } while (PE != FE);

    return SM.translateFile(FE);
  }

  // TODO: strip out forward declares too
  class ImportCallbacks : public clang::PPCallbacks {
  public:
    ImportCallbacks(const SourceManager &SM, ImportMatcher &M) :
      SM(SM), Matcher(M) { };

    void InclusionDirective(SourceLocation HashLoc,
                            const Token &IncludeTok,
                            StringRef FileName,
                            bool IsAngled,
                            CharSourceRange FilenameRange,
                            const FileEntry *File,
                            StringRef SearchPath,
                            StringRef RelativePath,
                            const Module *Imported) override {
      // TODO: use the imported module

      if (File && SM.isInSystemHeader(HashLoc)) {
        Matcher.addLibraryInclude(SM.getFileEntryForID(SM.getFileID(HashLoc)), File);
      } else {
        Matcher.removeImport(HashLoc, SM);
      }
    }
  private:
    const SourceManager &SM;
    ImportMatcher &Matcher;
  };

} // end anonymous namespace

namespace import_tidy {
  static const StringRef nodeKey = "key";

  bool FileCallbacks::handleBeginSource(CompilerInstance &CI, StringRef Filename) {
    auto &SM = CI.getSourceManager();
    auto &PP = CI.getPreprocessor();
    PP.addPPCallbacks(std::unique_ptr<ImportCallbacks>(new ImportCallbacks(SM, Matcher)));
    SourceMgr = &SM;

    return true;
  }

  void FileCallbacks::handleEndSource() {
    Matcher.flush(*SourceMgr);
  }

  void CallExprCallback::run(const MatchFinder::MatchResult &Result) {
    if (auto *FD = Result.Nodes.getNodeAs<CallExpr>(nodeKey)->getDirectCallee()) {
      auto &SM = *Result.SourceManager;
      Matcher.addImport(SM.getMainFileID(), FD->getLocation(), SM);
    }
  }

  void InterfaceCallback::run(const MatchFinder::MatchResult &Result) {
    if (auto *ID = Result.Nodes.getNodeAs<ObjCInterfaceDecl>(nodeKey)) {
      auto &SM = *Result.SourceManager;
      auto InFile = SM.getFileID(ID->getLocation());

      if (auto *SC = ID->getSuperClass()) {
        Matcher.addImport(InFile, SC->getLocation(), SM);
      }

      if (InFile != SM.getMainFileID()) {
        Matcher.addImport(SM.getMainFileID(), ID->getLocation(), SM);
      }

      for (auto *P : ID->protocols()) {
        Matcher.addImport(InFile, P->getLocation(), SM);
      }

      for (auto *C : ID->visible_categories()) {
        auto CategoryFile = SM.getFileID(C->getLocation());

        for (auto *P : C->protocols()) {
          Matcher.addImport(CategoryFile, P->getLocation(), SM);
        }
      }
    }
  }

  void MessageExprCallback::run(const MatchFinder::MatchResult &Result) {
    if (auto *E = Result.Nodes.getNodeAs<ObjCMessageExpr>(nodeKey)) {
      auto &SM = *Result.SourceManager;

      if (auto *ID = E->getReceiverInterface()) {
        Matcher.addImport(SM.getMainFileID(), ID->getLocation(), SM);
      } else if (auto *Ptr = E->getReceiverType()->getAs<ObjCObjectPointerType>()) {
        assert(Ptr->isObjCQualifiedIdType());
        for (auto i = Ptr->qual_begin(); i != Ptr->qual_end(); i++) {
          Matcher.addImport(SM.getMainFileID(), (*i)->getLocation(), SM);
        }
      } else {
        llvm::outs() << "failed to unpack expr of kind " << E->getReceiverKind();
        assert(0);
      }
    }
  }

  void MethodCallback::run(const MatchFinder::MatchResult &Result) {
    if (auto *M = Result.Nodes.getNodeAs<ObjCMethodDecl>(nodeKey)) {
      auto FID = Result.SourceManager->getFileID(M->getLocation());
      addType(FID, M->getReturnType(), *Result.SourceManager);

      for (auto i = M->param_begin(); i != M->param_end(); i++) {
        addType(FID, (*i)->getType(), *Result.SourceManager);
      }
    }
  }

  void MethodCallback::addType(const FileID InFile, QualType T, const SourceManager &SM) {
    if (auto *PT = T->getAs<ObjCObjectPointerType>()) {
      if (auto *ID = PT->getInterfaceDecl()) {
        // TODO: forward declare if it is a system library too
        // but check first if it is already imported
        if (SM.isInSystemHeader(ID->getLocation())) {
          Matcher.addImport(InFile, ID->getLocation(), SM);
        } else {
          Matcher.addForwardDeclare(InFile, ID->getName());
        }
      }
    }
  }

  void ProtocolCallback::run(const MatchFinder::MatchResult &Result) {
    if (auto *PD = Result.Nodes.getNodeAs<ObjCProtocolExpr>(nodeKey)->getProtocol()) {
      auto &SM = *Result.SourceManager;
      Matcher.addImport(SM.getMainFileID(), PD->getLocation(), SM);
    }
  }

  std::unique_ptr<FrontendActionFactory>
  ImportMatcher::getActionFactory(MatchFinder& Finder) {
    auto CallMatcher = callExpr(isExpansionInMainFile()).bind(nodeKey);
    auto InterfaceMatcher = interface(isImplementationInMainFile()).bind(nodeKey);
    auto MsgMatcher = message(isExpansionInMainFile()).bind(nodeKey);
    auto MtdMatcher = method(isDefinedInHeader()).bind(nodeKey);
    auto ProtoMatcher = protocol(isExpansionInMainFile()).bind(nodeKey);
    Finder.addMatcher(CallMatcher, &CallCallback);
    Finder.addMatcher(InterfaceMatcher, &InterfaceCallback);
    Finder.addMatcher(MsgMatcher, &MsgCallback);
    Finder.addMatcher(MtdMatcher, &MtdCallback);
    Finder.addMatcher(ProtoMatcher, &ProtoCallback);

    return newFrontendActionFactory(&Finder, &FileCallbacks);
  }

  void ImportMatcher::addLibraryInclude(const FileEntry *HE, const FileEntry *FE) {
    // some framework headers import themselves
    if (HE == FE)
      return;

    // don't allow circular imports
    if (LibraryImportMap.count(FE) > 0)
      return;

    // don't track includes across libraries
    if (HE->getDir() != FE->getDir())
      return;

    LibraryImportMap[HE].insert(FE);
  }

  void ImportMatcher::addForwardDeclare(const FileID InFile, llvm::StringRef Name) {
    ImportMap[InFile].insert(Import(ImportType::ForwardDeclare, Name));
  }

  void ImportMatcher::addImport(const FileID InFile,
                                const SourceLocation Loc,
                                const SourceManager &SM) {
    auto OfFile = SM.getFileID(Loc);
    auto ImportedFile = topFileIncludingFile(LibraryImportMap, OfFile, SM);
    auto ImportedLoc = SM.getLocForStartOfFile(ImportedFile);
    ImportMap[InFile].insert(importForFileLoc(ImportedLoc, SM));
  }

  void ImportMatcher::removeImport(const SourceLocation Loc, const SourceManager &SM) {
    auto fid = SM.getFileID(Loc);
    auto *fileStart = SM.getBuffer(fid)->getBufferStart();
    unsigned start = SM.getFileOffset(Loc);
    unsigned end = strchr(fileStart + start, '\n') - fileStart + 1;

    // TODO: this is a dangerous assumption, should be modelled as a set of ranges
    ImportOffset[fid] = std::max(ImportOffset[fid], end);
  }

  void ImportMatcher::flush(const SourceManager &SM) {
    auto &out = llvm::outs();

    for (auto &Pair : ImportMap) {
      std::string import;
      llvm::raw_string_ostream ImportStr(import);
      for (auto &Import : Pair.second) {
        ImportStr << Import << '\n';
      }

      auto fid = Pair.first;
      auto start = SM.getLocForStartOfFile(fid);
      auto replacementLength = ImportOffset[fid];
      if (replacementLength == 0) {
        // make sure there is at least a line of whitespace after the new imports
        ImportStr << '\n';
      }

      Replacements.insert(Replacement(SM, start, replacementLength, ImportStr.str()));
      out << "File ID: " << fid.getHashValue() << "\n" << ImportStr.str() << "\n";
    }
    ImportMap.clear();
    ImportOffset.clear();
  }

} // end namespace import_tidy
<|endoftext|>


<commit_before><commit_msg>Improve code documentation<commit_after><|endoftext|>


<commit_before>#include "mainwindow.h"
#include "edit_window.h"
#include "logic/settings.h"
#include "logic/tool_actions.h"
#include "tool_editor_widget.h"
#include "ui_mainwindow.h"

#include <QFile>
#include <QFileDialog>
#include <QFont>
#include <QFontDialog>
#include <QFontMetrics>

static MainWindow *main_window{};

MainWindow::MainWindow(QWidget *parent)
	: QMainWindow{parent}
	, ui{std::make_unique<Ui::MainWindow>()} {
	main_window = this;
	ui->setupUi(this);
	load_last_files();
	Tool_actions::set_actions(Settings::get<Settings::Key::tools>());
}

MainWindow::~MainWindow() { //required for destructors of otherwise incomplete type Ui::MainWindow
	save_last_files();
}

Edit_window *MainWindow::get_current_edit_window() {
	return dynamic_cast<Edit_window *>(main_window->ui->file_tabs->currentWidget());
}

QString MainWindow::get_current_path() {
	if (main_window == nullptr) {
		return {};
	}
	const auto tab_bar = main_window->ui->file_tabs->tabBar();
	return tab_bar->tabText(tab_bar->currentIndex());
}

MainWindow *MainWindow::get_main_window() {
	return main_window;
}

QString MainWindow::get_current_selection() {
	if (main_window == nullptr) {
		return {};
	}
	auto edit_window = dynamic_cast<Edit_window *>(main_window->ui->file_tabs->currentWidget());
	if (edit_window == nullptr) {
		return {};
	}
	return edit_window->textCursor().selectedText().replace("\u2029", "\n");
}

void MainWindow::on_actionOpen_File_triggered() {
	for (const auto &filename : QFileDialog::getOpenFileNames(this, tr("Select File(s) to open"))) {
		add_file_tab(filename);
	}
}

void MainWindow::on_file_tabs_tabCloseRequested(int index) {
	ui->file_tabs->removeTab(index);
}
void MainWindow::closeEvent(QCloseEvent *event) {
	tool_editor_widget = nullptr;
	event->accept();
}

void MainWindow::load_last_files() {
	for (const auto &filename : Settings::get<Settings::Key::files>()) {
		add_file_tab(filename);
	}
	ui->file_tabs->setCurrentIndex(Settings::get<Settings::Key::current_file>());
}

void MainWindow::save_last_files() {
	QStringList filename_list;
	for (int tab_index = 0; tab_index < ui->file_tabs->count(); tab_index++) {
		filename_list << ui->file_tabs->tabBar()->tabText(tab_index);
	}
	Settings::set<Settings::Key::files>(filename_list);
	Settings::set<Settings::Key::current_file>(ui->file_tabs->currentIndex());
}

void MainWindow::add_file_tab(const QString &filename) {
	auto file_edit = std::make_unique<Edit_window>();
	QFile file{filename};
	file.open(QFile::ReadOnly);
	if (file.isOpen()) {
		file_edit->setPlainText(file.readAll());
	} else {
		file_edit->setPlaceholderText(tr("Failed reading file %1").arg(filename));
	}
	QFont font;
	font.fromString(Settings::get<Settings::Key::font>("monospace"));
	file_edit->setFont(font);
	file_edit->setTabStopWidth(QFontMetrics{font}.width("    "));
	file_edit->setLineWrapMode(Edit_window::LineWrapMode::NoWrap);
	ui->file_tabs->addTab(file_edit.release(), filename);
}

void MainWindow::apply_to_all_edit_windows(const std::function<void(Edit_window *)> &function) {
	for (int tab_index = 0; tab_index < ui->file_tabs->count(); tab_index++) {
		auto edit = dynamic_cast<Edit_window *>(ui->file_tabs->widget(tab_index));
		function(edit);
	}
}

void MainWindow::on_action_Font_triggered() {
	bool success;
	const auto font = QFontDialog::getFont(&success, this);
	if (success == false) {
		return;
	}
	Settings::set<Settings::Key::font>(font.toString());
	apply_to_all_edit_windows([&font](Edit_window *edit) { edit->setFont(font); });
}

void MainWindow::on_action_Edit_triggered() {
	if (tool_editor_widget != nullptr && tool_editor_widget->isVisible()) {
		tool_editor_widget->activateWindow();
	} else {
		tool_editor_widget = std::make_unique<Tool_editor_widget>();
		tool_editor_widget->show();
	}
}
<commit_msg>Added tool tips for tabs in case they become unreadable when opening many tabs.<commit_after>#include "mainwindow.h"
#include "edit_window.h"
#include "logic/settings.h"
#include "logic/tool_actions.h"
#include "tool_editor_widget.h"
#include "ui_mainwindow.h"

#include <QFile>
#include <QFileDialog>
#include <QFont>
#include <QFontDialog>
#include <QFontMetrics>

static MainWindow *main_window{};

MainWindow::MainWindow(QWidget *parent)
	: QMainWindow{parent}
	, ui{std::make_unique<Ui::MainWindow>()} {
	main_window = this;
	ui->setupUi(this);
	load_last_files();
	Tool_actions::set_actions(Settings::get<Settings::Key::tools>());
}

MainWindow::~MainWindow() { //required for destructors of otherwise incomplete type Ui::MainWindow
	save_last_files();
}

Edit_window *MainWindow::get_current_edit_window() {
	return dynamic_cast<Edit_window *>(main_window->ui->file_tabs->currentWidget());
}

QString MainWindow::get_current_path() {
	if (main_window == nullptr) {
		return {};
	}
	const auto tab_bar = main_window->ui->file_tabs->tabBar();
	return tab_bar->tabText(tab_bar->currentIndex());
}

MainWindow *MainWindow::get_main_window() {
	return main_window;
}

QString MainWindow::get_current_selection() {
	if (main_window == nullptr) {
		return {};
	}
	auto edit_window = dynamic_cast<Edit_window *>(main_window->ui->file_tabs->currentWidget());
	if (edit_window == nullptr) {
		return {};
	}
	return edit_window->textCursor().selectedText().replace("\u2029", "\n");
}

void MainWindow::on_actionOpen_File_triggered() {
	for (const auto &filename : QFileDialog::getOpenFileNames(this, tr("Select File(s) to open"))) {
		add_file_tab(filename);
	}
}

void MainWindow::on_file_tabs_tabCloseRequested(int index) {
	ui->file_tabs->removeTab(index);
}
void MainWindow::closeEvent(QCloseEvent *event) {
	tool_editor_widget = nullptr;
	event->accept();
}

void MainWindow::load_last_files() {
	for (const auto &filename : Settings::get<Settings::Key::files>()) {
		add_file_tab(filename);
	}
	ui->file_tabs->setCurrentIndex(Settings::get<Settings::Key::current_file>());
}

void MainWindow::save_last_files() {
	QStringList filename_list;
	for (int tab_index = 0; tab_index < ui->file_tabs->count(); tab_index++) {
		filename_list << ui->file_tabs->tabBar()->tabText(tab_index);
	}
	Settings::set<Settings::Key::files>(filename_list);
	Settings::set<Settings::Key::current_file>(ui->file_tabs->currentIndex());
}

void MainWindow::add_file_tab(const QString &filename) {
	auto file_edit = std::make_unique<Edit_window>();
	QFile file{filename};
	file.open(QFile::ReadOnly);
	if (file.isOpen()) {
		file_edit->setPlainText(file.readAll());
	} else {
		file_edit->setPlaceholderText(tr("Failed reading file %1").arg(filename));
	}
	QFont font;
	font.fromString(Settings::get<Settings::Key::font>("monospace"));
	file_edit->setFont(font);
	file_edit->setTabStopWidth(QFontMetrics{font}.width("    "));
	file_edit->setLineWrapMode(Edit_window::LineWrapMode::NoWrap);
	auto index = ui->file_tabs->addTab(file_edit.release(), filename);
	ui->file_tabs->setTabToolTip(index, filename);
}

void MainWindow::apply_to_all_edit_windows(const std::function<void(Edit_window *)> &function) {
	for (int tab_index = 0; tab_index < ui->file_tabs->count(); tab_index++) {
		auto edit = dynamic_cast<Edit_window *>(ui->file_tabs->widget(tab_index));
		function(edit);
	}
}

void MainWindow::on_action_Font_triggered() {
	bool success;
	const auto font = QFontDialog::getFont(&success, this);
	if (success == false) {
		return;
	}
	Settings::set<Settings::Key::font>(font.toString());
	apply_to_all_edit_windows([&font](Edit_window *edit) { edit->setFont(font); });
}

void MainWindow::on_action_Edit_triggered() {
	if (tool_editor_widget != nullptr && tool_editor_widget->isVisible()) {
		tool_editor_widget->activateWindow();
	} else {
		tool_editor_widget = std::make_unique<Tool_editor_widget>();
		tool_editor_widget->show();
	}
}
<|endoftext|>


<commit_before>
#include "allocore/io/al_CSVReader.hpp"

CSVReader::~CSVReader() {
	for (auto row: mData) {
		delete[] row;
	}
	mData.clear();
}

void CSVReader::readFile(std::string fileName) {
	std::ifstream f(fileName);
	if (!f.is_open()) {
		std::cout << "Could not open:" << fileName << std::endl;
		return;
	}

	std::string line;
	size_t rowLength = calculateRowLength();

	getline(f, line); // TODO Process column names
//	std::cout << line << std::endl;
	while (getline(f, line)) {
		if (line.size() == 0) {
			continue;
		}
		if (std::count(line.begin(), line.end(), ',') == mDataTypes.size() - 1) { // Check that we have enough commas
			std::stringstream ss(line);
			char *row = new char[rowLength];
			mData.push_back(row);
			char *data = mData.back();
			int byteCount = 0;
			for(auto type:mDataTypes) {
				std::string field;
				std::getline(ss, field, ',');
				size_t stringLen = std::min(maxStringSize, field.size());
				int32_t intValue;
				double doubleValue;
				bool booleanValue;
				switch (type){
				case STRING:
					std::memcpy(data + byteCount, field.data(), stringLen * sizeof (char));
					byteCount += maxStringSize * sizeof (char);
					break;
				case INTEGER:
					intValue = std::atoi(field.data());
					std::memcpy(data + byteCount, &intValue, sizeof (int32_t));
					byteCount += sizeof (int32_t);
					break;
				case REAL:
					doubleValue = std::atof(field.data());
					std::memcpy(data + byteCount, &doubleValue, sizeof (double));
					byteCount += sizeof (double);
					break;
				case BOOLEAN:
					booleanValue = field == "True" || field == "true";
					std::memcpy(data + byteCount, &booleanValue, sizeof (bool));
					byteCount += sizeof (bool);
					break;
				case NONE:
					break;
				}
			}
		}
	}
	if (f.bad()) {
		std::cout << "Error reading:" << fileName << std::endl;
	}
}

std::vector<double> CSVReader::getColumn(int index) {
	std::vector<double> out;
	int offset = 0;
	for (int i = 0; i < index; i++) {
		switch (mDataTypes[i]){
		case STRING:
			offset += maxStringSize * sizeof (char);
			break;
		case INTEGER:
			offset += sizeof (int32_t);
			break;
		case REAL:
			offset += sizeof (double);
			break;
		case BOOLEAN:
			offset += sizeof (bool);
			break;
		case NONE:
			break;
		}
	}
//	std::cout << offset << std::endl;
	for (auto row: mData) {
		double *val = (double *)(row + offset);
		out.push_back(*val);
	}
	return out;
}

size_t CSVReader::calculateRowLength() {
	size_t len = 0;;
	for(auto type:mDataTypes) {
		switch(type) {
		case STRING:
			len += maxStringSize * sizeof (char);
			break;
		case INTEGER:
			len += sizeof (int32_t);
			break;
		case REAL:
			len += sizeof (double);
			break;
		case BOOLEAN:
			len += sizeof (bool);
			break;
		case NONE:
			break;
		}
	}
//	std::cout << len << std::endl;
	return len;
}
<commit_msg>Fix compiler warning<commit_after>
#include "allocore/io/al_CSVReader.hpp"

CSVReader::~CSVReader() {
	for (auto row: mData) {
		delete[] row;
	}
	mData.clear();
}

void CSVReader::readFile(std::string fileName) {
	std::ifstream f(fileName);
	if (!f.is_open()) {
		std::cout << "Could not open:" << fileName << std::endl;
		return;
	}

	std::string line;
	size_t rowLength = calculateRowLength();

	getline(f, line); // TODO Process column names
//	std::cout << line << std::endl;
	while (getline(f, line)) {
		if (line.size() == 0) {
			continue;
		}
		if (std::count(line.begin(), line.end(), ',') == int(mDataTypes.size() - 1)) { // Check that we have enough commas
			std::stringstream ss(line);
			char *row = new char[rowLength];
			mData.push_back(row);
			char *data = mData.back();
			int byteCount = 0;
			for(auto type:mDataTypes) {
				std::string field;
				std::getline(ss, field, ',');
				size_t stringLen = std::min(maxStringSize, field.size());
				int32_t intValue;
				double doubleValue;
				bool booleanValue;
				switch (type){
				case STRING:
					std::memcpy(data + byteCount, field.data(), stringLen * sizeof (char));
					byteCount += maxStringSize * sizeof (char);
					break;
				case INTEGER:
					intValue = std::atoi(field.data());
					std::memcpy(data + byteCount, &intValue, sizeof (int32_t));
					byteCount += sizeof (int32_t);
					break;
				case REAL:
					doubleValue = std::atof(field.data());
					std::memcpy(data + byteCount, &doubleValue, sizeof (double));
					byteCount += sizeof (double);
					break;
				case BOOLEAN:
					booleanValue = field == "True" || field == "true";
					std::memcpy(data + byteCount, &booleanValue, sizeof (bool));
					byteCount += sizeof (bool);
					break;
				case NONE:
					break;
				}
			}
		}
	}
	if (f.bad()) {
		std::cout << "Error reading:" << fileName << std::endl;
	}
}

std::vector<double> CSVReader::getColumn(int index) {
	std::vector<double> out;
	int offset = 0;
	for (int i = 0; i < index; i++) {
		switch (mDataTypes[i]){
		case STRING:
			offset += maxStringSize * sizeof (char);
			break;
		case INTEGER:
			offset += sizeof (int32_t);
			break;
		case REAL:
			offset += sizeof (double);
			break;
		case BOOLEAN:
			offset += sizeof (bool);
			break;
		case NONE:
			break;
		}
	}
//	std::cout << offset << std::endl;
	for (auto row: mData) {
		double *val = (double *)(row + offset);
		out.push_back(*val);
	}
	return out;
}

size_t CSVReader::calculateRowLength() {
	size_t len = 0;;
	for(auto type:mDataTypes) {
		switch(type) {
		case STRING:
			len += maxStringSize * sizeof (char);
			break;
		case INTEGER:
			len += sizeof (int32_t);
			break;
		case REAL:
			len += sizeof (double);
			break;
		case BOOLEAN:
			len += sizeof (bool);
			break;
		case NONE:
			break;
		}
	}
//	std::cout << len << std::endl;
	return len;
}
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"
#include <Eigen/Geometry>
#include <Eigen/LU>
#include <Eigen/SVD>

/* this test covers the following files:
   Geometry/OrthoMethods.h
*/

template<typename Scalar> void orthomethods_3()
{
  typedef Matrix<Scalar,3,3> Matrix3;
  typedef Matrix<Scalar,3,1> Vector3;

  typedef Matrix<Scalar,4,1> Vector4;

  Vector3 v0 = Vector3::Random(),
          v1 = Vector3::Random(),
          v2 = Vector3::Random();

  // cross product
  VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v1), Scalar(1));
  Matrix3 mat3;
  mat3 << v0.normalized(),
         (v0.cross(v1)).normalized(),
         (v0.cross(v1).cross(v0)).normalized();
  VERIFY(mat3.isUnitary());

  // colwise/rowwise cross product
  mat3.setRandom();
  Vector3 vec3 = Vector3::Random();
  Matrix3 mcross;
  int i = ei_random<int>(0,2);
  mcross = mat3.colwise().cross(vec3);
  VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
  mcross = mat3.rowwise().cross(vec3);
  VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));

  // cross3
  Vector4 v40 = Vector4::Random(),
          v41 = Vector4::Random(),
          v42 = Vector4::Random();
  v40.w() = v41.w() = v42.w() = 0;
  v42.template start<3>() = v40.template start<3>().cross(v41.template start<3>());
  VERIFY_IS_APPROX(v40.cross3(v41), v42);
}

template<typename Scalar, int Size> void orthomethods(int size=Size)
{
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar,Size,1> VectorType;
  typedef Matrix<Scalar,3,Size> Matrix3N;
  typedef Matrix<Scalar,Size,3> MatrixN3;
  typedef Matrix<Scalar,3,1> Vector3;

  VectorType v0 = VectorType::Random(size),
             v1 = VectorType::Random(size),
             v2 = VectorType::Random(size);

  // unitOrthogonal
  VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1));
  VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), RealScalar(1));

  if (size>3)
  {
    v0.template start<3>().setZero();
    v0.end(size-3).setRandom();

    VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1));
    VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), RealScalar(1));
  }

  // colwise/rowwise cross product
  Vector3 vec3 = Vector3::Random();
  int i = ei_random<int>(0,size-1);

  Matrix3N mat3N(3,size), mcross3N(3,size);
  mat3N.setRandom();
  mcross3N = mat3N.colwise().cross(vec3);
  VERIFY_IS_APPROX(mcross3N.col(i), mat3N.col(i).cross(vec3));

  MatrixN3 matN3(size,3), mcrossN3(size,3);
  matN3.setRandom();
  mcrossN3 = matN3.rowwise().cross(vec3);
  VERIFY_IS_APPROX(mcrossN3.row(i), matN3.row(i).cross(vec3));
}

void test_geo_orthomethods()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST( orthomethods_3<float>() );
    CALL_SUBTEST( orthomethods_3<double>() );
    CALL_SUBTEST( (orthomethods<float,2>()) );
    CALL_SUBTEST( (orthomethods<double,2>()) );
    CALL_SUBTEST( (orthomethods<float,3>()) );
    CALL_SUBTEST( (orthomethods<double,3>()) );
    CALL_SUBTEST( (orthomethods<float,7>()) );
    CALL_SUBTEST( (orthomethods<std::complex<double>,8>()) );
    CALL_SUBTEST( (orthomethods<float,Dynamic>(36)) );
    CALL_SUBTEST( (orthomethods<double,Dynamic>(35)) );
  }
}
<commit_msg>improve coverage of unitOrthogonal<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"
#include <Eigen/Geometry>
#include <Eigen/LU>
#include <Eigen/SVD>

/* this test covers the following files:
   Geometry/OrthoMethods.h
*/

template<typename Scalar> void orthomethods_3()
{
  typedef Matrix<Scalar,3,3> Matrix3;
  typedef Matrix<Scalar,3,1> Vector3;

  typedef Matrix<Scalar,4,1> Vector4;

  Vector3 v0 = Vector3::Random(),
          v1 = Vector3::Random(),
          v2 = Vector3::Random();

  // cross product
  VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v1), Scalar(1));
  Matrix3 mat3;
  mat3 << v0.normalized(),
         (v0.cross(v1)).normalized(),
         (v0.cross(v1).cross(v0)).normalized();
  VERIFY(mat3.isUnitary());

  // colwise/rowwise cross product
  mat3.setRandom();
  Vector3 vec3 = Vector3::Random();
  Matrix3 mcross;
  int i = ei_random<int>(0,2);
  mcross = mat3.colwise().cross(vec3);
  VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
  mcross = mat3.rowwise().cross(vec3);
  VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));

  // cross3
  Vector4 v40 = Vector4::Random(),
          v41 = Vector4::Random(),
          v42 = Vector4::Random();
  v40.w() = v41.w() = v42.w() = 0;
  v42.template start<3>() = v40.template start<3>().cross(v41.template start<3>());
  VERIFY_IS_APPROX(v40.cross3(v41), v42);
}

template<typename Scalar, int Size> void orthomethods(int size=Size)
{
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar,Size,1> VectorType;
  typedef Matrix<Scalar,3,Size> Matrix3N;
  typedef Matrix<Scalar,Size,3> MatrixN3;
  typedef Matrix<Scalar,3,1> Vector3;

  VectorType v0 = VectorType::Random(size),
             v1 = VectorType::Random(size),
             v2 = VectorType::Random(size);

  // unitOrthogonal
  VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1));
  VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), RealScalar(1));

  if (size>=3)
  {
    v0.template start<2>().setZero();
    v0.end(size-2).setRandom();

    VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1));
    VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), RealScalar(1));
  }

  // colwise/rowwise cross product
  Vector3 vec3 = Vector3::Random();
  int i = ei_random<int>(0,size-1);

  Matrix3N mat3N(3,size), mcross3N(3,size);
  mat3N.setRandom();
  mcross3N = mat3N.colwise().cross(vec3);
  VERIFY_IS_APPROX(mcross3N.col(i), mat3N.col(i).cross(vec3));

  MatrixN3 matN3(size,3), mcrossN3(size,3);
  matN3.setRandom();
  mcrossN3 = matN3.rowwise().cross(vec3);
  VERIFY_IS_APPROX(mcrossN3.row(i), matN3.row(i).cross(vec3));
}

void test_geo_orthomethods()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST( orthomethods_3<float>() );
    CALL_SUBTEST( orthomethods_3<double>() );
    CALL_SUBTEST( (orthomethods<float,2>()) );
    CALL_SUBTEST( (orthomethods<double,2>()) );
    CALL_SUBTEST( (orthomethods<float,3>()) );
    CALL_SUBTEST( (orthomethods<double,3>()) );
    CALL_SUBTEST( (orthomethods<float,7>()) );
    CALL_SUBTEST( (orthomethods<std::complex<double>,8>()) );
    CALL_SUBTEST( (orthomethods<float,Dynamic>(36)) );
    CALL_SUBTEST( (orthomethods<double,Dynamic>(35)) );
  }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <cmath>

#include "TH1.h"
#include "TH2.h"
#include "TH3.h"
#include "TCanvas.h"
#include "TRandom3.h"
#include "TVector2.h"
#include "TVector3.h"
#include "TLorentzVector.h"

#include "detector.hpp"

/* Simulated experiment is a K_L->PiPi decay (CP violating)*/

const double K_energy_average /*GeV*/ =  2; // Around the value of Cronin-Fitch experiment
const double K_energy_sigma   /*GeV*/ =  0.5;
const double K_path_average   /* m */ = 15.34;
const double K_mass           /*GeV*/ =  0.497611;

const double Pi_mass          /*GeV*/ =  0.139570; // charged pi

const double Pi_energy_cm = K_mass/2;
const double Pi_momentum_mod_cm = sqrt(Pi_energy_cm*Pi_energy_cm - Pi_mass*Pi_mass);

/* Plots constants */
const double hits_bound /* m */ = 100;

const int N_events = 1e5;

TRandom rng;

using namespace std;

ostream& operator<<(ostream& ost, TVector2& vec)
{
    return ost << vec.X() << " " << vec.Y();
}

ostream& operator<<(ostream& ost, TVector3& vec)
{
    return ost << vec.X() << " " << vec.Y() << " " << vec.Z();
}

inline double generate_K_energy()
{
    return max(K_mass, rng.Gaus(K_energy_average, K_energy_sigma));
}

inline double generate_K_path()
{
    return rng.Exp(K_path_average);
}

inline double gamma_from_K_energy(double K_energy)
{
    return K_energy/K_mass;
}

inline TVector3 generate_Pi_momentum_cm()
{
    double x,y,z;
    rng.Sphere(x, y, z, Pi_momentum_mod_cm);
    return TVector3(x, y, z);
}

inline TVector2 line_propagation(TVector3 Pi_momentum, double z_end, double z_start, double x_start=0, double y_start=0)
{
    double z_travelled = z_end - z_start;
    double scale = z_travelled/Pi_momentum.Pz();
    return TVector2(Pi_momentum.Px()*scale + x_start, Pi_momentum.Py()*scale + y_start);
}

inline TVector2 apply_chamber_smearing(TVector2 hit, double dx, double dy)
{
    double x = rng.Gaus(hit.X(), dx);
    double y = rng.Gaus(hit.Y(), dy);
    return TVector2(x, y);
}

int experiment()
{
    rng = TRandom3(12345); /* Fixed init */

    // Histograms declaration
    TCanvas* canv_K_energy = new TCanvas("canv_K_energy", "K energy distribution", 1000, 600);
    TH1D* histo_K_energy = new TH1D("histo_K_energy", "K energy distribution; E (GeV); N",
                                    180, K_energy_average - 3* K_energy_sigma, K_energy_average + 3* K_energy_sigma);

    TCanvas* canv_K_path = new TCanvas("canv_K_path", "K path distribution", 1000, 600);
    TH1D* histo_K_path = new TH1D("histo_K_path", "K path distribution; Path (m); N",
                                  180, 0, 10*gamma_from_K_energy(K_energy_average)*K_path_average);

    TCanvas* canv_Pi_momentum_cm = new TCanvas("canv_Pi_momentum_cm", "Pi momentum cm", 1000, 600);
    TH3D* histo_Pi_momentum_cm = new TH3D("histo_Pi_momentum_cm", "Pi momentum cm; Px (GeV); Py (GeV); Pz (GeV)",
                                          100, -Pi_momentum_mod_cm, +Pi_momentum_mod_cm,
                                          100, -Pi_momentum_mod_cm, +Pi_momentum_mod_cm,
                                          100, -Pi_momentum_mod_cm, +Pi_momentum_mod_cm);

    TCanvas* canv_Pi_pos = new TCanvas("canv_Pi_pos", "Pi pos", 1000, 600);
    TH3D* histo_Pi_pos = new TH3D("histo_Pi_pos", "Pi pos; Px (GeV); Py (GeV); Pz (GeV)",
                                  100, -Pi_momentum_mod_cm, +Pi_momentum_mod_cm,
                                  100, -Pi_momentum_mod_cm, +Pi_momentum_mod_cm,
                                  100, 0,                   +2*K_energy_average);

    TCanvas* canv_hit_p1 = new TCanvas("canv_hit_p1", "Hit pos ch1", 1000, 600);
    TH2D* histo_hit_p1 = new TH2D("histo_hit_p1", "Hit pos ch1; x (m); y (m); N",
                                  200, -hits_bound, +hits_bound, 200, -hits_bound, +hits_bound);

    TCanvas* canv_hit_p1_smeared = new TCanvas("canv_hit_p1_smeared", "Hit pos ch1 smeared", 1000, 600);
    TH2D* histo_hit_p1_smeared = new TH2D("histo_hit_p1_smeared", "Hit pos ch1 smeared; x (m); y (m); N",
                                          200, -hits_bound, +hits_bound, 200, -hits_bound, +hits_bound);

    TCanvas* canv_hit_p3 = new TCanvas("canv_hit_p13", "Hit pos ch3", 1000, 600);
    TH2D* histo_hit_p3 = new TH2D("histo_hit_p3", "Hit pos ch3; x (m); y (m); N",
                                  200, -hits_bound, +hits_bound, 200, -hits_bound, +hits_bound);

    // Out file
    ofstream outfile;
    outfile.open("experiment.txt");

    // Main loop
    for (int nev=0; nev<N_events; ++nev) {

        // Generate K energy
        double K_energy = generate_K_energy();
        histo_K_energy->Fill(K_energy);

        // Generate K path
        double path_cm = generate_K_path();
        double path = gamma_from_K_energy(K_energy)*path_cm;
        histo_K_path->Fill(path);

        // Discard K that have not decayed before the first chamber
        if (path > z1) continue;

        // Generate cm dynamic
        TVector3 Pi_momentum_cm = generate_Pi_momentum_cm();
        histo_Pi_momentum_cm->Fill(Pi_momentum_cm.Px(), Pi_momentum_cm.Py(), Pi_momentum_cm.Pz());

        // Boost to lab frame
        double K_beta_z = sqrt(1 - pow(K_mass/K_energy, 2));
        // double x = K_mass/K_energy;
        // double K_beta_z = 1 + pow(x, 2)/2 - pow(x, 4)/8 + pow(x, 6)/16;
        TVector3 K_beta = TVector3(0, 0, K_beta_z);
        TLorentzVector Pi_pos_4v = TLorentzVector( Pi_momentum_cm, Pi_energy_cm);
        TLorentzVector Pi_neg_4v = TLorentzVector(-Pi_momentum_cm, Pi_energy_cm); // Momentum cons. in cm
        Pi_pos_4v.Boost(K_beta);
        Pi_neg_4v.Boost(K_beta);
        TVector3 Pi_pos = Pi_pos_4v.Vect();
        TVector3 Pi_neg = Pi_neg_4v.Vect();
        histo_Pi_pos->Fill(Pi_pos.Px(), Pi_pos.Py(), Pi_pos.Pz());

        // Calculate hit points in first two chambers
        TVector2 hit_p1=line_propagation(Pi_pos, z1, path);
        TVector2 hit_n1=line_propagation(Pi_neg, z1, path);
        TVector2 hit_p2=line_propagation(Pi_pos, z2, path);
        TVector2 hit_n2=line_propagation(Pi_neg, z2, path);
        histo_hit_p1->Fill(hit_p1.X(), hit_p1.Y());

        // Apply chamber smearing
        TVector2 hit_p1_smeared = apply_chamber_smearing(hit_p1, dx, dy);
        TVector2 hit_n1_smeared = apply_chamber_smearing(hit_n1, dx, dy);
        TVector2 hit_p2_smeared = apply_chamber_smearing(hit_p2, dx, dy);
        TVector2 hit_n2_smeared = apply_chamber_smearing(hit_n2, dx, dy);
        histo_hit_p1_smeared->Fill(hit_p1_smeared.X(), hit_p1_smeared.Y());

        // The magnetic field is schematized as a kick of magnitude p_kick
        // applied at the center of the magnetic field region (z_kick)

        // Find position at kick
        TVector2 Pi_pos_position_kick = line_propagation(Pi_pos, z_kick, path);
        TVector2 Pi_neg_position_kick = line_propagation(Pi_neg, z_kick, path);
        TVector3 p_kick_vec = TVector3(p_kick, 0, 0);

        // Find hits in last two chambers - p_kick is opposite due to charge
        TVector2 hit_p3=line_propagation(Pi_pos + p_kick_vec, z3, z_kick, Pi_pos_position_kick.X(), Pi_pos_position_kick.Y());
        TVector2 hit_n3=line_propagation(Pi_neg - p_kick_vec, z3, z_kick, Pi_neg_position_kick.X(), Pi_neg_position_kick.Y());
        TVector2 hit_p4=line_propagation(Pi_pos + p_kick_vec, z4, z_kick, Pi_pos_position_kick.X(), Pi_pos_position_kick.Y());
        TVector2 hit_n4=line_propagation(Pi_neg - p_kick_vec, z4, z_kick, Pi_neg_position_kick.X(), Pi_neg_position_kick.Y());
        histo_hit_p3->Fill(hit_p3.X(), hit_p3.Y());

        // Apply chamber smearing
        TVector2 hit_p3_smeared = apply_chamber_smearing(hit_p3, dx, dy);
        TVector2 hit_n3_smeared = apply_chamber_smearing(hit_n3, dx, dy);
        TVector2 hit_p4_smeared = apply_chamber_smearing(hit_p4, dx, dy);
        TVector2 hit_n4_smeared = apply_chamber_smearing(hit_n4, dx, dy);

        // Write to file
        outfile << nev            << " ";
        outfile << hit_p1_smeared << " ";
        outfile << hit_n1_smeared << " ";
        outfile << hit_p2_smeared << " ";
        outfile << hit_n2_smeared << " ";
        outfile << hit_p3_smeared << " ";
        outfile << hit_n3_smeared << " ";
        outfile << hit_p4_smeared << " ";
        outfile << hit_n4_smeared << " ";
        outfile << K_energy       << " ";
        outfile << path           << " ";
        outfile << Pi_pos         << " ";
        outfile << Pi_neg         <<endl;
    }

    // Histogram drawing

    canv_K_energy->cd();
    histo_K_energy->Draw();

    canv_K_path->cd();
    canv_K_path->SetLogy();
    histo_K_path->Draw();

    canv_Pi_momentum_cm->cd();
    histo_Pi_momentum_cm->Draw();

    canv_Pi_pos->cd();
    histo_Pi_pos->Draw();

    canv_hit_p1->cd();
    histo_hit_p1->Draw();

    canv_hit_p1_smeared->cd();
    histo_hit_p1_smeared->Draw();

    canv_hit_p3->cd();
    histo_hit_p3->Draw();

    return 0;
}

int main(int, char**)
{
    return experiment();
}
<commit_msg>Made N_events configurable at runtime<commit_after>#include <iostream>
#include <fstream>
#include <cmath>

#include "TH1.h"
#include "TH2.h"
#include "TH3.h"
#include "TCanvas.h"
#include "TRandom3.h"
#include "TVector2.h"
#include "TVector3.h"
#include "TLorentzVector.h"

#include "detector.hpp"

/* Simulated experiment is a K_L->PiPi decay (CP violating)*/

const double K_energy_average /*GeV*/ =  2; // Around the value of Cronin-Fitch experiment
const double K_energy_sigma   /*GeV*/ =  0.5;
const double K_path_average   /* m */ = 15.34;
const double K_mass           /*GeV*/ =  0.497611;

const double Pi_mass          /*GeV*/ =  0.139570; // charged pi

const double Pi_energy_cm = K_mass/2;
const double Pi_momentum_mod_cm = sqrt(Pi_energy_cm*Pi_energy_cm - Pi_mass*Pi_mass);

/* Plots constants */
const double hits_bound /* m */ = 100;

TRandom rng;

using namespace std;

ostream& operator<<(ostream& ost, TVector2& vec)
{
    return ost << vec.X() << " " << vec.Y();
}

ostream& operator<<(ostream& ost, TVector3& vec)
{
    return ost << vec.X() << " " << vec.Y() << " " << vec.Z();
}

inline double generate_K_energy()
{
    return max(K_mass, rng.Gaus(K_energy_average, K_energy_sigma));
}

inline double generate_K_path()
{
    return rng.Exp(K_path_average);
}

inline double gamma_from_K_energy(double K_energy)
{
    return K_energy/K_mass;
}

inline TVector3 generate_Pi_momentum_cm()
{
    double x,y,z;
    rng.Sphere(x, y, z, Pi_momentum_mod_cm);
    return TVector3(x, y, z);
}

inline TVector2 line_propagation(TVector3 Pi_momentum, double z_end, double z_start, double x_start=0, double y_start=0)
{
    double z_travelled = z_end - z_start;
    double scale = z_travelled/Pi_momentum.Pz();
    return TVector2(Pi_momentum.Px()*scale + x_start, Pi_momentum.Py()*scale + y_start);
}

inline TVector2 apply_chamber_smearing(TVector2 hit, double dx, double dy)
{
    double x = rng.Gaus(hit.X(), dx);
    double y = rng.Gaus(hit.Y(), dy);
    return TVector2(x, y);
}

int experiment(int N_events = 1e5)
{
    rng = TRandom3(12345); /* Fixed init */

    // Histograms declaration
    TCanvas* canv_K_energy = new TCanvas("canv_K_energy", "K energy distribution", 1000, 600);
    TH1D* histo_K_energy = new TH1D("histo_K_energy", "K energy distribution; E (GeV); N",
                                    180, K_energy_average - 3* K_energy_sigma, K_energy_average + 3* K_energy_sigma);

    TCanvas* canv_K_path = new TCanvas("canv_K_path", "K path distribution", 1000, 600);
    TH1D* histo_K_path = new TH1D("histo_K_path", "K path distribution; Path (m); N",
                                  180, 0, 10*gamma_from_K_energy(K_energy_average)*K_path_average);

    TCanvas* canv_Pi_momentum_cm = new TCanvas("canv_Pi_momentum_cm", "Pi momentum cm", 1000, 600);
    TH3D* histo_Pi_momentum_cm = new TH3D("histo_Pi_momentum_cm", "Pi momentum cm; Px (GeV); Py (GeV); Pz (GeV)",
                                          100, -Pi_momentum_mod_cm, +Pi_momentum_mod_cm,
                                          100, -Pi_momentum_mod_cm, +Pi_momentum_mod_cm,
                                          100, -Pi_momentum_mod_cm, +Pi_momentum_mod_cm);

    TCanvas* canv_Pi_pos = new TCanvas("canv_Pi_pos", "Pi pos", 1000, 600);
    TH3D* histo_Pi_pos = new TH3D("histo_Pi_pos", "Pi pos; Px (GeV); Py (GeV); Pz (GeV)",
                                  100, -Pi_momentum_mod_cm, +Pi_momentum_mod_cm,
                                  100, -Pi_momentum_mod_cm, +Pi_momentum_mod_cm,
                                  100, 0,                   +2*K_energy_average);

    TCanvas* canv_hit_p1 = new TCanvas("canv_hit_p1", "Hit pos ch1", 1000, 600);
    TH2D* histo_hit_p1 = new TH2D("histo_hit_p1", "Hit pos ch1; x (m); y (m); N",
                                  200, -hits_bound, +hits_bound, 200, -hits_bound, +hits_bound);

    TCanvas* canv_hit_p1_smeared = new TCanvas("canv_hit_p1_smeared", "Hit pos ch1 smeared", 1000, 600);
    TH2D* histo_hit_p1_smeared = new TH2D("histo_hit_p1_smeared", "Hit pos ch1 smeared; x (m); y (m); N",
                                          200, -hits_bound, +hits_bound, 200, -hits_bound, +hits_bound);

    TCanvas* canv_hit_p3 = new TCanvas("canv_hit_p13", "Hit pos ch3", 1000, 600);
    TH2D* histo_hit_p3 = new TH2D("histo_hit_p3", "Hit pos ch3; x (m); y (m); N",
                                  200, -hits_bound, +hits_bound, 200, -hits_bound, +hits_bound);

    // Out file
    ofstream outfile;
    outfile.open("experiment.txt");

    // Main loop
    for (int nev=0; nev<N_events; ++nev) {

        // Generate K energy
        double K_energy = generate_K_energy();
        histo_K_energy->Fill(K_energy);

        // Generate K path
        double path_cm = generate_K_path();
        double path = gamma_from_K_energy(K_energy)*path_cm;
        histo_K_path->Fill(path);

        // Discard K that have not decayed before the first chamber
        if (path > z1) continue;

        // Generate cm dynamic
        TVector3 Pi_momentum_cm = generate_Pi_momentum_cm();
        histo_Pi_momentum_cm->Fill(Pi_momentum_cm.Px(), Pi_momentum_cm.Py(), Pi_momentum_cm.Pz());

        // Boost to lab frame
        double K_beta_z = sqrt(1 - pow(K_mass/K_energy, 2));
        // double x = K_mass/K_energy;
        // double K_beta_z = 1 + pow(x, 2)/2 - pow(x, 4)/8 + pow(x, 6)/16;
        TVector3 K_beta = TVector3(0, 0, K_beta_z);
        TLorentzVector Pi_pos_4v = TLorentzVector( Pi_momentum_cm, Pi_energy_cm);
        TLorentzVector Pi_neg_4v = TLorentzVector(-Pi_momentum_cm, Pi_energy_cm); // Momentum cons. in cm
        Pi_pos_4v.Boost(K_beta);
        Pi_neg_4v.Boost(K_beta);
        TVector3 Pi_pos = Pi_pos_4v.Vect();
        TVector3 Pi_neg = Pi_neg_4v.Vect();
        histo_Pi_pos->Fill(Pi_pos.Px(), Pi_pos.Py(), Pi_pos.Pz());

        // Calculate hit points in first two chambers
        TVector2 hit_p1=line_propagation(Pi_pos, z1, path);
        TVector2 hit_n1=line_propagation(Pi_neg, z1, path);
        TVector2 hit_p2=line_propagation(Pi_pos, z2, path);
        TVector2 hit_n2=line_propagation(Pi_neg, z2, path);
        histo_hit_p1->Fill(hit_p1.X(), hit_p1.Y());

        // Apply chamber smearing
        TVector2 hit_p1_smeared = apply_chamber_smearing(hit_p1, dx, dy);
        TVector2 hit_n1_smeared = apply_chamber_smearing(hit_n1, dx, dy);
        TVector2 hit_p2_smeared = apply_chamber_smearing(hit_p2, dx, dy);
        TVector2 hit_n2_smeared = apply_chamber_smearing(hit_n2, dx, dy);
        histo_hit_p1_smeared->Fill(hit_p1_smeared.X(), hit_p1_smeared.Y());

        // The magnetic field is schematized as a kick of magnitude p_kick
        // applied at the center of the magnetic field region (z_kick)

        // Find position at kick
        TVector2 Pi_pos_position_kick = line_propagation(Pi_pos, z_kick, path);
        TVector2 Pi_neg_position_kick = line_propagation(Pi_neg, z_kick, path);
        TVector3 p_kick_vec = TVector3(p_kick, 0, 0);

        // Find hits in last two chambers - p_kick is opposite due to charge
        TVector2 hit_p3=line_propagation(Pi_pos + p_kick_vec, z3, z_kick, Pi_pos_position_kick.X(), Pi_pos_position_kick.Y());
        TVector2 hit_n3=line_propagation(Pi_neg - p_kick_vec, z3, z_kick, Pi_neg_position_kick.X(), Pi_neg_position_kick.Y());
        TVector2 hit_p4=line_propagation(Pi_pos + p_kick_vec, z4, z_kick, Pi_pos_position_kick.X(), Pi_pos_position_kick.Y());
        TVector2 hit_n4=line_propagation(Pi_neg - p_kick_vec, z4, z_kick, Pi_neg_position_kick.X(), Pi_neg_position_kick.Y());
        histo_hit_p3->Fill(hit_p3.X(), hit_p3.Y());

        // Apply chamber smearing
        TVector2 hit_p3_smeared = apply_chamber_smearing(hit_p3, dx, dy);
        TVector2 hit_n3_smeared = apply_chamber_smearing(hit_n3, dx, dy);
        TVector2 hit_p4_smeared = apply_chamber_smearing(hit_p4, dx, dy);
        TVector2 hit_n4_smeared = apply_chamber_smearing(hit_n4, dx, dy);

        // Write to file
        outfile << nev            << " ";
        outfile << hit_p1_smeared << " ";
        outfile << hit_n1_smeared << " ";
        outfile << hit_p2_smeared << " ";
        outfile << hit_n2_smeared << " ";
        outfile << hit_p3_smeared << " ";
        outfile << hit_n3_smeared << " ";
        outfile << hit_p4_smeared << " ";
        outfile << hit_n4_smeared << " ";
        outfile << K_energy       << " ";
        outfile << path           << " ";
        outfile << Pi_pos         << " ";
        outfile << Pi_neg         <<endl;
    }

    // Histogram drawing

    canv_K_energy->cd();
    histo_K_energy->Draw();

    canv_K_path->cd();
    canv_K_path->SetLogy();
    histo_K_path->Draw();

    canv_Pi_momentum_cm->cd();
    histo_Pi_momentum_cm->Draw();

    canv_Pi_pos->cd();
    histo_Pi_pos->Draw();

    canv_hit_p1->cd();
    histo_hit_p1->Draw();

    canv_hit_p1_smeared->cd();
    histo_hit_p1_smeared->Draw();

    canv_hit_p3->cd();
    histo_hit_p3->Draw();

    return 0;
}

int main(int argc, char** argv)
{
    int N_events = 1e5;
    if (argc>1) N_events = atoi(argv[1]);
    return experiment(N_events);
}
<|endoftext|>


<commit_before>#ifndef AMGCL_COARSENING_AGGREGATION_HPP
#define AMGCL_COARSENING_AGGREGATION_HPP

/*
The MIT License

Copyright (c) 2012-2020 Denis Demidov <dennis.demidov@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * \file   amgcl/coarsening/aggregation.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Non-smoothed aggregation coarsening.
 */

#include <tuple>
#include <memory>

#include <amgcl/backend/builtin.hpp>
#include <amgcl/coarsening/detail/scaled_galerkin.hpp>
#include <amgcl/coarsening/pointwise_aggregates.hpp>
#include <amgcl/coarsening/tentative_prolongation.hpp>
#include <amgcl/util.hpp>

namespace amgcl {

/// Coarsening strategies
namespace coarsening {

/**
 * \defgroup coarsening Coarsening strategies
 * \brief Coarsening strategies for AMG hirarchy construction.
 *
 * A coarsener in AMGCL is a class that takes a system matrix and returns three
 * operators:
 *
 * 1. Restriction operator R that downsamples the residual error to a
 *    coarser level in AMG hierarchy,
 * 2. Prolongation operator P that interpolates a correction computed on a
 *    coarser grid into a finer grid,
 * 3. System matrix \f$A^H\f$ at a coarser level that is usually computed as a
 *    Galerkin operator \f$A^H = R A^h P\f$.
 *
 * The AMG hierarchy is constructed by recursive invocation of the selected
 * coarsener.
 */

/// Non-smoothed aggregation.
/**
 * \ingroup coarsening
 */
template <class Backend>
struct aggregation {
    typedef pointwise_aggregates Aggregates;

    /// Coarsening parameters.
    struct params {
        /// Aggregation parameters.
        Aggregates::params aggr;

        /// Near nullspace parameters.
        nullspace_params nullspace;

        /// Over-interpolation factor \f$\alpha\f$.
        /**
         * In case of aggregation coarsening, coarse-grid
         * correction of smooth error, and by this the overall convergence, can
         * often be substantially improved by using "over-interpolation", that is,
         * by multiplying the actual correction (corresponding to piecewise
         * constant interpolation) by some factor \f$\alpha > 1\f$. Equivalently,
         * this means that the coarse-level Galerkin operator is re-scaled by
         * \f$1 / \alpha\f$:
         * \f[I_h^HA_hI_H^h \to \frac{1}{\alpha}I_h^HA_hI_H^h.\f]
         *
         * \sa  \cite Stuben1999, Section 9.1 "Re-scaling of the Galerkin operator".
         */
        float over_interp;

        params() : over_interp(1.5f) { }

#ifndef AMGCL_NO_BOOST
        params(const boost::property_tree::ptree &p)
            : AMGCL_PARAMS_IMPORT_CHILD(p, aggr),
              AMGCL_PARAMS_IMPORT_CHILD(p, nullspace),
              AMGCL_PARAMS_IMPORT_VALUE(p, over_interp)
        {
            check_params(p, {"aggr", "nullspace", "over_interp"});
        }

        void get(boost::property_tree::ptree &p, const std::string &path) const {
            AMGCL_PARAMS_EXPORT_CHILD(p, path, aggr);
            AMGCL_PARAMS_EXPORT_CHILD(p, path, nullspace);
            AMGCL_PARAMS_EXPORT_VALUE(p, path, over_interp);
        }
#endif
    } prm;

    aggregation(const params &prm = params()) : prm(prm) {}

    /// Creates transfer operators for the given system matrix.
    /**
     * \param A   The system matrix.
     * \param prm Coarsening parameters.
     * \returns   A tuple of prolongation and restriction operators.
     */
    template <class Matrix>
    std::tuple<
        std::shared_ptr<Matrix>,
        std::shared_ptr<Matrix>
        >
    transfer_operators(const Matrix &A) {
        const size_t n = rows(A);

        AMGCL_TIC("aggregates");
        Aggregates aggr(A, prm.aggr, prm.nullspace.cols);
        AMGCL_TOC("aggregates");

        AMGCL_TIC("interpolation");
        auto P = tentative_prolongation<Matrix>(
                n, aggr.count, aggr.id, prm.nullspace, prm.aggr.block_size
                );
        AMGCL_TOC("interpolation");

        if (prm.nullspace.cols > 0)
            prm.aggr.block_size = prm.nullspace.cols;

        return std::make_tuple(P, transpose(*P));
    }

    /// Creates system matrix for the coarser level.
    /**
     * \param A The system matrix at the finer level.
     * \param P Prolongation operator returned by transfer_operators().
     * \param R Restriction operator returned by transfer_operators().
     * \returns System matrix for the coarser level.
     */
    template <class Matrix>
    std::shared_ptr<Matrix>
    coarse_operator(const Matrix &A, const Matrix &P, const Matrix &R) const {
        return detail::scaled_galerkin(A, P, R, 1 / prm.over_interp);
    }
};

} // namespace coarsening
} // namespace amgcl

#endif
<commit_msg>Increate default over interpolation for aggregation with block values<commit_after>#ifndef AMGCL_COARSENING_AGGREGATION_HPP
#define AMGCL_COARSENING_AGGREGATION_HPP

/*
The MIT License

Copyright (c) 2012-2020 Denis Demidov <dennis.demidov@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * \file   amgcl/coarsening/aggregation.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Non-smoothed aggregation coarsening.
 */

#include <tuple>
#include <memory>

#include <amgcl/backend/builtin.hpp>
#include <amgcl/coarsening/detail/scaled_galerkin.hpp>
#include <amgcl/coarsening/pointwise_aggregates.hpp>
#include <amgcl/coarsening/tentative_prolongation.hpp>
#include <amgcl/util.hpp>

namespace amgcl {

/// Coarsening strategies
namespace coarsening {

/**
 * \defgroup coarsening Coarsening strategies
 * \brief Coarsening strategies for AMG hirarchy construction.
 *
 * A coarsener in AMGCL is a class that takes a system matrix and returns three
 * operators:
 *
 * 1. Restriction operator R that downsamples the residual error to a
 *    coarser level in AMG hierarchy,
 * 2. Prolongation operator P that interpolates a correction computed on a
 *    coarser grid into a finer grid,
 * 3. System matrix \f$A^H\f$ at a coarser level that is usually computed as a
 *    Galerkin operator \f$A^H = R A^h P\f$.
 *
 * The AMG hierarchy is constructed by recursive invocation of the selected
 * coarsener.
 */

/// Non-smoothed aggregation.
/**
 * \ingroup coarsening
 */
template <class Backend>
struct aggregation {
    typedef pointwise_aggregates Aggregates;

    /// Coarsening parameters.
    struct params {
        /// Aggregation parameters.
        Aggregates::params aggr;

        /// Near nullspace parameters.
        nullspace_params nullspace;

        /// Over-interpolation factor \f$\alpha\f$.
        /**
         * In case of aggregation coarsening, coarse-grid
         * correction of smooth error, and by this the overall convergence, can
         * often be substantially improved by using "over-interpolation", that is,
         * by multiplying the actual correction (corresponding to piecewise
         * constant interpolation) by some factor \f$\alpha > 1\f$. Equivalently,
         * this means that the coarse-level Galerkin operator is re-scaled by
         * \f$1 / \alpha\f$:
         * \f[I_h^HA_hI_H^h \to \frac{1}{\alpha}I_h^HA_hI_H^h.\f]
         *
         * \sa  \cite Stuben1999, Section 9.1 "Re-scaling of the Galerkin operator".
         */
        float over_interp;

        params()
            : over_interp(math::static_rows<typename Backend::value_type>::value == 1 ? 1.5f : 2.0f)
        {}

#ifndef AMGCL_NO_BOOST
        params(const boost::property_tree::ptree &p)
            : AMGCL_PARAMS_IMPORT_CHILD(p, aggr),
              AMGCL_PARAMS_IMPORT_CHILD(p, nullspace),
              AMGCL_PARAMS_IMPORT_VALUE(p, over_interp)
        {
            check_params(p, {"aggr", "nullspace", "over_interp"});
        }

        void get(boost::property_tree::ptree &p, const std::string &path) const {
            AMGCL_PARAMS_EXPORT_CHILD(p, path, aggr);
            AMGCL_PARAMS_EXPORT_CHILD(p, path, nullspace);
            AMGCL_PARAMS_EXPORT_VALUE(p, path, over_interp);
        }
#endif
    } prm;

    aggregation(const params &prm = params()) : prm(prm) {}

    /// Creates transfer operators for the given system matrix.
    /**
     * \param A   The system matrix.
     * \param prm Coarsening parameters.
     * \returns   A tuple of prolongation and restriction operators.
     */
    template <class Matrix>
    std::tuple<
        std::shared_ptr<Matrix>,
        std::shared_ptr<Matrix>
        >
    transfer_operators(const Matrix &A) {
        const size_t n = rows(A);

        AMGCL_TIC("aggregates");
        Aggregates aggr(A, prm.aggr, prm.nullspace.cols);
        AMGCL_TOC("aggregates");

        AMGCL_TIC("interpolation");
        auto P = tentative_prolongation<Matrix>(
                n, aggr.count, aggr.id, prm.nullspace, prm.aggr.block_size
                );
        AMGCL_TOC("interpolation");

        if (prm.nullspace.cols > 0)
            prm.aggr.block_size = prm.nullspace.cols;

        return std::make_tuple(P, transpose(*P));
    }

    /// Creates system matrix for the coarser level.
    /**
     * \param A The system matrix at the finer level.
     * \param P Prolongation operator returned by transfer_operators().
     * \param R Restriction operator returned by transfer_operators().
     * \returns System matrix for the coarser level.
     */
    template <class Matrix>
    std::shared_ptr<Matrix>
    coarse_operator(const Matrix &A, const Matrix &P, const Matrix &R) const {
        return detail::scaled_galerkin(A, P, R, 1 / prm.over_interp);
    }
};

} // namespace coarsening
} // namespace amgcl

#endif
<|endoftext|>


<commit_before>//=============================================================================
// FloodIt
//
// @author: Elisha Lai
// @description: Module to provide functions to work with TextDisplay objects
// @version: 1.0 03/12/2014
//=============================================================================

// Textdisplay module (textdisplay.cc)

#include "textdisplay.h"

using namespace std; // Provides direct access to std

// See interface (header file).
TextDisplay::TextDisplay(int n)
   :theDisplay(0), gridSize(n) {
   char **newDisplay = new char*[gridSize];

   // Allocates new memory from the heap for theDisplay
   for (int i = 0; i < gridSize; ++i) {
   	newDisplay[i] = new char[gridSize];
   	for (int j = 0; j < gridSize; ++j) {
         newDisplay[i][j] = '0';
   	} // for
   } // for

   theDisplay = newDisplay;

   const int totalNumOfColours = 5;
   // Initializes each element in colourCount to zero
   for (int i = 0; i < totalNumOfColours; ++i) {
      colourCount[i] = 0;
   } // for

   colourCount[0] = gridSize * gridSize;

} // Constructor

// See interface (header file).
void TextDisplay::notify(int r, int c, char ch) {
   const char prevChar = theDisplay[r][c]; // Stores the old char
   colourCount[prevChar - '0'] -= 1;
   colourCount[ch - '0'] += 1;
   theDisplay[r][c] = ch;
} // notify

// See interface (header file).
bool TextDisplay::isFilled() {
   const int totalNumOfColours = 5;            // Stores the total number of colours possible

   // Checks whether there's a colour count equal to total
   // number of cells in theDisplay grid
   for (int i=0; i < totalNumOfColours; ++i) {
       if (colourCount[i] == (gridSize * gridSize)) { // A colour count equaling total number of cells in grid?
          return true;
       } // if
   } // for

   return false;
} // isFilled

// See interface (header file).
TextDisplay::~TextDisplay() {
   // Returns all allocated memory for theDisplay back to the heap.
   for (int i = 0; i < gridSize; ++i) {
   	  delete [] theDisplay[i];
   } // for

   delete [] theDisplay;
}// destructor

// See interface (header file).
ostream &operator<<(ostream &out, const TextDisplay &td) {
   // Prints out each element in theDisplay to the screen.
   for (int i = 0; i < td.gridSize; ++i) {
   	  for (int j = 0; j < td.gridSize; ++j) {
   	  	 out << td.theDisplay[i][j];
   	  } // for
   	  out << endl;
   } // for

   return out;
} // Overloaded operator<<
<commit_msg>Update textdisplay.cc<commit_after>//=============================================================================
// FloodIt
//
// @author: Elisha Lai
// @description: Module to provide functions to work with TextDisplay objects
// @version: 1.0 03/11/2014
//=============================================================================

// Textdisplay module (textdisplay.cc)

#include "textdisplay.h"

using namespace std; // Provides direct access to std

// See interface (header file).
TextDisplay::TextDisplay(int n)
   :theDisplay(0), gridSize(n) {
   char **newDisplay = new char*[gridSize];

   // Allocates new memory from the heap for theDisplay
   for (int i = 0; i < gridSize; ++i) {
   	newDisplay[i] = new char[gridSize];
   	for (int j = 0; j < gridSize; ++j) {
         newDisplay[i][j] = '0';
   	} // for
   } // for

   theDisplay = newDisplay;

   const int totalNumOfColours = 5;
   // Initializes each element in colourCount to zero
   for (int i = 0; i < totalNumOfColours; ++i) {
      colourCount[i] = 0;
   } // for

   colourCount[0] = gridSize * gridSize;

} // Constructor

// See interface (header file).
void TextDisplay::notify(int r, int c, char ch) {
   const char prevChar = theDisplay[r][c]; // Stores the old char
   colourCount[prevChar - '0'] -= 1;
   colourCount[ch - '0'] += 1;
   theDisplay[r][c] = ch;
} // notify

// See interface (header file).
bool TextDisplay::isFilled() {
   const int totalNumOfColours = 5;            // Stores the total number of colours possible

   // Checks whether there's a colour count equal to total
   // number of cells in theDisplay grid
   for (int i=0; i < totalNumOfColours; ++i) {
       if (colourCount[i] == (gridSize * gridSize)) { // A colour count equaling total number of cells in grid?
          return true;
       } // if
   } // for

   return false;
} // isFilled

// See interface (header file).
TextDisplay::~TextDisplay() {
   // Returns all allocated memory for theDisplay back to the heap.
   for (int i = 0; i < gridSize; ++i) {
   	  delete [] theDisplay[i];
   } // for

   delete [] theDisplay;
}// destructor

// See interface (header file).
ostream &operator<<(ostream &out, const TextDisplay &td) {
   // Prints out each element in theDisplay to the screen.
   for (int i = 0; i < td.gridSize; ++i) {
   	  for (int j = 0; j < td.gridSize; ++j) {
   	  	 out << td.theDisplay[i][j];
   	  } // for
   	  out << endl;
   } // for

   return out;
} // Overloaded operator<<
<|endoftext|>


<commit_before>AliAnalysisTaskSED0Mass *AddTaskD0Mass(Int_t flag=0/*0 = D0,1 = LS*/,Bool_t readMC=kTRUE)
{
  //
  // AddTask for the AliAnalysisTaskSE for D0 candidates
  // invariant mass histogram and association with MC truth
  // (using MC info in AOD) and cut variables distributions
  // C.Bianchin  chiara.bianchin@pd.infn.it
  //

  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskD0Distr", "No analysis manager to connect to.");
    return NULL;
  }

  TString filename="",out1name="",out2name="",out3name="",out4name="",out5name="",inname="";
  filename = AliAnalysisManager::GetCommonFileName();
  filename += ":PWG3_D2H_";
  if(flag==0){
    filename+="D0InvMass";
    out1name="coutputmassD0PPR";
    out2name="coutputmassD0mycuts";
    out3name="nEntriesD0";
    out4name="coutputmassD0distr";
    out5name="checksD0";
    inname="cinputmassD0_0";
  } else {
    filename+="D0InvMassLikeSign";
    out1name="coutputmassLSPPR";
    out2name="coutputmassLSmycuts";
    out3name="nEntriesLS";
    out4name="coutputmassLSdistr";
    inname="cinputmassD0_1";
  }

  // Aanalysis task
  AliAnalysisTaskSED0Mass *massD0Task = new AliAnalysisTaskSED0Mass("D0MassAndDistrAnalysis");
  massD0Task->SetDebugLevel(0);
  massD0Task->SetArray(flag);
  massD0Task->SetReadMC(readMC);
  mgr->AddTask(massD0Task);

  //
  // Create containers for input/output
  AliAnalysisDataContainer *cinputmassD0 = mgr->CreateContainer(inname,TChain::Class(),
							  AliAnalysisManager::kInputContainer);

  AliAnalysisDataContainer *coutputmassD01 = mgr->CreateContainer(out1name,TList::Class(),
							   AliAnalysisManager::kOutputContainer,
							   filename.Data());
  AliAnalysisDataContainer *coutputmassD02 = mgr->CreateContainer(out2name,TList::Class(),
							   AliAnalysisManager::kOutputContainer,
							   filename.Data());
  AliAnalysisDataContainer *coutputmassD03 = mgr->CreateContainer(out3name,TH1F::Class(),
							   AliAnalysisManager::kOutputContainer,
							   filename.Data());
  AliAnalysisDataContainer *coutputmassD04 = mgr->CreateContainer(out4name,TList::Class(),
							   AliAnalysisManager::kOutputContainer,
							   filename.Data());
  AliAnalysisDataContainer *coutputmassD05 = mgr->CreateContainer(out5name,TList::Class(),
						   AliAnalysisManager::kOutputContainer,
						   filename.Data());

  mgr->ConnectInput(massD0Task,0,mgr->GetCommonInputContainer());

  mgr->ConnectOutput(massD0Task,1,coutputmassD01);
  mgr->ConnectOutput(massD0Task,2,coutputmassD02);
  mgr->ConnectOutput(massD0Task,3,coutputmassD03);
  mgr->ConnectOutput(massD0Task,4,coutputmassD04);
  mgr->ConnectOutput(massD0Task,5,coutputmassD05);

  return massD0Task;
}
<commit_msg>Bug fix (Chiara)<commit_after>AliAnalysisTaskSED0Mass *AddTaskD0Mass(Int_t flag=0/*0 = D0,1 = LS*/,Bool_t readMC=kTRUE)
{
  //
  // AddTask for the AliAnalysisTaskSE for D0 candidates
  // invariant mass histogram and association with MC truth
  // (using MC info in AOD) and cut variables distributions
  // C.Bianchin  chiara.bianchin@pd.infn.it
  //

  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskD0Distr", "No analysis manager to connect to.");
    return NULL;
  }

  TString filename="",out1name="",out2name="",out3name="",out4name="",out5name="",inname="";
  filename = AliAnalysisManager::GetCommonFileName();
  filename += ":PWG3_D2H_";
  if(flag==0){
    filename+="D0InvMass";
    out1name="coutputmassD0PPR";
    out2name="coutputmassD0mycuts";
    out3name="nEntriesD0";
    out4name="coutputmassD0distr";
    out5name="checksD0";
    inname="cinputmassD0_0";
  } else {
    filename+="D0InvMassLikeSign";
    out1name="coutputmassLSPPR";
    out2name="coutputmassLSmycuts";
    out3name="nEntriesLS";
    out4name="coutputmassLSdistr";
    out5name="checksLS";
    inname="cinputmassD0_1";
  }

  // Aanalysis task
  AliAnalysisTaskSED0Mass *massD0Task = new AliAnalysisTaskSED0Mass("D0MassAndDistrAnalysis");
  massD0Task->SetDebugLevel(0);
  massD0Task->SetArray(flag);
  massD0Task->SetReadMC(readMC);
  mgr->AddTask(massD0Task);

  //
  // Create containers for input/output
  AliAnalysisDataContainer *cinputmassD0 = mgr->CreateContainer(inname,TChain::Class(),
							  AliAnalysisManager::kInputContainer);

  AliAnalysisDataContainer *coutputmassD01 = mgr->CreateContainer(out1name,TList::Class(),
							   AliAnalysisManager::kOutputContainer,
							   filename.Data());
  AliAnalysisDataContainer *coutputmassD02 = mgr->CreateContainer(out2name,TList::Class(),
							   AliAnalysisManager::kOutputContainer,
							   filename.Data());
  AliAnalysisDataContainer *coutputmassD03 = mgr->CreateContainer(out3name,TH1F::Class(),
							   AliAnalysisManager::kOutputContainer,
							   filename.Data());
  AliAnalysisDataContainer *coutputmassD04 = mgr->CreateContainer(out4name,TList::Class(),
							   AliAnalysisManager::kOutputContainer,
							   filename.Data());
  AliAnalysisDataContainer *coutputmassD05 = mgr->CreateContainer(out5name,TList::Class(),
						           AliAnalysisManager::kOutputContainer,
						           filename.Data());

  mgr->ConnectInput(massD0Task,0,mgr->GetCommonInputContainer());

  mgr->ConnectOutput(massD0Task,1,coutputmassD01);
  mgr->ConnectOutput(massD0Task,2,coutputmassD02);
  mgr->ConnectOutput(massD0Task,3,coutputmassD03);
  mgr->ConnectOutput(massD0Task,4,coutputmassD04);
  mgr->ConnectOutput(massD0Task,5,coutputmassD05);

  return massD0Task;
}
<|endoftext|>


<commit_before>AliAnalysisTaskJetCluster *AddTaskJetCluster(char* bRec = "AOD",char* bGen = "",UInt_t filterMask = 16, UInt_t iPhysicsSelectionFlag = AliVEvent::kAny,Char_t *jf = "KT", Float_t radius = 0.4,Int_t nSkip = 0,Int_t kWriteAOD = kFALSE,char* deltaFile = "",Float_t ptTrackCut = 0.15, Float_t etaTrackWindow = 0.9,Float_t vertexWindow = 10.,Int_t nSkipCone = 2);

Int_t kBackgroundMode = 0;
Float_t kPtTrackCut = 0.15;
Float_t kTrackEtaWindow = 0.8;
Float_t kVertexWindow = 10;

AliAnalysisTaskJetCluster *AddTaskJetClusterDelta(UInt_t filterMask = 16,Bool_t kUseAODMC = kFALSE,UInt_t iPhysicsSelectionFlag = AliVEvent::kMB,Char_t *jf = "KT", UInt_t iFlag){
   AliAnalysisTaskJetCluster *js = 0;
   if(kUseAODMC&&false){// do not use the MC info yet
     if(iFlag&(1<<0))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.00001);
     if(iFlag&(1<<1))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.1);
     if(iFlag&(1<<2))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.2);
     if(iFlag&(1<<4))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.4);
     if(iFlag&(1<<6))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.6);
     if(iFlag&(1<<8))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.8);
     if(iFlag&(1<<10))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,1.0);
   }
   else{
     if(iFlag&(1<<0))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.00001);
     if(iFlag&(1<<1))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.1);
     if(iFlag&(1<<2))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.2);
     if(iFlag&(1<<4))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.4);
     if(iFlag&(1<<6))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.6);
     if(iFlag&(1<<8))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.8);
     if(iFlag&(1<<10))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,1.0);
   }

   return js;
 }

AliAnalysisTaskJetCluster *AddTaskJetCluster(char* bRec,char* bGen ,UInt_t filterMask,UInt_t iPhysicsSelectionFlag,Char_t *jf,Float_t radius,Int_t nSkip,Int_t kWriteAOD,char *deltaFile,Float_t ptTrackCut,Float_t etaTrackWindow,Float_t vertexWindow,Int_t nSkipCone)
 {
 // Creates a jet fider task, configures it and adds it to the analysis manager.
   kPtTrackCut = ptTrackCut;
   kTrackEtaWindow = etaTrackWindow;
   kVertexWindow = vertexWindow;

   TString outputFile(deltaFile);
    // Get the pointer to the existing analysis manager via the static access method.
    //==============================================================================
    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
       ::Error("AddTaskJetCluster", "No analysis manager to connect to.");
       return NULL;
    }

    // Check the analysis type using the event handlers connected to the analysis manager.
    //==============================================================================
    if (!mgr->GetInputEventHandler()) {
      ::Error("AddTaskJetCluster", "This task requires an input event handler");
       return NULL;
    }

    TString type = mgr->GetInputEventHandler()->GetDataType();
    TString typeRec(bRec);
    TString typeGen(bGen);
    if(!typeRec.Contains("AODextra")) {
      typeGen.ToUpper();
      typeRec.ToUpper();
    }
    cout << "typeRec: " << typeRec << endl;
    // Create the task and configure it.
    //===========================================================================

    TString cAdd = "";
    cAdd += Form("%02d_",(int)((radius+0.01)*10.));
    cAdd += Form("B%d",(int)kBackgroundMode);
    cAdd += Form("_Filter%05d",filterMask);
    cAdd += Form("_Cut%05d",(int)(1000.*kPtTrackCut));
    cAdd += Form("_Skip%02d",nSkip);
    Printf("%s %E",cAdd.Data(),kPtTrackCut);
    AliAnalysisTaskJetCluster* clus = new  AliAnalysisTaskJetCluster(Form("JetCluster%s_%s%s",bRec,jf,cAdd.Data()));

   // or a config file
   // clus->SetAnalysisType(AliAnalysisTaskJetCluster::kAnaMC);
   // if(iAODanalysis)clus->SetAODInput(kTRUE);
   // clus->SetDebugLevel(11);
   clus->SetFilterMask(filterMask);
   //   clus->SetUseGlobalSelection(kTRUE);
   clus->SetVtxCuts(kVertexWindow,1);
   if(type == "AOD"){
     // Assume all jet are produced already
     clus->SetAODTrackInput(kTRUE);
     clus->SetAODMCInput(kTRUE);
   }

   if(typeRec.Contains("AODMC2b")){// work down from the top AODMC2b -> AODMC2 -> AODMC -> AOD
     clus->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCChargedAcceptance);
     clus->SetTrackPtCut(kPtTrackCut);
     clus->SetTrackEtaWindow(kTrackEtaWindow);
   }
   else if (typeRec.Contains("AODMC2")){
     clus->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCCharged);
     clus->SetTrackPtCut(kPtTrackCut);
     clus->SetTrackEtaWindow(5);
   }
   else if (typeRec.Contains("AODMC")){
     clus->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCAll);
     clus->SetTrackPtCut(kPtTrackCut);
     clus->SetTrackEtaWindow(5);
   }
   else if (typeRec.Contains("AODextraonly")) {
     clus->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODextraonly);
     clus->SetTrackPtCut(kPtTrackCut);
     clus->SetTrackEtaWindow(kTrackEtaWindow);
   }
   else if (typeRec.Contains("AODextra")) {
     cout << "AliAnalysisTaskJetCluster::kTrackAODextra: " << AliAnalysisTaskJetCluster::kTrackAODextra << endl;
     clus->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODextra);
     clus->SetTrackPtCut(kPtTrackCut);
     clus->SetTrackEtaWindow(kTrackEtaWindow);
   }
   else if (typeRec.Contains("AOD")) {
     clus->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAOD);
     clus->SetTrackPtCut(kPtTrackCut);
     clus->SetTrackEtaWindow(kTrackEtaWindow);
   }

   clus->SetRparam(radius);
   clus->SetGhostArea(0.005);
   clus->SetGhostEtamax(kTrackEtaWindow);

   switch (jf) {
   case "ANTIKT":
     clus->SetAlgorithm(2); // antikt from fastjet/JetDefinition.hh
     break;
   case "CA":
     clus->SetAlgorithm(1); // CA from fastjet/JetDefinition.hh
     break;
   case "KT":
     clus->SetAlgorithm(0); // kt from fastjet/JetDefinition.hh
     break;
   default:
     ::Error("AddTaskJetCluster", "Wrong jet finder selected\n");
     return 0;
   }

   if(kWriteAOD){
     if(outputFile.Length())clus->SetJetOutputFile(outputFile);
     clus->SetJetOutputBranch(Form("clusters%s_%s%s",bRec,jf,cAdd.Data()));
     clus->SetJetOutputMinPt(0); // store only jets / clusters above a certain threshold
   }

   clus->SetNSkipLeadingRan(nSkip);
   clus->SetNSkipLeadingCone(nSkipCone);

   if(iPhysicsSelectionFlag)clus->SelectCollisionCandidates(iPhysicsSelectionFlag);

   mgr->AddTask(clus);

   // Create ONLY the output containers for the data produced by the task.
   // Get and connect other common input/output containers via the manager as below
   //==============================================================================
   AliAnalysisDataContainer *coutput1_Spec = mgr->CreateContainer(Form("cluster_%s_%s_%s%s",bRec,bGen,jf,cAdd.Data()), TList::Class(),AliAnalysisManager::kOutputContainer,Form("%s:PWGJE_cluster_%s_%s_%s%s",AliAnalysisManager::GetCommonFileName(),bRec,bGen,jf,cAdd.Data()));

   mgr->ConnectInput  (clus, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput (clus, 0, mgr->GetCommonOutputContainer());
   mgr->ConnectOutput (clus,  1, coutput1_Spec );

   return clus;
}
<commit_msg>bug fixes naming<commit_after>AliAnalysisTaskJetCluster *AddTaskJetCluster(char* bRec = "AOD",char* bGen = "",UInt_t filterMask = 16, UInt_t iPhysicsSelectionFlag = AliVEvent::kAny,Char_t *jf = "KT", Float_t radius = 0.4,Int_t nSkip = 0,Int_t kWriteAOD = kFALSE,char* deltaFile = "",Float_t ptTrackCut = 0.15, Float_t etaTrackWindow = 0.9,Float_t vertexWindow = 10.,Int_t nSkipCone = 2);

Int_t kBackgroundModeCl = 0;
Float_t kPtTrackCutCl = 0.15;
Float_t kTrackEtaWindowCl = 0.8;
Float_t kVertexWindowCl = 10;

AliAnalysisTaskJetCluster *AddTaskJetClusterDelta(UInt_t filterMask = 16,Bool_t kUseAODMC = kFALSE,UInt_t iPhysicsSelectionFlag = AliVEvent::kMB,Char_t *jf = "KT", UInt_t iFlag){
   AliAnalysisTaskJetCluster *js = 0;
   if(kUseAODMC&&false){// do not use the MC info yet
     if(iFlag&(1<<0))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.00001);
     if(iFlag&(1<<1))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.1);
     if(iFlag&(1<<2))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.2);
     if(iFlag&(1<<4))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.4);
     if(iFlag&(1<<6))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.6);
     if(iFlag&(1<<8))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,0.8);
     if(iFlag&(1<<10))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelectionFlag,jf,1.0);
   }
   else{
     if(iFlag&(1<<0))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.00001);
     if(iFlag&(1<<1))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.1);
     if(iFlag&(1<<2))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.2);
     if(iFlag&(1<<4))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.4);
     if(iFlag&(1<<6))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.6);
     if(iFlag&(1<<8))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,0.8);
     if(iFlag&(1<<10))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelectionFlag,jf,1.0);
   }

   return js;
 }

AliAnalysisTaskJetCluster *AddTaskJetCluster(char* bRec,char* bGen ,UInt_t filterMask,UInt_t iPhysicsSelectionFlag,Char_t *jf,Float_t radius,Int_t nSkip,Int_t kWriteAOD,char *deltaFile,Float_t ptTrackCut,Float_t etaTrackWindow,Float_t vertexWindow,Int_t nSkipCone)
 {
 // Creates a jet fider task, configures it and adds it to the analysis manager.
   kPtTrackCutCl = ptTrackCut;
   kTrackEtaWindowCl = etaTrackWindow;
   kVertexWindowCl = vertexWindow;

   TString outputFile(deltaFile);
    // Get the pointer to the existing analysis manager via the static access method.
    //==============================================================================
    AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
    if (!mgr) {
       ::Error("AddTaskJetCluster", "No analysis manager to connect to.");
       return NULL;
    }

    // Check the analysis type using the event handlers connected to the analysis manager.
    //==============================================================================
    if (!mgr->GetInputEventHandler()) {
      ::Error("AddTaskJetCluster", "This task requires an input event handler");
       return NULL;
    }

    TString type = mgr->GetInputEventHandler()->GetDataType();
    TString typeRec(bRec);
    TString typeGen(bGen);
    if(!typeRec.Contains("AODextra")) {
      typeGen.ToUpper();
      typeRec.ToUpper();
    }
    cout << "typeRec: " << typeRec << endl;
    // Create the task and configure it.
    //===========================================================================

    TString cAdd = "";
    cAdd += Form("%02d_",(int)((radius+0.01)*10.));
    cAdd += Form("B%d",(int)kBackgroundModeCl);
    cAdd += Form("_Filter%05d",filterMask);
    cAdd += Form("_Cut%05d",(int)(1000.*kPtTrackCutCl));
    cAdd += Form("_Skip%02d",nSkip);
    Printf("%s %E",cAdd.Data(),kPtTrackCutCl);
    AliAnalysisTaskJetCluster* clus = new  AliAnalysisTaskJetCluster(Form("JetCluster%s_%s%s",bRec,jf,cAdd.Data()));

   // or a config file
   // clus->SetAnalysisType(AliAnalysisTaskJetCluster::kAnaMC);
   // if(iAODanalysis)clus->SetAODInput(kTRUE);
   // clus->SetDebugLevel(11);
   clus->SetFilterMask(filterMask);
   //   clus->SetUseGlobalSelection(kTRUE);
   clus->SetVtxCuts(kVertexWindowCl,1);
   if(type == "AOD"){
     // Assume all jet are produced already
     clus->SetAODTrackInput(kTRUE);
     clus->SetAODMCInput(kTRUE);
   }

   if(typeRec.Contains("AODMC2b")){// work down from the top AODMC2b -> AODMC2 -> AODMC -> AOD
     clus->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCChargedAcceptance);
     clus->SetTrackPtCut(kPtTrackCutCl);
     clus->SetTrackEtaWindow(kTrackEtaWindowCl);
   }
   else if (typeRec.Contains("AODMC2")){
     clus->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCCharged);
     clus->SetTrackPtCut(kPtTrackCutCl);
     clus->SetTrackEtaWindow(5);
   }
   else if (typeRec.Contains("AODMC")){
     clus->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCAll);
     clus->SetTrackPtCut(kPtTrackCutCl);
     clus->SetTrackEtaWindow(5);
   }
   else if (typeRec.Contains("AODextraonly")) {
     clus->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODextraonly);
     clus->SetTrackPtCut(kPtTrackCutCl);
     clus->SetTrackEtaWindow(kTrackEtaWindowCl);
   }
   else if (typeRec.Contains("AODextra")) {
     cout << "AliAnalysisTaskJetCluster::kTrackAODextra: " << AliAnalysisTaskJetCluster::kTrackAODextra << endl;
     clus->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODextra);
     clus->SetTrackPtCut(kPtTrackCutCl);
     clus->SetTrackEtaWindow(kTrackEtaWindowCl);
   }
   else if (typeRec.Contains("AOD")) {
     clus->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAOD);
     clus->SetTrackPtCut(kPtTrackCutCl);
     clus->SetTrackEtaWindow(kTrackEtaWindowCl);
   }

   clus->SetRparam(radius);
   clus->SetGhostArea(0.005);
   clus->SetGhostEtamax(kTrackEtaWindowCl);

   switch (jf) {
   case "ANTIKT":
     clus->SetAlgorithm(2); // antikt from fastjet/JetDefinition.hh
     break;
   case "CA":
     clus->SetAlgorithm(1); // CA from fastjet/JetDefinition.hh
     break;
   case "KT":
     clus->SetAlgorithm(0); // kt from fastjet/JetDefinition.hh
     break;
   default:
     ::Error("AddTaskJetCluster", "Wrong jet finder selected\n");
     return 0;
   }

   if(kWriteAOD){
     if(outputFile.Length())clus->SetJetOutputFile(outputFile);
     clus->SetJetOutputBranch(Form("clusters%s_%s%s",bRec,jf,cAdd.Data()));
     clus->SetJetOutputMinPt(0); // store only jets / clusters above a certain threshold
   }

   clus->SetNSkipLeadingRan(nSkip);
   clus->SetNSkipLeadingCone(nSkipCone);

   if(iPhysicsSelectionFlag)clus->SelectCollisionCandidates(iPhysicsSelectionFlag);

   mgr->AddTask(clus);

   // Create ONLY the output containers for the data produced by the task.
   // Get and connect other common input/output containers via the manager as below
   //==============================================================================
   AliAnalysisDataContainer *coutput1_Spec = mgr->CreateContainer(Form("cluster_%s_%s_%s%s",bRec,bGen,jf,cAdd.Data()), TList::Class(),AliAnalysisManager::kOutputContainer,Form("%s:PWGJE_cluster_%s_%s_%s%s",AliAnalysisManager::GetCommonFileName(),bRec,bGen,jf,cAdd.Data()));

   mgr->ConnectInput  (clus, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput (clus, 0, mgr->GetCommonOutputContainer());
   mgr->ConnectOutput (clus,  1, coutput1_Spec );

   return clus;
}
<|endoftext|>