diff --git a/raytracing/rays.py b/raytracing/rays.py
index 11de6ad..1963e25 100644
--- a/raytracing/rays.py
+++ b/raytracing/rays.py
@@ -4,20 +4,36 @@ import matplotlib.pyplot as plt
 import pickle
 import time
 import os
-
-""" A group of rays kept as a list, to be used as a starting
-point (i.e. an object) or as a cumulative detector (i.e. at an image
-or output plane) for ImagingPath, MatrixGroup or any tracing function.
-Subclasses can provide a computed ray for Monte Carlo simulation.
+import collections.abc as collections
+
+""" A source or a detector of rays
+
+We can obtain intensity distributions at from given plane by propagating
+many rays and collecting them at another plane. `Rays` is the base class
+that provides the essential mechanisms to obtain histograms on a list 
+of rays (created or collected). This list of rays is a property of the base
+class.  Subclasses are specific to a given ray distribution (Lambertian for 
+instance) and will create each ray on demand, then store them as they go
+in the rays list. 
+
+It is an iterable object, which means it can be used in an expression 
+like `for ray in rays:` which is convenient both when propagating rays 
+or when analysing the resulting rays that reached a plane in ImagingPath, 
+MatrixGroup or any tracing function. 
 """
 
-
 class Rays:
     def __init__(self, rays=None):
         if rays is None:
             self.rays = []
         else:
-            self.rays = rays
+            if isinstance(rays, collections.Iterable):
+                if all([isinstance(ray, Ray) for ray in rays]):
+                    self.rays = list(rays)
+                else:
+                    raise TypeError("'rays' elements must be of type Ray.")
+            else:
+                raise TypeError("'rays' must be iterable (i.e. a list or a tuple of Ray).")
 
         self.iteration = 0
         self.progressLog = 10000
@@ -160,6 +176,8 @@ class Rays:
         return self.rays[item]
 
     def append(self, ray):
+        if not isinstance(ray, Ray):
+            raise TypeError("'ray' must be a 'Ray' object.")
         if self.rays is not None:
             self.rays.append(ray)
 
@@ -214,21 +232,6 @@ class Rays:
     # https://en.wikipedia.org/wiki/Xiaolin_Wu's_line_algorithm
     # and https://stackoverflow.com/questions/3122049/drawing-an-anti-aliased-line-with-thepython-imaging-library
 
-    # @property
-    # def intensityError(self):
-    #     return list(map(lambda x : sqrt(x), self.distribution))
-
-    # @property
-    # def normalizedIntensity(self):
-    #     maxValue = max(self.values)
-    #     return list(map(lambda x : x/maxValue, self.distribution))
-
-    # @property
-    # def normalizedIntensityError(self):
-    #     maxValue = max(self.distribution)
-    #     return list(map(lambda x : x/maxValue, self.error))
-
-
 class UniformRays(Rays):
     def __init__(self, yMax=1.0, yMin=None, thetaMax=pi / 2, thetaMin=None, M=100, N=100):
         self.yMax = yMax

Rays() accepts objects from every type
This can cause further problems. In `__init__` itself it is not a big deal (except for coherence and logic) if `Rays` receive a string of nonsense or a list of numbers, but other methods will inevitably fail with exceptions of different types.
diff --git a/raytracing/tests/testsRays.py b/raytracing/tests/testsRays.py
index 9bb4c7c..1638b29 100644
--- a/raytracing/tests/testsRays.py
+++ b/raytracing/tests/testsRays.py
@@ -7,6 +7,31 @@ inf = float("+inf")
 
 class TestRays(unittest.TestCase):
 
+    def testRaysInitDifferentInputs(self):
+        listOfRays = [Ray(), Ray(1, 1), Ray(1, -2), Ray(0, -1)]
+        tupleOfRays = tuple(listOfRays)
+        npArrayOfRays = array(listOfRays)
+        raysFromList = Rays(listOfRays)
+        raysFromTuple = Rays(tupleOfRays)
+        raysFromArray = Rays(npArrayOfRays)
+        rays = Rays(listOfRays)
+        self.assertListEqual(raysFromList.rays, listOfRays)
+        self.assertListEqual(raysFromTuple.rays, listOfRays)
+        self.assertListEqual(raysFromArray.rays, listOfRays)
+        self.assertListEqual(Rays(rays).rays, listOfRays)
+
+        with self.assertRaises(TypeError) as error:
+            # This should raise an TypeError exception
+            Rays("Ray(), Ray(1), Ray(1,1)")
+
+        with self.assertRaises(TypeError) as error:
+            # This should raise an TypeError exception
+            Rays([Ray(), [1, 2], Ray()])
+
+        with self.assertRaises(TypeError) as error:
+            # This should raise an TypeError exception
+            Rays(Matrix())
+
     def testRayCountHist(self):
         r = Rays([Ray()])
         init = r.rayCountHistogram()

pip install -e .
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-xdist pytest-mock pytest-asyncio
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
contourpy==1.3.0
coverage==7.8.0
cycler==0.12.1
exceptiongroup==1.2.2
execnet==2.1.1
fonttools==4.56.0
importlib_resources==6.5.2
iniconfig==2.1.0
kiwisolver==1.4.7
matplotlib==3.9.4
numpy==2.0.2
packaging==24.2
pillow==11.1.0
pluggy==1.5.0
pyparsing==3.2.3
pytest==8.3.5
pytest-asyncio==0.26.0
pytest-cov==6.0.0
pytest-mock==3.14.0
pytest-xdist==3.6.1
python-dateutil==2.9.0.post0
-e git+https://github.com/DCC-Lab/RayTracing.git@203b3739d0804718664037706e2d43068fcd6ac5#egg=raytracing
six==1.17.0
tomli==2.2.1
typing_extensions==4.13.0
zipp==3.21.0

name: RayTracing
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - contourpy==1.3.0
      - coverage==7.8.0
      - cycler==0.12.1
      - exceptiongroup==1.2.2
      - execnet==2.1.1
      - fonttools==4.56.0
      - importlib-resources==6.5.2
      - iniconfig==2.1.0
      - kiwisolver==1.4.7
      - matplotlib==3.9.4
      - numpy==2.0.2
      - packaging==24.2
      - pillow==11.1.0
      - pluggy==1.5.0
      - pyparsing==3.2.3
      - pytest==8.3.5
      - pytest-asyncio==0.26.0
      - pytest-cov==6.0.0
      - pytest-mock==3.14.0
      - pytest-xdist==3.6.1
      - python-dateutil==2.9.0.post0
      - six==1.17.0
      - tomli==2.2.1
      - typing-extensions==4.13.0
      - zipp==3.21.0
prefix: /opt/conda/envs/RayTracing

raytracing/tests/testsRays.py::TestRays::testRaysInitDifferentInputs
raytracing/tests/testsRays.py::TestRays::testRayAnglesHist raytracing/tests/testsRays.py::TestRays::testRayCountHist
raytracing/rays.py
raytracing/rays.py