Use OpenMP for scanner
authorKevin M. Rosenberg <kevin@rosenberg.net>
Wed, 21 Mar 2018 04:31:14 +0000 (22:31 -0600)
committerKevin M. Rosenberg <kevin@rosenberg.net>
Wed, 21 Mar 2018 04:31:14 +0000 (22:31 -0600)
include/ctsupport.h
libctsim/scanner.cpp
libctsupport/xform.cpp

index b509eee0d26798e200c64516b95fc60a06323be9..6d1c1dcf8a9a6ad0c9249655a868a73d65f8d78e 100644 (file)
@@ -257,6 +257,7 @@ void scale_mtx2 (GRFMTX_2D m, const double sx, const double sy);
 void rot_mtx2 (GRFMTX_2D m, const double theta);
 void mult_mtx2 (const GRFMTX_2D m1, const GRFMTX_2D m2, GRFMTX_2D result);
 void xform_mtx2 (const GRFMTX_2D m, double& x, double& y);
+void copy_mtx2 (GRFMTX_2D to, const GRFMTX_2D from);
 void rotate2d (double x[], double y[], int pts, double angle);
 void xlat2d (double x[], double y[], int pts, double xoffset, double yoffset);
 void scale2d (double x[], double y[], int pts, double xfact, double yfact);
index 89745061240059b7aa3aaeece7dad440afcad907..1567bd8b0f2b32d20577c0b270b78961111ab1e3 100644 (file)
@@ -292,6 +292,15 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int iS
   collectProjections (proj, phm, iStartView, iNumViews, iOffsetView, iStorageOffset, trace, pSGP);
 }
 
+static void mtx2_offset_rot (GRFMTX_2D m, double angle, double x, double y) {
+  GRFMTX_2D temp;
+  xlat_mtx2 (m, -x, -y);
+  rot_mtx2 (temp, angle);
+  mult_mtx2 (m, temp, m);
+  xlat_mtx2 (temp, x, y);
+  mult_mtx2 (m, temp, m);
+}
+
 void
 Scanner::collectProjections (Projections& proj, const Phantom& phm, const int iStartView,
                              const int iNumViews, const int iOffsetView, int iStorageOffset,
@@ -300,36 +309,48 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int iS
   m_trace = trace;
   double start_angle = (iStartView + iOffsetView) * proj.rotInc();
 
-  // Calculate initial rotation matrix
-  GRFMTX_2D rotmtx_initial, temp;
-  xlat_mtx2 (rotmtx_initial, -m_dXCenter, -m_dYCenter);
-  rot_mtx2 (temp, start_angle);
-  mult_mtx2 (rotmtx_initial, temp, rotmtx_initial);
-  xlat_mtx2 (temp, m_dXCenter, m_dYCenter);
-  mult_mtx2 (rotmtx_initial, temp, rotmtx_initial);
-
+#ifndef HAVE_OPENMP
+  // Without OpenMP, precalculate source and detector at view 0, then rotate incrementally each time
+  GRFMTX_2D rotmtx_initial;
+  mtx2_offset_rot (rotmtx_initial, start_angle, m_dXCenter, m_dYCenter);
   double xd1=0, yd1=0, xd2=0, yd2=0;
   if (m_idGeometry != GEOMETRY_EQUIANGULAR) {
-    xd1 = m_initPos.xd1;
-    yd1 = m_initPos.yd1;
-    xd2 = m_initPos.xd2;
-    yd2 = m_initPos.yd2;
+    xd1 = m_initPos.xd1; yd1 = m_initPos.yd1;
+    xd2 = m_initPos.xd2; yd2 = m_initPos.yd2;
     xform_mtx2 (rotmtx_initial, xd1, yd1);      // rotate detector endpoints
     xform_mtx2 (rotmtx_initial, xd2, yd2);      // to initial view_angle
   }
 
-  double xs1 = m_initPos.xs1;
-  double ys1 = m_initPos.ys1;
-  double xs2 = m_initPos.xs2;
-  double ys2 = m_initPos.ys2;
+  double xs1 = m_initPos.xs1, ys1 = m_initPos.ys1;
+  double xs2 = m_initPos.xs2, ys2 = m_initPos.ys2;
   xform_mtx2 (rotmtx_initial, xs1, ys1);      // rotate source endpoints to
   xform_mtx2 (rotmtx_initial, xs2, ys2);      // initial view angle
-
-  int iView;
-  double viewAngle;
-  for (iView = 0, viewAngle = start_angle;  iView < iNumViews; iView++, viewAngle += proj.rotInc()) {
+#else
+  #pragma omp parallel for
+#endif
+  
+  for (int iView = 0;  iView < iNumViews; iView++) {
+    double viewAngle = start_angle + (iView * proj.rotInc());
+    
+#ifdef HAVE_OPENMP
+    // With OpenMP, need to calculate source and detector positions at each view
+    GRFMTX_2D rotmtx;
+    mtx2_offset_rot (rotmtx, viewAngle, m_dXCenter, m_dYCenter);
+    double xd1=0, yd1=0, xd2=0, yd2=0;
+    if (m_idGeometry != GEOMETRY_EQUIANGULAR) {
+      xd1 = m_initPos.xd1; yd1 = m_initPos.yd1;
+      xd2 = m_initPos.xd2; yd2 = m_initPos.yd2;
+      xform_mtx2 (rotmtx, xd1, yd1);      // rotate detector endpoints
+      xform_mtx2 (rotmtx, xd2, yd2);      // to initial view_angle
+    }
+    
+    double xs1 = m_initPos.xs1, ys1 = m_initPos.ys1;
+    double xs2 = m_initPos.xs2, ys2 = m_initPos.ys2;
+    xform_mtx2 (rotmtx, xs1, ys1);      // rotate source endpoints to
+    xform_mtx2 (rotmtx, xs2, ys2);      // initial view angle
+#endif
+    
     int iStoragePosition = iView + iStorageOffset;
-
     DetectorArray& detArray = proj.getDetectorArray( iStoragePosition );
 
 #ifdef HAVE_SGP
@@ -366,11 +387,8 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int iS
       traceShowParam ("Samples / Ray:", "%d", PROJECTION_TRACE_ROW_SAMPLES, C_BLUE, m_nSample);
 
       m_pSGP->setMarker (SGP::MARKER_BDIAMOND);
-    }
-#endif
 
-#ifdef HAVE_SGP
-    if (m_pSGP && m_trace >= Trace::TRACE_PHANTOM) {
+      
       m_pSGP->setColor (C_BLACK);
       m_pSGP->setPenWidth (2);
       if (m_idGeometry == GEOMETRY_PARALLEL) {
@@ -398,6 +416,7 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int iS
     if (m_trace > Trace::TRACE_CONSOLE)
       traceShowParam ("Current View:", "%d (%.0f%%)", PROJECTION_TRACE_ROW_CURR_VIEW, C_RED, iView + iStartView, (iView + iStartView) / static_cast<double>(m_nView) * 100.);
 #endif
+
     if (m_trace == Trace::TRACE_CONSOLE)
       std::cout << "Current View: " << iView+iStartView << std::endl;
 
@@ -409,12 +428,16 @@ Scanner::collectProjections (Projections& proj, const Phantom& phm, const int iS
       //        rs_plot (detArray, xd1, yd1, dXCenter, dYCenter, theta);
     }
 #endif
+
+#ifndef HAVE_OPENMP
+    // Without OpenMP, incrementally rotate source and detectors 
     xform_mtx2 (m_rotmtxIncrement, xs1, ys1);
     xform_mtx2 (m_rotmtxIncrement, xs2, ys2);
     if (m_idGeometry != GEOMETRY_EQUIANGULAR) {
       xform_mtx2 (m_rotmtxIncrement, xd1, yd1);  // rotate detector endpoints
       xform_mtx2 (m_rotmtxIncrement, xd2, yd2);
     }
+#endif    
   } /* for each iView */
 }
 
index cf35c4c9872bf2b2a168e58e4b5a49d3c4895b1c..a8f09560d7aaa8871729db151eccbbf64b31e053 100644 (file)
@@ -119,6 +119,13 @@ rot_mtx2 (GRFMTX_2D m, const double theta)
   m[1][0] = -s;  m[1][1] = c;
 }
 
+void
+copy_mtx2 (GRFMTX_2D to, const GRFMTX_2D from) {
+  for (int r = 0; r < 3; r++)
+    for (int c = 0; c < 3; c++)
+      to[r][c] = from[r][c];
+}
+
 void
 mult_mtx2 (const GRFMTX_2D m1, const GRFMTX_2D m2, GRFMTX_2D result)
 {
@@ -131,10 +138,7 @@ mult_mtx2 (const GRFMTX_2D m1, const GRFMTX_2D m2, GRFMTX_2D result)
             temp[row][col] += m1[row][calc] * m2[calc][col];
     }
   }
-
-  for (int r = 0; r < 3; r++)
-    for (int col = 0; col < 3; col++)
-      result[r][col] = temp[r][col];
+  copy_mtx2 (result, temp);
 }
 
 void