diff --git a/kernel/executables/2dx_backproject.cpp b/kernel/executables/2dx_backproject.cpp new file mode 100644 index 00000000..41a0b8f9 --- /dev/null +++ b/kernel/executables/2dx_backproject.cpp @@ -0,0 +1,189 @@ +/* + * @license GNU Public License + * @author Nikhil Biyani (nikhilbiyani@gmail.com) + * + */ + +#include +#include + +#include "2dx_toolkit.h" + +template +std::vector +matrix_multiply(const std::vector& mat1, const std::vector& mat2, int r1, int c1, int c2){ + + std::vector mult(r1*c2, ValueType_()); + + for(int i = 0; i < r1; ++i) { + for(int j = 0; j < c2; ++j) { + for(int k = 0; k < c1; ++k) { + mult[i+j*r1] += mat1[i+k*r1] * mat2[k+j*c1]; + } + } + } + + return mult; + +} + +void add_index(const tdx::data::MillerIndex& index_in, const tdx::Complex& value, + tdx::data::MillerToPeakMultiMap& current_refs, double psi, double theta, double phi) { + + // Values for transformation + double cpsi = cos(psi); + double cthe = cos(theta); + double cphi = cos(phi); + double spsi = sin(psi); + double sthe = sin(theta); + double sphi = sin(phi); + + //TRANFORMATION MATRICES + std::vector A = {cpsi, -1*spsi, 0, spsi, cpsi, 0, 0, 0, 1}; + std::vector B = {cthe, 0, sthe, 0, 1, 0, -1*sthe, 0, cthe}; + std::vector C = {cphi, -1*sphi, 0, sphi, cphi, 0, 0, 0, 1}; + std::vector in = {index_in.h()*1.0, index_in.k()*1.0, index_in.l()*1.0}; + + std::vector res = matrix_multiply(in, matrix_multiply(A, matrix_multiply(B, C, 3, 3, 3), 3, 3, 3), 1, 3, 3); + + int h_min = floor(res.at(0)); + int k_min = floor(res.at(1)); + int l_min = floor(res.at(2)); + + int h_max = ceil(res.at(0)); + int k_max = ceil(res.at(1)); + int l_max = ceil(res.at(2)); + + for(int h = h_min; h <= h_max; ++h) { + for(int k = k_min; k<= k_max; ++k) { + for(int l = l_min; l<-l_max; ++l) { + + double dist = sqrt((res[0]-h)*(res[0]-h) + (res[1]-k)*(res[1]-k) + (res[2]-l)*(res[2]-l)); + double sinc = 1; + if(dist != 0) sinc = sin(M_PI*dist)/(M_PI*dist); + auto amp_in = value.amplitude(); + auto phase_in = value.phase(); + + tdx::data::MillerIndex new_idx(h, k, l); + + if(new_idx.h() < 0) { + new_idx = new_idx.FriedelSpot(); + phase_in *= -1; + } + + double real_in = amp_in*sinc*cos(phase_in); + double imag_in = amp_in*sinc*sin(phase_in); + + tdx::Complex complex_in(real_in, imag_in); + tdx::data::PeakData value_out(complex_in, 1.0); + + current_refs.insert(tdx::data::MillerToPeakPair(new_idx, value_out)); + } + } + } +} + +int main(int argc, char* argv[]) +{ + + args::Executable exe("Program to backproject particles to 3D volume.", ' ', "1.0" ); + + //Select required arguments + TCLAP::ValueArg INPUT_VOLUME("", "input", "Input MRC stack file", true, "", "MRC FILE"); + TCLAP::ValueArg INPUT_PAR("", "par", "Input PAR file", true, "", "PAR FILE"); + TCLAP::ValueArg OUTPUT_VOLUME("", "output", "OUTPUT Volume file", true, "", "MRC FILE"); + TCLAP::ValueArg NUM_PARTICLES("", "particles", "Number of particles to consider", false, 0, "INT"); + TCLAP::ValueArg APIX("", "apix", "Pixel size (A/pixel)", false, 1.0, "FLOAT"); + TCLAP::ValueArg RES("", "cut_off", "Resolution cut-off (in A)", false, 1.0, "FLOAT"); + + INPUT_VOLUME.forceRequired(); + INPUT_PAR.forceRequired(); + OUTPUT_VOLUME.forceRequired(); + + //Add arguments + exe.add(OUTPUT_VOLUME); + exe.add(RES); + exe.add(NUM_PARTICLES); + exe.add(APIX); + exe.add(INPUT_PAR); + exe.add(INPUT_VOLUME); + + + //Parse the arguments + exe.parse(argc, argv); + + //Prepare the input + Volume2DX input; + std::cout << "Reading the particles... \n"; + input.read_volume(INPUT_VOLUME.getValue()); + + //Get number of particles to process + int number_particles = input.nz(); + if(NUM_PARTICLES.isSet() && NUM_PARTICLES.getValue() < number_particles) { + number_particles = NUM_PARTICLES.getValue(); + } + std::cout << number_particles << " particles would be processed..\n"; + + //Get apix + double apix = APIX.getValue(); + std::cout << "Pixel size is set to: " << apix << " A/px \n"; + + //Read the par file + std::vector > parameters(number_particles, std::vector(5, 0.0)); + tdx::File inFile (INPUT_PAR.getValue(), tdx::File::in); + if (!inFile.exists()){ + std::cerr << "File not found: " << INPUT_PAR.getValue() << std::endl; + exit(1); + } + while(!inFile.eof()) { + std::string line = inFile.read_line(); + if(line.length()==0) continue; + if(line[0] == 'C' || line[0] == 'c') continue; + std::vector values = tdx::String::split(tdx::String::trim(line), ' '); + if(values.size() < 6) { + //std::cerr << "Omitting " << line << "\n"; + continue; + } + int particle = std::stoi(values[0])-1; + if(particle < number_particles) { + parameters[particle] = {std::stod(values[1]), std::stod(values[2]), std::stod(values[3]), std::stod(values[4]), std::stod(values[5])}; + } + } + + tdx::data::MillerToPeakMultiMap all_reflections; + for(int i=0; i< number_particles; ++i) { + std::cout << "Processing particle: " << i+1 < SLAB("", "slab", "The membrane height in ratio of the Z length of the volume", false, 1.0,"FLOAT"); static TCLAP::ValueArg TEMP_LOC("", "temp", "Folder to keep temporary files for each iteration (if not specified temp files will not be written)", false, "","FOLDER"); static TCLAP::ValueArg MASK_RES("", "mask-res", "The volume in each iteration will be lowpassed with this resolution, before generating a thresholded mask.", false, 15.0,"FLOAT"); + static TCLAP::ValueArg SHIFTX("", "x_shift", "The shift in x direction to be performed", false, 0.0,"FLOAT"); + static TCLAP::ValueArg SHIFTY("", "y_shift", "The shift in y direction to be performed", false, 0.0,"FLOAT"); + static TCLAP::ValueArg SHIFTZ("", "z_shift", "The shift in z direction to be performed", false, 0.0,"FLOAT"); static TCLAP::SwitchArg INVERTED("", "inverted", "Produce an output map with inverted hand in all x,y,z direction", false); static TCLAP::SwitchArg INVERTX("", "invertx", "Produce an output map with inverted hand in x direction", false); diff --git a/kernel/toolkit/data_structures/miller_index.cpp b/kernel/toolkit/data_structures/miller_index.cpp index d418b675..44cea074 100644 --- a/kernel/toolkit/data_structures/miller_index.cpp +++ b/kernel/toolkit/data_structures/miller_index.cpp @@ -50,11 +50,6 @@ bool ds::MillerIndex::operator <(const MillerIndex& rhs) const ); } -std::ostream& ds::MillerIndex::operator <<(std::ostream& os) const -{ - return os << h() << " " << k() << " " << l(); -} - void ds::MillerIndex::set_values(int h, int k, int l) { this->initialize(h, k, l); diff --git a/kernel/toolkit/data_structures/miller_index.hpp b/kernel/toolkit/data_structures/miller_index.hpp index a634cfc6..7db62d23 100644 --- a/kernel/toolkit/data_structures/miller_index.hpp +++ b/kernel/toolkit/data_structures/miller_index.hpp @@ -71,7 +71,10 @@ namespace tdx * @param os * @return */ - std::ostream& operator<<(std::ostream& os) const; + friend inline std::ostream& operator<<(std::ostream& os, const MillerIndex& obj) { + os << " ( " << obj.h() << " " << obj.k() << " " << obj.l() << ") "; + return os; + } /** * Getter method for index h (x-dimension). diff --git a/kernel/toolkit/data_structures/volume2dx.cpp b/kernel/toolkit/data_structures/volume2dx.cpp index b3e36f7f..4d88cbf6 100644 --- a/kernel/toolkit/data_structures/volume2dx.cpp +++ b/kernel/toolkit/data_structures/volume2dx.cpp @@ -174,7 +174,7 @@ void ds::Volume2DX::set_real(const RealSpaceData& real) void ds::Volume2DX::fourier_from_real() { - std::cout << "Converting the real data to Fourier. \n"; + //std::cout << "Converting the real data to Fourier. \n"; if(_type == REAL) { _fourier.clear(); @@ -194,7 +194,7 @@ void ds::Volume2DX::fourier_from_real() void ds::Volume2DX::real_from_fourier() { - std::cout << "Converting the Fourier data to real. \n"; + //std::cout << "Converting the Fourier data to real. \n"; if(_type == FOURIER){ double* real_data = fftw_alloc_real(nx()*ny()*nz()); fftw_complex* complex_data = _fourier.fftw_data(fx(), fy(), fz()); @@ -569,6 +569,26 @@ ds::BinnedData ds::Volume2DX::calculate_structure_factors(double min_freq, doubl return binned_data; } +void ds::Volume2DX::shift_volume(double x_shift, double y_shift, double z_shift) { + int dim_x = nx(); + int dim_y = ny(); + int dim_z = nz(); + + tdx::data::ReflectionData current, shifted; + + current = get_fourier(); + for (const auto& data : current) { + auto index = data.first; + double amp = data.second.amplitude(); + double phase = data.second.phase() - (2 * M_PI) * ((x_shift * index.h() * 1.0/dim_x) + (y_shift * index.k() * 1.0/dim_y) + (z_shift * index.l() * 1.0/dim_z)); + tdx::Complex shift_complex(amp*cos(phase), amp*sin(phase)); + shifted.set_spot_at(index.h(), index.k(), index.l(), shift_complex, data.second.weight()); + } + + set_fourier(shifted); +} + + ds::BinnedData ds::Volume2DX::fourier_shell_correlation(ds::Volume2DX reference, double min_freq, double max_freq, int resolution_bins) { BinnedData binnedFSC(min_freq, max_freq, resolution_bins); @@ -1205,6 +1225,33 @@ ds::Volume2DX ds::Volume2DX::average2D(char axis) return averaged; } +ds::Volume2DX ds::Volume2DX::get_slice(int slice_no) { + VolumeHeader head = header(); + RealSpaceData current_data = get_real(); + RealSpaceData new_data; + + if(slice_no >= nz() || slice_no < 0) { + std::cerr << "Can't get slice: " << slice_no << " Range(0, " << nz() << ")\n"; + exit(1); + } + + head.set_mz(1); + head.set_sections(1); + new_data = RealSpaceData(nx(), ny(), 1); + for(int ix=0; ix