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