51 addUsageLine(
"Generates a list of candidates for angular assignment for each experimental image");
52 addParamsLine(
" -ref <md_file> : Metadata file with input reference projections");
53 addParamsLine(
" [-odir <outputDir=\".\">] : Output directory");
54 addParamsLine(
" [--sym <symfile=c1>] : Enforce symmetry in projections");
57 addParamsLine(
" [--maxShift <maxShift=-1.>] : Maximum shift allowed (+-this amount)");
58 addParamsLine(
" [--Nsimultaneous <Nprocessors=1>] : Nsimultaneous");
59 addParamsLine(
" [--refVol <refVolFile=NULL>] : reference volume to be reprojected when comparing with previous alignment");
60 addParamsLine(
" [--useForValidation] : Use the program for validation");
61 addParamsLine(
" [--thr <threads=4>] : How many threads to use");
74 inputReference_volume =
getParam(
"--refVol");
75 useForValidation=
checkParam(
"--useForValidation");
77 threadPool.
resize(threads);
78 transformersForImages.resize(threads);
79 ccMatrixBestCandidTransformers.resize(threads);
80 ccMatrixShifts.resize(threads);
86 printf(
"%d reference images of %d x %d\n",
int(sizeMdRef),
int(Xdim),
int(Ydim));
87 printf(
"%d exp images of %d x %d in this group\n",
int(sizeMdIn),
int(Xdim),
int(Ydim));
88 std::cout <<
"Sampling: " << sampling << std::endl;
89 std::cout <<
"Angular step: " << angStep << std::endl;
90 std::cout <<
"Maximum shift: " << maxShift << std::endl;
91 std::cout <<
"threads: " << threads << std::endl;
93 std::cout <<
"ref vol size: " << refXdim <<
" x "<< refYdim <<
" x "<< refZdim << std::endl;
94 std::cout <<
"useForValidation : " << useForValidation << std::endl;
97 std::cout <<
"Input references: " << fnRef << std::endl;
104 void ProgAngularAssignmentMag::computingNeighborGraph() {
105 std::vector< std::vector<int> > allNeighborsjp;
106 std::vector< std::vector<double> > allWeightsjp;
110 double maxSphericalDistance = angStep*2.;
111 std::cout<<
"processing neighbors graph..."<<std::endl;
113 for (
auto &rowj : mdRef){
122 std::vector<int> neighborsjp;
123 std::vector<double> weightsjp;
124 double thisSphericalDistance = 0.;
126 for (
auto &rowjp : mdRef){
136 if (thisSphericalDistance < maxSphericalDistance) {
137 neighborsjp.emplace_back(jp);
138 double val = exp(-thisSphericalDistance / maxSphericalDistance);
139 weightsjp.emplace_back(val);
143 allNeighborsjp.emplace_back(neighborsjp);
144 allWeightsjp.emplace_back(weightsjp);
149 computeLaplacianMatrix(L_mat, allNeighborsjp, allWeightsjp);
159 eigenvalues.
write(fnEigenVal);
161 eigenvectors.
write(fnEigenVect);
166 void ProgAngularAssignmentMag::computeLaplacianMatrix (
Matrix2D<double> &matL,
167 const std::vector< std::vector<int> > &allNeighborsjp,
168 const std::vector< std::vector<double> > &allWeightsjp)
const {
172 for(
int i=0;
i<sizeMdRef; ++
i){
173 std::vector<int> neighborsjp = allNeighborsjp[
i];
174 std::vector<double> weightsjp = allWeightsjp[
i];
175 double sumWeight = 0.;
178 for(
auto it=neighborsjp.begin(); it!=neighborsjp.end(); ++it){
182 sumWeight += weightsjp[
j];
190 long pages = sysconf(_SC_PHYS_PAGES);
191 long page_size = sysconf(_SC_PAGE_SIZE);
192 return pages * page_size;
195 void ProgAngularAssignmentMag::checkStorageSpace() {
197 referenceRot.resize(sizeMdRef);
198 referenceTilt.resize(sizeMdRef);
200 std::cout <<
"processing reference library..." << std::endl;
202 size_t dataSize = Xdim * Ydim * sizeMdRef *
sizeof(double);
203 size_t matrixSize = sizeMdRef * sizeMdRef *
sizeof(double);
204 size_t polarFourierSize = n_bands * n_ang2 * sizeMdRef
205 *
sizeof(std::complex<double>);
207 size_t totMemory = dataSize + matrixSize + polarFourierSize;
209 std::cout <<
"approx. memory to allocate: " << totMemory <<
" MB" 211 std::cout <<
"simultaneous MPI processes: " <<
Nprocessors << std::endl;
215 std::cout <<
"total available system memory: " << available <<
" MB" 219 if (available < totMemory) {
221 "You don't have enough memory. Try to use less MPI processes.");
226 void ProgAngularAssignmentMag::processGallery(
FileName &fnImgRef) {
240 for (
auto &rowj : mdRef) {
243 ImgRef.
read(fnImgRef);
253 referenceRot.at(j) = rot;
254 referenceTilt.at(j) = tilt;
256 vecMDaRef.push_back(MDaRef);
261 completeFourierShift(MDaRefFM, MDaRefFMs);
262 MDaRefFMs_polarPart = imToPolar(MDaRefFMs, startBand, finalBand);
263 transformerPolarImage.
FourierTransform(MDaRefFMs_polarPart, MDaRefFMs_polarF,
true);
264 vecMDaRefFMs_polarF.push_back(MDaRefFMs_polarF);
269 void ProgAngularAssignmentMag::computeEigenvectors() {
273 in.open(fnEigenVect.c_str());
278 computingNeighborGraph();
285 eigenvectors.
clear();
287 eigenvectors.
read(fnEigenVect);
301 n_rad = size_t((
double)Xdim / 2.);
302 startBand = size_t((sampling * (
double) Xdim) / 80.);
303 finalBand = size_t((sampling * (
double) Xdim) / (sampling * 3));
304 n_bands = finalBand - startBand;
308 maxShift = .10 * (double)Xdim;
313 sizeMdRef = (int)mdRef.
size();
316 sizeMdIn = (int)mdIn.
size();
322 processGallery(fnImgRef);
324 computeEigenvectors();
329 for (
int sym = 0; sym < SL.
symsNo(); sym++) {
339 if(useForValidation){
342 refVol.
read(inputReference_volume);
344 refVol().setXmippOrigin();
345 refXdim = (int)
XSIZE(refVol());
346 refYdim = (int)
YSIZE(refVol());
347 refZdim = (int)
ZSIZE(refVol());
357 std::vector<double> filt_iGFT_cc(sizeMdRef, 0);
360 ccGFT = eigenvectorTrans*ccVecIn;
363 int cutEig = (sizeMdRef>1000) ?
int(.05 * sizeMdRef + 1) : int(.50 * sizeMdRef + 1);
364 for(
int k = cutEig;
k < sizeMdRef; ++
k){
368 ccVecOut = eigenvectors*ccGFT;
391 completeFourierShift(MDaInFM, MDaInFMs);
392 MDaInFMs_polarPart = imToPolar(MDaInFMs, startBand, finalBand);
393 transformerPolarImage.
FourierTransform(MDaInFMs_polarPart, MDaInFMs_polarF,
true);
402 std::vector<unsigned int> Idx(sizeMdRef, 0);
407 std::vector<double> bestTx(sizeMdRef, 0);
408 std::vector<double> bestTy(sizeMdRef, 0);
409 std::vector<double> bestPsi(sizeMdRef, 0);
415 for (
int k = 0;
k < sizeMdRef; ++
k) {
417 ccMatrix(MDaInFMs_polarF, vecMDaRefFMs_polarF[
k], ccMatrixRot, ccMatrixProcessImageTransformer);
418 maxByColumn(ccMatrixRot, ccVectorRot);
420 std::vector<double> cand(maxAccepted, 0.);
421 psiCandidates(ccVectorRot, cand,
XSIZE(ccMatrixRot));
422 bestCand(MDaIn, MDaInF, vecMDaRef[k], cand, psi, Tx, Ty, cc_coeff);
432 std::vector<double> bestTx2(sizeMdRef, 0.);
433 std::vector<double> bestTy2(sizeMdRef, 0.);
434 std::vector<double> bestPsi2(sizeMdRef, 0.);
442 double minval, maxval;
446 thres = maxval - (maxval - minval) / 3.;
448 thres = maxval - (maxval - minval) / 2.;
451 for(
int k = 0;
k < sizeMdRef; ++
k) {
455 mCurrentImageAligned = MDaInAux;
457 corr =
alignImages(vecMDaRef[
k], mCurrentImageAligned, M, xmipp_transformation::DONT_WRAP);
461 if (maxShift>0 && (fabs(Tx)>maxShift || fabs(Ty)>maxShift))
471 bestTx2[
k] = bestTx[
k];
472 bestTy2[
k] = bestTy[
k];
473 bestPsi2[
k] = bestPsi[
k];
479 graphFourierFilter(ccvec,ccvec_filt);
485 int idxfilt = ccvec_filt.
maxIndex();
490 double sphericalDistance= angDistance(idx, idxfilt, dirj, dirjp);
493 double rotRef = referenceRot.at(idx);
494 double tiltRef = referenceTilt.at(idx);
495 double shiftX = bestTx2[idx];
496 double shiftY = bestTy2[idx];
497 double anglePsi = bestPsi2[idx];
514 validateAssignment(idx, idxfilt, rotRef, tiltRef, rowIn, rowOut, MDaIn, dirjp);
517 double ProgAngularAssignmentMag::angDistance(
int &idx,
int &idxfilt,
519 double rotj = referenceRot.at(idx);
520 double tiltj = referenceTilt.at(idx);
523 double rotjp = referenceRot.at(idxfilt);
524 double tiltjp = referenceTilt.at(idxfilt);
530 for (
size_t sym = 0; sym < SL.
symsNo(); sym++) {
531 double auxRot, auxTilt, auxPsi;
532 double auxSphericalDist;
537 if (auxSphericalDist < sphericalDistance)
538 sphericalDistance = auxSphericalDist;
540 return sphericalDistance;
543 void ProgAngularAssignmentMag::validateAssignment(
int &idx,
int &idxfilt,
double &rotRef,
544 double &tiltRef,
const MDRow &rowIn,
MDRow &rowOut,
546 if (!useForValidation) {
549 double graphCorr =
alignImages(vecMDaRef[idx], vecMDaRef[idxfilt], M2,
550 xmipp_transformation::DONT_WRAP);
556 double initPsiAngle = 0.;
557 projectVolume(refVol(), P2, refYdim, refXdim, rotRef, tiltRef,
560 projectedReference2 = P2();
562 double filtRotRef = referenceRot.at(idxfilt);
563 double filtTiltRef = referenceTilt.at(idxfilt);
565 projectVolume(refVol(), P3, refYdim, refXdim, filtRotRef, filtTiltRef,
568 projectedReference3 = P3();
572 double graphCorr =
alignImages(projectedReference2, projectedReference3,
573 M2, xmipp_transformation::DONT_WRAP);
577 double old_rot, old_tilt, old_psi, old_shiftX, old_shiftY;
586 projectVolume(refVol(), P, refYdim, refXdim, old_rot, old_tilt,
589 projectedReference = P();
594 projectedReference2 = P2();
595 double refCorr =
alignImages(projectedReference, projectedReference2, M,
596 xmipp_transformation::DONT_WRAP);
599 projectedReference = P();
600 projectedReference3 = P3();
601 graphCorr =
alignImages(projectedReference, projectedReference3, M,
602 xmipp_transformation::DONT_WRAP);
609 circularWindow(mdainShifted);
622 for (
size_t sym = 0; sym < SL.
symsNo(); sym++) {
624 double auxRot2, auxTilt2, auxPsi2;
625 double auxSphericalDist2;
627 auxRot2, auxTilt2, auxPsi2);
631 if (auxSphericalDist2 < algorithmSD)
632 algorithmSD = auxSphericalDist2;
650 for (
size_t objId : ptrMdOut.
ids())
654 if (thisMaxCC > maxCC)
656 if (thisMaxCC == 0.0)
660 for (
size_t objId : ptrMdOut.
ids())
676 size_t thisNbands = end - start;
678 auto pi = (double)3.141592653;
680 double cy = (double)(Ydim + (Ydim % 2)) / 2.0;
681 double cx = (double)(Xdim + (Xdim % 2)) / 2.0;
684 double sfy = (double)(Ydim - 1) / 2.0;
685 double sfx = (double)(Xdim - 1) / 2.0;
687 auto delR = 1.0 / ((double)n_rad);
688 double delT = 2.0 *
pi / ((double)n_ang2);
695 for (
size_t ri = start; ri < end; ++ri) {
696 for (
size_t ti = 0; ti < n_ang2; ++ti) {
697 r = (double)ri * delR;
698 t = (double)ti * delT;
699 x_coord = (r * cos(t)) * sfx + cx;
700 y_coord = (r * sin(t)) * sfy + cy;
702 DIRECT_A2D_ELEM(polarImg,ri-start,ti) = interpolate(cartIm,x_coord,y_coord);
710 double &x_coord,
double &y_coord)
const{
712 auto xf = (size_t)
floor((
double)x_coord);
713 auto xc = (size_t)ceil((
double)x_coord);
714 auto yf = (size_t)
floor((
double)y_coord);
715 auto yc = (size_t)ceil((
double)y_coord);
717 if ((xf ==
xc) && (yf ==
yc)) {
719 }
else if (xf ==
xc) {
720 val =
dAij(cartIm, xf, yf)
721 + (y_coord - (double) yf)
722 * (
dAij(cartIm, xf,
yc) -
dAij(cartIm, xf, yf));
723 }
else if (yf ==
yc) {
724 val =
dAij(cartIm, xf, yf)
725 + (x_coord - (double) xf)
726 * (
dAij(cartIm,
xc, yf) -
dAij(cartIm, xf, yf));
728 val = ((double) ((
dAij(cartIm,xf,yf) * ((double)
yc - y_coord)
729 +
dAij(cartIm,xf,
yc) * (y_coord - (double) yf))
730 * ((
double)
xc - x_coord))
731 + (double) ((
dAij(cartIm,
xc,yf) * ((double)
yc - y_coord)
732 +
dAij(cartIm,
xc,
yc) * (y_coord - (double) yf))
733 * (x_coord - (
double) xf)))
734 / (
double) ((
xc - xf) * (
yc - yf));
747 auto Cf = (size_t) ((
double)
YSIZE(in) / 2.0 + 0.5);
748 auto Cc = (size_t) ((
double)
XSIZE(in) / 2.0 + 0.5);
752 for (
size_t f = 0;
f <
YSIZE(in);
f++) {
753 ff = (
f + Cf) %
YSIZE(in);
754 for (
size_t c = 0;
c <
XSIZE(in);
c++) {
755 cc = (
c + Cc) %
XSIZE(in);
764 void ProgAngularAssignmentMag::ccMatrix(
const MultidimArray<std::complex<double>> &F1,
784 a = (*ptrFFT1)* dSize;
785 b = (*(ptrFFT1 + 1))* dSize;
787 d = (*ptrFFT2++) * (-1);
788 *ptrFFT1++ = (a * c - b *
d);
789 *ptrFFT1++ = (b * c + a *
d);
803 for (
int c = 0;
c <
XSIZE(in);
c++) {
804 maxVal =
dAij(in, 0,
c);
805 for (
int f = 1;
f <
YSIZE(in);
f++) {
820 for (
int f = 0;
f <
YSIZE(in);
f++) {
821 maxVal =
dAij(in,
f, 0);
822 for (
int c = 1;
c <
XSIZE(in);
c++) {
834 double InterpIdx = idx - ( (
dAi(in,idx+1) -
dAi(in, idx - 1))
835 / (
dAi(in,idx+1) +
dAi(in, idx - 1) - 2 *
dAi(in, idx)) )
841 void ProgAngularAssignmentMag::computeCircular() {
843 auto Cf = (double)(Ydim + (Ydim % 2)) / 2.0;
844 auto Cc = (double)(Xdim + (Xdim % 2)) / 2.0;
846 double rad2 = (Cf - pixReduc) * (Cf - pixReduc);
853 val = ((double)
j - Cf) * ((double)
j - Cf) + ((double)
i - Cc) * ((double)
i - Cc);
870 std::vector<double> &cand,
const size_t &size) {
871 double max1 = -1000.;
873 double max2 = -1000.;
878 for (
int i = 89;
i < 272; ++
i) {
880 if ((
dAi(in,
size_t(
i)) >
dAi(in,
size_t(
i - 1)))
881 && (
dAi(in,
size_t(
i)) >
dAi(in,
size_t(
i + 1)))) {
882 if (
dAi(in,
i) > max1) {
888 }
else if (
dAi(in,
i) > max2 &&
dAi(in,
i) != max1) {
897 std::vector<int> temp;
900 temp.resize(maxAccepted);
904 temp.resize(maxAccepted);
908 int tam = 2 * maxAccepted;
911 for (
int i = 0;
i < maxAccepted; ++
i) {
913 cand[
i] = double(size) / 2. - interpIdx;
914 cand[i + maxAccepted] = (cand[
i] >= 0.0) ? cand[
i] + 180. : cand[
i] - 180.;
925 void ProgAngularAssignmentMag::bestCand(
930 double &
psi,
double &shift_x,
double &shift_y,
double &bestCoeff) {
937 auto workload = [&](
int id,
int i) {
938 auto rotVar = -1. * cand[
i];
943 transformersForImages[id].FourierTransform(MDaRefRot, MDaRefRotF,
true);
944 auto &ccMatrixShift = ccMatrixShifts.at(
id);
945 ccMatrix(MDaInF, MDaRefRotF, ccMatrixShift, ccMatrixBestCandidTransformers.at(
id));
948 maxByColumn(ccMatrixShift, ccVectorTx);
950 getShift(ccVectorTx, tx,
XSIZE(ccMatrixShift));
952 maxByRow(ccMatrixShift, ccVectorTy);
954 getShift(ccVectorTy, ty,
YSIZE(ccMatrixShift));
969 circularWindow(MDaInShiftRot);
972 std::lock_guard lock(mutex);
973 if (tempCoeff > bestCoeff) {
974 bestCoeff = tempCoeff;
982 auto futures = std::vector<std::future<void>>();
983 for (
size_t i = 0;
i < peaksFound; ++
i) {
984 futures.emplace_back(threadPool.
push(workload,
i));
987 for (
auto &
f : futures) {
999 double cosine = cos(ang);
1000 double sine = sin(ang);
1017 double &shift,
const size_t &size)
const {
1018 double maxVal = -10.;
1020 auto lb = (int)((
double)size / 2. - maxShift);
1021 auto hb = (int)((
double)size / 2. + maxShift);
1022 for (
int i = lb;
i < hb; ++
i) {
1023 if ((
dAi(ccVector,
size_t(
i)) >
dAi(ccVector,
size_t(
i - 1)))
1024 && (
dAi(ccVector,
size_t(
i)) >
dAi(ccVector,
size_t(
i + 1))) &&
1025 (
dAi(ccVector,
i) > maxVal)) {
1026 maxVal =
dAi(ccVector,
i);
1035 shift = double(size) / 2. - interpIdx;
1037 shift = maxShift+1.;
1049 double cosine = cos(ang);
1050 double sine = sin(ang);
1053 double realTx = cosine * tx + sine * ty;
1054 double realTy = -sine * tx + cosine * ty;
double spherical_distance(const Matrix1D< double > &r1, const Matrix1D< double > &r2)
double getDoubleParam(const char *param, int arg=0)
__host__ __device__ float2 floor(const float2 v)
void getMatrices(int i, Matrix2D< double > &L, Matrix2D< double > &R, bool homogeneous=true) const
double alignImages(const MultidimArray< double > &Iref, const AlignmentTransforms &IrefTransforms, MultidimArray< double > &I, Matrix2D< double > &M, bool wrap, AlignmentAux &aux, CorrelationAux &aux2, RotationalCorrelationAux &aux3)
#define REPORT_ERROR(nerr, ErrormMsg)
void computeMinMax(T &minval, T &maxval) const
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(m)
void Euler_direction(double alpha, double beta, double gamma, Matrix1D< double > &v)
void resizeNoCopy(const MultidimArray< T1 > &v)
auto push(F &&f, Rest &&... rest) -> std::future< decltype(f(0, rest...))>
unsigned long long getTotalSystemMemory()
int readSymmetryFile(FileName fn_sym, double accuracy=SYM_ACCURACY)
There is not enough memory for allocation.
#define DIRECT_A2D_ELEM(v, i, j)
double correlationIndex(const MultidimArray< T > &x, const MultidimArray< T > &y, const MultidimArray< int > *mask=NULL, MultidimArray< double > *Contributions=NULL)
void preProcess() override
#define MULTIDIM_ARRAY(v)
void inv(Matrix2D< T > &result) const
void abs(Image< double > &op)
Matrix2D< T > transpose() const
void resize(int nThreads)
void Euler_apply_transf(const Matrix2D< double > &L, const Matrix2D< double > &R, double rot, double tilt, double psi, double &newrot, double &newtilt, double &newpsi)
void write(const FileName &fn) const
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
void resizeNoCopy(int Ydim, int Xdim)
double quadInterp(int idx, const MultidimArray< double > &in)
#define MAT_ELEM(m, i, j)
void CenterFFT(MultidimArray< T > &v, bool forward)
T & getValue(MDLabel label)
void applyShiftAndRotation(const MultidimArray< double > &MDaRef, double &rot, double &tx, double &ty, MultidimArray< double > &MDaRefRot) const
const char * getParam(const char *param, int arg=0)
void postProcess() override
virtual void synchronize()
Synchronize with other processors.
void readParams() override
ProgAngularAssignmentMag()
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
void generalizedEigs(const Matrix2D< double > &A, const Matrix2D< double > &B, Matrix1D< double > &D, Matrix2D< double > &P)
void projectVolume(FourierProjector &projector, Projection &P, int Ydim, int Xdim, double rot, double tilt, double psi, const MultidimArray< double > *ctf)
int verbose
Verbosity level.
void defineParams() override
void show() const override
void setValue(MDLabel label, const T &d, bool addLabel=true)
void processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut) override
void read(const FileName &fn)
double psi(const double x)
void write(const FileName &fn) const
String formatString(const char *format,...)
#define realWRAP(x, x0, xF)
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)
~ProgAngularAssignmentMag()
void addUsageLine(const char *line, bool verbatim=false)
void initZeros(const MultidimArray< T1 > &op)
int getIntParam(const char *param, int arg=0)
void FFT_magnitude(const MultidimArray< std::complex< double > > &v, MultidimArray< double > &mag)
void resize(size_t Ydim, size_t Xdim, bool noCopy=false)
void applyRotation(const MultidimArray< double > &, double &, MultidimArray< double > &) const
void addParamsLine(const String &line)