File: rigidbody_optimizer.cpp

package info (click to toggle)
ausaxs 1.1.8-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 72,592 kB
  • sloc: cpp: 49,853; ansic: 6,901; python: 730; makefile: 18
file content (130 lines) | stat: -rw-r--r-- 6,999 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// SPDX-License-Identifier: LGPL-3.0-or-later
// Author: Kristian Lytje

#include <CLI/CLI.hpp>

#include <data/Body.h>
#include <data/Molecule.h>
#include <rigidbody/RigidBody.h>
#include <rigidbody/BodySplitter.h>
#include <fitter/FitReporter.h>
#include <fitter/SmartFitter.h>
#include <hist/intensity_calculator/ICompositeDistanceHistogramExv.h>
#include <hist/intensity_calculator/CompositeDistanceHistogram.h>
#include <constants/Constants.h>
#include <utility/Console.h>
#include <io/File.h>
#include <plots/All.h>
#include <settings/All.h>
#include <rigidbody/sequencer/detail/SequenceParser.h>
#include <rigidbody/sequencer/All.h>

#include <vector>
#include <string>

using namespace ausaxs;

int main(int argc, char const *argv[]) { 
    settings::grid::scaling = 2;
    settings::grid::cubic = true;
    settings::grid::min_bins = 1000;
    settings::general::verbose = true;

    CLI::App app{"Rigid-body optimization."};
    io::File pdb, mfile, settings, config;
    std::vector<unsigned int> constraints;
    app.add_option("input_s", pdb, "Path to the structure file.")->required()->check(CLI::ExistingFile);
    app.add_option("input_m", mfile, "Path to the measuremed data.")->check(CLI::ExistingFile);
    app.add_option("output", settings::general::output, "Path to save the hydrated file at.")->default_val("output/rigidbody/");
    auto p_cal = app.add_option("--calibrate", settings::rigidbody::detail::calibration_file, "Path to the calibration data.")->expected(0, 1)->check(CLI::ExistingFile);
    app.add_option("--reduce,-r", settings::grid::water_scaling, "The desired number of water molecules as a percentage of the number of atoms. Use 0 for no reduction.");
    app.add_option("--grid_width,-w", settings::grid::cell_width, "The distance between each grid point in Ångström (default: 1). Lower widths increase the precision.");
    app.add_option_function<std::string>("--placement-strategy,--ps", [] (const std::string& s) {settings::detail::parse_option("placement_strategy", {s});}, "The placement strategy to use. Options: Radial, Axes, Jan.");
    app.add_option("--qmin", settings::axes::qmin, "Lower limit on used q values from measurement file.");
    app.add_option("--qmax", settings::axes::qmax, "Upper limit on used q values from measurement file.");
    auto p_settings = app.add_option("-s,--settings", settings, "Path to the settings file.")->check(CLI::ExistingFile);
    app.add_option("--iterations", settings::rigidbody::iterations, "Maximum number of iterations. Default: 1000.");
    app.add_option("--constraints", settings::rigidbody::detail::constraints, "Constraints to apply to the rigid body.");
    app.add_flag("--center,!--no-center", settings::molecule::center, "Decides whether the protein will be centered. Default: true.");
    app.add_flag("--quit-on-unknown-atom,!--no-quit-on-unknown-atom", settings::molecule::throw_on_unknown_atom, "Decides whether the program will quit if an unknown atom is found. Default: true.");
    CLI11_PARSE(app, argc, argv);

    console::print_info("Running AUSAXS " + std::string(constants::version));

    settings::rigidbody::constraint_generation_strategy = settings::rigidbody::ConstraintGenerationStrategyChoice::None;
    settings::molecule::implicit_hydrogens = false;

    //###################//
    //### PARSE INPUT ###//
    //###################//
    try {
        settings::general::output += mfile.stem() + "/";

        // check if pdb is a config script
        if (constants::filetypes::config.check(pdb)) {
            auto res = rigidbody::sequencer::SequenceParser().parse(pdb)->execute();
            fitter::FitReporter::report(res.get());
            fitter::FitReporter::save(res.get(), settings::general::output + "fit.txt");
            res->curves.save(settings::general::output + "ausaxs.fit", "chi2=" + std::to_string(res->fval/res->dof) + " dof=" + std::to_string(res->dof));
            return 0;
        }

        // if a settings file was provided
        if (p_settings->count() != 0) {
            settings::read(settings);        // read it
            CLI11_PARSE(app, argc, argv);   // re-parse the command line arguments so they take priority
        } else {                            // otherwise check if there is a settings file in the same directory
            if (settings::discover(std::filesystem::path(mfile.path()).parent_path().string())) {
                CLI11_PARSE(app, argc, argv);
            }
        }
        if (settings::rigidbody::detail::constraints.empty()) {
            throw except::missing_option("rigidbody: Constraints must be supplied. Use --constraints to specify them.");
        }

        settings::validate_settings();
        rigidbody::RigidBody rigidbody = rigidbody::BodySplitter::split(pdb, settings::rigidbody::detail::constraints);

        if (p_cal->count() != 0) {
            if (settings::rigidbody::detail::calibration_file.empty()) {
                // look for calibration file in the same directory as the measurement file
                for (const auto& f : mfile.directory().files()) {
                    if (constants::filetypes::saxs_data.check(f)) {
                        settings::rigidbody::detail::calibration_file = f.path();
                        std::cout << "\tUsing calibration file: \"" << f.path() << "\"" << std::endl;
                        break;
                    }
                }
            }
            if (settings::rigidbody::detail::calibration_file.empty()) {
                throw except::missing_option("rigidbody: Default calibration file not found. Use --calibrate <path> to specify it.");
            }

            settings::general::output += "calibrated/";
            rigidbody.generate_new_hydration();
            fitter::SmartFitter fitter({settings::rigidbody::detail::calibration_file}, rigidbody.get_histogram());
            auto res = fitter.fit();
            if (settings::general::verbose) {
                std::cout << "Calibration results:" << std::endl;
                fitter::FitReporter::report(res.get());
            }
            rigidbody.apply_calibration(std::move(res));
            // plots::PlotIntensityFit::quick_plot(res.get(), settings::general::output + "calibration.png");
        } else {
            settings::general::output += "uncalibrated/";
        }

        rigidbody.save(settings::general::output + "initial.pdb");
        rigidbody.optimize(mfile);
        rigidbody.save(settings::general::output + "optimized.pdb");

        auto res = rigidbody.get_unconstrained_fitter(mfile)->fit();
        fitter::FitReporter::report(res.get());
        fitter::FitReporter::save(res.get(), settings::general::output + "fit.txt", argc, argv);
        res->curves.save(settings::general::output + "ausaxs.fit", "chi2=" + std::to_string(res->fval/res->dof) + " dof=" + std::to_string(res->dof));
    } catch (const std::exception& e) {
        console::print_warning(e.what());
        throw e;
    }
    return 0;
}