Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-06-02 08:51:49

0001 #ifndef OBSERVABLE_SERVICE_H
0002 #define OBSERVABLE_SERVICE_H
0003 
0004 /**
0005  * @file ObservableService.h
0006  * @author Bryan BERTHOU (SPhN / CEA Saclay)
0007  * @date November 20, 2014
0008  * @version 1.0
0009  */
0010 
0011 #include <ElementaryUtils/logger/CustomException.h>
0012 #include <ElementaryUtils/parameters/GenericType.h>
0013 #include <ElementaryUtils/PropertiesManager.h>
0014 #include <ElementaryUtils/string_utils/Formatter.h>
0015 #include <ElementaryUtils/string_utils/StringUtils.h>
0016 #include <ElementaryUtils/thread/Packet.h>
0017 #include <string>
0018 
0019 #include "../beans/automation/Task.h"
0020 #include "../beans/gpd/GPDType.h"
0021 #include "../beans/List.h"
0022 #include "../modules/observable/Observable.h"
0023 #include "../modules/process/ProcessModule.h"
0024 #include "../ServiceObjectTyped.h"
0025 #include "../utils/VectorUtils.h"
0026 
0027 namespace PARTONS {
0028 
0029 /**
0030  * @class ObservableService
0031  *
0032  * @brief Abstract class for a service to handle and compute observables.
0033  */
0034 template<typename KinematicType, typename ResultType>
0035 class ObservableService: public ServiceObjectTyped<KinematicType, ResultType> {
0036 
0037 public:
0038 
0039     static const std::string OBSERVABLE_SERVICE_COMPUTE_SINGLE_KINEMATIC; ///< Name of the XML task used to compute an Observable at given kinematics.
0040     static const std::string OBSERVABLE_SERVICE_COMPUTE_MANY_KINEMATIC; ///< Name of the XML task used to compute an Observable for a list of kinematics.
0041 
0042     /**
0043      * Destructor.
0044      */
0045     virtual ~ObservableService() {
0046     }
0047 
0048     /**
0049      * See parent class for details.
0050      */
0051     virtual void resolveObjectDependencies() {
0052 
0053         ServiceObjectTyped<KinematicType, ResultType>::resolveObjectDependencies();
0054 
0055         try {
0056             this->m_batchSize = ElemUtils::GenericType(
0057                     ElemUtils::PropertiesManager::getInstance()->getString(
0058                             "observable.service.batch.size")).toUInt();
0059         } catch (const std::exception &e) {
0060             throw ElemUtils::CustomException(this->getClassName(), __func__,
0061                     e.what());
0062         }
0063     }
0064 
0065     virtual void computeTask(Task &task) {
0066 
0067         ServiceObjectTyped<KinematicType, ResultType>::computeTask(task);
0068 
0069         List<ResultType> resultList;
0070 
0071         if (ElemUtils::StringUtils::equals(task.getFunctionName(),
0072                 ObservableService::OBSERVABLE_SERVICE_COMPUTE_MANY_KINEMATIC)) {
0073             resultList = computeManyKinematicTask(task);
0074         }
0075 
0076         else if (ElemUtils::StringUtils::equals(task.getFunctionName(),
0077                 ObservableService::OBSERVABLE_SERVICE_COMPUTE_SINGLE_KINEMATIC)) {
0078             resultList.add(computeSingleKinematicTask(task));
0079         }
0080 
0081         else if (!this->computeGeneralTask(task)) {
0082             this->errorUnknownMethod(task);
0083         }
0084 
0085         this->updateResultInfo(resultList, this->m_resultInfo);
0086 
0087         this->m_resultListBuffer = resultList;
0088     }
0089 
0090     /**
0091      * Computes an Observable at specific kinematics.
0092      * @param observableKinematic Kinematics.
0093      * @param pObservable Observable to compute.
0094      * @param listOfGPDType List of GPDType to compute. Default: all the GPDTypes available with (both) the underlying ConvolCoeffFunctionModule (AND the underlying GPDModule, if any).
0095      * @return ObservableResult.
0096      */
0097     ResultType computeSingleKinematic(const KinematicType &observableKinematic,
0098             Observable<KinematicType, ResultType>* pObservable,
0099             const List<GPDType> & gpdTypeList = List<GPDType>()) const {
0100 
0101         //get list of GPD types
0102         List<GPDType> restrictedByGPDTypeListFinal = getFinalGPDTypeList(
0103                 pObservable, gpdTypeList);
0104 
0105         //return
0106         return pObservable->compute(observableKinematic, gpdTypeList);
0107     }
0108 
0109     /**
0110      * Computes an Observable for a list of kinematics.
0111      * @param listOfKinematic List of kinematics.
0112      * @param pObservable Observable to compute.
0113      * @param listOfGPDType List of GPDType to compute. Default: all the GPDTypes available with (both) the underlying ConvolCoeffFunctionModule (AND the underlying GPDModule, if any).
0114      * @param storeInDB Boolean to store the results and kinematics on the database. Default: false.
0115      * @return List of ObservableResult.
0116      */
0117     List<ResultType> computeManyKinematic(
0118             const List<KinematicType> & listOfKinematic,
0119             Observable<KinematicType, ResultType>* pObservable,
0120             const List<GPDType>& gpdTypeList = List<GPDType>()) {
0121 
0122         //debug information
0123         this->debug(__func__,
0124                 ElemUtils::Formatter() << listOfKinematic.size()
0125                         << " Observable kinematic(s) will be computed with "
0126                         << pObservable->getClassName());
0127 
0128         //initialize
0129         List<ResultType> results;
0130         List<ElemUtils::Packet> listOfPacket;
0131         List<GPDType> finalListOfGPDType = getFinalGPDTypeList(pObservable,
0132                 gpdTypeList);
0133 
0134         //if to be computed
0135         if (finalListOfGPDType.size() != 0) {
0136 
0137             //init thread
0138             this->initComputationalThread(pObservable);
0139 
0140             //print info
0141             this->info(__func__, "Thread(s) running ...");
0142 
0143             //batch feature
0144             unsigned int i = 0;
0145             unsigned int j = 0;
0146 
0147             //divide to packets
0148             while (i != listOfKinematic.size()) {
0149 
0150                 listOfPacket.clear();
0151                 j = 0;
0152 
0153                 while ((j != this->m_batchSize) && (i != listOfKinematic.size())) {
0154 
0155                     ElemUtils::Packet packet;
0156                     KinematicType kinematic;
0157                     kinematic = listOfKinematic[i];
0158                     packet << kinematic << finalListOfGPDType;
0159                     listOfPacket.add(packet);
0160                     i++;
0161                     j++;
0162                 }
0163 
0164                 //add, lunch and sort
0165                 this->addTasks(listOfPacket);
0166                 this->launchAllThreadAndWaitingFor();
0167                 this->sortResultList();
0168 
0169                 //print info
0170                 this->info(__func__,
0171                         ElemUtils::Formatter()
0172                                 << "Kinematic(s) already computed: " << i);
0173 
0174                 //update result info
0175                 this->updateResultInfo(this->getResultList(),
0176                         this->m_resultInfo);
0177 
0178                 //add to output
0179                 results.add(this->getResultList());
0180 
0181                 //clear buffer
0182                 this->clearResultListBuffer();
0183             }
0184 
0185             //clear threads
0186             this->clearAllThread();
0187 
0188         } else {
0189             this->info(__func__,
0190                     "Nothing to compute with your computation configuration ; there is no GPDType available");
0191         }
0192 
0193         return results;
0194     }
0195 
0196     /**
0197      * @brief Uses an automation task (XML file) to configure a ProcessModule, e.g.\ a DVCSModule.
0198      * @param task Automation task.
0199      * @return Pre-configured ProcessModule.
0200      */
0201     virtual ProcessModule<KinematicType, ResultType>* newProcessModuleFromTask(
0202             const Task &task) const = 0;
0203 
0204     /**
0205      * Uses an automation task (XML file) to configure an Observable.
0206      * @param task Automation task.
0207      * @return Pre-configured Observable.
0208      */
0209     virtual Observable<KinematicType, ResultType>* newObservableModuleFromTask(
0210             const Task &task) const = 0;
0211 
0212     /**
0213      * Uses an automation task (XML file) to set specific kinematics.
0214      * @param task
0215      * @return Observable kinematics.
0216      */
0217     virtual KinematicType newKinematicFromTask(const Task &task) const = 0;
0218 
0219     /**
0220      * Uses an automation task (XML file) to set a list of kinematics.
0221      * @param task
0222      * @return List of Observable kinematics.
0223      */
0224     virtual List<KinematicType> newListOfKinematicFromTask(
0225             const Task &task) const = 0;
0226 
0227 protected:
0228 
0229     /**
0230      * Default constructor.
0231      */
0232     ObservableService(const std::string &className) :
0233             ServiceObjectTyped<KinematicType, ResultType>(className) {
0234     }
0235 
0236 private:
0237 
0238     /**
0239      * Method used in the automated interface to compute an Observable.
0240      * @param task Automated XML task.
0241      * @return ObservableResult object.
0242      */
0243     ResultType computeSingleKinematicTask(Task &task) {
0244 
0245         //create a kinematic and init it with a list of parameters
0246         KinematicType kinematic = newKinematicFromTask(task);
0247 
0248         //get GPD types
0249         List<GPDType> gpdTypeList = this->getGPDTypeListFromTask(task);
0250 
0251         //get configured observable module
0252         Observable<KinematicType, ResultType>* pObservable =
0253                 newObservableModuleFromTask(task);
0254 
0255         //make computation
0256         ResultType result = computeSingleKinematic(kinematic, pObservable,
0257                 gpdTypeList);
0258 
0259         //remove reference to pConvolCoeffFunctionModule pointer.
0260         this->m_pModuleObjectFactory->updateModulePointerReference(pObservable,
0261                 0);
0262         pObservable = 0;
0263 
0264         return result;
0265     }
0266 
0267     /**
0268      * Method used in the automated interface to compute an Observable for a list of kinematics.
0269      * @param task Automated XML task.
0270      * @return List of ObservableResult.
0271      */
0272     List<ResultType> computeManyKinematicTask(Task &task) {
0273 
0274         //get kinematics
0275         List<KinematicType> listOfKinematic = newListOfKinematicFromTask(task);
0276 
0277         //get GPD types
0278         List<GPDType> gpdTypeList = this->getGPDTypeListFromTask(task);
0279 
0280         //get observable module
0281         Observable<KinematicType, ResultType>* pObservable =
0282                 newObservableModuleFromTask(task);
0283 
0284         //make computation
0285         List<ResultType> results = computeManyKinematic(listOfKinematic,
0286                 pObservable, gpdTypeList);
0287 
0288         //remove reference to pConvolCoeffFunctionModule pointer
0289         this->m_pModuleObjectFactory->updateModulePointerReference(pObservable,
0290                 0);
0291         pObservable = 0;
0292 
0293         //return
0294         return results;
0295     }
0296 
0297     /**
0298      * Method used to derive an intersection of available GPD types from the various underlying modules.
0299      * @param pConvolCoeffFunctionModule ConvolCoeffFunctionModule used for the computation.
0300      * @param gpdTypeList List of desired GPD types to compute.
0301      * @return List of GPD types.
0302      */
0303     List<GPDType> getFinalGPDTypeList(
0304             Observable<KinematicType, ResultType>* pObservable,
0305             const List<GPDType> &gpdTypeList) const {
0306 
0307         //initialize
0308         List<GPDType> restrictedByGPDTypeListFinal = gpdTypeList;
0309 
0310         //get list of GPD types available
0311         restrictedByGPDTypeListFinal =
0312                 pObservable->getListOfAvailableGPDTypeForComputation();
0313 
0314         //intersection between available GPDType and GPDType asked
0315         if (!gpdTypeList.isEmpty()) {
0316             restrictedByGPDTypeListFinal = VectorUtils::intersection(
0317                     restrictedByGPDTypeListFinal, gpdTypeList);
0318         }
0319 
0320         //debug info
0321         this->debug(__func__,
0322                 ElemUtils::Formatter() << restrictedByGPDTypeListFinal.size()
0323                         << " GPDType will be computed");
0324 
0325         //return
0326         return restrictedByGPDTypeListFinal;
0327     }
0328 };
0329 
0330 template<typename KinematicType, typename ResultType>
0331 const std::string ObservableService<KinematicType, ResultType>::OBSERVABLE_SERVICE_COMPUTE_SINGLE_KINEMATIC =
0332         "computeSingleKinematic";
0333 
0334 template<typename KinematicType, typename ResultType>
0335 const std::string ObservableService<KinematicType, ResultType>::OBSERVABLE_SERVICE_COMPUTE_MANY_KINEMATIC =
0336         "computeManyKinematic";
0337 
0338 } /* namespace PARTONS */
0339 
0340 #endif /* OBSERVABLE_SERVICE_H */