Xmipp  v3.23.11-Nereus
Classes | Functions | Variables
project_xr (project for tilt series)
Collaboration diagram for project_xr (project for tilt series):

Classes

struct  XrayThreadArgument
 Data struct to be passed to threads. More...
 
class  XrayProjPhantom
 
class  ProgXrayProject
 
struct  CIGTArgument
 
struct  PXSGTArgument
 

Functions

void XrayRotateAndProjectVolumeOffCentered (XrayProjPhantom &side, XRayPSF &psf, Projection &P, Projection &standardP, int Ydim, int Xdim)
 
void projectXrayVolume (MultidimArray< double > &muVol, MultidimArray< double > &IgeoVol, XRayPSF &psf, Projection &P, MultidimArray< double > *projNorm=nullptr, ThreadManager *ThrMgr=nullptr)
 
void threadXrayProject (ThreadArgument &thArg)
 Thread Job to generate an X-ray microscope projection. More...
 
void calculateIgeo (MultidimArray< double > &muVol, double sampling, MultidimArray< double > &IgeoVol, MultidimArray< double > &cumMu, MultidimArray< double > &IgeoZb, int nThreads=1, ThreadManager *ThrMgr=nullptr)
 Calculate the volume of the information of Igeometric at each plane of the phantom. More...
 
void calculateIgeoThread (ThreadArgument &thArg)
 
void projectXrayGridVolume (MultidimArray< double > &muVol, XRayPSF &psf, MultidimArray< double > &IgeoVol, Projection &proj, MultidimArray< double > *projNorm, int FORW, ThreadManager *thMgr)
 Project as in an X-ray microscope using a grids and blobs. More...
 
void projectXraySimpleGrid (MultidimArray< double > *vol, const XRayPSF &psf, MultidimArray< double > *IgeoVol, Projection *proj, MultidimArray< double > &projNorm, int FORW, int threadId=-1, int nThreads=1)
 
void projectXraySimpleGridThread (ThreadArgument &thArg)
 

Variables

Mutex mutex
 
Barrierbarrier
 
ThreadManagerthMgr
 

Detailed Description

Function Documentation

◆ calculateIgeo()

void calculateIgeo ( MultidimArray< double > &  muVol,
double  sampling,
MultidimArray< double > &  IgeoVol,
MultidimArray< double > &  cumMu,
MultidimArray< double > &  IgeoZb,
int  nThreads = 1,
ThreadManager ThrMgr = nullptr 
)

Calculate the volume of the information of Igeometric at each plane of the phantom.

Definition at line 616 of file project_xray.cpp.

619 {
620  // Checking sizes
621  if ( (XSIZE(muVol) != XSIZE(IgeoZb)) || (YSIZE(muVol) != YSIZE(IgeoZb)) )
622  REPORT_ERROR(ERR_MULTIDIM_SIZE, "CalculateIgeo: IgeoZb size does not match muVol size.");
623 
624  IgeoVol.initZeros(muVol);
625  cumMu.initZeros(YSIZE(muVol), XSIZE(muVol));
626 
627  ThreadManager * myThMgr;
628 
629  if (ThrMgr == nullptr)
630  myThMgr = new ThreadManager(nThreads);
631  else
632  myThMgr = ThrMgr;
633 
634  CIGTArgument iGeoArgs;
635  iGeoArgs.samplingZ = sampling;
636  iGeoArgs.muVol = &muVol;
637  iGeoArgs.IgeoVol = &IgeoVol;
638  iGeoArgs.cumMu = &cumMu;
639  iGeoArgs.IgeoZb = & IgeoZb;
640  iGeoArgs.td = new ThreadTaskDistributor(YSIZE(muVol),YSIZE(muVol)/nThreads/2);
641 
642  myThMgr->run(calculateIgeoThread,&iGeoArgs);
643 
644  delete iGeoArgs.td;
645 
646  if (ThrMgr == nullptr)
647  delete myThMgr;
648 }
void run(ThreadFunction function, void *data=NULL)
#define YSIZE(v)
double samplingZ
Definition: project_xray.h:158
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
Incorrect MultidimArray size.
Definition: xmipp_error.h:174
ParallelTaskDistributor * td
Intensity in the beginning of the volume to project.
Definition: project_xray.h:163
#define sampling
#define XSIZE(v)
MultidimArray< double > * muVol
Definition: project_xray.h:159
void calculateIgeoThread(ThreadArgument &thArg)
MultidimArray< double > * IgeoVol
Accumulated Mu == Standard EM projection used as reference for reconstruction.
Definition: project_xray.h:161
MultidimArray< double > * IgeoZb
Igeo accumulated along Z axis.
Definition: project_xray.h:162
MultidimArray< double > * cumMu
Phantom volume.
Definition: project_xray.h:160
void initZeros(const MultidimArray< T1 > &op)

◆ calculateIgeoThread()

void calculateIgeoThread ( ThreadArgument thArg)

Definition at line 650 of file project_xray.cpp.

651 {
652  auto *dataThread = (CIGTArgument*) thArg.data;
653 
654  double sampling = dataThread->samplingZ;
655  MultidimArray<double> &muVol = *(dataThread->muVol);
656  MultidimArray<double> &IgeoVol = *(dataThread->IgeoVol);
657  MultidimArray<double> &cumMu = *(dataThread->cumMu);
658  MultidimArray<double> &IgeoZb = *(dataThread->IgeoZb);
659  ParallelTaskDistributor * td = dataThread->td;
660 
661  // Resizing
662  // IgeoVol.resize(muVol, false);
663 
664  size_t first, last;
665  while (td->getTasks(first, last))
666  {
667  // first--;
668  // last--;
669  for (size_t i = first; i <= last; ++i)
670  {
671  // for (int j=0; j<XSIZE(muVol); ++j)
672  // dAkij(IgeoVol,0,i,j) = dAij(IgeoZb,i,j)*exp(-dAkij(muVol,0,i,j)*sampling);
673  //
674  // for (int k = 1; k < ZSIZE(muVol); ++k)
675  // for (int j=0; j<XSIZE(muVol); ++j)
676  // dAkij(IgeoVol,k,i,j) = dAkij(IgeoVol,k-1,i,j)*exp(-dAkij(muVol,k,i,j)*sampling);
677 
678  for (size_t k = 0; k < ZSIZE(muVol); ++k)
679  for (size_t j=0; j<XSIZE(muVol); ++j)
680  {
681  dAij(cumMu,i,j) += dAkij(muVol,k,i,j)*sampling;
682  dAkij(IgeoVol,k,i,j) = dAij(IgeoZb,i,j)*exp(-dAij(cumMu,i,j));
683  }
684  }
685  }
686 }
#define dAij(M, i, j)
bool getTasks(size_t &first, size_t &last)
#define i
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
glob_log first
#define sampling
#define XSIZE(v)
#define dAkij(V, k, i, j)
#define ZSIZE(v)
#define j

◆ projectXrayGridVolume()

void projectXrayGridVolume ( MultidimArray< double > &  muVol,
XRayPSF psf,
MultidimArray< double > &  IgeoVol,
Projection proj,
MultidimArray< double > *  projNorm,
int  FORW,
ThreadManager thMgr 
)

Project as in an X-ray microscope using a grids and blobs.

Parameters
projVol with the Igeometrical distribution along specimen volume

Definition at line 688 of file project_xray.cpp.

699 {
700  XrayThreadArgument projThrData;
701  Barrier barrier(thMgr->threads);
702 
703  projThrData.psf = &psf;
704  projThrData.muVol = &muVol;
705  projThrData.IgeoVol = &IgeoVol;
706  projThrData.projOut = &proj;
707  projThrData.projNorm = projNorm;
708  projThrData.forw = FORW;
709  projThrData.phantomSlabIdx = nullptr;
710  projThrData.psfSlicesIdx = nullptr;
711 
712  // //Create the job handler to distribute thread jobs
713  // size_t blockSize, numberOfJobs = psfSlicesIdx.size() ;
714  // blockSize = 1;
715  // ThreadTaskDistributor td(numberOfJobs, blockSize);
716  // projThrData.td = &td;
717  // projThrData.barrier = &barrier;
718 
719  //the really really final project routine, I swear by Snoopy.
720  // project_xr(psf,side.rotPhantomVol,P, idxSlice);
721 
722  thMgr->run(projectXraySimpleGridThread,(void*) &projThrData);
723 
724 }
void run(ThreadFunction function, void *data=NULL)
void projectXraySimpleGridThread(ThreadArgument &thArg)
Data struct to be passed to threads.
Definition: project_xray.h:41
MultidimArray< double > * IgeoVol
Definition: project_xray.h:45
int threads
number of working threads.
MultidimArray< double > * projNorm
Definition: project_xray.h:48
std::vector< int > * phantomSlabIdx
Definition: project_xray.h:50
std::vector< int > * psfSlicesIdx
Definition: project_xray.h:51
Barrier * barrier
double psf
Projection * projOut
Definition: project_xray.h:47
MultidimArray< double > * muVol
Definition: project_xray.h:44

◆ projectXraySimpleGrid()

void projectXraySimpleGrid ( MultidimArray< double > *  vol,
const XRayPSF psf,
MultidimArray< double > *  IgeoVol,
Projection proj,
MultidimArray< double > &  projNorm,
int  FORW,
int  threadId = -1,
int  nThreads = 1 
)

ARTK Equation mode

Definition at line 747 of file project_xray.cpp.

751 {
752 
753  MultidimArray<double> psfVol;
754  psfVol.alias(psf.psfVol());
755 
756 
757  Matrix1D<double> zero(3); // Origin (0,0,0)
758  Matrix1D<double> prjPix(3); // Position of the pixel within the projection
759  Matrix1D<double> prjX(3); // Coordinate: Projection of the
760  Matrix1D<double> prjY(3); // 3 grid vectors
761  Matrix1D<double> prjZ(3);
762  Matrix1D<double> prjOrigin(3); // Coordinate: Where in the 2D
763  // projection plane the origin of
764  // the grid projects
765  Matrix1D<double> prjDir(3); // Projection direction
766 
767  Matrix1D<double> actprj(3); // Coord: Actual position inside
768  // the projection plane
769  Matrix1D<double> beginZ(3); // Coord: Plane coordinates of the
770  // projection of the 3D point
771  // (z0,YY(lowest),XX(lowest))
772  Matrix1D<double> univ_beginY(3); // Coord: coordinates of the
773  // grid point
774  // (z0,y0,XX(lowest))
775  Matrix1D<double> univ_beginZ(3); // Coord: coordinates of the
776  // grid point
777  // (z0,YY(lowest),XX(lowest))
778  Matrix1D<double> beginY(3); // Coord: Plane coordinates of the
779  // projection of the 3D point
780  // (z0,y0,XX(lowest))
781  double XX_footprint_size; // The footprint is supposed
782  double YY_footprint_size; // to be defined between
783  // (-vmax,+vmax) in the Y axis,
784  // and (-umax,+umax) in the X axis
785  // This footprint size is the
786  // R2 vector (umax,vmax).
787 
788  int XX_corner2, XX_corner1; // Coord: Corners of the
789  int YY_corner2, YY_corner1; // footprint when it is projected
790  // onto the projection plane
791  // directions respectively
792  // inside the blobprint
793  double vol_corr=0.; // Correction for a volume element
794  int N_eq; // Number of equations in which
795  // a blob is involved
796  int i, j, k; // volume element indexes
797 
798  // Project grid axis ....................................................
799  // These vectors ((1,0,0),(0,1,0),...) are referred to the grid
800  // coord. system and the result is a 2D vector in the image plane
801  // The unit size within the image plane is 1, ie, the same as for
802  // the universal grid.
803  // actprj is reused with a different purpose
804  // VECTOR_R3(actprj, 1, 0, 0);
805  // Uproject_to_plane(actprj, proj->euler, prjX);
806  // VECTOR_R3(actprj, 0, 1, 0);
807  // Uproject_to_plane(actprj, proj->euler, prjY);
808  // VECTOR_R3(actprj, 0, 0, 1);
809  // Uproject_to_plane(actprj, proj->euler, prjZ);
810  proj->euler.getCol(0, prjX);
811  proj->euler.getCol(1, prjY);
812  proj->euler.getCol(2, prjZ);
813 
814  // This time the origin of the grid is in the universal coord system
815  // Uproject_to_plane(grid->origin, proj->euler, prjOrigin);
816  prjOrigin.initZeros();
817 
818  // Get the projection direction .........................................
819  proj->euler.getRow(2, prjDir);
820 
821  // Footprint size .......................................................
822  // The following vectors are integer valued vectors, but they are
823  // stored as real ones to make easier operations with other vectors
824  XX_footprint_size = FINISHINGX(psfVol) + XMIPP_EQUAL_ACCURACY;
825  YY_footprint_size = FINISHINGY(psfVol) + XMIPP_EQUAL_ACCURACY;
826 
827  // Project the whole grid ...............................................
828  // Corner of the plane defined by Z. These coordinates try to be within
829  // the valid indexes of the projection (defined between STARTING and
830  // FINISHING values, but it could be that they may lie outside.
831  // These coordinates need not to be integer, in general, they are
832  // real vectors.
833  // The vectors returned by the projection routines are R3 but we
834  // are only interested in their first 2 components, ie, in the
835  // in-plane components
836 
837  // This type conversion gives more speed
838 
839  int ZZ_lowest = STARTINGZ(*vol);
840  if( threadId != -1 )
841  ZZ_lowest += threadId;
842  int YY_lowest = STARTINGY(*vol);
843  int XX_lowest = STARTINGX(*vol);
844  int ZZ_highest = FINISHINGZ(*vol);
845  int YY_highest = FINISHINGY(*vol);
846  int XX_highest = FINISHINGX(*vol);
847 
848  beginZ = (double)XX_lowest * prjX + (double)YY_lowest * prjY + (double)ZZ_lowest * prjZ + prjOrigin;
849 
850 
851 #ifdef DEBUG_LITTLE
852 
853  int condition;
854  condition = threadId==1;
855  if (condition || numthreads==1)
856  {
857  std::cout << "Equation mode " << eq_mode << std::endl;
858  std::cout << "Footprint size " << YY_footprint_size << "x"
859  << XX_footprint_size << std::endl;
860  std::cout << "rot=" << proj->rot() << " tilt=" << proj->tilt()
861  << " psi=" << proj->psi() << std::endl;
862  std::cout << "Euler matrix " << proj->euler;
863  std::cout << "Projection direction " << prjDir << std::endl;
864  std::cout << *grid;
865  std::cout << "image limits (" << x0 << "," << y0 << ") (" << xF << ","
866  << yF << ")\n";
867  std::cout << "prjX " << prjX.transpose() << std::endl;
868  std::cout << "prjY " << prjY.transpose() << std::endl;
869  std::cout << "prjZ " << prjZ.transpose() << std::endl;
870  std::cout << "prjOrigin " << prjOrigin.transpose() << std::endl;
871  std::cout << "beginZ(coord) " << beginZ.transpose() << std::endl;
872  std::cout << "lowest " << XX_lowest << " " << YY_lowest
873  << " " << XX_lowest << std::endl;
874  std::cout << "highest " << XX_highest << " " << YY_highest
875  << " " << XX_highest << std::endl;
876  std::cout << "Stats of input basis volume ";
877  (*vol)().printStats();
878  std::cout << std::endl;
879  std::cout.flush();
880  }
881 #endif
882 
883  for (k = ZZ_lowest; k <= ZZ_highest; k += numthreads)
884  {
885  // Corner of the row defined by Y
886  beginY = beginZ;
887  for (i = YY_lowest; i <= YY_highest; i++)
888  {
889  // First point in the row
890  actprj = beginY;
891  for (j = XX_lowest; j <= XX_highest; j++)
892  {
893  // Ray length interesting
894  bool ray_length_interesting = true;
895 
896  // // Points out of 3DPSF
897  // ray_length_interesting = (ABS(zCenterDist) <= ZZ_footprint_size);
898  // // There is still missing the shift of the volume from focal plane
899 
900  if (ray_length_interesting)
901  {
902  // Be careful that you cannot skip any basis, although its
903  // value be 0, because it is useful for norm_proj
904 #ifdef DEBUG
905  condition = threadId == 1;
906  if (condition)
907  {
908  printf("\nProjecting grid coord (%d,%d,%d) ", j, i, k);
909  std::cout << "Vol there = " << A3D_ELEM(*vol, k, i, j) << std::endl;
910  printf(" 3D universal position (%f,%f,%f) \n",
911  XX(univ_position), YY(univ_position), ZZ(univ_position));
912  std::cout << " Center of the basis proj (2D) " << XX(actprj) << "," << YY(actprj) << std::endl;
913  Matrix1D<double> aux;
914  Uproject_to_plane(univ_position, proj->euler, aux);
915  std::cout << " Center of the basis proj (more accurate) " << aux.transpose() << std::endl;
916  }
917 #endif
918 
919  // Search for integer corners for this basis
920  XX_corner1 = CEIL(XMIPP_MAX(STARTINGX(IMGMATRIX(*proj)), XX(actprj) - XX_footprint_size));
921  YY_corner1 = CEIL(XMIPP_MAX(STARTINGY(IMGMATRIX(*proj)), YY(actprj) - YY_footprint_size));
922  XX_corner2 = FLOOR(XMIPP_MIN(FINISHINGX(IMGMATRIX(*proj)), XX(actprj) + XX_footprint_size));
923  YY_corner2 = FLOOR(XMIPP_MIN(FINISHINGY(IMGMATRIX(*proj)), YY(actprj) + YY_footprint_size));
924 
925 #ifdef DEBUG
926 
927  if (condition)
928  {
929  std::cout << "Clipped and rounded Corner 1 " << XX_corner1
930  << " " << YY_corner1 << " " << std::endl;
931  std::cout << "Clipped and rounded Corner 2 " << XX_corner2
932  << " " << YY_corner2 << " " << std::endl;
933  }
934 #endif
935 
936  // Check if the voxel falls outside the projection plane
937  // COSS: I have changed here
938  if (XX_corner1 <= XX_corner2 && YY_corner1 <= YY_corner2
939  && INSIDEZ(*IgeoVol,ZZ(actprj)))
940  {
941 
942  double IgeoValue = A3D_ELEM(*IgeoVol, (int)ZZ(actprj), (int)YY(actprj), (int)XX(actprj));
943 
944  if (!FORW)
945  vol_corr = 0;
946 
947  N_eq = 0;
948  for (int y = YY_corner1; y <= YY_corner2; y++)
949  {
950  for (int x = XX_corner1; x <= XX_corner2; x++)
951  {
952  // if (!((mask != NULL) && A2D_ELEM(*mask,y,x)<0.5))
953  {
954 #ifdef DEBUG
955  if (condition)
956  {
957  std::cout << "Position in projection (" << x << ","
958  << y << ") ";
959  double y, x;
960  if (basis->type == Basis::blobs)
961  {
962  std::cout << "in footprint ("
963  << foot_U << "," << foot_V << ")";
964  IMG2OVER(basis->blobprint, foot_V, foot_U, y, x);
965  std::cout << " (d= " << sqrt(y*y + x*x) << ") ";
966  fflush(stdout);
967  }
968  }
969 #endif
970 
971  double a, a2;
972 
973  a = A3D_ELEM(psfVol, (int)ZZ(actprj), y, x) * IgeoValue;
974  a2 = a * a;
975 
976 #ifdef DEBUG
977 
978  if (condition)
979  std::cout << "=" << a << " , " << a2;
980 #endif
981 
982  if (FORW)
983  {
985  IMGPIXEL(*proj, y, x) += A3D_ELEM(*vol, k, i, j) * a;
986  A2D_ELEM(projNorm , y, x) += a2;
987 
988 #ifdef DEBUG
989 
990  if (condition)
991  {
992  std::cout << " proj= " << IMGPIXEL(*proj, y, x)
993  << " norm_proj=" << A2D_ELEM(projNorm , y, x) << std::endl;
994  std::cout.flush();
995  }
996 #endif
997 
998  }
999  else
1000  {
1001  vol_corr += A2D_ELEM(projNorm , y, x) * a;
1002  if (a != 0)
1003  N_eq++;
1004 #ifdef DEBUG
1005 
1006  if (condition)
1007  {
1008  std::cout << " corr_img= " << A2D_ELEM(projNorm , y, x)
1009  << " correction=" << vol_corr << std::endl;
1010  std::cout.flush();
1011  }
1012 #endif
1013 
1014  }
1015  }// close possible mask constraint
1016  }
1017  } // Project this basis
1018 
1019  if (!FORW)
1020  {
1021  A3D_ELEM(*vol, k, i, j) += vol_corr;
1022 
1023 #ifdef DEBUG
1024 
1025  if (condition)
1026  {
1027  printf("\nFinal value at (%d,%d,%d) ", j, i, k);
1028  std::cout << " = " << A3D_ELEM(*vol, k, i, j) << std::endl;
1029  std::cout.flush();
1030  }
1031 #endif
1032 
1033  }
1034  } // If not collapsed
1035  // number_of_basis++;
1036  } // If interesting
1037 
1038  // Prepare for next iteration
1039  V3_PLUS_V3(actprj, actprj, prjX);
1040  }
1041  V3_PLUS_V3(beginY, beginY, prjY);
1042  }
1043  V3_PLUS_V3(beginZ, beginZ, prjZ * numthreads );
1044  }
1045 }
#define A2D_ELEM(v, i, j)
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
#define FINISHINGX(v)
double psi(const size_t n=0) const
void sqrt(Image< double > &op)
static double * y
Matrix2D< double > euler
Image< double > psfVol
3D PSF read from file
Definition: psf_xr.h:123
double rot(const size_t n=0) const
#define FINISHINGZ(v)
#define IMGMATRIX(I)
#define STARTINGX(v)
doublereal * x
#define i
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
Matrix1D< T > transpose() const
Definition: matrix1d.cpp:644
double tilt(const size_t n=0) const
#define STARTINGY(v)
#define A3D_ELEM(V, k, i, j)
#define FLOOR(x)
Definition: xmipp_macros.h:240
#define y0
#define x0
#define XX(v)
Definition: matrix1d.h:85
#define CEIL(x)
Definition: xmipp_macros.h:225
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
#define IMG2OVER(IO, iv, iu, v, u)
void alias(const MultidimArray< T > &m)
#define xF
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
#define j
#define YY(v)
Definition: matrix1d.h:93
void getCol(size_t j, Matrix1D< T > &v) const
Definition: matrix2d.cpp:890
#define FINISHINGY(v)
void getRow(size_t i, Matrix1D< T > &v) const
Definition: matrix2d.cpp:871
void Uproject_to_plane(const Matrix1D< double > &point, const Matrix1D< double > &direction, double distance, Matrix1D< double > &result)
Definition: geometry.cpp:39
#define yF
#define STARTINGZ(v)
#define ZZ(v)
Definition: matrix1d.h:101
doublereal * a
ql0001_ & zero(ctemp+1),(cvec+1),(a+1),(b+1),(bl+1),(bu+1),(x+1),(w+1), &iout, ifail, &zero,(w+3), &lwar2,(iw+1), &leniw, &glob_grd.epsmac
#define V3_PLUS_V3(a, b, c)
Definition: matrix1d.h:190
#define IMGPIXEL(I, i, j)
#define INSIDEZ(v, z)

◆ projectXraySimpleGridThread()

void projectXraySimpleGridThread ( ThreadArgument thArg)

Definition at line 726 of file project_xray.cpp.

727 {
728 
729  int threadId = thArg.thread_id;
730 
731  auto *dataThread = (XrayThreadArgument*) thArg.data;
732  const XRayPSF &psf = *(dataThread->psf);
733  MultidimArray<double> *muVol = (dataThread->muVol);
734  MultidimArray<double> *IgeoVol = (dataThread->IgeoVol);
735  Projection *proj = (dataThread->projOut);
736  MultidimArray<double> &projNorm = *(dataThread->projNorm);
737  int forw = dataThread->forw;
738 
739  projectXraySimpleGrid(muVol, psf, IgeoVol, proj, projNorm , forw,
740  threadId, thArg.threads);
741 
742 
743 
744 
745 }
Data struct to be passed to threads.
Definition: project_xray.h:41
double psf
void projectXraySimpleGrid(MultidimArray< double > *vol, const XRayPSF &psf, MultidimArray< double > *IgeoVol, Projection *proj, MultidimArray< double > &projNorm, int FORW, int threadId, int numthreads)
int threads
Number of threads.
int thread_id
The thread id.

◆ projectXrayVolume()

void projectXrayVolume ( MultidimArray< double > &  muVol,
MultidimArray< double > &  IgeoVol,
XRayPSF psf,
Projection P,
MultidimArray< double > *  projNorm = nullptr,
ThreadManager ThrMgr = nullptr 
)

Definition at line 334 of file project_xray.cpp.

337 {
338 
339  /* Now we have to split the phantom rotated volume into slabs, taking into
340  * account the possible different resolution and Z size.
341  *
342  * PhantomSlabIdx are the indexes of rotVol defining the slabs according to
343  * the splitting done to PSFVol.
344  *
345  * psfSlicesIdx are the indexes of the z planes of rotVol whose psf are
346  * used for the slabs.
347  */
348  std::vector<int> phantomSlabIdx, psfSlicesIdx;
349 
350  // Search for the PSFslab of the beginning of the volume
351  auto firstSlab = (int)(STARTINGZ(muVol)*psf.dzo/psf.dzoPSF);
352 
353  if (!XMIPP_EQUAL_ZERO(psf.slabThr))
354  {
355  for (size_t kk = 0; kk < psf.slabIndex.size(); ++kk)
356  {
357  if (firstSlab < psf.slabIndex[kk])
358  {
359  firstSlab = kk-1;
360  break;
361  }
362  }
363 
364  // Searching the equivalent index in rotvol for the indexes for the Slabs of PSFVol
365  phantomSlabIdx.push_back(STARTINGZ(muVol));
366 
367  for (size_t kk = firstSlab+1; kk < psf.slabIndex.size(); ++kk)
368  {
369  auto tempK = (int)(psf.slabIndex[kk] * psf.dzoPSF / psf.dzo);
370 
371  if (tempK <= FINISHINGZ(muVol))
372  {
373  phantomSlabIdx.push_back(tempK);
374  int tempKK = psf.slabIndex[kk-1];
375  auto psfMeanSlice = (int)((tempK + tempKK)*0.5 * psf.dzoPSF / psf.dzo);
376  psfSlicesIdx.push_back(psfMeanSlice);
377  }
378  else
379  {
380  phantomSlabIdx.push_back(FINISHINGZ(muVol));
381  int psfMeanSlice = (tempK + phantomSlabIdx[kk-1])/2;
382  psfSlicesIdx.push_back(psfMeanSlice);
383  continue;
384  }
385  }
386  }
387  else
388  {
389  for (int k = STARTINGZ(muVol); k <= FINISHINGZ(muVol); ++k)
390  {
391  phantomSlabIdx.push_back(k);
392  psfSlicesIdx.push_back(k);
393  }
394  // To define the last range
395  phantomSlabIdx.push_back(FINISHINGZ(muVol)+1);
396  }
397 
398  XrayThreadArgument projThrData;
400 
401  projThrData.psf = &psf;
402  projThrData.muVol = &muVol;
403  projThrData.IgeoVol = &IgeoVol;
404  projThrData.projOut = &P;
405  projThrData.projNorm = projNorm;
406  projThrData.phantomSlabIdx = & phantomSlabIdx;
407  projThrData.psfSlicesIdx = & psfSlicesIdx;
408 
409  //Create the job handler to distribute thread jobs
410  size_t blockSize, numberOfJobs = psfSlicesIdx.size() ;
411  blockSize = 1;
412  ThreadTaskDistributor td(numberOfJobs, blockSize);
413  projThrData.td = &td;
414  projThrData.barrier = &barrier;
415 
416  //the really really final project routine, I swear by Snoopy.
417  // project_xr(psf,side.rotPhantomVol,P, idxSlice);
418 
419  thMgr->run(threadXrayProject,(void*) &projThrData);
420  // P.write("projection_after_threads.spi");
421 }
void run(ThreadFunction function, void *data=NULL)
void threadXrayProject(ThreadArgument &thArg)
Generate an X-ray microscope projection for volume vol using the microscope configuration psf...
Data struct to be passed to threads.
Definition: project_xray.h:41
ThreadManager * thMgr
MultidimArray< double > * IgeoVol
Definition: project_xray.h:45
int threads
number of working threads.
#define FINISHINGZ(v)
ParallelTaskDistributor * td
Definition: project_xray.h:52
MultidimArray< double > * projNorm
Definition: project_xray.h:48
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
std::vector< int > * phantomSlabIdx
Definition: project_xray.h:50
std::vector< int > * psfSlicesIdx
Definition: project_xray.h:51
Barrier * barrier
double psf
std::vector< int > slabIndex
Z positions in the original PSF Volume to determine de slabs.
Definition: psf_xr.h:131
Projection * projOut
Definition: project_xray.h:47
double slabThr
Threshold to separate The volume into slabs to use the same PSF.
Definition: psf_xr.h:129
#define XMIPP_EQUAL_ZERO(x)
Definition: xmipp_macros.h:123
MultidimArray< double > * muVol
Definition: project_xray.h:44
double dzo
object space Z sampling rate
Definition: psf_xr.h:201
double dzoPSF
object space Z sampling rate of the PSF Volume
Definition: psf_xr.h:209
#define STARTINGZ(v)

◆ threadXrayProject()

void threadXrayProject ( ThreadArgument thArg)

Thread Job to generate an X-ray microscope projection.

Thread Job to generate an X-ray microscope projection.

Calculate projNorm

Definition at line 440 of file project_xray.cpp.

441 {
442 
443  int thread_id = thArg.thread_id;
444 
445  auto *dataThread = (XrayThreadArgument*) thArg.data;
446  const XRayPSF &psf = *(dataThread->psf);
447  MultidimArray<double> &muVol = *(dataThread->muVol);
448  MultidimArray<double> &IgeoVol = *(dataThread->IgeoVol);
449  Image<double> &imOutGlobal = *(dataThread->projOut);
450  MultidimArray<double> * projNorm = dataThread->projNorm;
451  std::vector<int> &phantomSlabIdx = *(dataThread->phantomSlabIdx);
452  std::vector<int> &psfSlicesIdx = *(dataThread->psfSlicesIdx);
453  ParallelTaskDistributor * td = dataThread->td;
454  Barrier * barrier = dataThread->barrier;
455 
456  size_t first = 0, last = 0;
457 
458  if (thread_id == 0)
459  {
460  muVol.setXmippOrigin();
461  MULTIDIM_ARRAY(imOutGlobal).resizeNoCopy(psf.Niy, psf.Nix);
462  MULTIDIM_ARRAY(imOutGlobal).initZeros();
463  MULTIDIM_ARRAY(imOutGlobal).setXmippOrigin();
464  }
465 
466  barrier->wait();
467 
468  MultidimArray<double> imOut(psf.Niy, psf.Nix), projNormTemp(psf.Niy, psf.Nix);
469  imOut.setXmippOrigin();
470  projNormTemp.setXmippOrigin();
471 
472  MultidimArray<double> imTemp(psf.Noy, psf.Nox),intExp(psf.Noy, psf.Nox),imTempSc(imOut),*imTempP=nullptr;
473  intExp.setXmippOrigin();
474  imTemp.setXmippOrigin();
475  imTempSc.setXmippOrigin();
476 
477  // Parallel thread jobs
478  while (td->getTasks(first, last))
479  {
480  //#define DEBUG
481 #ifdef DEBUG
482  Image<double> _Im;
483 #endif
484 
485  int kini = phantomSlabIdx[first];
486  int kend = phantomSlabIdx[last + 1] - 1 ;
487 
488  // double deltaZSlab = psf.dzo*(kend-kini+1);
489 
490  intExp.initZeros();
491 
493  {
494  for (int k = kini; k <= kend; k++)
495  {
496  double tempValue = A3D_ELEM(muVol,k,i,j);
497  A2D_ELEM(intExp,i,j) += tempValue;
498  }
499  A2D_ELEM(imTemp,i,j) = A3D_ELEM(IgeoVol,kini,i,j)*(1 - exp( -A2D_ELEM(intExp,i,j) * psf.dzo));
500  }
501 #ifdef DEBUG
502  _Im().alias(intExp);
503  _Im.write("projectXR-intExp.spi");
504 
505  _Im().alias(imTemp);
506  _Im.write("projectXR-imTemp.spi");
507 #endif
508 
509  switch (psf.AdjustType)
510  {
511  case PSFXR_INT:
512  imTempP = &imTempSc;
513  scaleToSize(xmipp_transformation::LINEAR,*imTempP,imTemp,psf.Nix,psf.Niy);
514  break;
515 
516  case PSFXR_STD:
517  imTempP = &imTemp;
518  break;
519 
520  case PSFXR_ZPAD:
521  // (*imTempSc).resize(imTemp);
522  imTempP = &imTempSc;
523  imTemp.window(*imTempP,-ROUND(psf.Niy/2)+1,-ROUND(psf.Nix/2)+1,ROUND(psf.Niy/2)-1,ROUND(psf.Nix/2)-1);
524  break;
525  }
526 
527 #ifdef DEBUG
528  _Im().alias(*imTempP);
529  _Im.write("projectXR-imTempEsc_before.spi");
530 #endif
531 
532  psf.applyOTF(*imTempP, imOutGlobal.Zoff()- psfSlicesIdx[first]*psf.dzo);
533 
534 #ifdef DEBUG
535 
536  _Im.write("projectXR-imTempEsc_after.spi");
537 #endif
538 
539  // Adding to the thread temporal imOut
541  dAij(imOut,i,j) += dAij(*imTempP,i,j);
542 
543 #ifdef DEBUG
544 
545  _Im().alias(imOut);
546  _Im.write("projectXR-imout.spi");
547 #endif
548 
550 
551  if (projNorm != nullptr)
552  {
553 
555  A2D_ELEM(imTemp,i,j) = A3D_ELEM(IgeoVol,kini,i,j) * psf.dzo;
556 
557  // IgeoVol.getSlice(kini, imTemp);
558  psf.applyOTF(imTemp, imOutGlobal.Zoff()- psfSlicesIdx[first]*psf.dzo);
559 
561  dAij(projNormTemp,i,j) += dAij(imTemp,i,j)*dAij(imTemp,i,j);
562  }
563 
564 
565  }
566 
567  //Lock to update the total addition and multiply for the pixel width (to avoid multiply several times)
568  mutex.lock();
570  dAij(MULTIDIM_ARRAY(imOutGlobal),i,j) += dAij(imOut,i,j);
571 
572  if (projNorm != nullptr)
573  {
575  dAij(*projNorm,i,j) += dAij(projNormTemp,i,j);
576  }
577  mutex.unlock();
578 #ifdef DEBUG
579 
580  imOutGlobal.write("projectXR-imoutGlobal.spi");
581 #endif
582 
583  barrier->wait();
584 
585  if (thread_id==0)
586  {
587  // The output is the addition of the accumulated differences, the real projection is background illumination minus this
588  // MULTIDIM_ARRAY(imOutGlobal) = 1.0- MULTIDIM_ARRAY(imOutGlobal);
589 
590  switch (psf.AdjustType)
591  {
592  case PSFXR_STD:
593  // Do nothing;
594  break;
595  case PSFXR_INT:
596  selfScaleToSize(xmipp_transformation::LINEAR,imOutGlobal(), psf.Nox, psf.Noy);
597  break;
598  case PSFXR_ZPAD:
599  MULTIDIM_ARRAY(imOutGlobal).selfWindow(-ROUND(psf.Noy/2)+1,-ROUND(psf.Nox/2)+1,ROUND(psf.Noy/2)-1,ROUND(psf.Nox/2)-1);
600  break;
601  }
602 
603  MULTIDIM_ARRAY(imOutGlobal).setXmippOrigin();
604 
605 #ifdef DEBUG
606 
607  imOutGlobal.write("projectXR-imoutGlobal_negative.spi");
608 #endif
609 
610  }
611  // std::cerr << "th" << thread_id << ": Thread Finished" <<std::endl;
612 
613 #undef DEBUG
614 }
Mutex mutex
#define A2D_ELEM(v, i, j)
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(m)
Data struct to be passed to threads.
Definition: project_xray.h:41
double Zoff(const size_t n=0) const
#define dAij(M, i, j)
bool getTasks(size_t &first, size_t &last)
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)
#define MULTIDIM_ARRAY(v)
#define i
void selfScaleToSize(int SplineDegree, MultidimArrayGeneric &V1, int Xdim, int Ydim, int Zdim)
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
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
#define A3D_ELEM(V, k, i, j)
Standard mode, image size does not changes.
Definition: psf_xr.h:44
glob_log first
Barrier * barrier
double psf
void window(MultidimArray< T1 > &result, int n0, int z0, int y0, int x0, int nF, int zF, int yF, int xF, T1 init_value=0) const
void wait()
#define ROUND(x)
Definition: xmipp_macros.h:210
#define j
void scaleToSize(int SplineDegree, MultidimArrayGeneric &V2, const MultidimArrayGeneric &V1, int Xdim, int Ydim, int Zdim)
Increasing the image size by Interpolating.
Definition: psf_xr.h:45
int thread_id
The thread id.
virtual void unlock()
virtual void lock()

◆ XrayRotateAndProjectVolumeOffCentered()

void XrayRotateAndProjectVolumeOffCentered ( XrayProjPhantom side,
XRayPSF psf,
Projection P,
Projection standardP,
int  Ydim,
int  Xdim 
)

From voxel volumes, off-centered tilt axis. This routine projects a volume that is rotating (angle) degrees around the axis defined by the two angles (axisRot,axisTilt) and that passes through the point raxis. The projection can be further inplane rotated and shifted through the parameters (inplaneRot) and (rinplane).

All vectors involved must be 3D.

The projection model is rproj=H Rinplane Raxis r + Rinplane (I-Raxis) raxis + rinplane

Where Raxis is the 3D rotation matrix given by the axis and the angle.

Off-centered not implemented. Rotations are around volume center

Calculation of IgeoVol to optimize process

Definition at line 210 of file project_xray.cpp.

212 {
213 
214  int iniXdim, iniYdim, iniZdim, newXdim, newYdim, newZdim, rotXdim, rotZdim;
215 
216  iniXdim = XSIZE(MULTIDIM_ARRAY(phantom.iniVol));
217  iniYdim = YSIZE(MULTIDIM_ARRAY(phantom.iniVol));
218  iniZdim = ZSIZE(MULTIDIM_ARRAY(phantom.iniVol));
219 
220  // Projection offset in pixels
221  Matrix1D<double> offsetNV(3);
222  P.getShifts(XX(offsetNV), YY(offsetNV), ZZ(offsetNV));
223 
224  // xOffsetN = P.Xoff()/psf.dxo;
225  // yOffsetN = P.Yoff()/psf.dxo;
226 
227 
228  /* If Xdim is greater than Zdim, then as we rotate the volume the rotated Zdim must be
229  * great enough to cover all the volume.
230  */
231  /* By now, we are going to keep it unused */
232  // if (true)
233  // {
234  // double radi, theta0, theta, tilt;
235  //
236  // radi = sqrt(iniZdim*iniZdim + iniXdim*iniXdim);
237  // theta0 = atan2(iniZdim, iniXdim);
238  // tilt = ((P.tilt() < 90)? P.tilt(): 180 - P.tilt())* PI / 180;
239  //
240  // rotZdim = XMIPP_MAX(ROUND(radi * sin(ABS(tilt) + ABS(theta0))), iniZdim);
241  // rotXdim = XMIPP_MAX(ROUND(radi * cos(ABS(tilt) - ABS(theta0))), iniXdim);
242  // rotYdim = iniYdim;
243  //
244  // // rotZdim = iniZdim;
245  // // rotXdim = iniXdim;
246  //
247  // newXdim = rotXdim + 2*ABS(XX(offsetNV));
248  // newYdim = iniYdim + 2*ABS(YY(offsetNV));
249  // newZdim = rotZdim;
250  // }
251  // else
252  rotXdim = iniXdim;
253  rotZdim = iniZdim;
254 
255  newXdim = (int)(rotXdim + 2*fabs(XX(offsetNV)));
256  newYdim = (int)(iniYdim + 2*fabs(YY(offsetNV)));
257  newZdim = rotZdim;
258 
259  // We set the dimensions only to obtain the values of starting X,Y,Z
260  // phantom.rotVol.setDimensions(rotXdim, rotYdim, rotZdim, 1);
261  phantom.rotVol.setDimensions(newXdim, newYdim, newZdim, 1);
262  phantom.rotVol.setXmippOrigin();
263 
264  if (psf.verbose > 1)
265  {
266  if (newXdim != iniXdim || newYdim != iniYdim)
267  {
268  std::cout << std::endl;
269  std::cout << "--------------------------------" << std::endl;
270  std::cout << "XrayProject::Volume_offCentered:" << std::endl;
271  std::cout << "--------------------------------" << std::endl;
272  std::cout << "(X,Y,Z) shifts = (" << XX(offsetNV) << "," << YY(offsetNV) << ","
273  << ZZ(offsetNV) << ") um" << std::endl;
274  std::cout << "Image resize (Nx,Ny): (" << iniXdim << "," << iniYdim << ") --> ("
275  << newXdim << "," << newYdim << ") " << std::endl;
276  }
277 #ifdef DEBUG
278 
279  std::cout <<"yoffsetN "<< YY(offsetNV) <<std::endl;
280  std::cout <<"xoffsetN "<< XX(offsetNV) <<std::endl;
281  std::cout <<"yinit " << yinit <<std::endl;
282  std::cout <<"yend " << yend <<std::endl;
283  std::cout <<"xinit " << xinit <<std::endl;
284  std::cout <<"xend " << xend <<std::endl;
285  std::cout <<"zinit " << zinit <<std::endl;
286  std::cout <<"zend " << zend <<std::endl;
287 #endif
288 
289  }
290 
291 
292 
293  // phantom.rotVol.setMmap(true);
294  phantom.rotVol.resizeNoCopy(newZdim, newYdim, newXdim);
295  phantom.rotVol.setXmippOrigin();
296 
297  // Rotate volume ....................................................
298 
299  Matrix2D<double> R, T;
300 
301  ZZ(offsetNV) = 0; // We are not interested in apply this Zshift
302  translation3DMatrix(offsetNV, T);
303  Euler_angles2matrix(P.rot(), P.tilt(), P.psi(), R, true);
304 
305  double outside = 0; //phantom.iniVol.getPixel(0,0,0,0);
306  MULTIDIM_ARRAY(phantom.iniVol).setXmippOrigin();
307 
308  applyGeometry(xmipp_transformation::LINEAR, phantom.rotVol, MULTIDIM_ARRAY(phantom.iniVol), T*R, xmipp_transformation::IS_NOT_INV, xmipp_transformation::DONT_WRAP, outside);
309 
310  psf.adjustParam(phantom.rotVol);
311 
312 
314  MultidimArray<double> IgeoVol, IgeoZb;
315  IgeoZb.resize(1, 1, YSIZE(phantom.rotVol), XSIZE(phantom.rotVol),false);
316  IgeoZb.initConstant(1.);
317 
318  calculateIgeo(phantom.rotVol, psf.dzo, IgeoVol, MULTIDIM_ARRAY(standardP), IgeoZb, psf.nThr, thMgr);
319 
320 
321 
322  projectXrayVolume(phantom.rotVol, IgeoVol, psf, P, nullptr, thMgr);
323 
324  int outXDim = XMIPP_MIN(Xdim,iniXdim);
325  int outYDim = XMIPP_MIN(Ydim,iniYdim);
326 
327  P().selfWindow(-ROUND(outYDim/2),
328  -ROUND(outXDim/2),
329  -ROUND(outYDim/2) + outYDim -1,
330  -ROUND(outXDim/2) + outXDim -1);
331 
332 }//XrayRotateAndProjectVolumeOffCentered
#define YSIZE(v)
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
double psi(const size_t n=0) const
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
ThreadManager * thMgr
void applyGeometry(int SplineDegree, MultidimArray< std::complex< double > > &V2, const MultidimArray< std::complex< double > > &V1, const Matrix2D< double > &A, bool inv, bool wrap, std::complex< double > outside, MultidimArray< double > *BcoeffsPtr)
#define MULTIDIM_ARRAY(v)
void projectXrayVolume(MultidimArray< double > &muVol, MultidimArray< double > &IgeoVol, XRayPSF &psf, Projection &P, MultidimArray< double > *projNorm, ThreadManager *thMgr)
void initConstant(T val)
double rot(const size_t n=0) const
int nThr
Definition: psf_xr.h:215
double tilt(const size_t n=0) const
#define XX(v)
Definition: matrix1d.h:85
template void translation3DMatrix(const Matrix1D< float > &translation, Matrix2D< float > &resMatrix, bool inverse)
#define XSIZE(v)
#define ZSIZE(v)
#define ROUND(x)
Definition: xmipp_macros.h:210
int verbose
Switch to control verbose mode.
Definition: psf_xr.h:212
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
#define YY(v)
Definition: matrix1d.h:93
void adjustParam()
Calculate if a resize of the X-Y plane is needed to avoid the Nyquist Limit.
Definition: psf_xr.cpp:673
double dzo
object space Z sampling rate
Definition: psf_xr.h:201
void calculateIgeo(MultidimArray< double > &muVol, double sampling, MultidimArray< double > &IgeoVol, MultidimArray< double > &cumMu, MultidimArray< double > &IgeoZb, int nThreads, ThreadManager *ThrMgr)
Calculate the volume of the information of Igeometric at each plane of the phantom.
#define ZZ(v)
Definition: matrix1d.h:101
void getShifts(double &xoff, double &yoff, double &zoff, const size_t n=0) const

Variable Documentation

◆ barrier

Barrier* barrier

Definition at line 77 of file project_xray.cpp.

◆ mutex

Mutex mutex

Definition at line 76 of file project_xray.cpp.

◆ thMgr

ThreadManager* thMgr

Definition at line 78 of file project_xray.cpp.