Back to home page

EIC code displayed by LXR

 
 

    


Warning, /jana2/docs/jana1to2/developers-transition-guide.md is written in an unsupported language. File is not indexed.

0001 
0002 
0003 # Developers Transition Guide
0004 
0005 ***Key Syntax Changes between JANA1 to JANA2***
0006 
0007 This guide outlines the critical syntax and functional updates between JANA1 and JANA2, helping developers navigate the transition smoothly.
0008 
0009 
0010 
0011 ## Namespace
0012 ##### **JANA1**
0013 Adding following on top of all files was necessary in JANA1:
0014 
0015 ```
0016 using namespace jana;
0017 ```
0018 ##### **JANA2**
0019 This line is no longer required in JANA2.
0020 
0021 
0022 ## Application
0023 
0024 ### JApplication
0025 #### Getting the JApplication
0026 
0027 ##### **JANA1**
0028 In JANA1 there is a global variable `japp` which is a pointer to the project's `JApplication`. You can also obtain it from `JEventLoop::GetJApplication()`.
0029 
0030 ##### **JANA2**
0031 In JANA2, `japp` is still around but we are strongly discouraging its future use. If you are within any JANA component (for instance: JFactory, JEventProcessor, JEventSource, JService) you can obtain the `JApplication` pointer from `this`, like so:
0032 
0033 ```cpp
0034 auto app = GetApplication();
0035 ```
0036 
0037 You can also obtain it from the `JEvent` the same way as you used to from `JEventLoop`, i.e. 
0038 
0039 ```cpp
0040 auto app = event->GetJApplication();
0041 ```
0042 
0043 ### DApplication
0044 ### Getting DApplication
0045 ##### **JANA1**
0046 
0047 ```cpp
0048 #include "DANA/DApplication.h"
0049 dApplication = dynamic_cast<DApplication*>(locEventLoop->GetJApplication
0050 ```
0051 
0052 ##### **JANA2**
0053 There is no `DApplication` anymore in JANA2. `JApplication` is `final`, which means you can't inherit from it. The functionality on `DApplication` has been moved into `JService`s, which can be accessed via `JApplication::GetService<ServiceT>()`. 
0054 
0055 ```cpp
0056 auto dapp = GetApplication()->GetService<DApplication>();
0057 ```
0058 
0059 
0060 ## Parameter Manager
0061 ### Setting Parameters
0062 
0063 ##### **JANA1**
0064 
0065 ```cpp
0066 gPARMS->SetDefaultParameter("component_prefix:value_name", ref_to_member_var);
0067 ```
0068 
0069 ##### **JANA2**
0070 You should set parameters as shown below. 
0071 
0072 ```cpp
0073 auto app = GetApplication();
0074 app->SetDefaultParameter("component_prefix:value_name", ref_to_member_var);
0075 ```
0076 
0077 We strongly recommend you register all parameters from inside the `Init()` callbacks of your JANA components, or from `InitPlugin()`. This helps JANA:
0078 
0079 - Report back which parameters are available without having to process an input file.
0080 - Emit a warning (or error!) when a user-provided parameter is misspelled
0081 - Emit a warning when two plugins register the same parameter with conflicting default values.
0082 - Inspect the exact parameter values used by a factory
0083 
0084 If you register parameters in other contexts, this machinery might not work and you might get incomplete parameter lists and missing or spurious error messages. Worse, your code might not see the parameter values you expect it to see. Registering parameters from inside constructors is less problematic but still discouraged because it won't work with some upcoming new features.
0085 
0086 ### Getting Parameters
0087 
0088 ##### **JANA1**
0089 
0090 ```cpp
0091 gPARMS->GetParameter("component_prefix:value_name", ref_to_member_var);
0092 ```
0093 
0094 ##### **JANA2**
0095 ```cpp
0096 auto app = GetApplication();
0097 // Method 1
0098 app->GetParameter("component_prefix:value_name", member_var);
0099 // Method 2
0100 member_var = app->GetParameterValue<value_type>("component_prefix:value_name");
0101 ```
0102 
0103 
0104 ### Getting Parameter Maps
0105 
0106 ##### **JANA1**
0107 To obtain a map of all parameters that share a common prefix:
0108 
0109 ```cpp
0110 //gets all parameters with this filter at the beginning of the key
0111 gPARMS->GetParameters(locParameterMap, "COMBO_DEDXCUT:"); 
0112 ```
0113 
0114 ##### **JANA2**
0115 In JANA2 this has been renamed to `FilterParameters` but the functionality is the same.
0116 Note that this method is not on `JApplication` directly; you have to obtain the parameter manager like so:
0117 
0118 ```cpp
0119 //gets all parameters with this filter at the beginning of the key
0120 GetApplication()->GetJParameterManager()->FilterParameters(locParameterMap, "COMBO_DEDXCUT:");
0121 ```
0122 
0123 
0124 ## DGeometry
0125 #### Getting DGeometry
0126 
0127 ##### **JANA1**
0128 ###### Using japp
0129 ```cpp
0130 #include "DANA/DApplication.h"
0131 #include "HDGEOMETRY/DGeometry.h"
0132 
0133 DApplication* dapp=dynamic_cast<DApplication*>(japp);
0134 const DGeometry *dgeom = dapp->GetDGeometry(runnumber);
0135 ```
0136 
0137 ###### Using eventLoop
0138 
0139 ```cpp
0140 #include "DANA/DApplication.h"
0141 #include "HDGEOMETRY/DGeometry.h"
0142 
0143 DGeometry *locGeom = dApplication ? dApplication->GetDGeometry(eventLoop->GetJEvent().GetRunNumber()) : NULL;
0144 ```
0145 
0146 ##### **JANA2**
0147 In JANA2, you obtain the `DGeometryManager` from the `JApplication` and from there you use the run number to obtain the corresponding `DGeometry`:
0148 
0149 ```cpp
0150 #include "HDGEOMETRY/DGeometry.h"
0151 
0152 auto runnumber = event->GetRunNumber();
0153 auto app = event->GetJApplication();
0154 auto geo_manager = app->GetService<DGeometryManager>();
0155 auto geom = geo_manager->GetDGeometry(runnumber);
0156 ```
0157 
0158 To reduce the boilerplate, we've provided a handy helper function, `DEvent::GetDGeometry()`, that does all of these steps for you:
0159 
0160 ```cpp
0161 #include "DANA/DEvent.h"
0162 
0163 DGeometry *locGeometry = DEvent::GetDGeometry(locEvent);
0164 ```
0165 
0166 You should call `GetDGeometry` from `JFactory::BeginRun` or `JEventProcessor::BeginRun`.
0167 
0168 
0169 ## Calibration
0170 #### Accessing Calibration Data - `GetCalib` 
0171 ##### **JANA1**
0172 
0173 ```cpp
0174 locEventLoop->GetCalib(locTOFParmsTable.c_str(), tofparms);
0175 ```
0176 
0177 ##### **JANA2**
0178 Analogously to `DGeometry`, you obtain the calibrations by obtaining the `JCalibrationManager` from `JApplication::GetService<>()` and then loading the calibration object corresponding to the event's run number. We recommend you use `DEvent::GetCalib` to avoid this boilerplate. You should call this from your `BeginRun` callback. 
0179 
0180 ```cpp
0181 #include "DANA/DEvent.h"
0182 
0183 DEvent::GetCalib(event, locTOFParmsTable.c_str(), tofparms);
0184 ```
0185 
0186 In principle, the calibrations could also be keyed off of event number intervals, in which case you should call it from `Process` and pass the event number as well:
0187 
0188 ```cpp
0189 #include <JANA/JEvent.h>
0190 #include <JANA/Calibrations/JCalibrationManager.h>
0191 
0192 auto event_number = event->GetEventNumber();
0193 auto run_number = event->GetRunNumber();
0194 
0195 auto app = GetApplication();
0196 auto calibration = app->GetService<JCalibrationManager>()->GetJCalibration(run_number);
0197 calibration->Get("BCAL/mc_parms", bcalparms, event_number)
0198 ```
0199 
0200 
0201 ## Status Bit
0202 #### Accessing Status Bit - `GetStatusBit`
0203 
0204 ##### **JANA1**
0205 
0206 ```cpp
0207 locEventLoop->GetJEvent().GetStatusBit(kSTATUS_PHYSICS_EVENT)
0208 ```
0209 
0210 ##### **JANA2**
0211 Status bits are no longer an event member variable. Instead, they are inserted and retrieved just like the other collections:
0212 
0213 ```cpp
0214 #include "DANA/DStatusBits.h"
0215 
0216 
0217 locEvent->GetSingle<DStatusBits>()->GetStatusBit(kSTATUS_PHYSICS_EVENT)
0218 
0219 // or, for a little bit more safety:
0220 
0221 locEvent->GetSingleStrict<DStatusBits>()->GetStatusBit(kSTATUS_REST);
0222 ```
0223 
0224 
0225 ## Magnetic Field
0226 #### Getting Magnetic Field - `GetBField`
0227 
0228 ##### **JANA1**
0229 
0230 ```cpp
0231 #include "DANA/DApplication.h"
0232 
0233 dApplication = dynamic_cast<DApplication*>(locEventLoop->GetJApplication());
0234 dMagFMap= dApplication->GetBfield(locEventLoop->GetJEvent().GetRunNumber());
0235 
0236 ```
0237 ##### **JANA2**
0238 In JANA2, the magnetic field map is a resource handled analogously to `DGeometry` and `JCalibrationManager`. Thus, we recommend obtaining the 
0239 field map by calling `DEvent::GetBField(event)` from inside `BeginRun`:
0240 
0241 ```cpp
0242 #include "DANA/DEvent.h"
0243 
0244 dMagneticFieldMap = DEvent::GetBfield(locEvent);
0245 ```
0246 
0247 
0248 ## Get Functions
0249 ### JObject Getters
0250 
0251 #### 1. `GetSingleT`
0252 
0253 `GetSingleT` has been replaced with `GetSingle`. Templated methods no longer have a `T` suffix; templated classes (such as `JFactoryT`) still do.
0254 The new `GetSingle` returns a pointer rather than updating an out parameter. If there isn't exactly one associated item of that type, it will return 
0255 `nullptr`.
0256 
0257 ##### **JANA1**
0258 
0259 Was present in JANA1
0260 
0261 
0262 ##### **JANA2**
0263 
0264 No longer available in JANA2; use ```GetSingle()``` instead
0265 
0266 
0267 #### 2. `GetSingle`
0268 ##### **JANA1**
0269 
0270 ```cpp
0271 // Pass by reference
0272 // Set passed param equal to pointer to object
0273 const Df250PulsePedestal* PPobj = NULL;
0274 digihit->GetSingle(PPobj);
0275 ```
0276 
0277 ##### **JANA2**
0278 ```cpp
0279 // Template function
0280 // Return pointer to object
0281 auto PPobj = digihit->GetSingle<Df250PulsePedestal>();
0282 ```
0283 
0284 
0285 #### 3. `Get`
0286 
0287 Similarly to `GetSingle`, `Get` returns a vector rather than updating an out parameter.
0288 ##### **JANA1**
0289 
0290 ```cpp
0291 // Pass by Reference
0292 vector<const DBCALUnifiedHit*> assoc_hits;
0293 point.Get(assoc_hits);
0294 ```
0295 
0296 ##### **JANA2**
0297 ```cpp
0298 // Templated Function
0299 // Return value
0300 vector<const DBCALUnifiedHit*> assoc_hits = point.Get<DBCALUnifiedHit>();
0301 ```
0302 ### JEvent Getters
0303 
0304 
0305 #### 1. `GetSingle`
0306 ##### **JANA1**
0307 
0308 ```cpp
0309 // Pass by Reference, 
0310 // passed param got assigned pointer to object
0311 
0312 const DTTabUtilities* locTTabUtilities = NULL;
0313 loop->GetSingle(locTTabUtilities); 
0314 ```
0315 
0316 ##### **JANA2**
0317 ```cpp
0318 // Return the pointer to object based on template type
0319 
0320 const DTTabUtilities* locTTabUtilities = event->GetSingle<DTTabUtilities>();
0321 ```
0322 
0323 #### 2. `Get`
0324 ##### **JANA1**
0325 
0326 ```cpp
0327 // Pass by Reference
0328 vector<const DBCALShower*> showers;
0329 loop->Get(showers, "IU");
0330 ```
0331 
0332 ##### **JANA2**
0333 ```cpp
0334 // JANA1 Get is still available but will be deprecated soon
0335 // So better to use the one given below
0336 
0337 // Templated function
0338 // Return value
0339 auto showers = event->Get<DBCALShower>("IU");
0340 ```
0341 
0342 ## **JEventSource**
0343 ### Key Differences
0344 #### **1. Type name and Resource name
0345 
0346 JEventSources are identified by both a type name, e.g. "JEventSource_EVIO", and a resource name, e.g. "./hd_rawdata_123456_000.evio". JANA2 handles both of these differently than JANA1.
0347 
0348 In JANA1, the user was required to provide the type name manually by providing two callbacks:
0349 ```c++
0350 virtual const char* className();
0351 static const char* static_className();
0352 ```
0353 
0354 In JANA2, the class name is simply a member variable on the `JEventSource` base class, which the user may access via getters and setters:
0355 ```c++
0356 void SetTypeName(std::string type_name);
0357 std::string GetTypeName() const;
0358 ```
0359 Note that `JEventSourceGeneratorT` will automatically populate the type name. If a custom generator is being used, or no generator is used at all (e.g. for test cases), `SetTypeName()` should be called from inside the `JEventSource` constructor, just like with the other components.
0360 
0361 The resource name has similarly evolved.
0362 In JANA1, the resource name was always passed as a constructor argument and later accessed using `inline const char* GetSourceName()`. In JANA2, the resource name is a member variable accessed by `SetResourceName(std::string)` and `std::string GetResourceName() const`. While JANA2 still optionally accepts the resource name as a constructor argument for backwards compatibility, this is no longer preferred and will eventually be deprecated in favor of having `JEventSources` be default-constructible. `JEventSourceGeneratorT` already supports both constructor styles, and will automatically populate the resource name just like the type name, so the user shouldn't need to manually call `SetResourceName()`.
0363 
0364 
0365 #### **2. Event Retrieval (`GetEvent` & `Emit`)**
0366 
0367 In JANA1, populating and emitting a fresh event into the stream was done using `GetEvent`, which returned a `jerror_t` code to indicate success or failure. 
0368 
0369 In JANA2, `jerror_t` has been removed completely, and the `GetEvent` callback has been replaced. JANA2 supports two new callback signatures, with different error-handling approaches. JANA2 will choose which callback to use based off the `callbackStyle` flag. For JEventSources, the available callback styles are `ExpertMode` and `LegacyMode`.
0370 The purpose of the callback style flag is to enable smooth, gradual migrations in the future: components can opt-in to using new features on their own timetable without
0371 having to update everything everywhere.
0372 
0373 1. **`JEventSource::Result Emit(JEvent &event)`** – This is the preferred replacement for `GetEvent()`. It returns a `Result` enum with the following values: `Success` (indicating that a fresh event was successfully read), `FailureTryAgain` (indicating that no event was found, but more may be coming later), or `FailureFinished` (indicating that the file has or stream has run out of events and is ready to close). To tell JANA2 to use `Emit`, set the callback style to `ExpertMode` by calling `SetCallbackStyle(CallbackStyle::ExpertMode)` in the constructor.
0374 
0375 2. `GetEvent(std::shared_ptr<JEvent> event)` – This callback signature will be deprecated in the near future, and so should not be used for new code. However, we are including it here for completeness. This method returns `void` and signals different statuses by throwing exceptions instead of returning an error code. It throws a `RETURN_STATUS` enum value, which includes `kNO_MORE_EVENTS`, `kBUSY`, `kTRY_AGAIN`, `kERROR`, or `kUNKNOWN`. This callback will be called by default, or if you set `SetCallbackStyle(CallbackStyle::LegacyMode)` in the `JEventSource` constructor.
0376 
0377 | **Aspect**               | **JANA1**                                                                                                | **JANA2**                                                                                                                                                      |
0378 | ------------------------ | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
0379 | **`GetEvent`**           | `GetEvent(JEvent &event)` returns a `jerror_t` error code (e.g., `NOERROR`, `NO_MORE_EVENTS_IN_SOURCE`). | `GetEvent(std::shared_ptr<JEvent> event)` returns `void` and signals different statuses by throwing `RETURN_STATUS` enum values as exceptions.                 |
0380 | **Recommended - `Emit`** | _Not available._                                                                                         | `Emit(JEvent &event)` provides an alternative way to retrieve events. Instead of throwing an exception, it returns one of `Result` enum values to show status. |
0381 
0382 #### **3. `GetObjects` Implementation**
0383 JANA1’s `GetObjects` returned a `jerror_t`.  
0384 JANA2 replaces this with a `bool` return type. Never return a `jerror_t`, as the compiler may mistakenly perceive it as `true` when the intended meaning is `false`. Always return `true` if objects are found and `false` otherwise.
0385 
0386 | **Aspect**                    | **JANA1**                                                                 | **JANA2**                                                                                                                                              |
0387 | ----------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
0388 | **GetObjects Implementation** | `jerror_t GetObjects(jana::JEvent &event, jana::JFactory_base *factory);` | `bool GetObjects(const std::shared_ptr<const JEvent> &event, JFactory* factory) override;` `bool` (return `true` if objects found, otherwise `false`). |
0389 
0390 #### **4. Enabling `GetObjects` Call**
0391 In **JANA1**, `GetObjects` was always called, leading to unnecessary performance overhead.  
0392 In **JANA2**, `GetObjects` is **disabled by default**. If the source file contains objects that should be used instead of being generated by factories, enable it in the event source constructor:
0393 
0394 ```cpp
0395 EnableGetObjects(true);
0396 ```
0397 
0398 |**Aspect**|**JANA1**|**JANA2**|
0399 |---|---|---|
0400 |**Enabling `GetObjects` Call**|Called by default for every event.|Disabled by default. Must be enabled with `EnableGetObjects(true)`.|
0401 
0402 #### **5. Calling `FinishEvent`**
0403 In **JANA1**, `FreeEvent` was always called automatically after an event was processed, but this required acquiring/releasing locks, adding performance overhead. In **JANA2**, `FinishEvent` replaces `FreeEvent` and is **disabled by default** for efficiency. If additional logic should run at the end of each event, enable it manually in the event source constructor:
0404 
0405 ```cpp
0406 EnableFinishEvent(true);
0407 ```
0408 
0409 |**Aspect**|**JANA1**|**JANA2**|
0410 |---|---|---|
0411 |**Calling `FinishEvent`**|`FreeEvent` was always called automatically.|`FinishEvent` is disabled by default to improve performance.|
0412 
0413 #### 6. Resource lifetimes (`Open()` and `Close()`)
0414 
0415 In **JANA1**, the initialization of parameters and opening of the file or socket was done inside the constructor, and the closing of the file or socket was done inside the destructor. In **JANA2**, the lifecycle is **explicitly managed** using the `Init()`, `Open()` and `Close()` callbacks:
0416 
0417 | **Aspect**           | **JANA1**                   | **JANA2**                                                                    |
0418 | -------------------- | --------------------------- | ---------------------------------------------------------------------------- |
0419 | **Initialization**   | Handled in the constructor. | `Init()` should be used for obtaining parameters and services. |
0420 | **Opening a Source** | Handled in the constructor. | `Open()` is called when JANA is ready to accept events from the event source |
0421 | **Closing a Source** | Handled in the destructor.  | `Close()` is called when the source is done processing events.               |
0422 
0423 These methods allow better resource management by ensuring that the event source is properly opened before processing events and properly cleaned up afterwards.
0424 
0425 ##### **Example Usage in JANA2**
0426 ```cpp
0427 void JEventSource_Sample::Open() {
0428 // Initialize resources (e.g., open files, set up connections)
0429 }
0430 
0431 void JEventSource_Sample::Close() {
0432  // Release resources (e.g., close files, disconnect)
0433 }
0434 ```
0435 
0436 
0437 ### **JEventSource Header Files**
0438 ##### **JANA1**
0439 ```cpp
0440 #ifndef _JEventSource_Sample_
0441 #define _JEventSource_Sample_
0442 
0443 #include <JANA/jerror.h>
0444 #include <JANA/JApplication.h>
0445 #include <JANA/JEventSource.h>
0446 #include <JANA/JEvent.h>
0447 #include <JANA/JFactory.h>
0448 #include <JANA/JStreamLog.h>
0449 
0450 class JEventSource_Sample: public jana::JEventSource {
0451 public:
0452     JEventSource_Sample(const char* source_name);
0453     virtual ~JEventSource_Sample();
0454 
0455     virtual const char* className(void) { return static_className(); }
0456     static const char* static_className(void) { return "JEventSource_Sample"; }
0457 
0458     jerror_t GetEvent(JEvent &event);
0459     void FreeEvent(JEvent &event);
0460     jerror_t GetObjects(JEvent &event, jana::JFactory_base *factory);
0461 };
0462 
0463 #endif // _JEventSource_Sample_
0464 ```
0465 ##### **JANA2**
0466 ```cpp
0467 #pragma once
0468 
0469 #include <JANA/JApplication.h>
0470 #include <JANA/JEventSource.h>
0471 #include <JANA/JEvent.h>
0472 #include <JANA/JFactory.h>
0473 #include <JANA/Compatibility/JStreamLog.h>
0474 
0475 class JEventSource_Sample : public JEventSource {
0476 public:
0477     JEventSource_Sample(std::string resource_name) {
0478             SetTypeName(NAME_OF_THIS);
0479             SetCallbackStyle(CallbackStyle::ExpertMode);
0480             EnableGetObjects(true); 
0481             EnableFinishEvent(true); 
0482     }
0483     virtual ~JEventSource_Sample();
0484 
0485     void Init() override;
0486     void Open() override;
0487     void Close() override;
0488     void FinishEvent(JEvent& event) override;
0489     Result Emit(JEvent& event) override;
0490     bool GetObjects(const std::shared_ptr<const JEvent>& event, JFactory* factory) override;
0491 };
0492 ```
0493 
0494 ## JEventProcessor
0495 ### JEventProcessor Header File
0496 
0497 `JEventProcessors` in JANA2 have a similar feel to JANA1. The key differences are:
0498 
0499 1. The names and type signatures of the callbacks have changed
0500 2. The event number and run number now live on the JEvent object rather than as separate arguments
0501 3. JANA2 doesn't use `jerror_t` anywhere for several reasons: there's too many options to exhaustively check, most 
0502 error codes don't apply to JEventProcessors, there's no clear indication which error codes represent failure conditions,
0503 and no reasonable strategy JANA can take if a failure is reached other than a premature exit. Thus the callbacks return
0504 void. 
0505 4. If a failure condition is reached in user code, the user should throw a `JException` with a detailed message. JANA will
0506 add additional context information (such as the component name, callback, plugin, and backtrace), log everything, and shut
0507 down cleanly.
0508 5. The user no longer provides a `className` callback. Instead, they call `SetTypeName(NAME_OF_THIS);` from the constructor.
0509 
0510 ##### JANA1
0511 
0512 ```cpp
0513 #ifndef _JEventProcessor_myplugin_
0514 #define _JEventProcessor_myplugin_
0515 
0516 #include <JANA/JApplication.h>
0517 #include <JANA/JFactory.h>
0518 #include <JANA/JEventProcessor.h>
0519 using namespace jana;
0520   
0521 
0522 class JEventProcessor_myplugin : public jana::JEventProcessor{
0523 public:
0524         JEventProcessor_myplugin();
0525         ~JEventProcessor_myplugin();
0526         const char* className(void){return "JEventProcessor_myplugin";}
0527 
0528 private:
0529         jerror_t init(void); 
0530         jerror_t brun(jana::JEventLoop *eventLoop, int32_t runnumber); 
0531         jerror_t evnt(jana::JEventLoop *eventLoop, uint64_t eventnumber); 
0532         jerror_t erun(void); 
0533         jerror_t fini(void); 
0534 
0535 };
0536 
0537 #endif // _JEventProcessor_myplugin_
0538 ```
0539 
0540 ##### JANA2
0541 
0542 ```cpp
0543 #ifndef _JEventProcessor_myplugin_
0544 #define _JEventProcessor_myplugin_
0545 #include <JANA/JEventProcessor.h>
0546 
0547 class JEventProcessor_myplugin : public JEventProcessor {
0548 
0549 public:
0550         JEventProcessor_myplugin() { 
0551         SetTypeName(NAME_OF_THIS);
0552     }
0553         ~JEventProcessor_myplugin() = default;
0554 
0555 private:
0556         void Init() override;
0557         void BeginRun(const std::shared_ptr<const JEvent>& event) override; 
0558         void Process(const std::shared_ptr<const JEvent>& event) override; 
0559         void EndRun() override; 
0560         void Finish() override; 
0561 };
0562 
0563 #endif // _JEventProcessor_myplugin_
0564 ```
0565 
0566 ## JObject
0567 ### JObject Header File
0568 
0569 
0570 `JObjects` in JANA2 are also conceptually similar to their JANA1 counterparts, with a
0571 syntax refresh aimed at future extensibility. The `toStrings` callback has been
0572 replaced with a `Summarize` callback as shown below. Note that in JANA2, data model classes
0573 do not need to inherit from `JObject` anymore - `JObject` merely provides clean, user-specified formatting, 
0574 and convenient simple tracking of object associations. JANA2 also supports using [PODIO](https://github.com/AIDASoft/podio)
0575 based data models, which provide free serialization/deserialization, a first-class Python interface, automatic
0576 memory management and immutability guarantees, and relational object associations.
0577 
0578 ##### JANA1
0579 ```cpp
0580 #include <JANA/JObject.h>
0581 #include <JANA/JFactory.h>
0582 
0583 using namespace jana;
0584 
0585 class DCereHit: public JObject {
0586 public:
0587 
0588     JOBJECT_PUBLIC(DCereHit);
0589     int sector; 
0590     float pe; 
0591     float t;
0592 
0593     void toStrings(vector<pair<string, string> >&items) const { 
0594         AddString(items, "sector", "%d", sector);
0595         AddString(items, "pe", "%1.3f", pe);
0596         AddString(items, "t", "%1.3f", t);
0597     }
0598 };
0599 ```
0600 
0601 ##### JANA2
0602 
0603 ```cpp
0604 #include <JANA/JObject.h>
0605 
0606 class DCereHit: public JObject {
0607 public:
0608 
0609     JOBJECT_PUBLIC(DCereHit);
0610     int sector;
0611     float pe;
0612     float t;
0613 
0614     void Summarize(JObjectSummary& summary) const override {
0615         summary.add(sector, "sector", "%d");
0616         summary.add(pe, "pe", "%1.3f");
0617         summary.add(t, "t", "%1.3f");
0618     }
0619 };
0620 ```
0621 ### JObject ID Handling
0622 
0623 In JANA1, JObjects provided an `id` field. However it was left up to the user how to set and use it. Because JANA can't guarantee
0624 that it is set reliably or consistently, it is fundamentally part of the data model and not part of the framework. Thus, JANA2 
0625 no longer provides a built-in object id. If needed, users are welcome to add their own `id` field to their data model classes and
0626 establish a convention for how and when it gets set. For reliable, automatic object IDs for all data model classes, consider using PODIO.
0627 
0628 
0629 ##### **JANA1**
0630 ```cpp
0631 // JANA1 JObject had a data member id
0632 
0633 DBCALShower *shower = new DBCALShower;
0634 shower->id = id++;
0635 ```
0636 ##### **JANA2**
0637 
0638 ```cpp
0639 // id data member does not exist in JObject anymore in JANA2
0640 
0641 DBCALShower *shower = new DBCALShower;
0642 shower->id = id++; // Compiler error
0643 ```
0644 
0645 Similarly, the `JObject::oid_t` type has been removed from JANA2 as well. If you need it, it lives on in the halld_recon codebase:
0646 
0647 ```cpp
0648 #include "DANA/DObjectID.h"
0649 
0650 oid_t // Not inside JObject anymore!
0651 ```
0652 
0653 ## JFactory
0654 ### Transition from JFactory to JFactoryT
0655 ##### **JANA1**
0656 In JANA1, `JFactory_base` was a common factory base class, and `JFactory` was a template that inherits from `JFactory_base` and adds functionality specific to the type of the factory's output collection.
0657 ##### **JANA2**
0658 In JANA2, the base class was renamed to `JFactory`, and the template was renamed to `JFactoryT`. JANA2 adds some new functionality, but the old functionality is largely consistent with JANA1. 
0659 
0660 The syntax differences between JANA1 and JANA2 `JFactory`s' are consistent with those for `JEventProcessor`s. 
0661 
0662 1. The names and type signatures of the callbacks have changed
0663 2. The event number and run number now live on the JEvent object rather than as separate arguments
0664 3. JANA2 doesn't use `jerror_t` anywhere for several reasons: there's too many options to exhaustively check, most 
0665 error codes don't apply to JEventProcessors, there's no clear indication which error codes represent failure conditions,
0666 and no reasonable strategy JANA can take if a failure is reached other than a premature exit. Thus the callbacks return
0667 void. 
0668 4. If a failure condition is reached in user code, the user should throw a `JException` with a detailed message. JANA will
0669 add additional context information (such as the component name, callback, plugin, and backtrace), log everything, and shut
0670 down cleanly.
0671 5. The user no longer provides a `className` callback. Instead, they call `SetTypeName(NAME_OF_THIS);` from the constructor.
0672 
0673 Another important difference is how factory tags are set. In JANA1, the user provides a `Tag()` callback, whereas in JANA2,
0674 the user sets the tag by calling `SetTag()` from the constructor. The user can retrieve the factory tag by calling `GetTag()`.
0675 
0676 One important semantic difference is that in JANA1, there is always one factory set assigned to each thread, whereas in JANA2, 
0677 there is one factory set for each event in flight. The number of in-flight events is a parameter controlled separately 
0678 from the thread count. This is important for ensuring that there is always work for threads to do when running 
0679 multi-level processing topologies. Another consequence of this design is that factories don't belong to just one thread and hence 
0680 shouldn't reference thread-local variables - instead, one thread can pop an event from a queue, process it, and push it to a 
0681 different queue, where it could later be picked up by a different thread. Importantly, however, only one thread has access to any 
0682 given JEvent and its corresponding factory set at any time, so you don't need to worry about thread safety in JFactories.
0683 
0684 ### Factory Header File
0685 
0686 ##### JANA1
0687 
0688 ```cpp
0689 #ifndef _myfactory_factory_
0690 #define _myfactory_factory_
0691 
0692 #include <JANA/JFactory.h>
0693 #include "myobject.h"
0694 
0695 class myfactory_factory : public jana::JFactory<myobject> {
0696 
0697 public:
0698     myfactory_factory() = default;
0699     ~myfactory_factory() = default;
0700 
0701     const char* Tag() { return "MyTag"; }
0702 
0703 private:
0704     jerror_t init(void); 
0705     jerror_t brun(jana::JEventLoop *eventLoop, int32_t runnumber); 
0706     jerror_t evnt(jana::JEventLoop *eventLoop, uint64_t eventnumber); 
0707     jerror_t erun(void); 
0708     jerror_t fini(void); 
0709 };
0710 
0711 #endif
0712 ```
0713 
0714 ##### JANA2
0715 
0716 ```cpp
0717 #ifndef _thirdFacTest_factory_
0718 #define _thirdFacTest_factory_
0719 
0720 #include <JANA/JFactoryT.h>
0721 #include "myobject.h"
0722 
0723 class thirdFacTest_factory : public JFactoryT<myobject> {
0724 public:
0725     thirdFacTest_factory() { 
0726         SetTag("MyTag");
0727     }
0728     ~thirdFacTest_factory() = default;
0729 
0730 private:
0731     void Init() override;
0732     void BeginRun(const std::shared_ptr<const JEvent>& event) override; 
0733     void Process(const std::shared_ptr<const JEvent>& event) override; 
0734     void EndRun() override; 
0735     void Finish() override; 
0736 };
0737 
0738 #endif
0739 ```
0740 
0741 ### Registering a New Factory
0742 
0743 In JANA1, the user creates a `JFactoryGenerator` with a `GenerateFactories()` callback. Within this callback, 
0744 the user instantiates new factories and adds them to a `JEventLoop`. (In `halld_recon`, there is a `DFactoryGenerator`
0745 which instantiates factories for all fundamental detector plugins, calling each plugin's corresponding 
0746 `$DETECTOR_init()` function.)
0747 
0748 In JANA2, the user is still free to create their own `JFactoryGenerator`. It's syntax has been modified (notably, 
0749 `GenerateFactories()` provides a `JFactorySet` argument that the user adds the factories to), but the core concepts
0750 are the same. However, there is now also a `JFactoryGeneratorT` utility which reduces the boilerplate. As long
0751 as the factory is default constructible, the user merely needs to pass the factory class as a template argument to
0752 `JFactoryGeneratorT`, and JANA will do the rest of the work. JANA2 is perfectly fine with users passing a single 
0753 `JFactoryGenerator` that instantiates every single factory in the system, but there are future benefits if users
0754 pass separate `JFactoryGeneratorT`s for each factory instead.
0755 
0756 
0757 ##### **JANA1**
0758 
0759 ```cpp
0760 #include <JANA/JApplication.h>
0761 #include "JFactoryGenerator_myfactory.h"
0762 #include "myfactory.h"
0763 
0764 using namespace jana;
0765 
0766 extern "C" {
0767 void InitPlugin(JApplication *app) {
0768         InitJANAPlugin(app);
0769         app->AddFactoryGenerator(new JFactoryGenerator_myfactory());
0770 }
0771 } // "C"
0772 ```
0773 
0774 ##### **JANA2**
0775 
0776 ```cpp
0777 #include <JANA/JApplication.h>
0778 #include <JANA/JFactoryGenerator.h>
0779 #include "myfactory.h"
0780 
0781 extern "C" {
0782 void InitPlugin(JApplication *app) {
0783         InitJANAPlugin(app);
0784         app->Add(new JFactoryGeneratorT<my_factory>());
0785 }
0786 } // "C"
0787 ```
0788 
0789 ### Getting All Factories
0790 
0791 Sometimes it is necessary to retrieve all factories that produce objects of a given type. In
0792 JANA1 this was done by retrieving all factories and doing a `dynamic_cast`. In JANA2 there's a
0793 dedicated method for this, `GetFactoryAll`. (Note that this will retrieve the factories without
0794 automatically running them!). JANA2 also supports retrieving all objects of type `T` from all
0795 factories using `GetAll()` and retrieving all objects descended from parent type `T` 
0796 (e.g. `JObject` or `TObject`) using `GetAlllChildren()`.
0797 
0798 ##### **JANA1**
0799 
0800 ```cpp
0801 vector<JFactory_base*> locFactories = locEventLoop->GetFactories();
0802 // Cast JFactory_base to particular factory type
0803 JFactory<DReaction>* locFactory = dynamic_cast<JFactory<DReaction>*>(locFactories[0]);
0804 ```
0805 
0806 ##### **JANA2**
0807 
0808 ```cpp
0809 // Retrieve all factories producing T directly
0810 vector<JFactoryT<DReaction>*> locFacs = locEvent->GetFactoryAll<DReaction>();
0811 ```
0812 
0813 ### Saving Created Object(s) to Factory
0814 
0815 When writing a factory, the user creates some data objects inside `Process()` and
0816 then needs to pass them back to JANA. In JANA1, this was done by modifying the
0817 `_data` member variable directly. In JANA2, we prefer using a dedicated setter method.
0818 For the sake of porting GlueX without having to rewrite certain complex factories, 
0819 we've left the member variable `protected`, though the member variable has been 
0820 renamed to `mData`.
0821 
0822 ##### _Single Object_
0823 ###### **JANA1**
0824 
0825 ```cpp
0826 _data.push_back(locAnalysisResults);
0827 ```
0828 
0829 ###### **JANA2**
0830 
0831 ```cpp
0832 Insert(locAnalysisResults);
0833 
0834 // Or (less preferred)
0835 mData.push_back(locAnalysisResults);
0836 ```
0837 
0838 ##### _Array of Objects_
0839 
0840 ```cpp
0841 std::vector<Hit*> results;
0842 results.push_back(new Hit(...));
0843 ```
0844 
0845 ###### **JANA1**
0846 
0847 ```cpp
0848 for (auto hit: results){
0849         _data.push_back(hit); 
0850 }
0851 ```
0852 
0853 ###### **JANA2**
0854 
0855 ```cpp
0856 Set(results)
0857 ```
0858 
0859 ### **Setting Factory Flag**
0860 In JANA1, factory flag was set by calling `SetFactoryFlag(FLAG_NAME)` inside the factory constructor. The available flags were:
0861 
0862 ```cpp
0863 enum JFactory_Flags_t {
0864     JFACTORY_NULL      = 0x00,
0865     PERSISTANT         = 0x01,  // Misspelling of "PERSISTENT"
0866     WRITE_TO_OUTPUT    = 0x02,
0867     NOT_OBJECT_OWNER   = 0x04
0868 };
0869 ```
0870 
0871 JANA2 retains the same approach but introduces an additional flag while correcting the spelling of `PERSISTANT`:
0872 
0873 ```cpp
0874 enum JFactory_Flags_t {
0875     JFACTORY_NULL     = 0x00,
0876     PERSISTENT        = 0x01,  // Corrected spelling
0877     WRITE_TO_OUTPUT   = 0x02,
0878     NOT_OBJECT_OWNER  = 0x04,
0879     REGENERATE        = 0x08   // New flag
0880 };
0881 ```
0882 #### **Key Differences**
0883 ##### **1. `REGENERATE` – Forcing the Factory to Regenerate Objects**
0884 In JANA2, the `REGENERATE` flag prevents JANA from searching for objects in the input file, replicating the behavior of `use_factory = 1` in JANA1.
0885 ###### **JANA1:**
0886 ```cpp
0887 DEventWriterROOT_factory_ReactionEfficiency() {
0888     use_factory = 1; 
0889 };
0890 ```
0891  ###### **JANA2:**
0892 ```cpp
0893 DEventWriterROOT_factory_ReactionEfficiency() {
0894     SetRegenerateFlag(REGENERATE);
0895 };
0896 ```
0897 
0898 Alternatively, you can enable the `REGENERATE` flag using a boolean value:
0899 
0900 ```cpp
0901 DEventWriterROOT_factory_ReactionEfficiency() {
0902     SetRegenerateFlag(true);
0903 };
0904 ```
0905 
0906 ##### **2. `PERSISTENT` – Making Factory-Generated Objects Persistent**
0907 In JANA1, objects were made persistent by calling `SetFactoryFlag(PERSISTANT)`. JANA2 corrects the spelling mistake, renaming it to `PERSISTENT`, while maintaining the same core functionality. However, there is a key difference in how persistent objects are handled:
0908 - **JANA1:** The destructors of persistent objects are called automatically when the process terminates.
0909 - **JANA2:** The destructors of persistent objects are never called automatically, meaning any logic inside them will not execute unless the objects are explicitly deleted by the user. Therefore, if you set the `PERSISTENT` flag, you must manually delete these objects inside the factory’s `Finish()` method to prevent memory leaks.
0910 &nbsp;
0911     ```cpp
0912     void Finish() {
0913         for (auto locInfo : mData) {
0914             delete locInfo;
0915         }
0916         mData.clear();
0917     }
0918     ```
0919 
0920 ## JEvent
0921 ### Transition from JEventLoop to JEvent
0922 ##### **JANA1**
0923 In JANA1, all processing operated on a `JEventLoop` object. In JANA2, this has been changed to `JEvent`.
0924 Conceptually, a `JEvent` is just a container for data that can be processed as a discrete unit, indepedently from the rest
0925 of the stream (this usually correspondings to a physics event, but also potentially a timeslice, block, subevent, etc). This includes the 
0926 event number, run number, all data read from the event source, all data created by factories so far, and all of
0927 the factory state necessary to generate additional data belonging to the same context. The factories themselves are managed by a `JFactorySet`
0928 which is one-to-one with and owned by the JEvent.
0929 
0930 ### Getting the Run Number
0931 ##### **JANA1**
0932 ```cpp
0933 run_number = locEventLoop->GetJEvent().GetRunNumber());
0934 ```
0935 ##### **JANA2**
0936 ```cpp
0937 locEvent->GetRunNumber()
0938 ```
0939 
0940 #### Getting the Event Number
0941 ##### **JANA1**
0942 
0943 ```cpp
0944 run_number = locEventLoop->GetJEvent().GetEventNumber());
0945 ```
0946 ##### **JANA2**
0947 
0948 ```cpp
0949 locEvent->GetEventNumber()
0950 ```
0951 
0952 ## Acquiring Locks
0953 
0954 JANA1 required the user to manually acquire and hold locks when accessing to shared resources in a JEventProcessor.
0955 JANA2 offers a different interface which handles all locks internally. However, using this new callback interface
0956 would require restructuring the existing `JEventProcessor` code. When migrating from JANA1 to JANA2 it 
0957 is much safer to avoid making such deep changes, at least initially. The old-style user-managed locks can be migrated
0958 to JANA2 as-is with one minor change: the various lock helper methods have been moved from `JApplication` to `JLockService`.
0959 
0960 
0961 ### ROOT Read/Write locks
0962 ##### JANA1
0963 
0964 ```cpp
0965 dActionLock = japp->RootReadLock(); 
0966 // ...
0967 japp->RootUnLock(locLockName);
0968 ```
0969 ##### JANA2
0970 
0971 ```cpp
0972 auto app = GetApplication(); // or event->GetJApplication()
0973 auto lock_svc = app->GetService<JLockService>();
0974 
0975 lock_svc->RootReadLock(); 
0976 // ...
0977 lock_svc->RootUnLock();
0978 ```
0979 
0980 To reduce boilerplate, we've added a helper function:
0981 
0982 ```cpp
0983 #include "DANA/DEvent.h"
0984 
0985 DEvent::GetLockService(locEvent)->RootWriteLock(); 
0986 DEvent::GetLockService(locEvent)->RootUnLock();
0987 ```
0988 
0989 ### Named locks
0990 
0991 ##### JANA1
0992 
0993 ```cpp
0994 dActionLock = japp->ReadLock(locLockName); 
0995 // ...
0996 pthread_rwlock_unlock(dActionLock);
0997 // Or: japp->Unlock(locLockName);
0998 ```
0999 
1000 ##### JANA2
1001 
1002 ```cpp
1003 auto app = GetApplication(); // or event->GetJApplication()
1004 auto lock_svc = app->GetService<JLockService>();
1005 
1006 dActionLock = lock_svc->ReadLock(locLockName); 
1007 // ...
1008 pthread_rwlock_unlock(dActionLock);
1009 // Or: lock_svc->Unlock(locLockName);
1010 ```
1011 
1012 To reduce boilerplate:
1013 
1014 ```cpp
1015 DEvent::GetLockService(locEvent)->ReadLock("app"); 
1016 DEvent::GetLockService(locEvent)->Unlock("app");
1017 ```
1018 ## Deprecated Headers & Functions
1019 
1020 ### Why Do These Warnings Appear?
1021 When building a plugin ported to JANA2, you may see deprecation warnings (deprecated headers etc.). These headers and functions exist in JANA2 only for backward compatibility with JANA1 and are marked as deprecated to discourage their use, as they may be removed in the future.
1022 
1023 ### Can These Warnings Be Ignored?
1024 Yes, as long as your plugin compiles without crashes. They don't have any immediate impact on functionality. However, it’s better to update to the latest headers and functions because:
1025 - Deprecated headers and functions may be removed completely in future JANA2 versions.
1026 - Using them can slightly slow down compilation.
1027 ### How to Remove These Warnings?
1028 Replace deprecated headers and functions in your plugin code with alternatives provided in following table:
1029 
1030 | **Deprecated** | **Use Instead** |  
1031 |--------------------------|---------------------------|  
1032 | `#include <JANA/Compatibility/JLockService.h>` | `#include <JANA/Services/JLockService.h>` |  
1033 | `#include <JANA/Compatibility/JGeometry.h>` | `#include <JANA/Geometry/JGeometry.h>` |  
1034 | `#include <JANA/Calibrations/JLargeCalibration.h>` | `#include <JANA/Calibrations/JResource.h>` |  
1035 | `auto *jlargecalib = DEvent::GetJLargeCalibration(event);` | `auto *res = DEvent::GetJResource(event);` |  
1036 | `jlargecalib->GetResource(dedx_i_theta_file_name["file_name"]);` | `res->GetResource(dedx_i_theta_file_name["file_name"]);` |  
1037 | `JLargeCalibration *jresman;` | `JResource *jresman;` |  
1038 | `jresman = calib_svc->GetLargeCalibration(runnumber);` | `jresman = calib_svc->GetResource(runnumber);` |  
1039 | `#include <JANA/Compatibility/JGeometryXML.h>` | `#include <JANA/Geometry/JGeometryXML.h>` |  
1040 | `#include <JANA/Compatibility/JGeometryManager.h>` | `#include <JANA/Geometry/JGeometryManager.h>` |  
1041 | `#include <JANA/Compatibility/JStatusBits.h>` | `#include <JANA/Utils/JStatusBits.h>` |  
1042 | `#include <JANA/Compatibility/jerror.h>` | `#include <DANA/jerror.h>` |  
1043 
1044 
1045 ## Rarely Used Features
1046 
1047 ### `Unknown` Handling
1048 
1049 The enum in `particleType.h` was experiencing a name conflict with a JANA2 enum, so it has been changed
1050 to an enum class.
1051 
1052 ##### **JANA1**
1053 
1054 ```cpp
1055 //Was a plain enum so could be accessed without any scope resolution operator
1056 
1057 #include "particleType.h"
1058 
1059 return ((locFirstStep->Get_TargetPID() != Unknown) || (locFirstStep->Get_SecondBeamPID() != Unknown));
1060 ```
1061 
1062 ##### **JANA2**
1063 ```cpp
1064 // Is Enum class now so could be accessed like this `Particle_t::Unknown` only
1065 
1066 #include "particleType.h"
1067 
1068 return ((locFirstStep->Get_TargetPID() != Particle_t::Unknown) || (locFirstStep->Get_SecondBeamPID() != Particle_t::Unknown));
1069 ```