diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a676003f8f9ccba725e90341c41f44c99ffb1d2d..5b1ad8f69a6822501a710ae64bbae286ae102f7f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,8 +1,9 @@
 stages:
   - checkRepository
   - checkFormat
+  - checkGeometries
   - finalise
-  
+
 RebaseCheck:
   stage: checkRepository
   image: alpine
@@ -117,6 +118,29 @@ FileMediaCheck:
     - git fetch upstream
     - gawk -f ci_scripts/static_check.awk media.geo
 
+CheckRadLen:
+  stage: checkGeometries
+  image: rootproject/root
+  tags:
+    - docker
+  only:
+    refs:
+      - merge_requests
+    variables:
+      - $CI_MERGE_REQUEST_PROJECT_PATH == "CbmSoft/cbmroot_geometry" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"
+  script:
+    # Get the upstream repository manually. I did not find any other way to have it for
+    # comparison
+    - apt update -y && apt install -y git bash
+    - ci_scripts/connect_upstream_repo.sh $CI_MERGE_REQUEST_PROJECT_URL
+    - git fetch upstream
+    - git diff HEAD^ --name-only 
+    - git diff HEAD^ --name-only 2>/dev/null | sed -ne '/\.geo\.root/p' | tee > LIST_GEO_FILES 
+    - FAIL=0
+    - cat LIST_GEO_FILES
+    - for geo in `cat LIST_GEO_FILES`; do echo $geo; sh ci_scripts/check_radlen.sh $geo; if [ $? -ne 0 ]; then let FAIL++; fi; done
+    - exit $FAIL;
+
 InformCodeOwners:
   stage: finalise
   tags:
@@ -133,3 +157,4 @@ InformCodeOwners:
     - ci_scripts/connect_upstream_repo.sh $CI_MERGE_REQUEST_PROJECT_URL
     - git fetch upstream
     - ci_scripts/inform_codeowners.sh upstream
+
diff --git a/ci_scripts/check_radlen.sh b/ci_scripts/check_radlen.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b5c08d37609f8b913f6e8453e7b63a37eec610c7
--- /dev/null
+++ b/ci_scripts/check_radlen.sh
@@ -0,0 +1,67 @@
+#/bin/bash
+# check_radlen.sh - checks radiation length of materials in user supplied geometry
+# Author: Eoin Clerkin (FAIR)  2022-01-31
+
+echo "Scanning the geometry" $1
+
+root -l -b -q 'ci_scripts/scan_geometry.C("'$1'")' 1>tmp
+ROOT_EXIT=$?;
+
+if [ 0 -ne $ROOT_EXIT ]; then
+  echo "root command failed, nothing more done";
+  exit ${ROOT_EXIT};
+fi;
+
+grep '^M\(at\|ix\)' tmp | \
+sort | \
+uniq -c | \
+sort -g -k 1 1>MATERIALS
+
+COUNT=0;
+FAIL=0;
+SKIP=0;
+OKAY=0;
+
+
+while IFS= read -r line;
+do
+
+variables=`echo "$line" | sed -e 's/eff//g' | sed -e 's/index/jndex/g' | sed -e 's/.*A=/ A=/g' | sed -e 's/ / -v /g'`
+
+    awk \
+    -v TOL=0.1 \
+    $variables \
+    'BEGIN{\
+        if(Z<1){
+        printf "SKIP \t "; \
+        exit 3;
+        };
+        cal_rad_len=(716.4*A/(Z*(Z+1)*log(287/sqrt(Z)))/rho);\
+        #print cal_rad_len;
+        diff=(cal_rad_len - radlen);\
+        if(diff*diff <= TOL*TOL*radlen*radlen ){\
+        printf "OKAY  " cal_rad_len; exit 1;
+        }else{\
+        printf "FAIL  " cal_rad_len; exit 2;
+        }}'
+
+    STATUS=$?;
+
+    if [ $STATUS -eq 1 ]; then OKAY=$((OKAY+1)); fi;
+    if [ $STATUS -eq 2 ]; then FAIL=$((FAIL+1)); fi;
+    if [ $STATUS -eq 3 ]; then SKIP=$((SKIP+1)); fi;
+
+    COUNT=$((COUNT+1));
+
+    echo " \t $line"
+
+done < MATERIALS
+
+rm tmp MATERIALS
+
+
+echo ${FAIL}" failures in " $COUNT " materials"
+
+echo "ENDED successfully"
+
+exit ${FAIL};
diff --git a/ci_scripts/scan_geometry.C b/ci_scripts/scan_geometry.C
new file mode 100644
index 0000000000000000000000000000000000000000..82072aed556464ebee514c0653db223a59f31814
--- /dev/null
+++ b/ci_scripts/scan_geometry.C
@@ -0,0 +1,141 @@
+/* Copyright (C) 2021 Facility for Antiproton and Ion Research in Europe, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Eoin Clerkin [committer] */
+
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+
+#define NODE_DEPTH 25
+
+TGeoNode* node[NODE_DEPTH];
+TGeoMedium* med;
+
+TGeoManager* gman;
+TGeoVolume* top;
+
+//const char* seekstr1 = "cable";
+
+void scan_geometry(const char* fileName = "test.geo.root")
+{
+
+  TString myName = "scan_and_graph";
+
+  TFile file(fileName, "READ");
+  if (!file.IsOpen()) {
+    std::cerr << "Was a root geo file supplied?" << endl;
+    exit(1);
+  };
+
+  file.GetListOfKeys()->Print();
+  file.GetSize();
+
+  char geo_tag[100];
+  strcpy(geo_tag, basename(fileName));
+  char* ptr = strstr(geo_tag, ".geo.root");
+  *(ptr)    = '\0';
+
+
+  gman = (TGeoManager*) file.Get("FAIRGeom");
+  if (gman != nullptr) { top = gman->GetTopVolume(); };
+
+  if (top == nullptr) top = (TGeoVolume*) file.Get(geo_tag);
+  if (top == nullptr) top = (TGeoVolume*) file.Get("FAIRGeom");
+  if (top == nullptr) top = (TGeoVolume*) file.Get("top");
+  if (top == nullptr) top = (TGeoVolume*) file.Get("TOP");
+  if (top == nullptr) top = (TGeoVolume*) file.Get("Top");
+  if (top == nullptr) top = (TGeoVolume*) file.Get("geometryFromGDML");
+
+  if (top == nullptr) top = (TGeoVolume *) file.Get(file.GetListOfKeys()->First()->GetName());
+
+  if (top == nullptr) {
+    std::cerr << "No Top Volume found. Is the TGeoManager or Top Volume unusally named" << std::endl;
+    exit(1);
+  }
+
+  FILE* graph = fopen("geo.gv", "w+");
+  fprintf(graph, "digraph D {\n");
+
+  TObjArray* nodes = top->GetNodes();
+  nodes->Print();
+
+  int i_array[NODE_DEPTH], num_array[NODE_DEPTH], j;
+  for (int i = 0; i < NODE_DEPTH; i++)
+    i_array[i] = 0;
+  for (int i = 0; i < NODE_DEPTH; i++)
+    num_array[i] = 0;
+
+  //TGeoNode* node[NODE_DEPTH];
+  //TGeoMedium* med;
+
+  j            = 0;
+  i_array[0]   = 0;
+  num_array[0] = nodes->GetEntries();
+
+  std::cout << "\n" << std::endl;
+
+  int k = 0;
+  while (num_array[0] != 0) {
+
+    k++;  // Only used for stop.
+          //if(k==3)break;
+
+    if (j == 0) { node[0] = static_cast<TGeoNode*>(nodes->At(i_array[0])); }
+    else {
+      node[j] = static_cast<TGeoNode*>(node[j - 1]->GetDaughter(i_array[j]));
+    };
+
+    i_array[j]++;  // Update number.
+    std::cout << "Node: \t";
+    for (int i = 0; i < j + 1; i++)
+      printf("%d/%d \t", i_array[i], num_array[i]);
+    printf("\n");
+
+    std::cout << "Name: ";
+    node[j]->Print();
+    //std::cout << "Mother: ";
+    //node[j]->GetMotherVolume()->Print();
+    std::cout << "Shape: ";
+    node[j]->GetVolume()->GetShape()->Print();
+    std::cout << "Medium: ";
+    med = node[j]->GetMedium();
+    med->Print();
+    med->GetMaterial()->Print();
+    std::cout << "Position: ";
+    node[j]->GetMatrix()->Print();
+    num_array[j + 1] = node[j]->GetNdaughters();
+    std::cout << "Number of daughters: " << num_array[j + 1];
+    std::cout << endl << endl << endl;
+
+    fprintf(graph, "%s (%s) -> %s (%s) \n", 
+	    node[j]->GetMotherVolume()->GetName(), 
+	    node[j]->GetMotherVolume()->GetName(),
+	    node[j]->GetVolume()->GetName(),
+	    node[j]->GetVolume()->GetName()
+    );
+    
+    if (num_array[j + 1] > 0) {
+      j++;
+      num_array[j + 2] = 0;
+    };
+
+    while (i_array[j] == num_array[j]) {
+      num_array[j] = 0;
+      i_array[j]   = 0;  // Reset the counter before falling back.
+      j--;
+    };
+
+    if (j >= NODE_DEPTH) {
+      std::cerr << "Maximum depth of " << NODE_DEPTH << " exceeded. Increase NODE_DEPTH in header of macro," << endl;
+      exit(NODE_DEPTH);
+    };
+  };
+
+  fprintf(graph, "}\n");
+  fclose(graph);
+  file.Close();
+
+
+  printf("Processed %d nodes.\n", k);
+  std::cout << "Program Ends" << std::endl;
+}  // End of macro