Repository: DCC-Lab/RayTracing

Issue:
rayCountHistogram() and rayAnglesHistogram() of Rays raise exception when already computed
When we compute `rayCountHistogram()` for a first time, it works perfectly. But when we run it a second time, it throws an exception because a variable is referenced before asignment.

Discussion:

Patch:
diff --git a/raytracing/rays.py b/raytracing/rays.py
index 7787434..11de6ad 100644
--- a/raytracing/rays.py
+++ b/raytracing/rays.py
@@ -29,6 +29,12 @@ class Rays:
         self._thetaHistogram = None
         self._directionBinEdges = None
 
+        self._countHistogramParameters = None
+        self._xValuesCountHistogram = None
+
+        self._anglesHistogramParameters = None
+        self._xValuesAnglesHistogram = None
+
     def __len__(self) -> int:
         if self.rays is None:
             return 0
@@ -53,15 +59,17 @@ class Rays:
         return self._thetaValues
 
     def rayCountHistogram(self, binCount=None, minValue=None, maxValue=None):
-        if self._yHistogram is None:
-            if binCount is None:
-                binCount = 40
 
-            if minValue is None:
-                minValue = min(self.yValues)
+        if binCount is None:
+            binCount = 40
+
+        if minValue is None:
+            minValue = min(self.yValues)
+
+        if maxValue is None:
+            maxValue = max(self.yValues)
 
-            if maxValue is None:
-                maxValue = max(self.yValues)
+        if self._countHistogramParameters != (binCount, minValue, maxValue):
 
             (self._yHistogram, binEdges) = histogram(self.yValues,
                                                      bins=binCount,
@@ -70,27 +78,30 @@ class Rays:
             xValues = []
             for i in range(len(binEdges) - 1):
                 xValues.append((binEdges[i] + binEdges[i + 1]) / 2)
+            self._xValuesCountHistogram = xValues
 
-        return (xValues, self._yHistogram)
+        return (self._xValuesCountHistogram, self._yHistogram)
 
     def rayAnglesHistogram(self, binCount=None, minValue=None, maxValue=None):
-        if self._thetaHistogram is None:
-            if binCount is None:
-                binCount = 40
+        if binCount is None:
+            binCount = 40
 
-            if minValue is None:
-                minValue = min(self.thetaValues)
+        if minValue is None:
+            minValue = min(self.thetaValues)
 
-            if maxValue is None:
-                maxValue = max(self.thetaValues)
+        if maxValue is None:
+            maxValue = max(self.thetaValues)
+
+        if self._anglesHistogramParameters != (binCount, minValue, maxValue):
 
             (self._thetaHistogram, binEdges) = histogram(self.thetaValues, bins=binCount, range=(minValue, maxValue))
             self._thetaHistogram = list(self._thetaHistogram)
             xValues = []
             for i in range(len(binEdges) - 1):
                 xValues.append((binEdges[i] + binEdges[i + 1]) / 2)
+            self._xValuesAnglesHistogram = xValues
 
-        return (xValues, self._thetaHistogram)
+        return (self._xValuesAnglesHistogram, self._thetaHistogram)
 
     def display(self, title="Intensity profile", showTheta=True):
         plt.ioff()
@@ -159,6 +170,12 @@ class Rays:
         self._thetaHistogram = None
         self._directionBinEdges = None
 
+        self._countHistogramParameters = None
+        self._xValuesCountHistogram = None
+
+        self._anglesHistogramParameters = None
+        self._xValuesAnglesHistogram = None
+
     def load(self, filePath, append=False):
         with open(filePath, 'rb') as infile:
             loadedRays = pickle.Unpickler(infile).load()


Test patch:
diff --git a/raytracing/tests/testsRays.py b/raytracing/tests/testsRays.py
new file mode 100644
index 0000000..9bb4c7c
--- /dev/null
+++ b/raytracing/tests/testsRays.py
@@ -0,0 +1,34 @@
+import unittest
+import envtest  # modifies path
+from raytracing import *
+
+inf = float("+inf")
+
+
+class TestRays(unittest.TestCase):
+
+    def testRayCountHist(self):
+        r = Rays([Ray()])
+        init = r.rayCountHistogram()
+        self.assertIsNotNone(init)  # First time compute
+        final = r.rayCountHistogram()
+        self.assertIsNotNone(final)  # Second time compute, now works
+
+        self.assertTupleEqual(init, final)
+        final = r.rayCountHistogram(10)
+        self.assertNotEqual(init, final)
+
+    def testRayAnglesHist(self):
+        r = Rays([Ray()])
+        init = r.rayAnglesHistogram()
+        self.assertIsNotNone(init)  # First time compute
+        final = r.rayAnglesHistogram()
+        self.assertIsNotNone(final)  # Second time compute, now works
+
+        self.assertTupleEqual(init, final)
+        final = r.rayAnglesHistogram(10)
+        self.assertNotEqual(init, final)
+
+
+if __name__ == '__main__':
+    unittest.main()