Xmipp  v3.23.11-Nereus
nma_alignment_vol.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar Sanchez Sorzano coss@cnb.csic.es
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18  * 02111-1307 USA
19  *
20  * All comments concerning this program package may be sent to the
21  * e-mail address 'xmipp@cnb.uam.es'
22  ***************************************************************************/
23 
24 #include <limits>
25 #include "nma_alignment_vol.h"
26 #include "volume_from_pdb.h"
27 #include "program_extension.h"
28 #include "condor/Solver.h"
29 
30 // Empty constructor =======================================================
32  rangen = 0;
33  resume = false;
34  currentVolName = "";
36  produces_an_output = true;
38  alignVolumes=false;
39 }
40 
42  delete progVolumeFromPDB;
43 }
44 
45 // Params definition ============================================================
47  addUsageLine("Align volumes with an atomic or pseudo-atomic (from EM volume) structure by computing deformation amplitudes along normal modes");
48  addUsageLine("You may also align the two volumes during the process");
49  defaultComments["-i"].clear();
50  defaultComments["-i"].addComment("Metadata with volume filenames");
51  defaultComments["-o"].clear();
52  defaultComments["-o"].addComment("Metadata with output Euler angles, shifts, and deformation amplitudes");
54  addParamsLine(" --pdb <PDB_filename> : Reference atomic or pseudo-atomic structure in PDB format");
55  addParamsLine(" [--odir <outputDir=\".\">] : Output directory");
56  addParamsLine(" [--resume] : Resume processing");
57  addParamsLine(" [--opdb <PDB_filename=\"\">] : Output PDB which is the deformed input PDB");
58  addParamsLine("==Generation of the deformed reference volumes==");
59  addParamsLine(" --modes <filename> : File with a list of mode filenames");
60  addParamsLine(" [--sampling_rate <Ts=1>] : Pixel size in Angstroms");
61  addParamsLine(" [--filterVol <cutoff=15.>] : Filter the volume after deforming. If this option is used, the default cut-off is 15 A.");
62  addParamsLine(" [--centerPDB] : Center the PDB structure");
63  addParamsLine(" [--fixed_Gaussian <std=-1>] : For pseudo-atoms fixed_Gaussian must be used.");
64  addParamsLine(" : Default standard deviation <std> is read from the PDB file.");
65  addParamsLine(" [--trustradius_scale <s=1>] : Positive scaling factor to scale the initial trust region radius");
66  addParamsLine("==Combined elastic and rigid-body alignment==");
67  addParamsLine(" [--alignVolumes <frm_freq=0.25> <frm_shift=10>] : Align the deformed volume to the input volume before comparing, this is using frm method for volume alignment with frm_freq and frm_shift as parameters");
68  addParamsLine(" : You need to compile Xmipp with SHALIGNMENT support (see install.sh)");
69  addParamsLine(" [--mask <m=\"\">] : 3D masking of the projections of the deformed volume");
70  addParamsLine(" [--tilt_values <tilt0=-90> <tiltF=90>] : only use if you are trying to compensate for the missing wedge");
71  addParamsLine(" [--condor_params <rhoStartBase=250.> <rhoEndBase=50.> <niter=10000>] : parameters for the CONDOR optimiser (recommended to keep default)");
72  addParamsLine(" : rhoStartBase > 0 : the lower the better, yet the slower");
73  addParamsLine(" : rhoEndBase no specific rule, however it is better to keep it < 1000, if set very high we risk distortions");
74  addParamsLine(" : niter should be big enough to guarantee that the search converges to the right set of nma deformation amplitudes");
75  addExampleLine("xmipp_nma_alignment_vol -i volumes.xmd --pdb 2tbv.pdb --modes modelist.xmd --sampling_rate 3.2 -o output.xmd --resume");
76 }
77 
78 // Read arguments ==========================================================
81  fnPDB = getParam("--pdb");
82  fnOutPDB = getParam("--opdb");
83  fnOutDir = getParam("--odir");
84  Rerunable::setFileName(fnOutDir + "/nmaDone.xmd");
85  fnModeList = getParam("--modes");
86  resume = checkParam("--resume");
87  sampling_rate = getDoubleParam("--sampling_rate");
88  fnmask = getParam("--mask");
89  do_centerPDB = checkParam("--centerPDB");
90  do_FilterPDBVol = checkParam("--filterVol");
91  trustradius_scale = std::abs(getDoubleParam("--trustradius_scale"));
92  if (do_FilterPDBVol)
93  cutoff_LPfilter = getDoubleParam("--filterVol");
94  useFixedGaussian = checkParam("--fixed_Gaussian");
95  if (useFixedGaussian)
96  sigmaGaussian = getDoubleParam("--fixed_Gaussian");
97  alignVolumes=checkParam("--alignVolumes");
98  if (alignVolumes){
99  frm_freq = getDoubleParam("--alignVolumes",0);
100  frm_shift= getIntParam("--alignVolumes",1);
101  }
102  tilt0=getIntParam("--tilt_values",0);
103  tiltF=getIntParam("--tilt_values",1);
104 
105  rhoStartBase = getDoubleParam("--condor_params",0);
106  rhoEndBase = getDoubleParam("--condor_params",1);
107  niter = getIntParam("--condor_params",2);
108 
109 }
110 // Show ====================================================================
113  std::cout
114  << "Output directory: " << fnOutDir << std::endl
115  << "PDB: " << fnPDB << std::endl
116  << "Resume: " << resume << std::endl
117  << "Mode list: " << fnModeList << std::endl
118  << "Pixel size: " << sampling_rate << std::endl
119  << "Mask: " << fnmask << std::endl
120  << "Center PDB: " << do_centerPDB << std::endl
121  << "Filter PDB volume: " << do_FilterPDBVol << std::endl
122  << "Use pseudo-atoms: " << useFixedGaussian << std::endl
123  << "Pseudo-atom sigma: " << sigmaGaussian << std::endl
124  << "Trust-region scale: " << trustradius_scale << std::endl;
125 }
126 
127 // Produce side information ================================================
129 
132  SF.removeDisabled();
133  numberOfModes = SF.size();
134  // Get the size of the images in the selfile
135  imgSize = xdimOut;
136  // Set the pointer of the program to this object
137  global_nma_vol_prog = this;
138  //create some neededs files
139  createWorkFiles();
140  if (fnmask!="")
141  {
142  Image<double> aux;
143  aux.read(fnmask);
144  typeCast(aux(),mask);
145  }
146 }
147 
150  rename(Rerunable::getFileName().c_str(), fn_out.c_str());
151 }
152 
153 // Create deformed PDB =====================================================
154 void deformPDB(const FileName &PDBin, const FileName &PDBout, const FileName &fnModeList,
155  const Matrix1D<double> &trial)
156 {
157  String program = "xmipp_pdb_nma_deform";
158  String arguments = formatString("--pdb %s -o %s --nma %s --deformations ",PDBin.c_str(), PDBout.c_str(), fnModeList.c_str());
159  for (size_t i = 0; i < VEC_XSIZE(trial); ++i)
160  arguments += floatToString(trial(i)) + " ";
161  runSystem(program, arguments, false);
162 }
163 
165  String program;
166  String arguments;
167  FileName fnRandom;
169  const char * randStr = fnRandom.c_str();
170 
171  deformPDB(fnPDB,formatString("%s_deformedPDB.pdb",randStr),fnModeList,trial);
172  program = "xmipp_volume_from_pdb";
173  arguments = formatString(
174  "-i %s_deformedPDB.pdb --size %i --sampling %f -v 0", randStr,
176 
177  if (do_centerPDB)
178  arguments.append(" --centerPDB ");
179 
180  if (useFixedGaussian) {
181  arguments.append(" --intensityColumn Bfactor --fixed_Gaussian ");
182  if (sigmaGaussian >= 0)
183  arguments += formatString("%f",sigmaGaussian);
184  }
185 
186  progVolumeFromPDB->read(arguments);
188 
189  if (do_FilterPDBVol) {
190  program = "xmipp_transform_filter";
191  arguments = formatString(
192  "-i %s_deformedPDB.vol --sampling %f --fourier low_pass %f -v 0",
193  randStr, sampling_rate, cutoff_LPfilter);
194  runSystem(program, arguments, false);
195  }
196 
197  return fnRandom;
198 }
199 
201  if (fitness < fitness_min) {
203  trial_best = trial;
204  return true;
205  }
206  return false;
207 }
208 
209 // Compute fitness =========================================================
210 double ObjFunc_nma_alignment_vol::eval(Vector X, int *nerror) {
211  int dim = global_nma_vol_prog->numberOfModes;
212 
213  for (int i = 0; i < dim; i++) {
214  global_nma_vol_prog->trial(i) = X[i];
215  }
216 
217  FileName fnRandom = global_nma_vol_prog->createDeformedPDB();
218  const char * randStr = fnRandom.c_str();
219  double retval=std::numeric_limits<double>::max();
220 
221  FileName fnShiftsAngles = fnRandom + "_angles_shifts.txt";
222  const char * shifts_angles = fnShiftsAngles.c_str();
223 
224  String fnVolume1 = global_nma_vol_prog->currentVolName;
225  String fnVolume2 = fnRandom + "_deformedPDB.vol";
226 
227  if (global_nma_vol_prog->tilt0!=-90 || global_nma_vol_prog->tiltF!=90 ){
228  global_nma_vol_prog->flip = true;
229  runSystem("xmipp_transform_geometry",formatString("-i %s -o %s_currentvolume.vol --rotate_volume euler 0 90 0 -v 0",fnVolume1.c_str(),randStr));
230  fnVolume1 = fnRandom+"_currentvolume.vol";
231  }
232 
233  const char * Volume1 = fnVolume1.c_str();
234  const char * Volume2 = fnVolume2.c_str();
235 
236  int err;
237 
238  if (global_nma_vol_prog->alignVolumes){
239  runSystem("xmipp_volume_align",formatString("--i1 %s --i2 %s --frm %f %d %d %d --store %s -v 0 ",
240  Volume1,Volume2,global_nma_vol_prog->frm_freq, global_nma_vol_prog->frm_shift, global_nma_vol_prog->tilt0, global_nma_vol_prog->tiltF, shifts_angles));
241  //first just see what is the score
242  global_nma_vol_prog->AnglesShiftsAndScore = fopen(shifts_angles, "r");
243  //fit_value is the 7th element in a single line CSV
244  for (int i = 0; i < 7; i++){
245  err = fscanf(global_nma_vol_prog->AnglesShiftsAndScore, "%f,", &global_nma_vol_prog->fit_value);
246  if (1!=err)
247  REPORT_ERROR(ERR_IO, "reading the fitness value was not successful");
248  }
249  fclose(global_nma_vol_prog->AnglesShiftsAndScore);
250  retval = 1 + global_nma_vol_prog->fit_value;
251  }
252 
253  else{
254  global_nma_vol_prog->Vdeformed.read(formatString("%s_deformedPDB.vol",fnRandom.c_str()));
255  auto mask = (0 == XSIZE(global_nma_vol_prog->mask)) ? nullptr : &global_nma_vol_prog->mask;
256  retval = 1 - correlationIndex(global_nma_vol_prog->V(), global_nma_vol_prog->Vdeformed(), mask);
257  //global_nma_vol_prog->V().printStats();
258  //global_nma_vol_prog->Vdeformed().printStats();
259  //std::cout << correlationIndex(global_nma_vol_prog->V(),global_nma_vol_prog->Vdeformed()) << std::endl;
260  }
261 
262  if(global_nma_vol_prog->updateBestFit(retval) && global_nma_vol_prog->alignVolumes){
263  global_nma_vol_prog->AnglesShiftsAndScore = fopen(shifts_angles, "r");
264  for (int i = 0; i < 6; i++){
265  err = fscanf(global_nma_vol_prog->AnglesShiftsAndScore, "%f,", &global_nma_vol_prog->Best_Angles_Shifts[i]);
266  if (1!=err)
267  REPORT_ERROR(ERR_IO, "reading the angles and shifts was not successful");
268  }
269  fclose(global_nma_vol_prog->AnglesShiftsAndScore);
270  }
271 
272  runSystem("rm", formatString("-rf %s* &", randStr));
273  //std::cout << global_nma_vol_prog->trial << " -> " << retval << std::endl;
274  return retval;
275 }
276 
278 }
279 
281  const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut) {
282  static size_t imageCounter = 0;
283  ++imageCounter;
284 
285  ObjectiveFunction *of;
286 
287  int dim = numberOfModes;
288 
289  parameters.initZeros(dim);
290  V.read(fnImg);
291  currentVolName = fnImg;
292  sprintf(nameTemplate, "_node%d_img%lu_XXXXXX", rangen, (long unsigned int)imageCounter);
293 
294  trial.initZeros(dim);
295  trial_best.initZeros(dim);
296 
297  fitness_min=1000000.0;
298 
299  of = new ObjFunc_nma_alignment_vol(1, dim);
300 
301  of->xStart.setSize(dim);
302  for (int i = 0; i < dim; i++)
303  of->xStart[i] = 0.;
304 
305  double rhoStart=trustradius_scale*rhoStartBase;
306  double rhoEnd=trustradius_scale*rhoEndBase;
307 
308  CONDOR(rhoStart, rhoEnd, niter, of);
309 
311 
314 
315  writeVolumeParameters(fnImg);
316  if (fnOutPDB!="")
318  delete of;
319 }
320 
322  MetaDataVec md;
323  size_t objId = md.addObject();
324  md.setValue(MDL_IMAGE, fnImg, objId);
325  md.setValue(MDL_ENABLED, 1, objId);
326 
327  std::vector<double> vectortemp;
328  double energy=0;
329  for (int j = 0; j < numberOfModes; j++)
330  {
331  double lambdaj=parameters(j);
332  vectortemp.push_back(lambdaj);
333  energy+=lambdaj*lambdaj;
334  }
335 
336 
337  energy/=numberOfModes;
338  md.setValue(MDL_ANGLE_ROT, (double)global_nma_vol_prog->Best_Angles_Shifts[0], objId);
339  md.setValue(MDL_ANGLE_TILT, (double)global_nma_vol_prog->Best_Angles_Shifts[1], objId);
340  md.setValue(MDL_ANGLE_PSI, (double)global_nma_vol_prog->Best_Angles_Shifts[2], objId);
341  md.setValue(MDL_SHIFT_X, (double)global_nma_vol_prog->Best_Angles_Shifts[3], objId);
342  md.setValue(MDL_SHIFT_Y, (double)global_nma_vol_prog->Best_Angles_Shifts[4], objId);
343  md.setValue(MDL_SHIFT_Z, (double)global_nma_vol_prog->Best_Angles_Shifts[5], objId);
344  md.setValue(MDL_NMA, vectortemp, objId);
345  md.setValue(MDL_NMA_ENERGY, energy, objId);
346  md.setValue(MDL_MAXCC, 1-parameters(numberOfModes), objId);
347  if (global_nma_vol_prog->flip){
348  md.setValue(MDL_ANGLE_Y, 90.0 , objId);
349  }
350  else{
351  md.setValue(MDL_ANGLE_Y, 0.0 , objId);
352  }
353 
355 }
void readParams()
Read arguments from command line.
Rotation angle of an image (double,degrees)
FileName fnOutPDB
Output PDB.
double getDoubleParam(const char *param, int arg=0)
virtual void read(int argc, const char **argv, bool reportErrors=true)
void defineParams()
Define params.
FileName fnOutDir
Output directory.
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
virtual void processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut)
#define VEC_XSIZE(m)
Definition: matrix1d.h:77
virtual int tryRun()
ProgNmaAlignmentVol()
Empty constructor.
bool do_FilterPDBVol
Low-pass filter the volume from PDB.
Definition: Vector.h:37
Tilting angle of an image (double,degrees)
double sampling_rate
Pixel size in Angstroms.
FileName fnPDB
Reference atomic or pseudo-atomic structure in PDB format.
double eval(Vector v, int *nerror=nullptr)
Shift for the image in the X axis (double)
double correlationIndex(const MultidimArray< T > &x, const MultidimArray< T > &y, const MultidimArray< int > *mask=NULL, MultidimArray< double > *Contributions=NULL)
FileName fnModeList
File with a list of mode filenames.
Special label to be used when gathering MDs in MpiMetadataPrograms.
void abs(Image< double > &op)
Input/Output general error.
Definition: xmipp_error.h:134
void setFileName(const FileName &fn)
void initUniqueName(const char *templateStr="xmippTemp_XXXXXX", const String &fnDir="")
bool updateBestFit(double fitness)
FileName fnmask
Mask file for 2D masking of the projections of the deformed volume.
void deformPDB(const FileName &PDBin, const FileName &PDBout, const FileName &fnModeList, const Matrix1D< double > &trial)
void runSystem(const String &program, const String &arguments, bool useSystem)
String floatToString(float F, int _width, int _prec)
size_t size() const override
#define i
Is this image enabled? (int [-1 or 1])
void setSize(int _n)
Definition: Vector.cpp:112
Matrix1D< double > parameters
virtual void writeVolumeParameters(const FileName &fnImg)
const FileName & getFileName() const
const char * getParam(const char *param, int arg=0)
bool do_centerPDB
Center the PDB structure.
double trustradius_scale
Parameters required from the CONDOR optimization.
bool setValue(const MDObject &mdValueIn, size_t id)
size_t addObject() override
Angle between y-axis and tilt-axis (double, degrees) for untilted micrographs.
FileName createDeformedPDB() const
~ProgNmaAlignmentVol()
Destructor.
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
#define XSIZE(v)
bool useFixedGaussian
Use pseudo-atoms instead of atoms.
void max(Image< double > &op1, const Image< double > &op2)
Normal mode displacements (vector double)
bool produces_an_output
Indicate that a unique final output is produced.
void addExampleLine(const char *example, bool verbatim=true)
Matrix1D< double > trial_best
Maximum cross-correlation for the image (double)
ObjFunc_nma_alignment_vol(int _t, int _n=0)
void initZeros()
Definition: matrix1d.h:592
ProgPdbConverter * progVolumeFromPDB
#define j
bool alignVolumes
Align volumes.
double sigmaGaussian
Gaussian standard deviation for pseudo-atoms.
void show() const override
NMA energy contained in the NMA displacement vector.
virtual void removeDisabled()
void typeCast(const Matrix1D< T1 > &v1, Matrix1D< T2 > &v2)
Definition: matrix1d.h:1227
void append(const FileName &outFile) const
std::string String
Definition: xmipp_strings.h:34
Matrix1D< double > trial
String formatString(const char *format,...)
Shift for the image in the Z axis (double)
double cutoff_LPfilter
Low-pass cut-off frequency.
bool checkParam(const char *param)
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
ProgNmaAlignmentVol * global_nma_vol_prog
bool each_image_produces_an_output
Indicate that an output is produced for each image in the input.
Shift for the image in the Y axis (double)
void addUsageLine(const char *line, bool verbatim=false)
virtual void finishProcessing()
MultidimArray< int > mask
int getIntParam(const char *param, int arg=0)
void CONDOR(double rhoStart, double rhoEnd, int niter, ObjectiveFunction *of, int nnode)
Definition: CNLSolver.cpp:75
virtual void createWorkFiles()
Name of an image (std::string)
double fitness(double *p)
void addParamsLine(const String &line)
std::map< String, CommentList > defaultComments
Definition: xmipp_program.h:83
Image< double > Vdeformed