Create Experiment class
This commit is contained in:
152
src/sims.cpp
152
src/sims.cpp
@@ -1,169 +1,34 @@
|
||||
#include "sims.h"
|
||||
#include "times/base.h"
|
||||
#include "utils/functions.h"
|
||||
#include "utils/ranges.h"
|
||||
#include "utils/io.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
|
||||
|
||||
|
||||
void run_spectrum(
|
||||
void run_simulation(
|
||||
Experiment& experiment,
|
||||
std::unordered_map<std::string, double>& parameter,
|
||||
std::unordered_map<std::string, double> optional,
|
||||
std::unordered_map<std::string, double>& optional,
|
||||
motions::BaseMotion& motion,
|
||||
times::BaseDistribution& dist,
|
||||
std::mt19937_64& rng
|
||||
) {
|
||||
const int num_walker = static_cast<int>(parameter["num_walker"]);
|
||||
|
||||
// time axis for all time signals
|
||||
const int num_acq = static_cast<int>(parameter["num_acq"]);
|
||||
const std::vector<double> t_fid = arange(num_acq, parameter["dwell_time"]);
|
||||
const std::vector<double> echo_times = linspace(parameter["techo_start"], parameter["techo_stop"], static_cast<int>(parameter["techo_steps"]));
|
||||
|
||||
// make timesignal vectors and set them to zero
|
||||
std::map<double, std::vector<double>> fid_dict;
|
||||
for (auto t_echo_i: echo_times) {
|
||||
fid_dict[t_echo_i] = std::vector<double>(num_acq);
|
||||
std::fill(fid_dict[t_echo_i].begin(), fid_dict[t_echo_i].end(), 0.);
|
||||
}
|
||||
|
||||
// calculate min length of a trajectory
|
||||
const double tmax = *std::max_element(echo_times.begin(), echo_times.end()) * 2 + t_fid.back();
|
||||
|
||||
// set parameter in distribution and motion model
|
||||
dist.setParameters(parameter);
|
||||
motion.setParameters(parameter);
|
||||
experiment.setup(parameter, optional);
|
||||
|
||||
const auto start = printStart(optional);
|
||||
auto last_print_out = std::chrono::system_clock::now();
|
||||
|
||||
// let the walker walk
|
||||
for (int mol_i = 0; mol_i < num_walker; mol_i++){
|
||||
auto traj = make_trajectory(motion, dist, tmax, rng);
|
||||
|
||||
for (auto& [t_echo_j, fid_j] : fid_dict) {
|
||||
// get phase at echo pulse
|
||||
int current_pos = nearest_index(traj.time, t_echo_j, 0);
|
||||
const double phase_techo = lerp(traj.time, traj.phase, t_echo_j, current_pos);
|
||||
|
||||
|
||||
for (int acq_idx = 0; acq_idx < num_acq; acq_idx++) {
|
||||
const double real_time = t_fid[acq_idx] + 2 * t_echo_j;
|
||||
|
||||
current_pos = nearest_index(traj.time, real_time, current_pos);
|
||||
const double phase_acq = lerp(traj.time, traj.phase, real_time, current_pos);
|
||||
|
||||
fid_j[acq_idx] += std::cos(phase_acq - 2 * phase_techo) / num_walker;
|
||||
}
|
||||
last_print_out = printSteps(last_print_out, start, num_walker, mol_i);
|
||||
}
|
||||
}
|
||||
|
||||
// write fid to files
|
||||
const auto path = make_directory(motion, dist);
|
||||
save_parameter_to_file(std::string("timesignal"), path, parameter, optional);
|
||||
save_data_to_file(std::string("timesignal"), path, t_fid, fid_dict, optional);
|
||||
|
||||
printEnd(start);
|
||||
}
|
||||
|
||||
|
||||
void run_ste(
|
||||
std::unordered_map<std::string, double>& parameter,
|
||||
std::unordered_map<std::string, double> optional,
|
||||
motions::BaseMotion& motion,
|
||||
times::BaseDistribution& dist,
|
||||
std::mt19937_64& rng
|
||||
) {
|
||||
const int num_walker = static_cast<int>(parameter[std::string("num_walker")]);
|
||||
|
||||
const int num_mix_times = static_cast<int>(parameter["tmix_steps"]);
|
||||
const std::vector<double> evolution_times = linspace(parameter["tevo_start"], parameter["tevo_stop"], static_cast<int>(parameter["tevo_steps"]));
|
||||
const std::vector<double> mixing_times = logspace(parameter["tmix_start"], parameter["tmix_stop"], num_mix_times);
|
||||
const double tpulse4 = parameter["tpulse4"];
|
||||
|
||||
// make ste decay vectors and set them to zero
|
||||
std::map<double, std::vector<double>> cc_dict;
|
||||
std::map<double, std::vector<double>> ss_dict;
|
||||
for (auto t_evo_i: evolution_times) {
|
||||
cc_dict[t_evo_i] = std::vector<double>(num_mix_times);
|
||||
ss_dict[t_evo_i] = std::vector<double>(num_mix_times);
|
||||
std::fill(cc_dict[t_evo_i].begin(), cc_dict[t_evo_i].end(), 0.);
|
||||
std::fill(ss_dict[t_evo_i].begin(), ss_dict[t_evo_i].end(), 0.);
|
||||
}
|
||||
std::vector<double> f2(num_mix_times);
|
||||
|
||||
// each trajectory must have a duration of at least tmax
|
||||
const double tmax = *std::max_element(evolution_times.begin(), evolution_times.end()) * 2 + *std::max_element(mixing_times.begin(), mixing_times.end()) + 2*tpulse4;
|
||||
|
||||
// set parameter in distribution and motion model
|
||||
dist.setParameters(parameter);
|
||||
motion.setParameters(parameter);
|
||||
|
||||
const auto start = printStart(optional);
|
||||
auto last_print_out = std::chrono::system_clock::now();
|
||||
|
||||
// let the walker walk
|
||||
for (int mol_i = 0; mol_i < num_walker; mol_i++){
|
||||
auto traj = make_trajectory(motion, dist, tmax, rng);
|
||||
|
||||
int f2_pos = 0;
|
||||
for (int f2_idx=0; f2_idx < num_mix_times; f2_idx++) {
|
||||
const double t_mix_f2 = mixing_times[f2_idx];
|
||||
f2_pos = nearest_index(traj.time, t_mix_f2, f2_pos);
|
||||
f2[f2_idx] += traj.omega[f2_pos] * motion.getInitOmega() / num_walker;
|
||||
}
|
||||
|
||||
|
||||
for (auto& [t_evo_j, _] : cc_dict) {
|
||||
auto& cc_j = cc_dict[t_evo_j];
|
||||
auto& ss_j = ss_dict[t_evo_j];
|
||||
|
||||
// get phase at beginning of mixing time
|
||||
int current_pos = nearest_index(traj.time, t_evo_j, 0);
|
||||
const double dephased = lerp(traj.time, traj.phase, t_evo_j, current_pos);
|
||||
const double cc_tevo = std::cos(dephased);
|
||||
const double ss_tevo = std::sin(dephased);
|
||||
|
||||
for (int mix_idx = 0; mix_idx < num_mix_times; mix_idx++) {
|
||||
// get phase at end of mixing time
|
||||
const double time_end_mix = mixing_times[mix_idx] + t_evo_j;
|
||||
current_pos = nearest_index(traj.time, time_end_mix, current_pos);
|
||||
const double phase_mix_end = lerp(traj.time, traj.phase, time_end_mix, current_pos);
|
||||
|
||||
// get phase at position of 4th pulse
|
||||
const double time_pulse4 = time_end_mix + tpulse4;
|
||||
current_pos = nearest_index(traj.time, time_pulse4, current_pos);
|
||||
const double phase_4pulse = lerp(traj.time, traj.phase, time_pulse4, current_pos);
|
||||
|
||||
// get phase at echo position
|
||||
const double time_echo = time_pulse4 + tpulse4 + t_evo_j;
|
||||
current_pos = nearest_index(traj.time, time_echo, current_pos);
|
||||
double rephased = lerp(traj.time, traj.phase, time_echo, current_pos) + phase_mix_end - 2*phase_4pulse;
|
||||
|
||||
cc_j[mix_idx] += cc_tevo * std::cos(rephased) / num_walker;
|
||||
ss_j[mix_idx] += ss_tevo * std::sin(rephased) / num_walker;
|
||||
}
|
||||
}
|
||||
for (int mol_i = 0; mol_i < num_walker; mol_i++) {
|
||||
auto traj = make_trajectory(motion, dist, experiment.tmax(), rng);
|
||||
experiment.accumulate(traj, motion.getInitOmega(), num_walker);
|
||||
last_print_out = printSteps(last_print_out, start, num_walker, mol_i);
|
||||
}
|
||||
|
||||
// write to files
|
||||
const auto folders = make_directory(motion, dist);
|
||||
save_parameter_to_file(std::string("ste"), folders, parameter, optional);
|
||||
save_data_to_file(std::string("coscos"), folders, mixing_times, cc_dict, optional);
|
||||
save_data_to_file(std::string("sinsin"), folders, mixing_times, ss_dict, optional);
|
||||
save_data_to_file(std::string("f2"), folders, mixing_times, f2, optional);
|
||||
|
||||
experiment.save(motion, dist);
|
||||
printEnd(start);
|
||||
}
|
||||
|
||||
@@ -174,7 +39,6 @@ Trajectory make_trajectory(
|
||||
const double t_max,
|
||||
std::mt19937_64& rng
|
||||
) {
|
||||
// Starting position
|
||||
double t_passed = 0;
|
||||
double phase = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user