Xmipp  v3.23.11-Nereus
volume_pca.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar coss@cnb.csic.es (2015)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
28 #include "volume_pca.h"
29 
30 // Read arguments ==========================================================
32 {
33  fnVols = getParam("-i");
34  fnVolsOut = getParam("-o");
35  NPCA = getIntParam("--Npca");
36  fnBasis = getParam("--saveBasis");
37  fnAvgVol = getParam("--avgVolume");
38  fnOutStack = getParam("--opca");
39  if (checkParam("--generatePCAVolumes"))
40  getListParam("--generatePCAVolumes",listOfPercentiles);
41  if (checkParam("--mask"))
42  mask.readParams(this);
43 }
44 
45 // Show ====================================================================
46 void ProgVolumePCA::show() const
47 {
48  if (verbose==0)
49  return;
50  std::cout << "Input volumes: " << fnVols << std::endl
51  << "Output metadata:" << fnVolsOut << std::endl
52  << "Number of PCAs: " << NPCA << std::endl
53  << "Basis: " << fnBasis << std::endl
54  << "Avg. volume: " << fnAvgVol << std::endl
55  << "Output PCA vols:" << fnOutStack << std::endl;
56  std::cout << "Percentiles: ";
57  for (size_t i=0; i<listOfPercentiles.size(); i++)
58  std::cout << listOfPercentiles[i] << " ";
59  std::cout << std::endl;
60  if (mask.type!=NO_MASK)
61  mask.show();
62 }
63 
64 // usage ===================================================================
66 {
67  addUsageLine("Compute the PCA of a set of volumes, within a mask (optional).");
68  addParamsLine(" -i <volumes> : Metadata with aligned volumes");
69  addParamsLine(" [-o <volumes=\"\">] : Output metadata with PCA projections");
70  addParamsLine(" [--Npca <N=1>] : Number of PCA bases");
71  addParamsLine(" [--saveBasis <stack=\"\">]: Save the bases as a stack of volumes");
72  addParamsLine(" [--generatePCAVolumes <...>]: List of percentiles (typically, \"10 90\"), to generate volumes along the 1st PCA basis");
73  addParamsLine(" [--avgVolume <volume=\"\">] : Volume on which to add the PCA basis");
74  addParamsLine(" [--opca <stack=\"\">] : Stack of generated volumes");
76 }
77 
78 // Produce side information ================================================
80 {
83 
84  size_t Xdim, Ydim, Zdim, Ndim;
85  getImageSize(mdVols, Xdim, Ydim, Zdim, Ndim);
86  if (mask.type!=NO_MASK)
87  mask.generate_mask(Zdim,Ydim,Xdim);
88  else
89  {
90  mask.imask.resizeNoCopy(Zdim,Ydim,Xdim);
92  }
93 }
94 
96 {
97  show();
99 
100  const MultidimArray<int> &imask=mask.imask;
101  size_t Nvoxels=imask.sum();
103  v.initZeros(Nvoxels);
104 
105  // Add all volumes to the analyzer
106  FileName fnVol;
107  for (size_t objId : mdVols.ids())
108  {
109  mdVols.getValue(MDL_IMAGE,fnVol,objId);
110  V.read(fnVol);
111 
112  // Construct vector
113  const MultidimArray<double> &mV=V();
114  size_t idx=0;
116  {
117  if (DIRECT_MULTIDIM_ELEM(imask,n))
119  }
120 
121  analyzer.addVector(v);
122  }
123 
124  // Construct PCA basis
127 
128  // Project onto the PCA basis
129  Matrix2D<double> proj;
131  std::vector<double> dimredProj;
132  dimredProj.resize(NPCA);
133  int i=0;
134  for (size_t objId : mdVols.ids())
135  {
136  memcpy(&dimredProj[0],&MAT_ELEM(proj,i,0),NPCA*sizeof(double));
137  mdVols.setValue(MDL_DIMRED,dimredProj,objId);
138  i++;
139  }
140  if (fnVolsOut!="")
142  else
144 
145  // Save the basis
146  const MultidimArray<double> &mV=V();
147  for (int i=NPCA-1; i>=0; --i)
148  {
149  V().initZeros();
150  size_t idx=0;
153  {
154  if (DIRECT_MULTIDIM_ELEM(imask,n))
156  }
157  if (fnBasis!="")
158  V.write(fnBasis,i+1,true,WRITE_OVERWRITE);
159  }
160 
161  // Generate the PCA volumes
162  if (listOfPercentiles.size()>0 && fnOutStack!="" && fnAvgVol!="")
163  {
164  Image<double> Vavg;
165  if (fnAvgVol!="")
166  Vavg.read(fnAvgVol);
167  else
168  Vavg().initZeros(V());
169 
171  proj.toVector(p);
172  Matrix1D<double> psorted=p.sort();
173 
174  Image<double> Vpca;
175  Vpca()=Vavg();
176  createEmptyFile(fnOutStack,(int)XSIZE(Vavg()),(int)YSIZE(Vavg()),(int)ZSIZE(Vavg()),listOfPercentiles.size());
177  std::cout << "listOfPercentiles.size()=" << listOfPercentiles.size() << std::endl;
178  for (size_t i=0; i<listOfPercentiles.size(); i++)
179  {
180  auto idx=(int)round(textToFloat(listOfPercentiles[i].c_str())/100.0*VEC_XSIZE(p));
181  std::cout << "Percentile " << listOfPercentiles[i] << " -> idx=" << idx << " p(idx)=" << psorted(idx) << std::endl;
182  Vpca()+=psorted(idx)*V();
183  Vpca.write(fnOutStack,i+1,true,WRITE_REPLACE);
184  }
185  }
186 }
#define YSIZE(v)
void addVector(const MultidimArray< float > &_v)
Add vector.
Definition: basic_pca.h:100
void show() const
Show.
Definition: volume_pca.cpp:46
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
#define VEC_XSIZE(m)
Definition: matrix1d.h:77
void projectOnPCABasis(Matrix2D< double > &CtY)
Project on basis.
Definition: basic_pca.cpp:119
void resizeNoCopy(const MultidimArray< T1 > &v)
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
FileName fnVols
Input set of volumes.
Definition: volume_pca.h:42
void getImageSize(const MetaData &md, size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim, MDLabel image_label)
void subtractAvg()
Subtract average.
Definition: basic_pca.cpp:33
void toVector(Matrix1D< T > &op1) const
Definition: matrix2d.cpp:832
void initConstant(T val)
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
MetaDataVec mdVols
Definition: volume_pca.h:59
void getListParam(const char *param, StringVector &list)
virtual IdIteratorProxy< false > ids()
#define NO_MASK
Definition: mask.h:364
#define i
static void defineParams(XmippProgram *program, int allowed_data_types=ALL_KINDS, const char *prefix=nullptr, const char *comment=nullptr, bool moreOptions=false)
Definition: mask.cpp:1203
void produce_side_info()
Definition: volume_pca.cpp:79
FileName fnOutStack
Output PCA stack.
Definition: volume_pca.h:56
#define MAT_ELEM(m, i, j)
Definition: matrix2d.h:116
PCAMahalanobisAnalyzer analyzer
Definition: volume_pca.h:65
const char * getParam(const char *param, int arg=0)
bool setValue(const MDObject &mdValueIn, size_t id)
float textToFloat(const char *str)
FileName fnBasis
Output basis.
Definition: volume_pca.h:50
void defineParams()
Define parameters.
Definition: volume_pca.cpp:65
#define XSIZE(v)
void readParams()
Read arguments.
Definition: volume_pca.cpp:31
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
int type
Definition: mask.h:402
Projection onto a reduced manifold (vector double)
#define ZSIZE(v)
#define DIRECT_MULTIDIM_ELEM(v, n)
std::vector< MultidimArray< double > > PCAbasis
Definition: basic_pca.h:69
void readParams(XmippProgram *program)
Definition: mask.cpp:1284
void createEmptyFile(const FileName &filename, int xdim, int ydim, int Zdim, size_t select_img, bool isStack, int mode, int _swapWrite, const MDRowVec *md)
int verbose
Verbosity level.
Mask mask
Mask.
Definition: volume_pca.h:48
bool getValue(MDObject &mdValueOut, size_t id) const override
void generate_mask(bool apply_geo=false)
Definition: mask.cpp:1577
int round(double x)
Definition: ap.cpp:7245
Image< double > V
Definition: volume_pca.h:62
int NPCA
Number of PCA bases.
Definition: volume_pca.h:46
virtual void removeDisabled()
FileName fnAvgVol
Average volume.
Definition: volume_pca.h:54
#define INT_MASK
Definition: mask.h:385
FileName fnVolsOut
Output set of volumes.
Definition: volume_pca.h:44
StringVector listOfPercentiles
List of percentiles to generate volumes.
Definition: volume_pca.h:52
void learnPCABasis(size_t NPCA, size_t Niter)
Learn basis.
Definition: basic_pca.cpp:170
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)
MultidimArray< int > imask
Definition: mask.h:499
Matrix1D< T > sort() const
Definition: matrix1d.cpp:850
void addUsageLine(const char *line, bool verbatim=false)
void initZeros(const MultidimArray< T1 > &op)
int getIntParam(const char *param, int arg=0)
int * n
Name of an image (std::string)
double sum() const
void show() const
Definition: mask.cpp:1021
void addParamsLine(const String &line)