diff --git a/NPLib/Core/NPDetectorManager.cxx b/NPLib/Core/NPDetectorManager.cxx index f8a1933c8f7c8712f0598ce13ce3dfc5042719de..0d3385c78ab1f0a26f92b00863484e2bbf2a670e 100644 --- a/NPLib/Core/NPDetectorManager.cxx +++ b/NPLib/Core/NPDetectorManager.cxx @@ -268,7 +268,7 @@ void NPL::DetectorManager::BuildPhysicalEvent(){ (it->second->*m_ClearEventPhysicsPtr)(); (it->second->*m_BuildPhysicalPtr)(); (it->second->*m_FillSpectra)(); - if(m_CheckSpectra) + if(m_CheckSpectra) { (it->second->*m_CheckSpectra)(); } } diff --git a/NPLib/Detectors/ComptonTelescope/TComptonTelescopePhysics.h b/NPLib/Detectors/ComptonTelescope/TComptonTelescopePhysics.h index e63650cc71b1fbe501339488bfa1790c5463c32b..ae07f7afbbb134c6f5df82bd5d8bcdf1690e3697 100644 --- a/NPLib/Detectors/ComptonTelescope/TComptonTelescopePhysics.h +++ b/NPLib/Detectors/ComptonTelescope/TComptonTelescopePhysics.h @@ -57,18 +57,18 @@ class TComptonTelescopePhysics : public TObject, public NPL::VDetector // DSSD int EventMultiplicity; vector<int> EventType; - //vector<int> TowerNumber; + vector<int> TowerNumber;// vector<int> DetectorNumber; vector<int> Strip_Front; vector<int> Strip_Back; - //vector<double> Strip_E; + vector<double> Strip_E;// vector<double> Strip_T; vector<double> Front_Energy; vector<double> Back_Energy; - //vector<double> Half_Energy; + vector<double> Half_Energy;// vector<double> Front_Time; vector<double> Back_Time; - //vector<bool> Same_FBTime; + vector<bool> Same_FBTime;// // Calorimeter vector<double> Calor_E; vector<double> Calor_T; @@ -240,8 +240,8 @@ class TComptonTelescopePhysics : public TObject, public NPL::VDetector Int_t m_CounterEvt[50]; //! Int_t m_CounterHit[50]; //! // physical events - vector<int> TowerNumber; - vector<double> Half_Energy; + //vector<int> TowerNumber; + //vector<double> Half_Energy; //vector<bool> Same_FBTime; }; diff --git a/NPSimulation/Detectors/Strasse/CADMesh.hh b/NPSimulation/Detectors/Strasse/CADMesh.hh new file mode 100644 index 0000000000000000000000000000000000000000..1f2db2a16b14c3e2f1794fcdbbb502bdfa39fd1c --- /dev/null +++ b/NPSimulation/Detectors/Strasse/CADMesh.hh @@ -0,0 +1,2704 @@ +// The MIT License (MIT) +// +// Copyright (c) 2011-2020 Christopher M. Poole <mail@christopherpoole.net> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// CADMESH - Load CAD files into Geant4 quickly and easily. +// +// Read all about it at: https://github.com/christopherpoole/CADMesh +// +// Basic usage: +// +// #include "CADMesh.hh" // This file. +// ... +// auto mesh = CADMesh::TessellatedMesh::FromSTL("mesh.stl"); +// G4VSolid* solid = mesh->GetSolid(); +// ... +// + +// !! THIS FILE HAS BEEN AUTOMATICALLY GENERATED. DON'T EDIT IT DIRECTLY. !! + +#pragma once + +class BuiltInReader; +class CADMeshTemplate; +class Mesh; +class STLReader; +class ASSIMPReader; +class PLYReader; +class FileTypes; +class OBJReader; +class Exceptions; +class TetrahedralMesh; +class Reader; +class Lexer; +class LexerMacros; +class TessellatedMesh; + +#include "G4String.hh" + +#include <algorithm> +#include <map> + +namespace CADMesh { + +namespace File { + +enum Type { + Unknown, + PLY, + STL, + DAE, + OBJ, + TET, + OFF, +}; + +static std::map<Type, G4String> Extension = { + {Unknown, "unknown"}, {PLY, "ply"}, {STL, "stl"}, {DAE, "dae"}, + {OBJ, "obj"}, {TET, "tet"}, {OFF, "off"}}; + +static std::map<Type, G4String> TypeString = { + {Unknown, "UNKNOWN"}, {PLY, "PLY"}, {STL, "STL"}, {DAE, "DAE"}, + {OBJ, "OBJ"}, {TET, "TET"}, {OFF, "OFF"}}; + +static std::map<Type, G4String> TypeName = { + {Unknown, "Unknown File Format"}, {PLY, "Stanford Triangle Format (PLY)"}, + {STL, "Stereolithography (STL)"}, {DAE, "COLLADA (DAE)"}, + {OBJ, "Wavefront (OBJ)"}, {TET, "TetGet (TET)"}, + {OFF, "Object File Format (OFF)"}}; + +Type TypeFromExtension(G4String extension); +Type TypeFromName(G4String name); +} +} + +#include "G4ThreeVector.hh" +#include "G4TriangularFacet.hh" + +#include <memory> +#include <vector> + +namespace CADMesh { + +typedef std::vector<G4ThreeVector> Points; +typedef std::vector<G4TriangularFacet *> Triangles; + +class Mesh { +public: + Mesh(Points points, Triangles triangles, G4String name = ""); + + static std::shared_ptr<Mesh> New(Points points, Triangles triangles, + G4String name = ""); + + static std::shared_ptr<Mesh> New(Triangles triangles, G4String name = ""); + + static std::shared_ptr<Mesh> New(std::shared_ptr<Mesh> mesh, + G4String name = ""); + +public: + G4String GetName(); + Points GetPoints(); + Triangles GetTriangles(); + + G4bool IsValidForNavigation(); + +private: + G4String name_ = ""; + + Points points_; + Triangles triangles_; +}; + +typedef std::vector<std::shared_ptr<Mesh>> Meshes; +} + +namespace CADMesh { + +namespace File { + +class Reader { +public: + Reader(G4String reader_name); + ~Reader(); + + virtual G4bool Read(G4String filepath) = 0; + virtual G4bool CanRead(Type file_type) = 0; + +public: + G4String GetName(); + + std::shared_ptr<Mesh> GetMesh(); + std::shared_ptr<Mesh> GetMesh(size_t index); + std::shared_ptr<Mesh> GetMesh(G4String name, G4bool exact = true); + + size_t GetNumberOfMeshes(); + + Meshes GetMeshes(); + +protected: + size_t AddMesh(std::shared_ptr<Mesh> mesh); + void SetMeshes(Meshes meshs); + +private: + Meshes meshes_; + + G4String name_ = ""; +}; +} +} + +#include <iostream> +#include <string> + +namespace CADMesh { + +namespace File { + +struct Token { + std::string name; + + bool operator==(Token other) { return name == other.name; }; + bool operator!=(Token other) { return name != other.name; }; +}; + +static Token ErrorToken{"ErrorToken"}; +static Token EnfOfFileToken{"EndOfFileToken"}; + +static Token ParentToken{"Parent"}; +static Token WordToken{"Word"}; +static Token NumberToken{"Number"}; +static Token ThreeVectorToken{"ThreeVector"}; +static Token VertexToken{"Vertex"}; +static Token VerticesToken{"Vertices"}; +static Token FacetToken{"Facet"}; +static Token LineToken{"Line"}; +static Token NormalToken{"Normal"}; +static Token TextureToken{"Texture"}; +static Token SolidToken{"Solid"}; +static Token ObjectToken{"Object"}; +static Token CommentToken{"Comment"}; +static Token BlankLineToken{"BlankLine"}; + +struct Item { + Token token; + + size_t position; + size_t line; + + std::string value; + std::string error; + + Item *parent; + + std::vector<Item> children; +}; + +typedef std::vector<Item> Items; +typedef Items::iterator ItemsIterator; + +class Lexer; + +struct State { + virtual State *operator()(Lexer *) const = 0; +}; + +struct __FinalState : public State { + State *operator()(Lexer *) const { return nullptr; } +}; + +class Lexer { +public: + Lexer(std::string filepath, State *initial_state = nullptr); + +public: + std::string String(); + + void Run(State *initial_state, size_t lines = 0); + Items GetItems(); + + void Backup(); + void BackupTo(int position); + + std::string Next(); + std::string Peek(); + + void Skip(); + + Item *ThisIsA(Token token, std::string error = ""); + Item *StartOfA(Token token, std::string error = ""); + Item *EndOfA(Token token, std::string error = ""); + Item *MaybeEndOfA(Token token, std::string error = ""); + + bool OneOf(std::string possibles); + bool ManyOf(std::string possibles); + bool Until(std::string match); + bool MatchExactly(std::string match); + + bool OneDigit(); + bool ManyDigits(); + + bool OneLetter(); + bool ManyLetters(); + + bool ManyCharacters(); + + bool Integer(); + bool Float(); + bool Number(); + + bool SkipWhiteSpace(); + bool SkipLineBreak(); + bool SkipLineBreaks(); + bool SkipLine(); + + State *Error(std::string message); + State *LastError(); + + bool TestState(State *state); + + bool IsDryRun(); + + void PrintMessage(std::string name, std::string message); + void PrintItem(Item item); + + size_t LineNumber(); + +private: + State *state_; + + Item *parent_item_ = nullptr; + Items items_; + + std::string input_; + + size_t position_ = 0; + size_t start_ = 0; + size_t width_ = 1; + size_t line_ = 1; + size_t end_line_ = 0; + + bool dry_run_ = false; + + int depth_ = 0; + + std::string last_error_ = ""; +}; +} +} + +#ifdef USE_CADMESH_ASSIMP_READER + +#include "assimp/Importer.hpp" +#include "assimp/postprocess.h" +#include "assimp/scene.h" + +namespace CADMesh { + +namespace File { + +class ASSIMPReader : public File::Reader { +public: + ASSIMPReader(); + ~ASSIMPReader(); + +public: + G4bool Read(G4String filepath); + G4bool CanRead(Type file_type); + +private: + Assimp::Importer *importer_; +}; + +std::shared_ptr<ASSIMPReader> ASSIMP(); +} +} +#endif + +namespace CADMesh { + +namespace File { + +class BuiltInReader : public Reader { +public: + BuiltInReader() : Reader("BuiltInReader"){}; + +public: + G4bool Read(G4String filepath); + G4bool CanRead(File::Type file_type); +}; + +std::shared_ptr<BuiltInReader> BuiltIn(); +} +} +#ifndef CADMESH_DEFAULT_READER +#define CADMESH_DEFAULT_READER BuiltIn +#endif + +#include "G4AssemblyVolume.hh" +#include "G4LogicalVolume.hh" +#include "G4Material.hh" +#include "G4TessellatedSolid.hh" +#include "G4Tet.hh" +#include "G4UIcommand.hh" + +namespace CADMesh { + +template <typename T> class CADMeshTemplate { +public: + CADMeshTemplate(); + + CADMeshTemplate(G4String file_name); + + CADMeshTemplate(G4String file_name, File::Type file_type); + + CADMeshTemplate(std::shared_ptr<File::Reader> reader); + + CADMeshTemplate(G4String file_name, std::shared_ptr<File::Reader> reader); + + CADMeshTemplate(G4String file_name, File::Type file_type, + std::shared_ptr<File::Reader> reader); + + static std::shared_ptr<T> From(G4String file_name); + + static std::shared_ptr<T> From(G4String file_name, + std::shared_ptr<File::Reader> reader); + + static std::shared_ptr<T> FromPLY(G4String file_name); + + static std::shared_ptr<T> FromPLY(G4String file_name, + std::shared_ptr<File::Reader> reader); + + static std::shared_ptr<T> FromSTL(G4String file_name); + + static std::shared_ptr<T> FromSTL(G4String file_name, + std::shared_ptr<File::Reader> reader); + + static std::shared_ptr<T> FromOBJ(G4String file_name); + + static std::shared_ptr<T> FromOBJ(G4String file_name, + std::shared_ptr<File::Reader> reader); + + ~CADMeshTemplate(); + +public: + virtual G4VSolid *GetSolid() = 0; + virtual G4VSolid *GetSolid(G4int index) = 0; + virtual G4VSolid *GetSolid(G4String name, G4bool exact = true) = 0; + + virtual std::vector<G4VSolid *> GetSolids() = 0; + + virtual G4AssemblyVolume *GetAssembly() = 0; + + bool IsValidForNavigation(); + +public: + G4String GetFileName(); + + File::Type GetFileType(); + + void SetVerbose(G4int verbose); + G4int GetVerbose(); + + void SetScale(G4double scale); + G4double GetScale(); + + void SetOffset(G4double x, G4double y, G4double z); + void SetOffset(G4ThreeVector offset); + G4ThreeVector GetOffset(); + +protected: + G4String file_name_; + File::Type file_type_; + G4int verbose_; + G4double scale_; + G4ThreeVector offset_; + + G4AssemblyVolume *assembly_ = nullptr; + + std::shared_ptr<File::Reader> reader_ = nullptr; +}; +} + +#include "globals.hh" + +namespace CADMesh { + +namespace Exceptions { + +void FileNotFound(G4String origin, G4String filepath); + +void LexerError(G4String origin, G4String message); + +void ParserError(G4String origin, G4String message); + +void ReaderCantReadError(G4String origin, File::Type file_type, + G4String filepath); + +void MeshNotFound(G4String origin, size_t index); +void MeshNotFound(G4String origin, G4String name); +} +} + +namespace CADMesh { + +class TessellatedMesh : public CADMeshTemplate<TessellatedMesh> { + using CADMeshTemplate::CADMeshTemplate; + +public: + G4VSolid *GetSolid(); + G4VSolid *GetSolid(G4int index); + G4VSolid *GetSolid(G4String name, G4bool exact = true); + + std::vector<G4VSolid *> GetSolids(); + + G4TessellatedSolid *GetTessellatedSolid(); + G4TessellatedSolid *GetTessellatedSolid(G4int index); + G4TessellatedSolid *GetTessellatedSolid(G4String name, G4bool exact = true); + G4TessellatedSolid *GetTessellatedSolid(std::shared_ptr<Mesh> mesh); + + G4AssemblyVolume *GetAssembly(); + +public: + void SetReverse(G4bool reverse) { this->reverse_ = reverse; }; + + G4bool GetReverse() { return this->reverse_; }; + +private: + G4bool reverse_; +}; +} + +#ifdef USE_CADMESH_TETGEN + +#include "tetgen.h" + +namespace CADMesh { + +class TetrahedralMesh : public CADMeshTemplate<TetrahedralMesh> { +public: + using CADMeshTemplate::CADMeshTemplate; + + TetrahedralMesh(); + ~TetrahedralMesh(); + +public: + G4VSolid *GetSolid(); + G4VSolid *GetSolid(G4int index); + G4VSolid *GetSolid(G4String name, G4bool exact = true); + + std::vector<G4VSolid *> GetSolids(); + + G4AssemblyVolume *GetAssembly(); + +public: + void SetMaterial(G4Material *material) { this->material_ = material; }; + + G4Material *GetMaterial() { return this->material_; }; + + void SetQuality(G4double quality) { this->quality_ = quality; }; + + G4double GetQuality() { return this->quality_; }; + + std::shared_ptr<tetgenio> GetTetgenInput() { return in_; }; + + std::shared_ptr<tetgenio> GetTetgenOutput() { return out_; }; + +private: + G4ThreeVector GetTetPoint(G4int index_offset); + +private: + std::shared_ptr<tetgenio> in_ = nullptr; + std::shared_ptr<tetgenio> out_ = nullptr; + + G4double quality_; + + G4Material *material_; +}; +} +#endif + +namespace CADMesh { + +namespace File { + +inline Type TypeFromExtension(G4String extension) { + std::for_each(extension.begin(), extension.end(), + [](char &e) { e = ::tolower(e); }); + + for (auto e = Extension.begin(); e != Extension.end(); ++e) { + if (e->second == extension) { + return e->first; + } + } + + return Unknown; +} + +inline Type TypeFromName(G4String name) { + auto extension = name.substr(name.find_last_of(".") + 1); + + return TypeFromExtension(extension); +} +} +} + +namespace CADMesh { + +inline Mesh::Mesh(Points points, Triangles triangles, G4String name) + : name_(name), points_(points), triangles_(triangles) {} + +inline std::shared_ptr<Mesh> Mesh::New(Points points, Triangles triangles, + G4String name) { + return std::make_shared<Mesh>(points, triangles, name); +} + +inline std::shared_ptr<Mesh> Mesh::New(Triangles triangles, G4String name) { + Points points; + + return New(points, triangles, name); +} + +inline std::shared_ptr<Mesh> Mesh::New(std::shared_ptr<Mesh> mesh, + G4String name) { + return New(mesh->GetPoints(), mesh->GetTriangles(), name); +} + +inline G4String Mesh::GetName() { return name_; } + +inline Points Mesh::GetPoints() { return points_; } + +inline Triangles Mesh::GetTriangles() { return triangles_; } + +inline G4bool Mesh::IsValidForNavigation() { + std::map<G4ThreeVector, size_t> point_index; + + size_t index = 0; + for (auto point : points_) { + point_index[point] = index; + index++; + } + + typedef std::pair<size_t, size_t> Edge; + std::map<Edge, G4int> edge_use_count; + + for (size_t i = 0; i < triangles_.size(); i++) { + auto triangle = triangles_[i]; + + size_t a = point_index[triangle->GetVertex(0)]; + size_t b = point_index[triangle->GetVertex(1)]; + size_t c = point_index[triangle->GetVertex(2)]; + + if (a < b) { + edge_use_count[Edge(a, b)] += 1; + } + + else if (a > b) { + edge_use_count[Edge(b, a)] += 1; + } + + if (b < c) { + edge_use_count[Edge(b, c)] += 1; + } + + else if (b > c) { + edge_use_count[Edge(c, b)] += 1; + } + + if (c < a) { + edge_use_count[Edge(c, a)] += 1; + } + + else if (c > a) { + edge_use_count[Edge(a, c)] += 1; + } + } + + for (auto count : edge_use_count) { + if (count.second != 2) { + return false; + } + } + + return true; +} +} + +namespace CADMesh { + +namespace File { + +inline Reader::Reader(G4String reader_name) : name_(reader_name) {} + +inline Reader::~Reader() {} + +inline G4String Reader::GetName() { return name_; } + +inline std::shared_ptr<Mesh> Reader::GetMesh() { + if (meshes_.size() > 0) { + return meshes_[0]; + } + + return nullptr; +} + +inline std::shared_ptr<Mesh> Reader::GetMesh(size_t index) { + if (index < meshes_.size()) { + return meshes_[index]; + } + + Exceptions::MeshNotFound("Reader::GetMesh", index); + + return nullptr; +} + +inline std::shared_ptr<Mesh> Reader::GetMesh(G4String name, G4bool exact) { + for (auto mesh : meshes_) { + if (exact) { + if (mesh->GetName() == name) + return mesh; + } + + else { + if (mesh->GetName().find(name) != std::string::npos) + return mesh; + } + } + + Exceptions::MeshNotFound("Reader::GetMesh", name); + + return nullptr; +} + +inline Meshes Reader::GetMeshes() { return meshes_; } + +inline size_t Reader::GetNumberOfMeshes() { return meshes_.size(); } + +inline size_t Reader::AddMesh(std::shared_ptr<Mesh> mesh) { + meshes_.push_back(mesh); + + return meshes_.size(); +} + +inline void Reader::SetMeshes(Meshes meshes) { meshes_ = meshes; } +} +} + +#include <fstream> +#include <sstream> +#include <streambuf> + +namespace CADMesh { + +namespace File { + +inline Lexer::Lexer(std::string filepath, State *initial_state) { + std::ifstream file(filepath); + input_ = std::string((std::istreambuf_iterator<char>(file)), + std::istreambuf_iterator<char>()); + + if (initial_state) { + Run(initial_state); + } +} + +inline std::string Lexer::String() { + return input_.substr(start_, position_ - start_); +} + +inline void Lexer::Run(State *initial_state, size_t lines) { + parent_item_ = new Item{ParentToken, position_, line_, "", "", + nullptr, std::vector<Item>()}; + + state_ = initial_state; + + end_line_ = 0; + + if (lines > 0) + end_line_ = line_ + lines; + + while (state_) { + state_ = (*state_)(this); + } +} + +inline Items Lexer::GetItems() { return parent_item_->children; } + +inline void Lexer::Backup() { + position_ -= width_; + + auto next = input_.substr(position_, 1); + + if (next == "\n") { + line_--; + } +} + +inline void Lexer::BackupTo(int position) { + auto s = input_.substr(position, position_ - position); + line_ -= std::count(s.begin(), s.end(), '\n'); + + position_ = position; +} + +inline std::string Lexer::Next() { + if (position_ >= input_.length()) { + return ""; + } + + auto next = input_.substr(position_, 1); + + width_ = 1; + position_ += width_; + + if (next == "\n") + line_++; + + return next; +} + +inline std::string Lexer::Peek() { + auto next = Next(); + + if (next != "") + Backup(); + + return next; +} + +inline void Lexer::Skip() { start_ = position_; } + +inline Item *Lexer::ThisIsA(Token token, std::string error) { + if (dry_run_) + return nullptr; + + auto item = + Item{token, position_, line_, String(), error, parent_item_, Items()}; + Skip(); + + if (parent_item_) { + PrintItem(item); + + parent_item_->children.push_back(item); + return &(parent_item_->children.back()); + } + + else { + depth_++; + PrintItem(item); + + items_.push_back(item); + return &(items_.back()); + } +} + +inline Item *Lexer::StartOfA(Token token, std::string error) { + if (dry_run_) + return nullptr; + + parent_item_ = ThisIsA(token, error); + + depth_++; + + return parent_item_; +} + +inline Item *Lexer::EndOfA(Token token, std::string /*error*/) { + if (dry_run_) + return nullptr; + + depth_--; + + PrintItem(*parent_item_); + + if (parent_item_->token.name != token.name) { + Exceptions::LexerError("Lexer::EndOfA", + "Trying to end a '" + parent_item_->token.name + + "' with a '" + token.name + "' token."); + } + + if (parent_item_) { + parent_item_ = parent_item_->parent; + } + + return nullptr; +} + +inline Item *Lexer::MaybeEndOfA(Token token, std::string error) { + if (parent_item_->token.name == token.name) { + return EndOfA(token, error); + } + + else { + return nullptr; + } +} + +inline bool Lexer::OneOf(std::string possibles) { + auto peek = Peek(); + + size_t position = possibles.find(Peek()); + + if (position != std::string::npos) { + auto next = Next(); + return next != ""; + } + + return false; +} + +inline bool Lexer::ManyOf(std::string possibles) { + bool has = false; + + while (OneOf(possibles)) { + has = true; + } + + return has; +} + +inline bool Lexer::Until(std::string match) { + while (!OneOf(match)) { + if (Next() == "") + return false; + } + + return true; +} + +inline bool Lexer::MatchExactly(std::string match) { + auto start_position = position_; + + for (auto m : match) { + if (!OneOf(std::string(1, m))) { + BackupTo(start_position); + return false; + } + } + + return true; +} + +inline bool Lexer::OneDigit() { return OneOf("0123456789"); } + +inline bool Lexer::ManyDigits() { return ManyOf("0123456789"); } + +inline bool Lexer::OneLetter() { + return OneOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); +} + +inline bool Lexer::ManyLetters() { + return ManyOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); +} + +inline bool Lexer::ManyCharacters() { + return ManyOf("!\"#$%&\\\'()*+,-./" + "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[|]^_`" + "abcdefghijklmnopqrstuvwxyz{}~"); +} + +inline bool Lexer::Integer() { + auto start_position = position_; + + OneOf("+-"); + + if (!ManyDigits()) { + BackupTo(start_position); + return false; + } + + return true; +} + +inline bool Lexer::Float() { + auto start_position = position_; + + OneOf("+-"); + + bool has_integer = Integer(); + + if (!OneOf(".")) { + BackupTo(start_position); + return false; + } + + bool has_decimal = ManyDigits(); + + if (!has_integer || !has_decimal) { + BackupTo(start_position); + return false; + } + + return true; +} + +inline bool Lexer::Number() { + if (!Float()) { + if (!Integer()) { + return false; + } + } + + auto start_position = position_; + + if (OneOf("eE")) { + if (!Float()) { + if (!Integer()) { + BackupTo(start_position); + } + } + } + + return true; +} + +inline bool Lexer::SkipWhiteSpace() { + if (!ManyOf(" \t\r")) { + Skip(); + return false; + } + + Skip(); + return true; +} + +inline bool Lexer::SkipLineBreak() { + if (!OneOf("\n")) { + return false; + } + + Skip(); + return true; +} + +inline bool Lexer::SkipLineBreaks() { + if (!ManyOf("\n")) { + return false; + } + + Skip(); + return true; +} + +inline bool Lexer::SkipLine() { + if (!Until("\n")) { + return false; + } + + Skip(); + return true; +} + +inline State *Lexer::Error(std::string message) { + + std::stringstream error; + error << "Error around line " << line_ << ": " << message << std::endl; + + last_error_ = error.str(); + + if (dry_run_) + return nullptr; + + Item item{ErrorToken, position_, line_, "", + error.str(), parent_item_, Items()}; + items_.push_back(item); + + Exceptions::LexerError("Lexer", error.str()); + + return nullptr; +} + +inline State *Lexer::LastError() { + if (last_error_ == "") { + Exceptions::LexerError("Lexer", "Something went wrong."); + } + + else { + Exceptions::LexerError("Lexer", last_error_); + } + + return nullptr; +} + +inline bool Lexer::TestState(State *state) { + if (dry_run_) + return false; + + if (end_line_ > 0 && line_ > end_line_) + return false; + + auto start_position = position_; + + dry_run_ = true; + + bool state_transition = ((*state)(this) != nullptr); + + dry_run_ = false; + + BackupTo(start_position); + + return state_transition; +} + +inline bool Lexer::IsDryRun() { return dry_run_; } + +inline size_t Lexer::LineNumber() { return line_; } + +#ifdef CADMESH_LEXER_VERBOSE +inline void Lexer::PrintMessage(std::string name, std::string message) { + std::cout << "Lexer::" << name << " : " << message << std::endl; +} +#else +inline void Lexer::PrintMessage(std::string, std::string) {} +#endif + +#ifdef CADMESH_LEXER_VERBOSE +inline void Lexer::PrintItem(Item item) { + auto depth = std::max(0, depth_) * 2; + std::cout << std::string(depth, ' ') << item.token.name << ": " << item.value + << std::endl; +} +#else +inline void Lexer::PrintItem(Item) {} +#endif +} +} + +namespace CADMesh { + +template <typename T> +CADMeshTemplate<T>::CADMeshTemplate() : CADMeshTemplate<T>("") {} + +template <typename T> +CADMeshTemplate<T>::CADMeshTemplate(G4String file_name) + : CADMeshTemplate<T>(file_name, File::Unknown) {} + +template <typename T> +CADMeshTemplate<T>::CADMeshTemplate(G4String file_name, File::Type file_type) + : CADMeshTemplate<T>(file_name, file_type, File::CADMESH_DEFAULT_READER()) { +} + +template <typename T> +CADMeshTemplate<T>::CADMeshTemplate(std::shared_ptr<File::Reader> reader) + : CADMeshTemplate<T>("", reader) {} + +template <typename T> +CADMeshTemplate<T>::CADMeshTemplate(G4String file_name, + std::shared_ptr<File::Reader> reader) + : CADMeshTemplate<T>(file_name, File::Unknown, reader) {} + +template <typename T> +CADMeshTemplate<T>::CADMeshTemplate(G4String file_name, File::Type file_type, + std::shared_ptr<File::Reader> reader) { + if (!reader->CanRead(file_type)) { + Exceptions::ReaderCantReadError(reader->GetName(), file_type, file_name); + } + + file_name_ = file_name; + file_type_ = file_type; + + scale_ = 1.0; + + offset_ = G4ThreeVector(); + + verbose_ = 0; + + reader_ = reader; + + reader_->Read(file_name_); +} + +template <typename T> +std::shared_ptr<T> CADMeshTemplate<T>::From(G4String file_name) { + return std::make_shared<T>(file_name); +} + +template <typename T> +std::shared_ptr<T> +CADMeshTemplate<T>::From(G4String file_name, + std::shared_ptr<File::Reader> reader) { + return std::make_shared<T>(file_name, reader); +} + +template <typename T> +std::shared_ptr<T> CADMeshTemplate<T>::FromPLY(G4String file_name) { + return std::make_shared<T>(file_name, File::PLY); +} + +template <typename T> +std::shared_ptr<T> +CADMeshTemplate<T>::FromPLY(G4String file_name, + std::shared_ptr<File::Reader> reader) { + return std::make_shared<T>(file_name, File::PLY, reader); +} + +template <typename T> +std::shared_ptr<T> CADMeshTemplate<T>::FromSTL(G4String file_name) { + return std::make_shared<T>(file_name, File::STL); +} + +template <typename T> +std::shared_ptr<T> +CADMeshTemplate<T>::FromSTL(G4String file_name, + std::shared_ptr<File::Reader> reader) { + return std::make_shared<T>(file_name, File::STL, reader); +} + +template <typename T> +std::shared_ptr<T> CADMeshTemplate<T>::FromOBJ(G4String file_name) { + return std::make_shared<T>(file_name, File::OBJ); +} + +template <typename T> +std::shared_ptr<T> +CADMeshTemplate<T>::FromOBJ(G4String file_name, + std::shared_ptr<File::Reader> reader) { + return std::make_shared<T>(file_name, File::OBJ, reader); +} + +template <typename T> CADMeshTemplate<T>::~CADMeshTemplate() {} + +template <typename T> bool CADMeshTemplate<T>::IsValidForNavigation() { + return reader_->GetMesh()->IsValidForNavigation(); +} + +template <typename T> G4String CADMeshTemplate<T>::GetFileName() { + return file_name_; +} + +template <typename T> File::Type CADMeshTemplate<T>::GetFileType() { + return file_type_; +} + +template <typename T> void CADMeshTemplate<T>::SetVerbose(G4int verbose) { + verbose_ = verbose; +} + +template <typename T> G4int CADMeshTemplate<T>::GetVerbose() { + return verbose_; +} + +template <typename T> void CADMeshTemplate<T>::SetScale(G4double scale) { + scale_ = scale; +} + +template <typename T> G4double CADMeshTemplate<T>::GetScale() { return scale_; } + +template <typename T> +void CADMeshTemplate<T>::SetOffset(G4double x, G4double y, G4double z) { + SetOffset(G4ThreeVector(x, y, z)); +} + +template <typename T> void CADMeshTemplate<T>::SetOffset(G4ThreeVector offset) { + offset_ = offset; +} + +template <typename T> G4ThreeVector CADMeshTemplate<T>::GetOffset() { + return offset_; +} +} + +namespace CADMesh { + +namespace Exceptions { + +inline void FileNotFound(G4String origin, G4String filepath) { + G4Exception( + ("CADMesh in " + origin).c_str(), "FileNotFound", FatalException, + ("\nThe file: \n\t" + filepath + "\ncould not be found.").c_str()); +} + +inline void LexerError(G4String origin, G4String message) { + G4Exception( + ("CADMesh in " + origin).c_str(), "LexerError", FatalException, + ("\nThe CAD file appears to contain incorrect syntax:\n\t" + message) + .c_str()); +} + +inline void ParserError(G4String origin, G4String message) { + G4Exception(("CADMesh in " + origin).c_str(), "ParserError", FatalException, + ("\nThe CAD file appears to contain invalid data:\n\t" + message) + .c_str()); +} + +inline void ReaderCantReadError(G4String origin, File::Type file_type, + G4String filepath) { + G4Exception( + ("CADMesh in " + origin).c_str(), "ReaderCantReadError", FatalException, + (G4String("\nThe the reader can't read files of type '") + + File::TypeString[file_type] + + ".'\n\tSpecified the incorrect file type (?) for file:\n\t\t" + filepath) + .c_str()); +} + +inline void MeshNotFound(G4String origin, size_t index) { + std::stringstream message; + message << "\nThe mesh with index '" << index << "' could not be found."; + + G4Exception(("CADMesh in " + origin).c_str(), "MeshNotFound", FatalException, + message.str().c_str()); +} + +inline void MeshNotFound(G4String origin, G4String name) { + G4Exception( + ("CADMesh in " + origin).c_str(), "MeshNotFound", FatalException, + ("\nThe mesh with name '" + name + "' could not be found.").c_str()); +} +} +} + +#include "Randomize.hh" + +namespace CADMesh { + +inline G4VSolid *TessellatedMesh::GetSolid() { + return (G4VSolid *)GetTessellatedSolid(); +} + +inline G4VSolid *TessellatedMesh::GetSolid(G4int index) { + return (G4VSolid *)GetTessellatedSolid(index); +} + +inline G4VSolid *TessellatedMesh::GetSolid(G4String name, G4bool exact) { + return (G4VSolid *)GetTessellatedSolid(name, exact); +} + +inline std::vector<G4VSolid *> TessellatedMesh::GetSolids() { + std::vector<G4VSolid *> solids; + + for (auto mesh : reader_->GetMeshes()) { + solids.push_back(GetTessellatedSolid(mesh)); + } + + return solids; +} + +inline G4AssemblyVolume *TessellatedMesh::GetAssembly() { + if (assembly_) { + return assembly_; + } + + for (auto mesh : reader_->GetMeshes()) { + auto solid = GetTessellatedSolid(mesh); + + G4Material *material = nullptr; + + auto logical = + new G4LogicalVolume(solid, material, mesh->GetName() + "_logical"); + + G4ThreeVector position = G4ThreeVector(); + G4RotationMatrix *rotation = new G4RotationMatrix(); + + assembly_->AddPlacedVolume(logical, position, rotation); + } + + return assembly_; +} + +inline G4TessellatedSolid *TessellatedMesh::GetTessellatedSolid() { + return GetTessellatedSolid(0); +} + +inline G4TessellatedSolid *TessellatedMesh::GetTessellatedSolid(G4int index) { + return GetTessellatedSolid(reader_->GetMesh(index)); +} + +inline G4TessellatedSolid *TessellatedMesh::GetTessellatedSolid(G4String name, + G4bool exact) { + return GetTessellatedSolid(reader_->GetMesh(name, exact)); +} + +inline G4TessellatedSolid * +TessellatedMesh::GetTessellatedSolid(std::shared_ptr<Mesh> mesh) { + auto volume_solid = new G4TessellatedSolid(mesh->GetName()); + + for (auto triangle : mesh->GetTriangles()) { + auto a = triangle->GetVertex(0) * scale_ + offset_; + auto b = triangle->GetVertex(1) * scale_ + offset_; + auto c = triangle->GetVertex(2) * scale_ + offset_; + + auto t = new G4TriangularFacet(a, b, c, ABSOLUTE); + + if (reverse_) { + volume_solid->AddFacet((G4VFacet *)t->GetFlippedFacet()); + } + + else { + volume_solid->AddFacet((G4VFacet *)t); + } + } + + volume_solid->SetSolidClosed(true); + if (volume_solid->GetNumberOfFacets() == 0) { + G4Exception("TessellatedMesh::GetTessellatedSolid", + "The loaded mesh has 0 faces.", FatalException, + "The file may be empty."); + return nullptr; + } + return volume_solid; +} +} + +#ifdef USE_CADMESH_TETGEN + +namespace CADMesh { + +inline TetrahedralMesh::TetrahedralMesh() {} + +inline TetrahedralMesh::~TetrahedralMesh() {} + +inline G4VSolid *TetrahedralMesh::GetSolid() { return GetSolid(0); } + +inline G4VSolid *TetrahedralMesh::GetSolid(G4int /*index*/) { return nullptr; } + +inline G4VSolid *TetrahedralMesh::GetSolid(G4String /*name*/, + G4bool /*exact*/) { + + return nullptr; +} + +inline std::vector<G4VSolid *> TetrahedralMesh::GetSolids() { + + return std::vector<G4VSolid *>(); +} + +inline G4AssemblyVolume *TetrahedralMesh::GetAssembly() { + if (assembly_) { + return assembly_; + } + + assembly_ = new G4AssemblyVolume(); + + in_ = std::make_shared<tetgenio>(); + out_ = std::make_shared<tetgenio>(); + + char *fn = (char *)file_name_.c_str(); + + G4bool do_tet = true; + + if (file_type_ == File::STL) { + in_->load_stl(fn); + } + + else if (file_type_ == File::PLY) { + in_->load_ply(fn); + } + + else if (file_type_ == File::TET) { + out_->load_tetmesh(fn, 0); + do_tet = false; + } + + else if (file_type_ == File::OFF) { + out_->load_off(fn); + do_tet = false; + } + + if (do_tet) { + tetgenbehavior *behavior = new tetgenbehavior(); + behavior->nobisect = 1; + behavior->plc = 1; + behavior->quality = quality_; + + tetrahedralize(behavior, in_.get(), out_.get()); + } + + G4RotationMatrix *element_rotation = new G4RotationMatrix(); + G4ThreeVector element_position = G4ThreeVector(); + G4Transform3D assembly_transform = G4Translate3D(); + + for (int i = 0; i < out_->numberoftetrahedra; i++) { + int index_offset = i * 4; + + G4ThreeVector p1 = GetTetPoint(index_offset); + G4ThreeVector p2 = GetTetPoint(index_offset + 1); + G4ThreeVector p3 = GetTetPoint(index_offset + 2); + G4ThreeVector p4 = GetTetPoint(index_offset + 3); + + G4String tet_name = + file_name_ + G4String("_tet_") + G4UIcommand::ConvertToString(i); + + auto tet_solid = + new G4Tet(tet_name + G4String("_solid"), p1, p2, p3, p4, 0); + + auto tet_logical = new G4LogicalVolume( + tet_solid, material_, tet_name + G4String("_logical"), 0, 0, 0); + + assembly_->AddPlacedVolume(tet_logical, element_position, element_rotation); + } + + return assembly_; +} + +inline G4ThreeVector TetrahedralMesh::GetTetPoint(G4int index_offset) { + return G4ThreeVector( + out_->pointlist[out_->tetrahedronlist[index_offset] * 3] * scale_ - + offset_.x(), + out_->pointlist[out_->tetrahedronlist[index_offset] * 3 + 1] * scale_ - + offset_.y(), + out_->pointlist[out_->tetrahedronlist[index_offset] * 3 + 2] * scale_ - + offset_.z()); +} +} +#endif + +#define CADMeshLexerToken(name) \ + static Token name##Token { #name } + +#define CADMeshLexerStateDefinition(name) \ + struct name##State : public State { \ + State *operator()(Lexer *lexer) const; \ + } + +#define CADMeshLexerState(name) name##State::operator()(Lexer *lexer) const + +#define ThisIsA(name) lexer->ThisIsA(name##Token) +#define StartOfA(name) lexer->StartOfA(name##Token) +#define EndOfA(name) lexer->EndOfA(name##Token) +#define MaybeEndOfA(name) lexer->MaybeEndOfA(name##Token) + +#define Skip() lexer->Skip() + +#define Next() lexer->Peek() +#define PrintNext() std::cout << lexer->Peek() << std::endl; + +#define OneOf(possibles) lexer->OneOf(possibles) +#define NotOneOf(possibles) !OneOf(possibles) + +#define ManyOf(possibles) lexer->ManyOf(possibles) +#define NotManyOf(possibles) !ManyOf(possibles) + +#define Until(match) lexer->Until(match) + +#define RestOfLine() \ + if (Until("\n\r")) \ + lexer->Backup() + +#define MatchExactly(match) lexer->MatchExactly(match) +#define DoesNotMatchExactly(match) !MatchExactly(match) + +#define OneDigit() lexer->OneDigit() +#define NotOneDigit() !OneDigit() + +#define ManyDigits() lexer->ManyDigits() +#define NotManyDigits() !ManyDigits() + +#define OneLetter() lexer->OneLetter() +#define NotOneLetter() !OneLetter() + +#define ManyLetters() lexer->ManyLetters() +#define NotManyLetters() !ManyLetters() + +#define ManyCharacters() lexer->ManyCharacters() +#define NotManyCharacters() !ManyCharacters() + +#define Integer() lexer->Integer() +#define NotAnInteger() !Integer() + +#define Float() lexer->Float() +#define NotAFloat() !Float() + +#define Number() lexer->Number() +#define NotANumber() !Number() + +#define SkipWhiteSpace() lexer->SkipWhiteSpace() +#define DidNotSkipWhiteSpace() !SkipWhiteSpace() + +#define SkipLineBreak() lexer->SkipLineBreak() +#define DidNotSkipLineBreak() !SkipLineBreak() + +#define SkipLineBreaks() lexer->SkipLineBreaks() +#define DidNotSkipLineBreaks() !SkipLineBreaks() + +#define SkipLine() lexer->SkipLine() +#define DidNotSkipLine() !SkipLine() + +#define AtEndOfLine() Next() == "\n" || Next() == "\r" + +#define Error(message) \ + { \ + lexer->Error(message); \ + return nullptr; \ + } + +#define NextState(next) return new next##State() +#define TestState(next) lexer->TestState(new next##State()) +#define TryState(next) \ + if (TestState(next)) \ + NextState(next) +#define FinalState() return new __FinalState(); + +#define RunLexer(filepath, start) Lexer(filepath, new start##State).GetItems() + +namespace CADMesh { + +namespace File { + +class STLReader : public Reader { +public: + STLReader() : Reader("STLReader"){}; + + G4bool Read(G4String filepath); + G4bool CanRead(Type file_type); + +protected: + CADMeshLexerStateDefinition(StartSolid); + CADMeshLexerStateDefinition(EndSolid); + + CADMeshLexerStateDefinition(StartFacet); + CADMeshLexerStateDefinition(EndFacet); + + CADMeshLexerStateDefinition(StartVertices); + CADMeshLexerStateDefinition(EndVertices); + + CADMeshLexerStateDefinition(Vertex); + + CADMeshLexerStateDefinition(ThreeVector); + + std::shared_ptr<Mesh> ParseMesh(Items items); + G4TriangularFacet *ParseFacet(Items items); + G4TriangularFacet *ParseVertices(Items items); + G4ThreeVector ParseThreeVector(Items items); +}; +} +} + +namespace CADMesh { + +namespace File { + +class OBJReader : public Reader { +public: + OBJReader() : Reader("OBJReader"){}; + + G4bool Read(G4String filepath); + G4bool CanRead(Type file_type); + +protected: + CADMeshLexerStateDefinition(StartSolid); + CADMeshLexerStateDefinition(EndSolid); + + CADMeshLexerStateDefinition(Ignore); + CADMeshLexerStateDefinition(Vertex); + CADMeshLexerStateDefinition(Facet); + CADMeshLexerStateDefinition(Object); + + std::shared_ptr<Mesh> ParseMesh(Items items); + G4ThreeVector ParseVertex(Items items); + G4TriangularFacet *ParseFacet(Items items, G4bool quad); + +private: + Points vertices_; +}; +} +} + +namespace CADMesh { + +namespace File { + +CADMeshLexerToken(Header); +CADMeshLexerToken(Element); +CADMeshLexerToken(Property); + +class PLYReader : public Reader { +public: + PLYReader() : Reader("PLYReader"){}; + + G4bool Read(G4String filepath); + G4bool CanRead(Type file_type); + +protected: + CADMeshLexerStateDefinition(StartHeader); + CADMeshLexerStateDefinition(EndHeader); + + CADMeshLexerStateDefinition(Element); + CADMeshLexerStateDefinition(Property); + CADMeshLexerStateDefinition(Ignore); + + CADMeshLexerStateDefinition(Vertex); + CADMeshLexerStateDefinition(Facet); + + void ParseHeader(Items items); + + std::shared_ptr<Mesh> ParseMesh(Items vertex_items, Items face_items); + G4ThreeVector ParseVertex(Items items); + G4TriangularFacet *ParseFacet(Items items, Points vertices); + + size_t vertex_count_ = 0; + size_t facet_count_ = 0; + + size_t x_index_ = 0; + size_t y_index_ = 0; + size_t z_index_ = 0; + + size_t facet_index_ = 0; +}; +} +} + +namespace CADMesh { + +namespace File { + +inline State *STLReader::CADMeshLexerState(StartSolid) { + if (DoesNotMatchExactly("solid")) + Error("STL files start with 'solid'. Make sure you are using an ASCII STL " + "file."); + + SkipWhiteSpace(); + + RestOfLine(); + + StartOfA(Solid); + + SkipLineBreak(); + NextState(StartFacet); +} + +inline State *STLReader::CADMeshLexerState(EndSolid) { + SkipWhiteSpace(); + SkipLineBreaks(); + SkipWhiteSpace(); + + if (DoesNotMatchExactly("endsolid")) + Error("STL files end with 'endsolid'."); + + Skip(); + EndOfA(Solid); + + FinalState(); +} + +inline State *STLReader::CADMeshLexerState(StartFacet) { + SkipWhiteSpace(); + SkipLineBreaks(); + SkipWhiteSpace(); + + if (DoesNotMatchExactly("facet normal")) + Error("Facets are indicated by the tag 'facet normal'."); + + SkipWhiteSpace(); + + StartOfA(Facet); + + SkipLine(); + + NextState(StartVertices); +} + +inline State *STLReader::CADMeshLexerState(EndFacet) { + SkipWhiteSpace(); + SkipLineBreaks(); + SkipWhiteSpace(); + + if (DoesNotMatchExactly("endfacet")) + Error("The end of a facets is indicated by the tag 'endfacet'."); + + SkipWhiteSpace(); + SkipLineBreak(); + + EndOfA(Facet); + + TryState(StartFacet); + + NextState(EndSolid); +} + +inline State *STLReader::CADMeshLexerState(StartVertices) { + SkipWhiteSpace(); + SkipLineBreaks(); + SkipWhiteSpace(); + + if (DoesNotMatchExactly("outer loop")) + Error("The start of the vertices is indicated by the tag 'outer loop'."); + + SkipWhiteSpace(); + SkipLineBreak(); + + StartOfA(Vertices); + + NextState(Vertex); +} + +inline State *STLReader::CADMeshLexerState(EndVertices) { + SkipWhiteSpace(); + SkipLineBreaks(); + SkipWhiteSpace(); + + if (DoesNotMatchExactly("endloop")) + Error("The end of the vertices is indicated by the tag 'endloop'."); + + SkipWhiteSpace(); + SkipLineBreak(); + + EndOfA(Vertices); + + NextState(EndFacet); +} + +inline State *STLReader::CADMeshLexerState(Vertex) { + SkipWhiteSpace(); + SkipLineBreaks(); + SkipWhiteSpace(); + + if (DoesNotMatchExactly("vertex")) + Error("A vertex is indicated by the tag 'vertex'."); + + SkipWhiteSpace(); + + NextState(ThreeVector); +} + +inline State *STLReader::CADMeshLexerState(ThreeVector) { + SkipWhiteSpace(); + + StartOfA(ThreeVector); + + if (NotANumber()) + Error("First number in three vector not found."); + + ThisIsA(Number); + SkipWhiteSpace(); + + if (NotANumber()) + Error("Second number in three vector not found."); + + ThisIsA(Number); + SkipWhiteSpace(); + + if (NotANumber()) + Error("Third number in three vector not found."); + + ThisIsA(Number); + EndOfA(ThreeVector); + + SkipWhiteSpace(); + + if (DidNotSkipLineBreak()) + Error("Expecting a new line at the end of a three vector."); + + TryState(StartVertices); + + TryState(Vertex); + + NextState(EndVertices); +} + +inline G4bool STLReader::Read(G4String filepath) { + auto items = RunLexer(filepath, StartSolid); + + if (items.size() == 0) { + Exceptions::ParserError("STLReader::Read", + "The STL file appears to be empty."); + } + + for (auto item : items) { + if (item.children.size() == 0) { + std::stringstream error; + error << "The mesh appears to be empty." + << "Error around line " << item.line << "."; + + Exceptions::ParserError("STLReader::Read", error.str()); + } + + auto mesh = ParseMesh(item.children); + + auto name = G4String(item.value); + AddMesh(Mesh::New(mesh, name)); + } + + return true; +} + +inline G4bool STLReader::CanRead(Type file_type) { return (file_type == STL); } + +inline std::shared_ptr<Mesh> STLReader::ParseMesh(Items items) { + Triangles triangles; + + for (auto item : items) { + if (item.children.size() == 0) { + std::stringstream error; + error << "The facet appears to be empty." + << "Error around line " << item.line << "."; + + Exceptions::ParserError("STLReader::Mesh", error.str()); + } + + triangles.push_back(ParseFacet(item.children)); + } + + return Mesh::New(triangles); +} + +inline G4TriangularFacet *STLReader::ParseFacet(Items items) { + Triangles triangles; + + for (auto item : items) { + if (item.children.size() == 0) { + std::stringstream error; + error << "The vertex appears to be empty." + << "Error around line " << item.line << "."; + + Exceptions::ParserError("STLReader::ParseFacet", error.str()); + } + + triangles.push_back(ParseVertices(item.children)); + } + + if (triangles.size() != 1) { + std::stringstream error; + error << "STL files expect exactly 1 triangle per facet."; + + if (items.size() != 0) { + error << "Error around line " << items[0].line << "."; + } + + Exceptions::ParserError("STLReader::ParseFacet", error.str()); + } + + return triangles[0]; +} + +inline G4TriangularFacet *STLReader::ParseVertices(Items items) { + std::vector<G4ThreeVector> vertices; + + for (auto item : items) { + if (item.children.size() == 0) { + std::stringstream error; + error << "The vertex appears to be empty." + << "Error around line " << item.line << "."; + + Exceptions::ParserError("STLReader::ParseVertices", error.str()); + } + + vertices.push_back(ParseThreeVector(item.children)); + } + + if (vertices.size() != 3) { + std::stringstream error; + error << "STL files expect exactly 3 vertices for a triangular facet. "; + + if (items.size() != 0) { + error << "Error around line " << items[0].line << "."; + } + + Exceptions::ParserError("STLReader::ParseVertices", error.str()); + } + + return new G4TriangularFacet(vertices[0], vertices[1], vertices[2], ABSOLUTE); +} + +inline G4ThreeVector STLReader::ParseThreeVector(Items items) { + std::vector<double> numbers; + + for (auto item : items) { + numbers.push_back((double)atof(item.value.c_str())); + } + + if (numbers.size() != 3) { + std::stringstream error; + error << "Three vectors in STL files require exactly 3 numbers"; + + if (items.size() != 0) { + error << "Error around line " << items[0].line << "."; + } + + Exceptions::ParserError("STLReader::ParseThreeVector", error.str()); + } + + return G4ThreeVector(numbers[0], numbers[1], numbers[2]); +} +} +} + +namespace CADMesh { + +namespace File { + +inline State *OBJReader::CADMeshLexerState(StartSolid) { + StartOfA(Solid); + + TryState(Object); + TryState(Vertex); + TryState(Ignore); + + Error("Invalid element tag."); +} + +inline State *OBJReader::CADMeshLexerState(EndSolid) { + if (Next() != "") + lexer->LastError(); + + EndOfA(Solid); + FinalState(); +} + +inline State *OBJReader::CADMeshLexerState(Ignore) { + if (DidNotSkipLine()) + NextState(EndSolid); + + TryState(Object); + TryState(Vertex); + TryState(Facet); + TryState(Ignore); + + NextState(EndSolid); +} + +inline State *OBJReader::CADMeshLexerState(Vertex) { + SkipLineBreaks(); + + if (DoesNotMatchExactly("v ")) + Error("A vertex is indicated by the tag 'v'."); + + SkipWhiteSpace(); + StartOfA(Vertex); + + if (NotANumber()) + Error("First number in three vector not found."); + + ThisIsA(Number); + SkipWhiteSpace(); + + if (NotANumber()) + Error("Second number in three vector not found."); + + ThisIsA(Number); + SkipWhiteSpace(); + + if (NotANumber()) + Error("Third number in three vector not found."); + + ThisIsA(Number); + + EndOfA(Vertex); + + SkipLine(); + + TryState(Vertex); + TryState(Object); + TryState(Facet); + TryState(Ignore); + + NextState(EndSolid); +} + +inline State *OBJReader::CADMeshLexerState(Facet) { + SkipLineBreaks(); + + if (DoesNotMatchExactly("f ")) + Error("A facet is indicated by the tag 'f'."); + + SkipWhiteSpace(); + StartOfA(Facet); + + if (NotANumber()) + Error("First number in three vector not found."); + + ThisIsA(Number); + + OneOf("/"); + Number(); + OneOf("/"); + Number(); + SkipWhiteSpace(); + + if (NotANumber()) + Error("Second number in three vector not found."); + + ThisIsA(Number); + + OneOf("/"); + Number(); + OneOf("/"); + Number(); + SkipWhiteSpace(); + + if (NotANumber()) + Error("Third number in three vector not found."); + + ThisIsA(Number); + + OneOf("/"); + Number(); + OneOf("/"); + Number(); + SkipWhiteSpace(); + + if (Number()) + ThisIsA(Number); + + EndOfA(Facet); + + SkipLine(); + + TryState(Facet); + TryState(Vertex); + TryState(Object); + TryState(Ignore); + + NextState(EndSolid); +} + +inline State *OBJReader::CADMeshLexerState(Object) { + SkipLineBreaks(); + + if (DoesNotMatchExactly("o ")) + Error("An object is indicated by the tag 'o'."); + + EndOfA(Solid); + + SkipWhiteSpace(); + StartOfA(Solid); + + ManyCharacters(); + ThisIsA(Word); + SkipWhiteSpace(); + + TryState(Vertex); + TryState(Facet); + TryState(Object); + TryState(Ignore); + + NextState(EndSolid); +} + +inline G4bool OBJReader::Read(G4String filepath) { + auto items = RunLexer(filepath, StartSolid); + + if (items.size() == 0) { + Exceptions::ParserError("OBJReader::Read", + "The OBJ file appears to be empty."); + } + + for (auto item : items) { + if (item.children.size() == 0) { + continue; + } + + auto mesh = ParseMesh(item.children); + + if (mesh->GetTriangles().size() == 0) { + continue; + } + + G4String name; + + if (item.children[0].token == WordToken) { + name = item.children[0].value; + } + + AddMesh(Mesh::New(mesh, name)); + } + + return true; +} + +inline G4bool OBJReader::CanRead(Type file_type) { return (file_type == OBJ); } + +inline std::shared_ptr<Mesh> OBJReader::ParseMesh(Items items) { + Triangles facets; + + for (auto item : items) { + if (item.token != VertexToken) { + continue; + } + + if (item.children.size() == 0) { + std::stringstream error; + error << "The vertex appears to be empty." + << "Error around line " << item.line << "."; + + Exceptions::ParserError("OBJReader::Mesh", error.str()); + } + + vertices_.push_back(ParseVertex(item.children)); + } + + for (auto item : items) { + if (item.token != FacetToken) { + continue; + } + + if (item.children.size() == 0) { + std::stringstream error; + error << "The facet appears to be empty." + << "Error around line " << item.line << "."; + + Exceptions::ParserError("OBJReader::Mesh", error.str()); + } + + facets.push_back(ParseFacet(item.children, false)); + + if (item.children.size() == 4) { + facets.push_back(ParseFacet(item.children, true)); + } + } + + return Mesh::New(facets); +} + +inline G4ThreeVector OBJReader::ParseVertex(Items items) { + std::vector<double> numbers; + + for (auto item : items) { + numbers.push_back((double)atof(item.value.c_str())); + } + + if (numbers.size() != 3) { + std::stringstream error; + error << "Three vectors in OBJ files require exactly 3 numbers"; + + if (items.size() != 0) { + error << "Error around line " << items[0].line << "."; + } + + Exceptions::ParserError("OBJReader::ParseThreeVector", error.str()); + } + + return G4ThreeVector(numbers[0], numbers[1], numbers[2]); +} + +inline G4TriangularFacet *OBJReader::ParseFacet(Items items, G4bool quad) { + std::vector<int> indices; + + for (auto item : items) { + indices.push_back((int)atoi(item.value.c_str())); + } + + if (indices.size() < 3) { + std::stringstream error; + error << "Facets in OBJ files require at least 3 indicies"; + + if (items.size() != 0) { + error << "Error around line " << items[0].line << "."; + } + + Exceptions::ParserError("OBJReader::ParseFacet", error.str()); + } + + if (quad && indices.size() != 4) { + std::stringstream error; + error << "Trying to triangle-ify a facet that isn't a quad"; + + if (items.size() != 0) { + error << "Error around line " << items[0].line << "."; + } + + Exceptions::ParserError("OBJReader::ParseFacet", error.str()); + } + + if (quad) { + return new G4TriangularFacet(vertices_[indices[0] - 1], + vertices_[indices[2] - 1], + vertices_[indices[3] - 1], ABSOLUTE); + } + + else { + return new G4TriangularFacet(vertices_[indices[0] - 1], + vertices_[indices[1] - 1], + vertices_[indices[2] - 1], ABSOLUTE); + } +} +} +} + +namespace CADMesh { + +namespace File { + +inline State *PLYReader::CADMeshLexerState(StartHeader) { + if (DoesNotMatchExactly("ply")) + Error("PLY files start with 'ply'."); + + StartOfA(Header); + + SkipLine(); + + TryState(Element); + TryState(Ignore); + + Error("Invalid header tag."); +} + +inline State *PLYReader::CADMeshLexerState(EndHeader) { + if (DoesNotMatchExactly("end_header")) + Error("PLY file headers end with 'end_header'."); + + MaybeEndOfA(Element); + + EndOfA(Header); + FinalState(); +} + +inline State *PLYReader::CADMeshLexerState(Element) { + if (DoesNotMatchExactly("element ")) + Error("An element is indicated by the tag 'element'."); + + MaybeEndOfA(Element); + + SkipWhiteSpace(); + StartOfA(Element); + + if (NotManyCharacters()) + Error("Element type not found."); + + ThisIsA(Word); + SkipWhiteSpace(); + + if (NotANumber()) + Error("Element count not found."); + + ThisIsA(Number); + SkipLine(); + + TryState(Property); + TryState(Ignore); + + NextState(EndHeader); +} + +inline State *PLYReader::CADMeshLexerState(Property) { + if (DoesNotMatchExactly("property ")) + Error("An property is indicated by the tag 'property'."); + + SkipWhiteSpace(); + StartOfA(Property); + + if (NotManyCharacters()) + Error("Element type not found."); + + ThisIsA(Word); + SkipWhiteSpace(); + + RestOfLine(); + ThisIsA(Word); + + EndOfA(Property); + + SkipLineBreak(); + + TryState(Property); + TryState(Element); + TryState(EndHeader); + TryState(Ignore); + + NextState(EndHeader); +} + +inline State *PLYReader::CADMeshLexerState(Ignore) { + if (DidNotSkipLine()) + NextState(EndHeader); + + TryState(Element); + TryState(Property); + TryState(EndHeader); + + NextState(Ignore); +} + +inline State *PLYReader::CADMeshLexerState(Vertex) { + SkipLineBreaks(); + SkipWhiteSpace(); + SkipLineBreaks(); + + StartOfA(Vertex); + + size_t i = 0; + + while (i < 32) { + if (AtEndOfLine()) + break; + + SkipWhiteSpace(); + + if (NotANumber()) + Error("Expecting only numbers in the vertex specification."); + + ThisIsA(Number); + SkipWhiteSpace(); + + i++; + } + + EndOfA(Vertex); + + SkipLine(); + + TryState(Vertex); + + FinalState(); +} + +inline State *PLYReader::CADMeshLexerState(Facet) { + SkipLineBreaks(); + SkipWhiteSpace(); + SkipLineBreaks(); + + StartOfA(Facet); + + size_t i = 0; + + while (i < 32) { + if (AtEndOfLine()) + break; + + SkipWhiteSpace(); + + if (NotANumber()) + Error("Expecting only numbers in the facet specification."); + + ThisIsA(Number); + SkipWhiteSpace(); + + i++; + } + + EndOfA(Facet); + + SkipLine(); + + TryState(Facet); + + FinalState(); +} + +inline G4bool PLYReader::Read(G4String filepath) { + auto lexer = Lexer(filepath, new StartHeaderState); + auto items = lexer.GetItems(); + + if (items.size() == 0) { + std::stringstream error; + error << "The header appears to be empty."; + + Exceptions::ParserError("PLYReader::Read", error.str()); + } + + ParseHeader(items); + + lexer.Run(new VertexState, vertex_count_); + auto vertex_items = lexer.GetItems(); + + if (vertex_items.size() == 0) { + Exceptions::ParserError("PLYReader::Read", + "The PLY file appears to have no vertices."); + } + + if (vertex_items.size() != vertex_count_) { + Exceptions::ParserError("PLYReader::Read", + "The PLY file appears to be missing vertices."); + } + + lexer.Run(new FacetState, facet_count_); + auto face_items = lexer.GetItems(); + + if (face_items.size() == 0) { + Exceptions::ParserError("PLYReader::Read", + "The PLY file appears to have no facets."); + } + + if (face_items.size() != facet_count_) { + Exceptions::ParserError("PLYReader::Read", + "The PLY file appears to be missing facets"); + } + + auto mesh = ParseMesh(vertex_items, face_items); + AddMesh(Mesh::New(mesh)); + + return true; +} + +inline G4bool PLYReader::CanRead(Type file_type) { return (file_type == PLY); } + +inline void PLYReader::ParseHeader(Items items) { + if (items.size() != 1) { + std::stringstream error; + error << "The header appears to be invalid or missing." + << "Error around line 1."; + + Exceptions::ParserError("PLYReader::ParseHeader", error.str()); + } + + for (auto item : items[0].children) { + if (item.token == ElementToken) { + if (item.children.size() < 2) { + std::stringstream error; + error << "Invalid element information in header. Expecting 'vertex' or " + "'face' and a number." + << "Error around line " << item.line << "."; + + Exceptions::ParserError("PLYReader::ParseHeader", error.str()); + } + + if (item.children[0].token == WordToken && + item.children[1].token == NumberToken) { + if (item.children[0].value == "vertex") { + vertex_count_ = atoi(item.children[1].value.c_str()); + + for (size_t i = 2; i < item.children.size(); i++) { + auto property = item.children[i]; + + if (property.children.size() > 1) { + if (property.children[1].token == WordToken) { + if (property.children[1].value == "x") { + x_index_ = i - 2; + } + + if (property.children[1].value == "y") { + y_index_ = i - 2; + } + + if (property.children[1].value == "z") { + z_index_ = i - 2; + } + } + } + } + } + + else if (item.children[0].value == "face") { + facet_count_ = atoi(item.children[1].value.c_str()); + + for (size_t i = 2; i < item.children.size(); i++) { + auto property = item.children[i]; + + if (property.children.size() > 1) { + if (property.children[1].token == WordToken) { + if (property.children[1].value == "uchar int vertex_indices") { + facet_index_ = i - 2; + } + } + } + } + } + } + } + } + + if (vertex_count_ == 0) { + std::stringstream error; + error << "The number of vertices was not found in the header."; + + Exceptions::ParserError("PLYReader::ParseHeader", error.str()); + } + + if (facet_count_ == 0) { + std::stringstream error; + error << "The number of faces was not found in the header."; + + Exceptions::ParserError("PLYReader::ParseHeader", error.str()); + } + + if ((x_index_ == y_index_) || (y_index_ == z_index_) || + (x_index_ == z_index_)) { + std::stringstream error; + error << "The vertex x, y, z indices were not found in the header."; + + Exceptions::ParserError("PLYReader::ParseHeader", error.str()); + } +} + +inline std::shared_ptr<Mesh> PLYReader::ParseMesh(Items vertex_items, + Items face_items) { + Points vertices; + Triangles facets; + + for (auto item : vertex_items) { + if (item.children.size() == 0) { + std::stringstream error; + error << "The vertex appears to be empty." + << "Error around line " << item.line << "."; + + Exceptions::ParserError("PLYReader::ParseMesh", error.str()); + } + + if (item.token == VertexToken) { + vertices.push_back(ParseVertex(item.children)); + } + } + + for (auto item : face_items) { + if (item.children.size() == 0) { + std::stringstream error; + error << "The facet appears to be empty." + << "Error around line " << item.line << "."; + + Exceptions::ParserError("PLYReader::Mesh", error.str()); + } + + if (item.token == FacetToken) { + facets.push_back(ParseFacet(item.children, vertices)); + } + } + + return Mesh::New(facets); +} + +inline G4ThreeVector PLYReader::ParseVertex(Items items) { + std::vector<double> numbers; + + for (auto item : items) { + numbers.push_back((double)atof(item.value.c_str())); + } + + if (numbers.size() < 3) { + std::stringstream error; + error << "Vertices in PLY files require atleast 3 numbers. "; + + if (items.size() != 0) { + error << "Error around line " << items[0].line << "."; + } + + Exceptions::ParserError("PLYReader::ParseVertex", error.str()); + } + + return G4ThreeVector(numbers[x_index_], numbers[y_index_], numbers[z_index_]); +} + +inline G4TriangularFacet *PLYReader::ParseFacet(Items items, Points vertices) { + std::vector<int> indices; + + for (auto item : items) { + indices.push_back((int)atoi(item.value.c_str())); + } + + if (indices.size() < 4) { + std::stringstream error; + error << "Facets in PLY files require 3 indicies"; + + if (items.size() != 0) { + error << "Error around line " << items[0].line << "."; + } + + Exceptions::ParserError("PLYReader::ParseFacet", error.str()); + } + + return new G4TriangularFacet(vertices[indices[1 + facet_index_]], + vertices[indices[2 + facet_index_]], + vertices[indices[3 + facet_index_]], ABSOLUTE); +} +} +} + +#ifdef USE_CADMESH_ASSIMP_READER + +namespace CADMesh { + +namespace File { + +inline ASSIMPReader::ASSIMPReader() : Reader("ASSIMPReader") { + importer_ = new Assimp::Importer(); +} + +inline ASSIMPReader::~ASSIMPReader() { delete importer_; } + +inline G4bool ASSIMPReader::Read(G4String filepath) { + auto scene = importer_->ReadFile(filepath.c_str(), + aiProcess_Triangulate | + aiProcess_JoinIdenticalVertices | + aiProcess_CalcTangentSpace); + + if (!scene) { + Exceptions::FileNotFound("ASSIMP::Read", filepath); + return false; + } + + for (unsigned int index = 0; index < scene->mNumMeshes; index++) { + aiMesh *mesh = scene->mMeshes[index]; + auto name = mesh->mName.C_Str(); + + Triangles triangles; + + for (unsigned int i = 0; i < mesh->mNumFaces; i++) { + const aiFace &face = mesh->mFaces[i]; + + G4ThreeVector a(mesh->mVertices[face.mIndices[0]].x, + mesh->mVertices[face.mIndices[0]].y, + mesh->mVertices[face.mIndices[0]].z); + + G4ThreeVector b(mesh->mVertices[face.mIndices[1]].x, + mesh->mVertices[face.mIndices[1]].y, + mesh->mVertices[face.mIndices[1]].z); + + G4ThreeVector c(mesh->mVertices[face.mIndices[2]].x, + mesh->mVertices[face.mIndices[2]].y, + mesh->mVertices[face.mIndices[2]].z); + + triangles.push_back(new G4TriangularFacet(a, b, c, ABSOLUTE)); + } + + AddMesh(Mesh::New(triangles, name)); + } + + return true; +} + +inline G4bool ASSIMPReader::CanRead(Type /*file_type*/) { return true; } + +std::shared_ptr<ASSIMPReader> ASSIMP() { + return std::make_shared<ASSIMPReader>(); +} +} +} +#endif + +namespace CADMesh { + +namespace File { + +inline G4bool BuiltInReader::Read(G4String filepath) { + File::Reader *reader = nullptr; + + auto type = TypeFromName(filepath); + + if (type == STL) { + reader = new File::STLReader(); + } + + else if (type == OBJ) { + reader = new File::OBJReader(); + } + + else if (type == PLY) { + reader = new File::PLYReader(); + } + + else { + Exceptions::ReaderCantReadError("BuildInReader::Read", type, filepath); + } + + if (!reader->Read(filepath)) { + return false; + } + + SetMeshes(reader->GetMeshes()); + return true; +} + +inline G4bool BuiltInReader::CanRead(Type type) { + return type == STL || type == OBJ || type == PLY; +} + +inline std::shared_ptr<BuiltInReader> BuiltIn() { + return std::make_shared<BuiltInReader>(); +} +} +} diff --git a/NPSimulation/Detectors/Strasse/Strasse.cc b/NPSimulation/Detectors/Strasse/Strasse.cc index 47e27e931ffd16034842e0504ec7d246cda232c3..0ee0ab3daf49125fde7313d92332e070399c7085 100644 --- a/NPSimulation/Detectors/Strasse/Strasse.cc +++ b/NPSimulation/Detectors/Strasse/Strasse.cc @@ -55,6 +55,9 @@ // CLHEP header #include "CLHEP/Random/RandGauss.h" +// CAD Mesh +#include "CADMesh.hh" + using namespace std; using namespace CLHEP; @@ -85,6 +88,8 @@ namespace Strasse_NS{ double Inner_PCB_DownstreamWidth=2*mm; double Inner_PCB_MidWidth=2*mm; double Inner_PCB_Thickness=3*mm; + double Inner_PCB_Ledge = 1*mm ; + double Inner_PCB_Step = 2*mm ; double Inner_Wafer_TransverseStrips= 128; double Inner_Wafer_LongitudinalStrips= 128; @@ -108,6 +113,8 @@ namespace Strasse_NS{ double Outer_PCB_DownstreamWidth=2*mm; double Outer_PCB_MidWidth=2*mm; double Outer_PCB_Thickness=3*mm; + double Outer_PCB_Ledge = 1*mm ; + double Outer_PCB_Step = 2*mm ; double Outer_Wafer_TransverseStrips= 128; double Outer_Wafer_LongitudinalStrips= 128; @@ -140,8 +147,14 @@ Strasse::Strasse(){ m_InnerDetector=0; m_OuterDetector=0; m_Chamber=0; - m_Frame=0; + m_Blades=0; + m_Stars=0; + m_Base=0; m_Electronic=0; + found_chamber = false; + found_stars = false; + found_blades = false; + found_base = false; // Dark Grey SiliconVisAtt = new G4VisAttributes(G4Colour(0.5, 0.5, 0.5)) ; // Green @@ -149,11 +162,13 @@ Strasse::Strasse(){ // Gold Yellow PADVisAtt = new G4VisAttributes(G4Colour(0.5, 0.5, 0.2)) ; // Light Grey - FrameVisAtt = new G4VisAttributes(G4Colour(0.5, 0.5, 0.5)) ; + StarsVisAtt = new G4VisAttributes(G4Colour(0.5, 0.5, 0.5)) ; // Space transparent ChamberVisAtt = new G4VisAttributes(G4Colour(0.3, 0.4, 0.5,0.2)) ; // Light Blue - GuardRingVisAtt = new G4VisAttributes(G4Colour(0, 0, 0,0.5)) ; + GuardRingVisAtt = new G4VisAttributes(G4Colour(0.85, 0.85, 0.85,0.5)) ; + // Light Blue + BladeVisAtt = new G4VisAttributes(G4Colour(1, 0.65, 0.0,0.7)) ; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... @@ -199,12 +214,15 @@ G4LogicalVolume* Strasse::BuildInnerDetector(){ +Inner_PCB_PortWidth; vector<G4TwoVector> PCBCrossSection; - double l1 = Inner_PCB_Thickness*0.5/tan(Inner_PCB_BevelAngle); + + double l1; + if(Inner_PCB_BevelAngle==90) l1 = 0; + else l1 = Inner_PCB_Thickness*0.5/tan(Inner_PCB_BevelAngle); PCBCrossSection.push_back(G4TwoVector(Inner_PCB_Width*0.5-l1,-Inner_PCB_Thickness*0.5)); PCBCrossSection.push_back(G4TwoVector(Inner_PCB_Width*0.5,Inner_PCB_Thickness*0.5)); - PCBCrossSection.push_back(G4TwoVector(-Inner_PCB_Width*0.5-l1,Inner_PCB_Thickness*0.5)); - PCBCrossSection.push_back(G4TwoVector(-Inner_PCB_Width*0.5,-Inner_PCB_Thickness*0.5)); + PCBCrossSection.push_back(G4TwoVector(-Inner_PCB_Width*0.5,Inner_PCB_Thickness*0.5)); + PCBCrossSection.push_back(G4TwoVector(-Inner_PCB_Width*0.5+l1,-Inner_PCB_Thickness*0.5)); G4ExtrudedSolid* PCBFull = new G4ExtrudedSolid("PCBFull", @@ -219,7 +237,7 @@ G4LogicalVolume* Strasse::BuildInnerDetector(){ m_InnerDetector->SetVisAttributes(G4VisAttributes::Invisible); /////////////////////////////////////////////////////////////////////////// - // Build the external PCB layer + // Build the external PCB frame // Calculate the hole shift within the PCB double Width_Shift= -0.5*Inner_PCB_Width + 0.5*Inner_Wafer_Width // Flush to border +Inner_PCB_PortWidth; // add the port side shift @@ -256,33 +274,23 @@ G4LogicalVolume* Strasse::BuildInnerDetector(){ false,0); /////////////////////////////////////////////////////////////////////////// - // Build the internal PCB layer - double offsetPCB2 = -0.3; - double Inner_PCB2_Thickness = Inner_PCB_Thickness + offsetPCB2; + // Build the PCB Ledge on wich Silicon is glued + double Inner_PCB2_Thickness = Inner_PCB_Step; //Step size + double offsetPCB2 = Inner_PCB2_Thickness - Inner_PCB_Thickness; - double Inner_PCB2_StarboardWidth = Inner_PCB_StarboardWidth; - double Inner_PCB2_PortWidth = Inner_PCB_PortWidth; - double Inner_PCB2_UpstreamWidth = Inner_PCB_UpstreamWidth; double Inner_PCB2_MidWidth = Inner_PCB_MidWidth; - double Inner_PCB2_DownstreamWidth =Inner_PCB_DownstreamWidth; // perpendicular to beam axis - double Inner_PCB2_Width= Inner_Wafer_Width-Inner_PCB_PortWidth*2 - +Inner_PCB2_StarboardWidth - +Inner_PCB2_PortWidth; + double Inner_PCB2_Width= Inner_Wafer_Width; vector<G4TwoVector> PCB2CrossSection; - double l21 = Inner_PCB2_Thickness*0.5/tan(Inner_PCB_BevelAngle); - - PCB2CrossSection.push_back(G4TwoVector(Inner_PCB2_Width*0.5-l21,-Inner_PCB2_Thickness*0.5)); + PCB2CrossSection.push_back(G4TwoVector(Inner_PCB2_Width*0.5,-Inner_PCB2_Thickness*0.5)); PCB2CrossSection.push_back(G4TwoVector(Inner_PCB2_Width*0.5,Inner_PCB2_Thickness*0.5)); - PCB2CrossSection.push_back(G4TwoVector(-Inner_PCB2_Width*0.5-l21,Inner_PCB2_Thickness*0.5)); + PCB2CrossSection.push_back(G4TwoVector(-Inner_PCB2_Width*0.5,Inner_PCB2_Thickness*0.5)); PCB2CrossSection.push_back(G4TwoVector(-Inner_PCB2_Width*0.5,-Inner_PCB2_Thickness*0.5)); - double Inner_PCB2_Length= 2*(Inner_Wafer_Length-Inner_PCB_PortWidth) - +Inner_PCB2_UpstreamWidth - +Inner_PCB2_MidWidth - +Inner_PCB2_DownstreamWidth; + //double Inner_PCB2_Length= Inner_PCB_Length; + double Inner_PCB2_Length= 2*Inner_Wafer_Length + Inner_PCB_MidWidth; G4ExtrudedSolid* PCB2Full = new G4ExtrudedSolid("PCB2Full", @@ -291,36 +299,54 @@ G4LogicalVolume* Strasse::BuildInnerDetector(){ G4TwoVector(0,0),1,// offset, scale G4TwoVector(0,0),1);// offset, scale - G4ThreeVector HoleShift21 = G4ThreeVector(0, 0, 0); + + double Length_Shift21 = -0.5*Inner_PCB_Length // Flush to border + + 0.5*(Inner_PCB_UpstreamWidth+Inner_PCB_DownstreamWidth) // add Upstream side shift + + 0.5*Inner_Wafer_Length; + double Length_Shift22 = Length_Shift21 // overlap detector 1 + + Inner_Wafer_Length // at opposing edge + + Inner_PCB_MidWidth; // after mid width + + G4ThreeVector HoleShift21 = G4ThreeVector(0, 0, Length_Shift21); + G4ThreeVector HoleShift22 = G4ThreeVector(0, 0, Length_Shift22); + G4Box* HoleShape2 = new G4Box("HoleShape2", - Inner_PCB2_Width*0.5 -1, + Inner_Wafer_Width*0.5 - Inner_PCB_Ledge, Inner_PCB2_Thickness, - Inner_PCB2_Length*0.5-1); + Inner_Wafer_Length*0.5 - Inner_PCB_Ledge); // Substracting the hole Shape from the Stock PCB G4SubtractionSolid* PCB2_1 = new G4SubtractionSolid("PCB2_1", PCB2Full, HoleShape2, new G4RotationMatrix,HoleShift21); - + G4SubtractionSolid* PCB2_2 = new G4SubtractionSolid("PCB2_2", PCB2_1, HoleShape2, + new G4RotationMatrix,HoleShift22); + G4ThreeVector HoleCenterBar = G4ThreeVector(0, 0, 0); G4Box* HoleShapeCenterBar = new G4Box("HoleShapeCenterBar", - Inner_PCB2_Width*0.5, + Inner_PCB2_Width*0.5+0.1, Inner_PCB2_Thickness, - 0.5*mm); + Inner_PCB2_MidWidth*0.5); - // Substracting the hole Shape from the Stock PCB - G4SubtractionSolid* PCB2_2 = new G4SubtractionSolid("PCB2_2", PCB2_1, HoleShapeCenterBar, + G4SubtractionSolid* PCB2_3 = new G4SubtractionSolid("PCB2_3", PCB2_2, HoleShapeCenterBar, new G4RotationMatrix,HoleCenterBar); // Sub Volume PCB G4LogicalVolume* logicPCB2 = - new G4LogicalVolume(PCB2_2,m_MaterialPCB,"logicPCB2", 0, 0, 0); - logicPCB2->SetVisAttributes(PCBVisAtt); + new G4LogicalVolume(PCB2_3,m_MaterialPCB,"logicPCB2", 0, 0, 0); + logicPCB2->SetVisAttributes(PADVisAtt); + + // Offset along beam axis between PCB middle and (2*Wafer+MiddleBar) volume center + double CentralZOffset = - Inner_PCB_Length*0.5 + + Inner_PCB_UpstreamWidth + + Inner_Wafer_Length + + Inner_PCB_MidWidth*0.5; new G4PVPlacement(new G4RotationMatrix(0,0,0), - G4ThreeVector(0,-0.5*offsetPCB2,0), + G4ThreeVector(0,-0.5*offsetPCB2,CentralZOffset), logicPCB2,"Strasse_Inner_PCB2",m_InnerDetector, false,0); + /////////////////////////////////////////////////////////////////////////// // Build the Wafer // Sub volume Wafer @@ -337,19 +363,23 @@ G4LogicalVolume* Strasse::BuildInnerDetector(){ new G4LogicalVolume(WaferShape,m_MaterialSilicon,"logicWafer2", 0, 0, 0); logicWafer2->SetVisAttributes(GuardRingVisAtt); + // Shift along Y to flush the wafer to the pcb ledge on one side + G4ThreeVector WaferShiftY = G4ThreeVector(0,-0.5*Inner_Wafer_Thickness + -Inner_Wafer_AlThickness + -0.5*Inner_PCB_Thickness + -offsetPCB2-0.05,0); + + G4ThreeVector WaferShiftZ = G4ThreeVector(0,0,-Inner_PCB_UpstreamWidth-Inner_PCB_MidWidth); + new G4PVPlacement(new G4RotationMatrix(0,0,0), - G4ThreeVector(0,0.5*Inner_Wafer_Thickness - +Inner_Wafer_AlThickness - -0.5*Inner_PCB_Thickness,0) // flush the wafer to the pcb on one side - +HoleShift1, // Shift wafer in the hole + WaferShiftY+WaferShiftZ // Shift along Y + +HoleShift21, // Shift along Z to putwafer in the 1st hole logicWafer1,"Strasse_Inner_Wafer1",m_InnerDetector, false,0); new G4PVPlacement(new G4RotationMatrix(0,0,0), - G4ThreeVector(0,0.5*Inner_Wafer_Thickness - +Inner_Wafer_AlThickness - -0.5*Inner_PCB_Thickness,0)// flush the wafer to the pcb on one side - +HoleShift2, // Shift wafer in the hole + WaferShiftY+WaferShiftZ// Shift along Y + +HoleShift22, // Shift along Z to put wafer in the 2nd hole logicWafer2,"Strasse_Inner_Wafer2",m_InnerDetector, false,0); @@ -378,7 +408,9 @@ G4LogicalVolume* Strasse::BuildInnerDetector(){ G4ThreeVector(0,0,-0.5*(Inner_Wafer_PADExternal-Inner_Wafer_PADInternal)), // assymetric pading for bounding logicActiveWafer2,"Strasse_Inner_ActiveWafer2",logicWafer2, false,2); + } + return m_InnerDetector; } @@ -399,12 +431,14 @@ G4LogicalVolume* Strasse::BuildOuterDetector(){ vector<G4TwoVector> PCBCrossSection; - double l1 = Outer_PCB_Thickness*0.5/tan(Outer_PCB_BevelAngle); + double l1; + if(Outer_PCB_BevelAngle==90) l1 = 0; + else l1 = Outer_PCB_Thickness*0.5/tan(Outer_PCB_BevelAngle); PCBCrossSection.push_back(G4TwoVector(Outer_PCB_Width*0.5-l1,-Outer_PCB_Thickness*0.5)); PCBCrossSection.push_back(G4TwoVector(Outer_PCB_Width*0.5,Outer_PCB_Thickness*0.5)); - PCBCrossSection.push_back(G4TwoVector(-Outer_PCB_Width*0.5-l1,Outer_PCB_Thickness*0.5)); - PCBCrossSection.push_back(G4TwoVector(-Outer_PCB_Width*0.5,-Outer_PCB_Thickness*0.5)); + PCBCrossSection.push_back(G4TwoVector(-Outer_PCB_Width*0.5,Outer_PCB_Thickness*0.5)); + PCBCrossSection.push_back(G4TwoVector(-Outer_PCB_Width*0.5+l1,-Outer_PCB_Thickness*0.5)); G4ExtrudedSolid* PCBFull = new G4ExtrudedSolid("PCBFull", @@ -456,32 +490,21 @@ G4LogicalVolume* Strasse::BuildOuterDetector(){ /////////////////////////////////////////////////////////////////////////// // Build the internal PCB layer - double offsetPCB2 = -0.3; - double Outer_PCB2_Thickness = Outer_PCB_Thickness + offsetPCB2; + double Outer_PCB2_Thickness = Outer_PCB_Step;//Step size + double offsetPCB2 = Outer_PCB2_Thickness - Outer_PCB_Thickness; - double Outer_PCB2_StarboardWidth = Outer_PCB_StarboardWidth; - double Outer_PCB2_PortWidth = Outer_PCB_PortWidth; - double Outer_PCB2_UpstreamWidth =Outer_PCB_UpstreamWidth; - double Outer_PCB2_MidWidth =Outer_PCB_MidWidth; - double Outer_PCB2_DownstreamWidth =Outer_PCB_DownstreamWidth; + double Outer_PCB2_MidWidth = Outer_PCB_MidWidth; // perpendicular to beam axis - double Outer_PCB2_Width= Outer_Wafer_Width-Outer_PCB_PortWidth*2 - +Outer_PCB2_StarboardWidth - +Outer_PCB2_PortWidth; + double Outer_PCB2_Width= Outer_Wafer_Width; vector<G4TwoVector> PCB2CrossSection; - double l21 = Outer_PCB2_Thickness*0.5/tan(Outer_PCB_BevelAngle); - - PCB2CrossSection.push_back(G4TwoVector(Outer_PCB2_Width*0.5-l21,-Outer_PCB2_Thickness*0.5)); + PCB2CrossSection.push_back(G4TwoVector(Outer_PCB2_Width*0.5,-Outer_PCB2_Thickness*0.5)); PCB2CrossSection.push_back(G4TwoVector(Outer_PCB2_Width*0.5,Outer_PCB2_Thickness*0.5)); - PCB2CrossSection.push_back(G4TwoVector(-Outer_PCB2_Width*0.5-l21,Outer_PCB2_Thickness*0.5)); + PCB2CrossSection.push_back(G4TwoVector(-Outer_PCB2_Width*0.5,Outer_PCB2_Thickness*0.5)); PCB2CrossSection.push_back(G4TwoVector(-Outer_PCB2_Width*0.5,-Outer_PCB2_Thickness*0.5)); - double Outer_PCB2_Length= 2*(Outer_Wafer_Length-Outer_PCB_PortWidth) - +Outer_PCB2_UpstreamWidth - +Outer_PCB2_MidWidth - +Outer_PCB2_DownstreamWidth; + double Outer_PCB2_Length= 2*Outer_Wafer_Length + Outer_PCB_MidWidth; G4ExtrudedSolid* PCB2Full = new G4ExtrudedSolid("PCB2Full", @@ -490,33 +513,51 @@ G4LogicalVolume* Strasse::BuildOuterDetector(){ G4TwoVector(0,0),1,// offset, scale G4TwoVector(0,0),1);// offset, scale - G4ThreeVector HoleShift21 = G4ThreeVector(0, 0, 0); + // Offset along beam axis between PCB middle and (2*Wafer+MiddleBar) volume center + double CentralZOffset = - Outer_PCB_Length*0.5 + + Outer_PCB_UpstreamWidth + + Outer_Wafer_Length + + Outer_PCB_MidWidth*0.5; + + double Length_Shift21 = -0.5*Outer_PCB_Length // Flush to border + + 0.5*(Outer_PCB_UpstreamWidth+Outer_PCB_DownstreamWidth) // add Upstream side shift + + 0.5*Outer_Wafer_Length; + double Length_Shift22 = Length_Shift21 // overlap detector 1 + + Outer_Wafer_Length // at opposing edge + + Outer_PCB_MidWidth; // after mid width + + G4ThreeVector HoleShift21 = G4ThreeVector(0, 0, Length_Shift21); + G4ThreeVector HoleShift22 = G4ThreeVector(0, 0, Length_Shift22); + G4Box* HoleShape2 = new G4Box("HoleShape2", - Outer_PCB2_Width*0.5 -1, + Outer_Wafer_Width*0.5 - Outer_PCB_Ledge, Outer_PCB2_Thickness, - Outer_PCB2_Length*0.5-1); + Outer_Wafer_Length*0.5 - Outer_PCB_Ledge); // Substracting the hole Shape from the Stock PCB G4SubtractionSolid* PCB2_1 = new G4SubtractionSolid("PCB2_1", PCB2Full, HoleShape2, new G4RotationMatrix,HoleShift21); + G4SubtractionSolid* PCB2_2 = new G4SubtractionSolid("PCB2_2", PCB2_1, HoleShape2, + new G4RotationMatrix,HoleShift22); G4ThreeVector HoleCenterBar = G4ThreeVector(0, 0, 0); G4Box* HoleShapeCenterBar = new G4Box("HoleShapeCenterBar", - Outer_PCB2_Width*0.5, + Outer_PCB2_Width*0.5+0.1, Outer_PCB2_Thickness, - 0.5*mm); + Outer_PCB2_MidWidth*0.5); // Substracting the hole Shape from the Stock PCB - G4SubtractionSolid* PCB2_2 = new G4SubtractionSolid("PCB2_2", PCB2_1, HoleShapeCenterBar, + G4SubtractionSolid* PCB2_3 = new G4SubtractionSolid("PCB2_3", PCB2_2, HoleShapeCenterBar, new G4RotationMatrix,HoleCenterBar); // Sub Volume PCB G4LogicalVolume* logicPCB2 = - new G4LogicalVolume(PCB2_2,m_MaterialPCB,"logicPCB2", 0, 0, 0); - logicPCB2->SetVisAttributes(PCBVisAtt); + new G4LogicalVolume(PCB2_3,m_MaterialPCB,"logicPCB2", 0, 0, 0); + logicPCB2->SetVisAttributes(PADVisAtt); new G4PVPlacement(new G4RotationMatrix(0,0,0), - G4ThreeVector(0,-0.5*offsetPCB2,0), + //G4ThreeVector(0,-0.5*offsetPCB2,Outer_PCB_UpstreamWidth-Outer_PCB_MidWidth), + G4ThreeVector(0,-0.5*offsetPCB2,CentralZOffset), logicPCB2,"Strasse_Outer_PCB2",m_OuterDetector, false,0); @@ -577,6 +618,7 @@ G4LogicalVolume* Strasse::BuildOuterDetector(){ G4ThreeVector(0,0,-0.5*(Outer_Wafer_PADExternal-Outer_Wafer_PADInternal)), // assymetric pading for bounding logicActiveWafer2,"Strasse_Outer_ActiveWafer2",logicWafer2, false,2); + } return m_OuterDetector; } @@ -655,6 +697,78 @@ G4LogicalVolume* Strasse::BuildChamber(){ } +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +G4LogicalVolume* Strasse::BuildChamberFromCAD(string path){ + if(!m_Chamber){ + auto mesh = CADMesh::TessellatedMesh::FromSTL((char*) path.c_str()); + mesh->SetScale(mm); + //mesh->SetOffset(offset); + mesh->SetReverse(false); + + auto cad_solid = mesh->GetSolid(); + m_Chamber = new G4LogicalVolume(cad_solid, + m_MaterialAl, + "Strasse_Chamber", 0, 0, 0); + + m_Chamber->SetVisAttributes(ChamberVisAtt); + } + return m_Chamber; + +} +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +G4LogicalVolume* Strasse::BuildBlades(string path){ + if(!m_Blades){ + auto mesh = CADMesh::TessellatedMesh::FromSTL((char*) path.c_str()); + mesh->SetScale(mm); + //mesh->SetOffset(offset); + mesh->SetReverse(false); + + auto cad_solid = mesh->GetSolid(); + m_Blades = new G4LogicalVolume(cad_solid, + m_MaterialCu, + "Strasse_Blades", 0, 0, 0); + + m_Blades->SetVisAttributes(BladeVisAtt); + } + return m_Blades; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +G4LogicalVolume* Strasse::BuildStars(string path){ + if(!m_Stars){ + auto mesh = CADMesh::TessellatedMesh::FromSTL((char*) path.c_str()); + mesh->SetScale(mm); + //mesh->SetOffset(offset); + mesh->SetReverse(false); + + auto cad_solid = mesh->GetSolid(); + m_Stars = new G4LogicalVolume(cad_solid, + m_MaterialAl, + "Strasse_Stars", 0, 0, 0); + + m_Stars->SetVisAttributes(StarsVisAtt); + } + return m_Stars; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +G4LogicalVolume* Strasse::BuildBase(string path){ + if(!m_Base){ + auto mesh = CADMesh::TessellatedMesh::FromSTL((char*) path.c_str()); + mesh->SetScale(mm); + //mesh->SetOffset(offset); + mesh->SetReverse(false); + + auto cad_solid = mesh->GetSolid(); + m_Base = new G4LogicalVolume(cad_solid, + m_MaterialAl, + "Strasse_Base", 0, 0, 0); + + m_Base->SetVisAttributes(StarsVisAtt); + } + return m_Base; +} + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... @@ -688,6 +802,8 @@ void Strasse::ReadConfiguration(NPL::InputParser parser){ "Inner_PCB_DownstreamWidth", "Inner_PCB_MidWidth", "Inner_PCB_Thickness", + "Inner_PCB_Ledge", + "Inner_PCB_Step", "Inner_Wafer_TransverseStrips", "Inner_Wafer_LongitudinalStrips", "Outer_Wafer_Length", @@ -704,6 +820,8 @@ void Strasse::ReadConfiguration(NPL::InputParser parser){ "Outer_PCB_DownstreamWidth", "Outer_PCB_MidWidth", "Outer_PCB_Thickness", + "Outer_PCB_Ledge", + "Outer_PCB_Step", "Outer_Wafer_TransverseStrips", "Outer_Wafer_LongitudinalStrips", "Chamber_Thickness", @@ -734,6 +852,8 @@ void Strasse::ReadConfiguration(NPL::InputParser parser){ Inner_PCB_DownstreamWidth = blocks_info[0]->GetDouble("Inner_PCB_DownstreamWidth","mm"); Inner_PCB_MidWidth = blocks_info[0]->GetDouble("Inner_PCB_MidWidth","mm"); Inner_PCB_Thickness = blocks_info[0]->GetDouble("Inner_PCB_Thickness","mm"); + Inner_PCB_Ledge = blocks_info[0]->GetDouble("Inner_PCB_Ledge","mm"); + Inner_PCB_Step = blocks_info[0]->GetDouble("Inner_PCB_Step","mm"); Outer_Wafer_Length = blocks_info[0]->GetDouble("Outer_Wafer_Length","mm"); Outer_Wafer_Width = blocks_info[0]->GetDouble("Outer_Wafer_Width","mm"); Outer_Wafer_Thickness = blocks_info[0]->GetDouble("Outer_Wafer_Thickness","mm"); @@ -750,6 +870,8 @@ void Strasse::ReadConfiguration(NPL::InputParser parser){ Outer_PCB_DownstreamWidth = blocks_info[0]->GetDouble("Outer_PCB_DownstreamWidth","mm"); Outer_PCB_MidWidth = blocks_info[0]->GetDouble("Outer_PCB_MidWidth","mm"); Outer_PCB_Thickness = blocks_info[0]->GetDouble("Outer_PCB_Thickness","mm"); + Outer_PCB_Ledge = blocks_info[0]->GetDouble("Outer_PCB_Ledge","mm"); + Outer_PCB_Step = blocks_info[0]->GetDouble("Outer_PCB_Step","mm"); Chamber_Thickness= blocks_info[0]->GetDouble("Chamber_Thickness","mm"); Chamber_Cylinder_Length= blocks_info[0]->GetDouble("Chamber_Cylinder_Length","mm"); Chamber_Radius= blocks_info[0]->GetDouble("Chamber_Radius","mm"); @@ -837,6 +959,32 @@ void Strasse::ReadConfiguration(NPL::InputParser parser){ } + // Inactive material inside chamber imported form CAD drawings + vector<NPL::InputBlock*> blocks_material = parser.GetAllBlocksWithTokenAndValue("Strasse","InactiveMaterial"); + if(NPOptionManager::getInstance()->GetVerboseLevel()) + cout << "//// " << blocks_material.size() << " inactive material found " << endl; + + for(unsigned int i = 0 ; i < blocks_material.size() ; i++){ + if(NPOptionManager::getInstance()->GetVerboseLevel()) + cout << endl << "//// Strasse Inactive material from CAD " << i+1 << endl; + + if(blocks_material[i]->HasToken("Chamber")){ + ChamberPath= blocks_material[i]->GetString("Chamber"); + found_chamber = true; + } + if(blocks_material[i]->HasToken("Stars")){ + StarsPath= blocks_material[i]->GetString("Stars"); + found_stars = true; + } + if(blocks_material[i]->HasToken("Blades")){ + BladesPath= blocks_material[i]->GetString("Blades"); + found_blades = true; + } + if(blocks_material[i]->HasToken("Base")){ + BasePath= blocks_material[i]->GetString("Base"); + found_base = true; + } + } } @@ -848,7 +996,7 @@ void Strasse::ConstructDetector(G4LogicalVolume* world){ // Inner Barrel for (unsigned short i = 0 ; i < m_Inner_R.size() ; i++) { - G4ThreeVector Det_pos = G4ThreeVector(m_Inner_Shift[i],m_Inner_R[i]+0.5*Inner_PCB_Thickness,m_Inner_Z[i]) ; + G4ThreeVector Det_pos = G4ThreeVector(m_Inner_Shift[i],m_Inner_R[i]+0.5*Inner_PCB_Thickness+0.001,m_Inner_Z[i]) ; //0.001 offset just to avoid overlap with frame Det_pos.rotate(-m_Inner_Phi[i],G4ThreeVector(0,0,1)); G4RotationMatrix* Rot = new G4RotationMatrix(0*deg,0*deg,m_Inner_Phi[i]); @@ -859,7 +1007,7 @@ void Strasse::ConstructDetector(G4LogicalVolume* world){ // Outer Barrel for (unsigned short i = 0 ; i < m_Outer_R.size() ; i++) { - G4ThreeVector Det_pos = G4ThreeVector(m_Outer_Shift[i],m_Outer_R[i]+0.5*Inner_PCB_Thickness,m_Outer_Z[i]) ; + G4ThreeVector Det_pos = G4ThreeVector(m_Outer_Shift[i],m_Outer_R[i]+0.5*Inner_PCB_Thickness+0.001,m_Outer_Z[i]) ;//0.001 offset just to avoid overlap with frame Det_pos.rotate(-m_Outer_Phi[i],G4ThreeVector(0,0,1)); G4RotationMatrix* Rot = new G4RotationMatrix(0*deg,0*deg,m_Outer_Phi[i]); @@ -869,6 +1017,7 @@ void Strasse::ConstructDetector(G4LogicalVolume* world){ } // Chamber + /* for (unsigned short i = 0 ; i < m_Chamber_Z.size() ; i++) { G4ThreeVector Det_pos = G4ThreeVector(0,0,-m_Chamber_Z[i]) ; G4RotationMatrix* Rot = new G4RotationMatrix(); @@ -877,6 +1026,35 @@ void Strasse::ConstructDetector(G4LogicalVolume* world){ BuildChamber(), "Strasse",world,false,i+1); } + */ + + + //G4ThreeVector Det_pos = G4ThreeVector(0,0,+11.5) ; + G4ThreeVector Det_pos = G4ThreeVector(0,0,0) ; + G4RotationMatrix* Rot = new G4RotationMatrix(); + Rot->rotateY(270.*deg); + Rot->rotateX(0.*deg); + + if(found_chamber){ + new G4PVPlacement(Rot, Det_pos, BuildChamberFromCAD(ChamberPath), + "Strasse_Chamber",world, false, 0); + } + + if(found_blades){ + new G4PVPlacement(Rot, Det_pos, BuildBlades(BladesPath), + "Strasse_Blades",world, false, 0); + } + if(found_stars){ + G4ThreeVector Det_pos2 = G4ThreeVector(0,0,0) ; + new G4PVPlacement(Rot, Det_pos2, BuildStars(StarsPath), + "Strasse_Stars",world, false, 0); + } + if(found_base){ + G4ThreeVector Det_pos3 = G4ThreeVector(0,0,0) ; + new G4PVPlacement(Rot, Det_pos3, BuildBase(BasePath), + "Strasse_Base",world, false, 0); + } + } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... // Add Detector branch to the EventTree. @@ -1087,6 +1265,7 @@ void Strasse::InitializeMaterial(){ m_MaterialSilicon = MaterialManager::getInstance()->GetMaterialFromLibrary("Si"); m_MaterialAl = MaterialManager::getInstance()->GetMaterialFromLibrary("Al"); m_MaterialPCB = MaterialManager::getInstance()->GetMaterialFromLibrary("PCB"); + m_MaterialCu = MaterialManager::getInstance()->GetMaterialFromLibrary("Cu"); m_MaterialVacuum = MaterialManager::getInstance()->GetMaterialFromLibrary("Vacuum"); } diff --git a/NPSimulation/Detectors/Strasse/Strasse.hh b/NPSimulation/Detectors/Strasse/Strasse.hh index f2012f6ee502b60b8c250f8b7a2c858450866c8a..0250f105e330526b09a2647d71867cc38f665c5c 100644 --- a/NPSimulation/Detectors/Strasse/Strasse.hh +++ b/NPSimulation/Detectors/Strasse/Strasse.hh @@ -57,16 +57,29 @@ class Strasse : public NPS::VDetector{ G4LogicalVolume* BuildInnerDetector(); G4LogicalVolume* BuildOuterDetector(); G4LogicalVolume* BuildElectronic(); - G4LogicalVolume* BuildFrame(); G4LogicalVolume* BuildChamber(); + G4LogicalVolume* BuildChamberFromCAD(string path); + G4LogicalVolume* BuildStars(string path); + G4LogicalVolume* BuildBlades(string path); + G4LogicalVolume* BuildBase(string path); private: G4LogicalVolume* m_InnerDetector; G4LogicalVolume* m_OuterDetector; G4LogicalVolume* m_Electronic; - G4LogicalVolume* m_Frame; + G4LogicalVolume* m_Stars; G4LogicalVolume* m_Chamber; - + G4LogicalVolume* m_Blades; + G4LogicalVolume* m_Base; + + string ChamberPath; + string BasePath; + string StarsPath; + string BladesPath; + bool found_chamber; + bool found_blades; + bool found_stars; + bool found_base; private: // Initialize material used in detector definition @@ -78,6 +91,7 @@ class Strasse : public NPS::VDetector{ G4Material* m_MaterialAl ; G4Material* m_MaterialVacuum ; G4Material* m_MaterialPCB ; + G4Material* m_MaterialCu ; // calculated dimension double m_Active_InnerWafer_Width; @@ -141,8 +155,6 @@ class Strasse : public NPS::VDetector{ vector<double> m_Chamber_Z; - // Visualisation Attribute - //G4VisAttributes* m_VisTrap; // Needed for dynamic loading of the library public: @@ -153,9 +165,10 @@ class Strasse : public NPS::VDetector{ G4VisAttributes* SiliconVisAtt ; G4VisAttributes* PCBVisAtt; G4VisAttributes* PADVisAtt ; - G4VisAttributes* FrameVisAtt ; + G4VisAttributes* StarsVisAtt ; G4VisAttributes* ChamberVisAtt ; G4VisAttributes* GuardRingVisAtt ; + G4VisAttributes* BladeVisAtt ; }; diff --git a/NPSimulation/Scorers/InteractionScorers.cc b/NPSimulation/Scorers/InteractionScorers.cc index 1ab9bed3eee5aae3836793c0927582ab22cdbb4e..00f040f1ecfc58a711fa0c45cdd064ca7ca31954 100644 --- a/NPSimulation/Scorers/InteractionScorers.cc +++ b/NPSimulation/Scorers/InteractionScorers.cc @@ -66,7 +66,7 @@ G4bool PS_Interactions::ProcessHits(G4Step* aStep, G4TouchableHistory*){ //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void PS_Interactions::Initialize(G4HCofThisEvent*){ // Clear is called by EventAction - + clear(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... @@ -76,7 +76,6 @@ void PS_Interactions::EndOfEvent(G4HCofThisEvent*){ for(unsigned int i = 0 ; i < size ; i++) m_InterractionCoordinates->SetInteraction(m_DataVector[i]->GetEnergy(),m_DataVector[i]->GetTime(),m_DataVector[i]->GetPositionX(),m_DataVector[i]->GetPositionY(),m_DataVector[i]->GetPositionZ(),m_DataVector[i]->GetTheta()/deg,m_DataVector[i]->GetPhi()/deg); - clear(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... diff --git a/Projects/ComptonTelescope/online/src/DecodeD.cpp b/Projects/ComptonTelescope/online/src/DecodeD.cpp index 3ef51c8149014f24bed107e60cabd8fb34956b30..3a09dd750da7436982bdd3c75c199e770ad85892 100644 --- a/Projects/ComptonTelescope/online/src/DecodeD.cpp +++ b/Projects/ComptonTelescope/online/src/DecodeD.cpp @@ -100,7 +100,7 @@ __EVENTTYPE__* DecodeD::getEvent() void DecodeD::decodeEvent() { - this -> Clear(); + /*this -> */Clear(); switch (datatype) { case D_ROOT: if (cursor < length) { diff --git a/Projects/ComptonTelescope/online/src/online_coinc.cpp b/Projects/ComptonTelescope/online/src/online_coinc.cpp index a8ad64d2676ed419b98101a0e2e2cd48aae51346..3b6cedac406382013936dbc79bb7685b8364181c 100644 --- a/Projects/ComptonTelescope/online/src/online_coinc.cpp +++ b/Projects/ComptonTelescope/online/src/online_coinc.cpp @@ -16,6 +16,10 @@ #include "DecodeD.h" #include "DecodeT.h" +#define __RUN__ 3 + +#define __1DET__ + #define __TEST_ZONE__ #undef __TEST_ZONE__ @@ -105,15 +109,47 @@ int main(int argc, char** argv) auto ccamPhys = (TComptonTelescopePhysics*) m_NPDetectorManager->GetDetector("ComptonTelescope"); ccamPhys->SetRawDataPointer(ccamData); +#ifdef __1DET__ + ifstream is; + is.open("/disk/proto-data/data/20210510_Bi207/mfm_rdd_rosmap_04_mfm_rosmap_04_2021-05-10_07_41_50.raw"); + is.seekg(0, ios::end); + int len = is.tellg(); + is.seekg(0, ios::beg); + char* buff = new char[len]; + is.read(buff, len); + is.close(); + DecodeR* DR = new DecodeR(false, buff); + while(DR -> getCursor() < len) { + DR -> decodeBlobMFM(); + m_NPDetectorManager->ClearEventPhysics(); + m_NPDetectorManager->ClearEventData(); + ccamData -> SetCTCalorimeter(1, 4, DR->getPixelNumber(), DR->getTime(), DR->getData(), 64); + m_NPDetectorManager->BuildPhysicalEvent(); + m_OutputTree->Fill(); + m_NPDetectorManager->CheckSpectraServer(); + } + delete DR; + delete [] buff; + m_NPDetectorManager -> WriteSpectra(); +#else + // read data file/flux and fill ccamData object std::cout << "Reading data\n"; DecodeR* DR = new DecodeR(false); // Instantiates DecodeR object reading calorimeter data flux DecodeT* DT = new DecodeT(false); // Instantiates DecodeT object reading trigger data flux DecodeD* DD = new DecodeD(false); // Instantiates DecodeD object reading DSSSD(s) data flux // newframe_t* event; - //DD -> setTree("/disk/proto-data/data/20210304_run2/bb7_3309-7_cs137_20210304_14h35_conv.root"); + #if __RUN__ == 0 + DD -> setTree("../data/20210210_run1/bb7_3309-7_cs137-20210210_11h05_coinc_run1_conv.root"); + #elif __RUN__ == 1 + DD -> setTree("/disk/proto-data/data/20210210_run1/bb7_3309-7_cs137-20210210_11h05_coinc_run1_conv.root"); + #elif __RUN__ == 2 + DD -> setTree("/disk/proto-data/data/20210304_run2/bb7_3309-7_cs137_20210304_14h35_conv.root"); + #elif __RUN__ == 3 DD -> setTree("/disk/proto-data/data/20210305_run3/bb7_3309-7_cs137_20210305_14h53_conv.root"); - //DD -> setTree("../data/20210210_run1/bb7_3309-7_cs137-20210210_11h05_coinc_run1_conv.root"); + #elif __RUN__ == 4 + DD -> setTree("/disk/proto-data/data/20210407_run4/bb7_3309-7_cs137_20210407_14h53_conv.root"); + #endif int dlen = DD -> getLength(); int i = 0;// ROSMAP files loop counter @@ -126,8 +162,16 @@ int main(int argc, char** argv) ifstream iros, itrig; cout << "Loading data files " << std::flush; + #if __RUN__ == 0 + itrig.open("../data/20210210_run1/mfm_trigger_202102101104.raw", ios::binary); + #elif __RUN__ == 1 + itrig.open("/disk/proto-data/data/20210210_run1/mfm_trigger_202102101104.raw", ios::binary); + #elif __RUN__ == 2 + #elif __RUN__ == 3 itrig.open("/disk/proto-data/data/20210305_run3/mfm_trigger_20210305_run3.raw", ios::binary); - //itrig.open("../data/20210210_run1/mfm_trigger_202102101104.raw", ios::binary); + #elif __RUN__ == 4 + itrig.open("/disk/proto-data/data/20210407_run4/mfm_trigger_20210407_run4.raw", ios::binary); + #endif itrig.seekg(0, ios::end); int tlen = itrig.tellg(); itrig.seekg(0, ios::beg); @@ -136,8 +180,16 @@ int main(int argc, char** argv) itrig.close(); cout << "... " << std::flush; + #if __RUN__ == 0 + iros.open("../data/20210210_run1/mfm_rdd_rosmap_04_mfm_rosmap_04_2021-02-10_10_04_59.raw.0001", ios::binary); + #elif __RUN__ == 1 + iros.open("/disk/proto-data/data/20210210_run1/mfm_rdd_rosmap_04_mfm_rosmap_04_2021-02-10_10_04_59.raw.0001", ios::binary); + #elif __RUN__ == 2 + #elif __RUN__ == 3 iros.open("/disk/proto-data/data/20210305_run3/mfm_rosmap_20210305_run3.raw", ios::binary); - //iros.open("../data/20210210_run1/mfm_rdd_rosmap_04_mfm_rosmap_04_2021-02-10_10_04_59.raw.0001", ios::binary); + #elif __RUN__ == 4 + iros.open("/disk/proto-data/data/20210407_run4/mfm_rosmap_20210407_run4.raw", ios::binary); + #endif iros.seekg(0, ios::end); int rlen = iros.tellg(); iros.seekg(0, ios::beg); @@ -157,6 +209,22 @@ int main(int argc, char** argv) resetCount = DT->getResetCount() - resetCount; resetCount = -resetCount; // T B C !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! cout << "Found reset count: " << resetCount << endl; + + if (resetCount == 0) { + string ans; + cout << "reset count is 0. Continue ? y/[n]"; + cin >> ans; + if (ans != "y" and ans != "Y") { + DT -> setRaw(tbuff); + DT -> decodeBlobMFM(); + resetCount = DT -> getResetCount(); + while (not(DT->hasTrigged(2))) { + DT -> decodeBlobMFM(); + } + resetCount = DT->getResetCount() - resetCount; + cout << "Found reset count: " << resetCount << endl; + } + } int cr, cd, tr, td; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ @@ -261,7 +329,7 @@ int main(int argc, char** argv) DR -> decodeBlobMFM(); //#ifdef __TEST_ZONE__ - cout << "Entering test zone." << endl; +// cout << "Entering test zone." << endl; //#else DD -> rewind(); @@ -271,7 +339,7 @@ int main(int argc, char** argv) tr = DR -> getTime(); td = DD -> getTime(); - while(DR -> getCursor() < rlen and DD -> getCursor() < dlen) + while(DR -> getCursor() < rlen and DD -> getCursor() < dlen and c < 10000) { if (cr == cd) { #ifndef __TEST_ZONE__ @@ -283,7 +351,6 @@ int main(int argc, char** argv) //DR -> Dump(); //DD -> Dump(); c++; - cout << cc << " " << c /*<< "(" << cr << ", " << cd << ") : " << tr << " " << td*/ << "\n"; // Clear raw and physics data m_NPDetectorManager->ClearEventPhysics(); m_NPDetectorManager->ClearEventData(); @@ -307,6 +374,7 @@ int main(int argc, char** argv) m_OutputTree->Fill(); cc++; #endif + cout << cc << " " << c /*<< "(" << cr << ", " << cd << ") : " << tr << " " << td*/ << " |\t"; } // check spectra @@ -353,7 +421,7 @@ int main(int argc, char** argv) deltaT->Write(); } fout->Close(); - +#endif // Essential #if __cplusplus > 199711L && NPMULTITHREADING m_NPDetectorManager->StopThread(); diff --git a/Projects/Strasse/geometry/strasse_CAD.detector b/Projects/Strasse/geometry/strasse_CAD.detector new file mode 100644 index 0000000000000000000000000000000000000000..1acb1346fd57bcc8452680ae3d0d678122e51f2d --- /dev/null +++ b/Projects/Strasse/geometry/strasse_CAD.detector @@ -0,0 +1,101 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Target + THICKNESS= 150 mm + ANGLE= 0 deg + RADIUS= 15 mm + MATERIAL= LH2 + X= 0 mm + Y= 0 mm + Z= 0 mm + NbSlices= 10 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%1 +Strasse Info + Inner_Wafer_Length= 124 mm + Inner_Wafer_Width= 32 mm + Inner_Wafer_Thickness= 200 micrometer + Inner_Wafer_AlThickness= 0.4 micrometer + Inner_Wafer_PADExternal= 0 mm + Inner_Wafer_PADInternal= 0 mm + Inner_Wafer_GuardRing= 1.0 mm + Inner_Wafer_TransverseStrips= 610 + Inner_Wafer_LongitudinalStrips= 150 + Inner_PCB_PortWidth= 1 mm + Inner_PCB_StarboardWidth= 1 mm + Inner_PCB_BevelAngle= 90 deg + Inner_PCB_UpstreamWidth= 12 mm + Inner_PCB_DownstreamWidth= 38 mm + Inner_PCB_MidWidth= 1 mm + Inner_PCB_Thickness= 2.4 mm + Inner_PCB_Ledge= 1 mm + Inner_PCB_Step= 2 mm + Outer_Wafer_Length= 123 mm + Outer_Wafer_Width= 64.6 mm + Outer_Wafer_Thickness= 300 micrometer + Outer_Wafer_AlThickness= 0.4 micrometer + Outer_Wafer_PADExternal= 0 mm + Outer_Wafer_PADInternal= 0 mm + Outer_Wafer_GuardRing= 1.0 mm + Outer_PCB_PortWidth= 1 mm + Outer_PCB_StarboardWidth= 1 mm + Outer_PCB_BevelAngle= 90 deg + Outer_PCB_UpstreamWidth= 40 mm + Outer_PCB_DownstreamWidth= 12 mm + Outer_PCB_MidWidth= 1 mm + Outer_PCB_Thickness= 2.4 mm + Outer_PCB_Ledge= 1 mm + Outer_PCB_Step= 2 mm + Outer_Wafer_TransverseStrips= 605 + Outer_Wafer_LongitudinalStrips= 313 + % unused if using CAD file (.stl) chamber + Chamber_Thickness= 3 mm + Chamber_Cylinder_Length= 360 mm + Chamber_Radius= 180 mm + Chamber_ExitTube_Radius= 79.5 mm + Chamber_ExitTube_Length= 100 mm + Chamber_Flange_Inner_Radius= 50 mm + Chamber_Sphere_Radius= 220 mm + Chamber_Sphere_Shift= 60 mm + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Alias InnerPhi + Action= Copy +% Value= 116 + Value= -4 56 116 176 236 296 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Strasse Inner + Radius= 27.6 mm + Z= 76.5 mm + Phi= @InnerPhi deg + Shift= 3 mm + Ref= 0 0 0 mm + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Alias OuterPhi + Action= Copy +% Value= 0 + Value= 0 60 120 180 240 300 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Strasse Outer + Radius= 58.5 mm + Z= 76.5 mm + Phi= @OuterPhi deg + Shift= 0 mm + Ref= 0 0 0 mm + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Strasse InactiveMaterial + Chamber= ./geometry/STRASSE_Chamber.stl + Stars= ./geometry/STRASSE_StarSupports.stl + Base= ./geometry/STRASSE_Base.stl + Blades= ./geometry/STRASSE_Blades.stl +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%1 +%Catana CSV +% Path= geometry/Catana.csv +% Pos= 0 0 100 mm +% Rshift= 100 micrometer + +