36 addUsageLine(
"This algorithm estimates the existence of angular alignment errors by measuring a set of directional FSC.");
37 addUsageLine(
"To do that, the method only makes use of two half maps, but it does not use the set of particles.");
38 addUsageLine(
"The result is a plot resolution-radius. When this plot presents a slope the map has angular assignment error.");
39 addUsageLine(
"In contrast, if the curve is flat, the map is error free or there is shift errors in the particle alignment.");
40 addUsageLine(
"Reference: J.L. Vilas, et. al, XXXXX (2023)");
41 addUsageLine(
"+ The optimal con angle is 17 degree.",
true);
42 addUsageLine(
" This fact was proved in J.L Vilas & H.D. Tagare Nat. Meth 2023. Other values can be used,");
43 addUsageLine(
" and this parameter does not seems to affect in a significative manner");
45 addUsageLine(
" If the map is a helix, the helix option should be activated. This option ensures a better estimation of the angular");
46 addUsageLine(
" assignment errors. The helix is assumen that is oriented along the z-axis. This flag modifies the shape of the ");
54 addParamsLine(
" [--directional_resolution] : (Optional) Uses direcitonal FSC instead of global FSC shell ");
55 addParamsLine(
" [--limit_radius] : (Optional) Limits the maximum radius ");
57 addParamsLine(
" [-o <output_folder=\"\">] : Folder where the results will be stored.");
59 addParamsLine(
" [--sampling <Ts=1>] : (Optical) Pixel size (Angstrom). If it is not provided by default will be 1 A/px.");
60 addParamsLine(
" [--mask <input_file=\"\">] : (Optional) Smooth mask to remove noise. If it is not provided, the computation will be carried out without mask.");
62 addParamsLine(
" [--anglecone <ang_con=17>] : (Optional) Angle Cone (angle between the axis and the generatrix) for estimating the directional FSC");
63 addParamsLine(
" [--threshold <thrs=0.143>] : (Optional) Threshold for the FSC/directionalFSC estimation ");
64 addParamsLine(
" [--helix] : (Optional) If the reconstruction is a helix put this flag. The axis of the helix must be along the z-axis");
65 addParamsLine(
" [--threads <Nthreads=1>] : (Optional) Number of threads to be used");
67 addExampleLine(
"Resolution of two half maps half1.mrc and half2.mrc with a sampling rate of 2 A/px",
false);
68 addExampleLine(
"xmipp_angular_resolution_alignment --half1 half1.mrc --half2 half2.mrc --sampling 2 ");
69 addExampleLine(
"Resolution of two half maps half1.mrc and half2.mrc with a sampling rate of 2 A/px and a mask mask.mrc",
false);
70 addExampleLine(
"xmipp_angular_resolution_alignment --half1 half1.mrc --half2 half2.mrc --mask mask.mrc --sampling 2 ");
81 directionalRes =
checkParam(
"--directional_resolution");
93 xvoldim =
XSIZE(inputVol);
94 yvoldim =
YSIZE(inputVol);
95 zvoldim =
ZSIZE(inputVol);
98 size_t xdimFourier =
XSIZE(inputVol)/2 + 1;
99 size_t zdimFourier = zvoldim;
100 size_t ydimFourier = yvoldim;
113 for(
size_t k=1;
k<zdimFourier; ++
k){
119 for(
size_t k=1;
k<ydimFourier; ++
k){
125 for(
size_t k=1;
k<xdimFourier; ++
k){
132 freqMap.
initZeros(1, zdimFourier, ydimFourier, xdimFourier);
137 double uz, uy, ux, uz2, uz2y2;
144 for(
size_t k=0;
k<zdimFourier; ++
k)
148 for(
size_t i=0;
i<ydimFourier; ++
i)
153 for(
size_t j=0;
j<xdimFourier; ++
j)
156 ux =
sqrt(uz2y2 + ux*ux);
161 idx = (int)
round(ux * xvoldim);
167 if ((
j == 0) && (uy<0))
174 if ((
i == 0) && (
j == 0) && (uz<0))
191 void ProgAngResAlign::arrangeFSC_and_fscGlobal()
211 absz1_vec = real_z1z2;
212 absz2_vec = real_z1z2;
231 auto ZdimFT1=(int)
ZSIZE(FT1);
232 auto YdimFT1=(int)
YSIZE(FT1);
233 auto XdimFT1=(int)
XSIZE(FT1);
244 for (
int k=0;
k<ZdimFT1;
k++)
247 for (
int i=0;
i<YdimFT1;
i++)
250 for (
int j=0;
j<XdimFT1;
j++)
266 auto idx = (int)
round(f * xvoldim);
280 std::complex<double> &z1 =
dAkij(FT1,
k,
i,
j);
281 std::complex<double> &z2 =
dAkij(FT2,
k,
i,
j);
283 double absz1 =
abs(z1);
284 double absz2 =
abs(z2);
296 void ProgAngResAlign::fscGlobal(
double &
threshold,
double &resol)
304 auto ZdimFT1=(int)
ZSIZE(FT1);
305 auto YdimFT1=(int)
YSIZE(FT1);
306 auto XdimFT1=(int)
XSIZE(FT1);
309 for (
int k=0;
k<ZdimFT1;
k++)
311 for (
int i=0;
i<YdimFT1;
i++)
313 for (
int j=0;
j<XdimFT1;
j++)
327 auto idx = (int)
round(f * xvoldim);
330 std::complex<double> &z1 =
dAkij(FT1,
k,
i,
j);
331 std::complex<double> &z2 =
dAkij(FT2,
k,
i,
j);
333 double absz1 =
abs(z1);
334 double absz2 =
abs(z2);
356 double ff = (double)
i / (xvoldim * sampling);
370 auto ff =
dAi(frc,
i);
371 if ( (ff<=thrs) && (
i>2) )
373 double y2, y1, x2, x1, slope, ny;
378 slope = (y2 - y1)/(x2 - x1);
381 double fscResolution;
382 fscResolution = (thrs - ny)/slope;
383 std::cout <<
"Resolution " << 1/fscResolution << std::endl;
392 double &thrs,
double &resol)
409 float x_dir, y_dir, z_dir, cosAngle, aux;
410 x_dir = sinf(tilt)*cosf(rot);
411 y_dir = sinf(tilt)*sinf(rot);
414 cosAngle = (float) cos(ang_con);
420 aux = (4.0/((cosAngle -1)*(cosAngle -1)));
431 float cosine = fabs(x_dir*ux + y_dir*uy + z_dir*uz);
434 if (cosine >= cosAngle)
438 cosine = expf( -((cosine -1)*(cosine -1))*aux);
460 if (flagRes && (
i>2) && (
dAi(fsc,
i)<=thrs))
463 double ff = (float)
i / (xvoldim * sampling);
470 void ProgAngResAlign::generateDirections(
Matrix2D<float> &angles,
bool alot)
810 MAT_ELEM(angles, 0, 10) = 108.000000f;
MAT_ELEM(angles, 1, 10) = 47.576224f;
811 MAT_ELEM(angles, 0, 11) = 108.000000f;
MAT_ELEM(angles, 1, 11) = 63.434965f;
812 MAT_ELEM(angles, 0, 12) = 134.494295f;
MAT_ELEM(angles, 1, 12) = -76.558393f;
813 MAT_ELEM(angles, 0, 13) = 126.000000f;
MAT_ELEM(angles, 1, 13) = 90.000000f;
814 MAT_ELEM(angles, 0, 14) = 117.505705f;
MAT_ELEM(angles, 1, 14) = 76.558393f;
815 MAT_ELEM(angles, 0, 15) = 144.000000f;
MAT_ELEM(angles, 1, 15) = -15.858741f;
816 MAT_ELEM(angles, 0, 16) = 144.000000f;
MAT_ELEM(angles, 1, 16) = -31.717482f;
817 MAT_ELEM(angles, 0, 17) = 144.000000f;
MAT_ELEM(angles, 1, 17) = -47.576224f;
818 MAT_ELEM(angles, 0, 18) = 144.000000f;
MAT_ELEM(angles, 1, 18) = -63.434965f;
819 MAT_ELEM(angles, 0, 19) = 170.494295f;
MAT_ELEM(angles, 1, 19) = 76.558393f;
820 MAT_ELEM(angles, 0, 20) = 162.000000f;
MAT_ELEM(angles, 1, 20) = 90.000000f;
821 MAT_ELEM(angles, 0, 21) = 153.505705f;
MAT_ELEM(angles, 1, 21) = -76.558393f;
822 MAT_ELEM(angles, 0, 22) = 72.000000f;
MAT_ELEM(angles, 1, 22) = -15.858741f;
823 MAT_ELEM(angles, 0, 23) = 72.000000f;
MAT_ELEM(angles, 1, 23) = -31.717482f;
824 MAT_ELEM(angles, 0, 24) = 72.000000f;
MAT_ELEM(angles, 1, 24) = -47.576224f;
825 MAT_ELEM(angles, 0, 25) = 72.000000f;
MAT_ELEM(angles, 1, 25) = -63.434965f;
828 MAT_ELEM(angles, 0, 28) = 81.505705f;
MAT_ELEM(angles, 1, 28) = -76.558393f;
849 MAT_ELEM(angles, 0, 49) = 144.000000f;
MAT_ELEM(angles, 1, 49) = 26.565058f;
850 MAT_ELEM(angles, 0, 50) = 131.188979f;
MAT_ELEM(angles, 1, 50) = 42.234673f;
851 MAT_ELEM(angles, 0, 51) = 156.811021f;
MAT_ELEM(angles, 1, 51) = 42.234673f;
852 MAT_ELEM(angles, 0, 52) = 125.533003f;
MAT_ELEM(angles, 1, 52) = 59.620797f;
853 MAT_ELEM(angles, 0, 53) = 144.000000f;
MAT_ELEM(angles, 1, 53) = 58.282544f;
854 MAT_ELEM(angles, 0, 54) = 162.466996f;
MAT_ELEM(angles, 1, 54) = 59.620797f;
855 MAT_ELEM(angles, 0, 55) = 144.000000f;
MAT_ELEM(angles, 1, 55) = 90.000000f;
856 MAT_ELEM(angles, 0, 56) = 135.132791f;
MAT_ELEM(angles, 1, 56) = 75.219088f;
857 MAT_ELEM(angles, 0, 57) = 152.867209f;
MAT_ELEM(angles, 1, 57) = 75.219088f;
858 MAT_ELEM(angles, 0, 58) = 180.000000f;
MAT_ELEM(angles, 1, 58) = -26.565058f;
859 MAT_ELEM(angles, 0, 59) = 167.188979f;
MAT_ELEM(angles, 1, 59) = -42.234673f;
860 MAT_ELEM(angles, 0, 60) = 180.000000f;
MAT_ELEM(angles, 1, 60) = -58.282544f;
861 MAT_ELEM(angles, 0, 61) = 161.533003f;
MAT_ELEM(angles, 1, 61) = -59.620797f;
862 MAT_ELEM(angles, 0, 62) = 171.132791f;
MAT_ELEM(angles, 1, 62) = -75.219088f;
863 MAT_ELEM(angles, 0, 63) = 108.000000f;
MAT_ELEM(angles, 1, 63) = -26.565058f;
864 MAT_ELEM(angles, 0, 64) = 120.811021f;
MAT_ELEM(angles, 1, 64) = -42.234673f;
865 MAT_ELEM(angles, 0, 65) = 95.188979f;
MAT_ELEM(angles, 1, 65) = -42.234673f;
866 MAT_ELEM(angles, 0, 66) = 126.466996f;
MAT_ELEM(angles, 1, 66) = -59.620797f;
867 MAT_ELEM(angles, 0, 67) = 108.000000f;
MAT_ELEM(angles, 1, 67) = -58.282544f;
868 MAT_ELEM(angles, 0, 68) = 89.533003f;
MAT_ELEM(angles, 1, 68) = -59.620797f;
869 MAT_ELEM(angles, 0, 69) = 108.000000f;
MAT_ELEM(angles, 1, 69) = 90.000000f;
870 MAT_ELEM(angles, 0, 70) = 116.867209f;
MAT_ELEM(angles, 1, 70) = -75.219088f;
871 MAT_ELEM(angles, 0, 71) = 99.132791f;
MAT_ELEM(angles, 1, 71) = -75.219088f;
872 MAT_ELEM(angles, 0, 72) = 36.000000f;
MAT_ELEM(angles, 1, 72) = -26.565058f;
873 MAT_ELEM(angles, 0, 73) = 48.811021f;
MAT_ELEM(angles, 1, 73) = -42.234673f;
874 MAT_ELEM(angles, 0, 74) = 23.188979f;
MAT_ELEM(angles, 1, 74) = -42.234673f;
875 MAT_ELEM(angles, 0, 75) = 54.466996f;
MAT_ELEM(angles, 1, 75) = -59.620797f;
876 MAT_ELEM(angles, 0, 76) = 36.000000f;
MAT_ELEM(angles, 1, 76) = -58.282544f;
877 MAT_ELEM(angles, 0, 77) = 17.533003f;
MAT_ELEM(angles, 1, 77) = -59.620797f;
879 MAT_ELEM(angles, 0, 79) = 44.867209f;
MAT_ELEM(angles, 1, 79) = -75.219088f;
880 MAT_ELEM(angles, 0, 80) = 27.132791f;
MAT_ELEM(angles, 1, 80) = -75.219088f;
889 std::cout <<
"Reading data..." << std::endl;
891 imgHalf1.
read(fnhalf1);
892 imgHalf2.
read(fnhalf2);
897 maxRadius =
XSIZE(half1)*0.5;
903 auto mapMask = inMask();
906 size_t xdim =
XSIZE(mapMask)*0.5;
907 size_t ydim =
YSIZE(mapMask)*0.5;
908 size_t zdim =
ZSIZE(mapMask)*0.5;
913 Nelems =
round(
sqrt(xdim*xdim + ydim*ydim)+1);
917 Nelems =
round(
sqrt(xdim*xdim + ydim*ydim + zdim*zdim)+1);
929 for(
size_t k=0;
k<
ZSIZE(mapMask); ++
k)
931 for(
size_t i=0;
i<
YSIZE(mapMask); ++
i)
933 size_t yy = (
i-ydim);
936 for(
size_t j=0;
j<
XSIZE(mapMask); ++
j)
938 size_t xx = (
j-xdim);
941 auto idx = (int)
round(rad);
942 dAi(radiusTheoretical, idx) += 1;
947 dAi(radiusElems, idx) += 1;
958 for(
size_t k=0;
k<
ZSIZE(mapMask); ++
k)
960 size_t zz = (
k-zdim);
963 for(
size_t i=0;
i<
YSIZE(mapMask); ++
i)
965 size_t yy = (
i-ydim);
968 for(
size_t j=0;
j<
XSIZE(mapMask); ++
j)
970 size_t xx = (
j-xdim);
973 auto idx = (int)
round(rad);
974 dAi(radiusTheoretical, idx) += 1;
979 dAi(radiusElems, idx) += 1;
992 double radiusThreshold;
994 radiusThreshold = 0.75;
999 if (
dAi(radiusElems,
k) > radiusThreshold *
dAi(radiusTheoretical,
k))
1003 std::cout <<
"maxRadius = -> " << maxRadius << std::endl;
1018 void ProgAngResAlign::generateShellMask(
MultidimArray<double> &shellMask,
size_t shellNum,
bool ishelix)
1020 double sigma2 = 5*5;
1022 inv2sigma2 = 1/(2*sigma2);
1028 radius = radius - shellNum;
1029 A3D_ELEM(shellMask,
k,
i, j) = exp(-(radius*radius)*inv2sigma2);
1036 radius = radius - shellNum;
1037 A3D_ELEM(shellMask,
k,
i, j) = exp(-(radius*radius)*inv2sigma2);
1070 std::cout <<
"Starting ... " << std::endl << std::endl;
1076 readData(phalf1, phalf2);
1080 defineFrequenciesSimple(phalf1);
1088 generateDirections(angles,
false);
1089 ang_con = ang_con*
PI/180.0;
1100 for (
size_t shellRadius = 0; shellRadius<maxRadius; shellRadius++)
1104 generateShellMask(shellMask, shellRadius, isHelix);
1112 applyShellMask(half1, half2, shellMask, half1_aux, half2_aux);
1120 transformer2.FourierTransform(half2_aux, FT2,
false);
1125 arrangeFSC_and_fscGlobal();
1131 std::vector<double> radialResolution(angles.
mdimx);
1133 for (
size_t k = 0;
k<angles.
mdimx;
k++)
1138 double resInterp = -1;
1142 fscDir_fast(fsc, rot, tilt, thrs, resInterp);
1144 radialResolution[
k] = resInterp;
1147 std::sort(radialResolution.begin(),radialResolution.end());
1149 res = radialResolution[
round(0.5*angles.
mdimx)];
1150 radialResolution.clear();
1154 fscGlobal(thrs, res);
1157 std::cout <<
"Radius "<< shellRadius <<
"/" << maxRadius <<
" " << res <<
"A" << std::endl;
void min(Image< double > &op1, const Image< double > &op2)
alglib::complex conj(const alglib::complex &z)
double getDoubleParam(const char *param, int arg=0)
void resizeNoCopy(const MultidimArray< T1 > &v)
void sqrt(Image< double > &op)
void setValue(const MDObject &object) override
void abs(Image< double > &op)
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 addSeeAlsoLine(const char *seeAlso)
#define MAT_ELEM(m, i, j)
void CenterFFT(MultidimArray< T > &v, bool forward)
void threshold(double *phi, unsigned long nvox, double limit)
#define A3D_ELEM(V, k, i, j)
#define FOR_ALL_ELEMENTS_IN_ARRAY3D(V)
const char * getParam(const char *param, int arg=0)
void max(Image< double > &op1, const Image< double > &op2)
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
#define dAkij(V, k, i, j)
#define DIRECT_MULTIDIM_ELEM(v, n)
void addExampleLine(const char *example, bool verbatim=true)
void sort(struct DCEL_T *dcel)
__device__ float FFT_IDX2DIGFREQ(int idx, int size)
#define FOR_ALL_ELEMENTS_IN_ARRAY1D(v)
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)
void addUsageLine(const char *line, bool verbatim=false)
void initZeros(const MultidimArray< T1 > &op)
int getIntParam(const char *param, int arg=0)
void addParamsLine(const String &line)