#ifndef _mdet_Scintillator_h #define _mdet_Scintillator_h #include #include // #include // #include #include #include #include #include #include #include // #include #include namespace det { struct ParentCreator; struct ComponentUpdater; } namespace mdet { class Module; /** * \class Scintillator Scintillator.h "mdet/Scintillator.h" * \brief Actual muon-sensitive objects. * * In short, the Scintillators are made of an special plastic * which has a response (light) when an impinging muon reach * one of them. Actually they are sensible to negative particles. * At last, they represent a body of this material, a body that's * arranged within a given Module. * * \todo Check some library for geometrical stuff (ROOT or some * other CERN related stuff). Anyway, it seems better to hide * that concern to the clients of this class. * * \author Rodolfo Federico Gamarra * \date 09 Jan 2009 * \ingroup mdet */ class Scintillator: public MDetectorComponent::Type, public det::MPositionable { public: static const char* const kComponentName; static const char* const kComponentId; /** * \name Geometrical body-like interface. * * The intention of these methods is to hide to the clients * the actual shape of the Scintillator, while providing the * necessary functions to query the geometrical characteristics * of the Scintillator. * * For example, it was discussed to have composite scintillators, built * from multiple strips. These composite ones would make a single unit * as a detecting device. On the other hand the principal quantities that * may be used are shape independent, like the lenght of the * path of a particle on the scint manterial: it seems better, so, to hide * the actual shape. In fact, the current box-shaped Scintillators * aren't actually exactly box-shaped because the Scinttillators have a * wedge were the mdet::Fiber is buried into. So precisely the shape * of the mdet::Scintillator is obtained as substraction of the mdet::Fiber * volume from that of the mdet::Scintillator. */ //@{ /** * \brief Answers if \p point lies within the Scintillator. */ bool Contains(const utl::Point& point) const; /** * \brief Answers if \p line crosses the body of the Scintillator. */ bool IntersectedBy(const utl::Line& line) const; /** * \brief Computes the intersection of \p line within the Scintillator. * * \sa IntersectedBy */ utl::Segment ComputeIntersectionWith(const utl::Line& line) const; /** * \brief Computes the intersection of \p line with the ground (until * reaching the Scintillator). * * Computes the segment (of the given line) that joins the ground * with the Scintillator (in that order, from the ground * to the Scint). * * \sa IntersectedBy */ utl::Segment ComputeUndergroundIntersectionOf(const utl::Line& line) const; /** * \brief Computes the amount of mass transversed until reaching * the Scintillator. * * Given the soil density distribution, this method computes the * transversed mass, from the ground to the scint. * * \sa IntersectedBy * \sa ComputeGroundIntersectionOf */ double ComputeUndergroundGrammageFor(const utl::Line& l) const; /** * \brief Compute Scintillator's total area in square metres * * \sa GetLength */ double GetArea() const; /** * \brief Callback method for inspecting shape-aware properties. * \param v Callback object (see details). * \return The argument \p v to allow function call chaining. * * As stated, the intention is to hide the actual shape of the Scitillator via * the previous functions. Nevertheless, it seems reasonable to give a way * to inspect shape-dependant properties just in case it's neccesary and * those function aren't enough. * * The template argument is assumed to provide shape-aware methods, which * are called with the Scintillator and those (hidden) shape-dependant properties: * - Box(const Scintillator& s, double w, double l, double h) * where s is the scint and w its width, l its length and h its height. * * For example, you can define some class like * * \code * class ShapeAware { * public: * // Box callback function. * void Box(const mdet::Scintillator& s, double w, double l, double h) { * double localResult; * // Box aware stuff. * fResult = localResult; // Keep the result in the field. * } * // Let's say your return a double. * double GetResult() { return fResult; } * private: * double fResult; * // your other data: you may have to define other methods to fill these fields, * // in order to have that information available in the callback methods. * }; * \endcode * * then you can use it like * * \code * const mdet::Scintillator s; * ShapeAware sa; * //... stuff * // Pass the sa to the scintillator, then chain the GetResultFunction call. * double result = s.VisitShape(sa).GetResult(); * \endcode * * \sa Boost's Variant library or Visitor pattern literature * (http://en.wikipedia.org/wiki/Visitor_pattern or * Design Patterns: Elements of Reusable Object-Oriented Software by Gamma et al). * * Other possibilities: * - build a oo-hierarchy but that would be too much. * - leave public those properties (putting a nice comment). * - build (instead of templating) interfaces to be called with * shape-dependant parameters. * * Other possibilities: * The visit shape could be defined to return what would be returned * by the called function. To do this (i) another template argument may be added or * (ii) a traits type could be supposed to be included in V. * The first choice has two drawbacks: this VisitShape method * has to assume a certain cv-qualification and the calls to * VisitShape have to include the return type specialized in the template * args (the return type should be the first template arg, so it isn't * neccesary to specify the type of the callback object). * The second choice requires to define the typedef. * Another, different, posssibility is to add a (templated) output argument. * At last, returning the arg seemed to be the most general choice. */ template V& VisitShape(V& v) const { /* * When more shapes (if ever!) came up this code should be changed * accordingly to handle them. This could be done with virtual functions * , an ugly flag-based switch-case (that could be enough), * typelists (http://www.ddj.com/cpp/184403813) or anything else. * In any case, that decission would be kept here and won't spread in client * code: that would have to define the proper functions for the new shapes, * but I will only know about a unique Scintillator class-type. */ // Up to now, just a box... v.Box(*this, GetWidth(), GetLength(), GetHeight()); return v; } //@} /** * \brief Computes a delay due to decay process. */ double ComputeDecayDelay() const; /** * \brief The mean value of the delay time. * * This method is provided for completeness, so as to allow * the user to query the particular mean value. * * For the computation of an specific value the user has to call * the "Compute", which will give a value acording the actual * distribution followed by the processes involved. * * \sa ComputeDecayDelay */ double GetDecayDelayMean() const; /** * \brief The standard deviation fo the delay time. * * \sa GetDecayDelayMean */ double GetDecayDelayStdDev() const; /** * \brief Retrieve the parent mdet::Module. */ const Module& GetModule() const; private: /** * \brief The reference is the local coordinate system of mdet::Module. * * The local coordinate system of the scintillator is in the center of it. * * \sa mdet::Module::GetLocalCoordinateSystem */ utl::CoordinateSystemPtr GetReferenceCoordinateSystem() const; /** * \brief Constructs the Scintillator (obviously!). * * \param sId The identifier to be used. * \param parentMap The identifiers of the parent within the hierarchy. * \param parent The parent mdet::Module. * * A reference to the parent is kept in this class and part * of the construction is delegated to the first super-class. * * \sa mdet::MDectectorComponent::Type */ Scintillator(int sId, const det::VManager::IndexMap& parentMap, const Module& parent); /** * */ ~Scintillator(){ } /** * \brief Frienship for GetData callback. */ friend class det::MPositionable; /** * \brief Friendship to allow creation (or call it construction). */ friend struct det::ParentCreator; /** * \brief Friendship for destruction. * * Depends on det::ComponentGroup innards. */ template friend void boost::checked_delete(T*); /// See mdet::Counter. friend struct det::ComponentUpdater; /** * \name Internal part of the body-like geometrical interface. */ //@{ /** * \brief Helper function for another specific member. * * \param v Container of for the selected planes (passed by non-const reference). * \param l Line wrt which things are computed. * \param ComputePlane Member pointer for delayed plane calculation. * * \sa IntersectionWith */ template void IntersectionHelper( Container& v, const utl::Line& l, utl::Plane (Scintillator::* ComputePlane)() const ) const; /** * \brief Checks if the vector lies within Scintillator's extent for the given axis. * * \param ext Extent of the Scintillator in the desidered direction. * \param pLocal Vector with origin on the local coordinate system. * \param normal Normal vector to perform the projection. * */ bool InExtent(double ext, const utl::Vector& pLocal, const utl::Vector& normal) const; /** * \brief Indicates whether the \p line hits the Scintillator on the side contained in * \p sidePlane. */ bool OnSide(const utl::Plane& sidePlane, const utl::Line& line) const; /** * \brief The (inifite) plane that coincides with the ground. */ utl::Plane ComputeGroundPlane() const; /** * \brief The plane where the top of the Scintillator lays. * * Computes the (infinite) plane where the top of the Scintillator (z direction * in the local coordinate system) lays up to half of its height. */ utl::Plane ComputeTopPlane() const; /** * \brief The plane where the bottom of the Scintillator lays. * * Computes the (infinite) plane where the bottom of the Scintillator (z direction * in the local coordinate system) lays in the negative * side of the axis up to half of its height. */ utl::Plane ComputeBottomPlane() const; /** * \brief The plane where the front of the Scintillator lays. * * Computes the (infinite) plane where the front of the Scintillator (y direction * in the local coordinate system) lays up to half of its length. */ utl::Plane ComputeFrontPlane() const; /** * \brief The plane where the back of the Scintillator lays. * * Computes the (infinite) plane where the back of the Scintillator (y direction * in the local coordinate system) lays in the negative * side of the axis up to half of its length. */ utl::Plane ComputeBackPlane() const; /** * \brief The plane where the right of the Scintillator lays. * * Computes the (infinite) plane where the right of the Scintillator (x direction * in the local coordinate system) lays up to half of its width. */ utl::Plane ComputeRightPlane() const; /** * \brief The plane where the left of the Scintillator lays. * * Computes the (infinite) plane where the left of the Scintillator * (x direction in the local coordinate system) lays in the negative * side of the axis up to half of its width. */ utl::Plane ComputeLeftPlane() const; /** * \brief Helper to construct the different planes. * * \param ext The magnitud of the extent in the direction, position of the anchor point. * \param x Factor for x direction. * \param y Idem for y. * \param z Idem for z.. */ utl::Plane ComputePlaneHelper(double ext, double x, double y, double z) const; /** * \brief Length of the strip (y direction * in the local coordinate system). * * Up to now the mdet::Scintillator have the simplest * (and currently actual) possible shape. * They are strips, so under currently normal conditions * the following holds: * - Lenght is the largest extent (~m). * - Width lies in between (~dm). * - Height is the shortest (~cm). */ double GetLength() const; /** * \brief Width of the strip (x direction in the local * coordinate system). * * \sa GetLength */ double GetWidth() const; /** * \brief Height of the strip (z direction in the local * coordinate system). * * \sa GetLegth */ double GetHeight() const; //@} /** * \brief Simplest density distribution: constant value. */ double GetLocalSoilDensity() const; /** * \brief Characteristic decay time. */ double GetDecayTime() const; /** * \brief FP comparison limit. */ double GetEpsilon() const; /** * \brief FP Comparison criteria. */ bool IsCloseTo(double a, double b) const; /** * \brief Check for intersection. */ bool Intersects(const utl::Plane& p, const utl::Line& l) const; mutable utl::Validated fLength; mutable utl::Validated fWidth; mutable utl::Validated fHeight; mutable utl::Validated fLocalSoilDensity; mutable utl::Validated fDecayTime; mutable utl::Validated fEpsilon; const Module& fModule; }; } #endif // _mdet_Scintillator_h