Warning, /firebird/README.md is written in an unsupported language. File is not indexed.
0001 # EIC Phoenix based event display
0002
0003 [![Frontend CI/CD Workflow](https://github.com/eic/firebird/actions/workflows/frontend.yaml/badge.svg?branch=main)](https://github.com/eic/firebird/actions/workflows/frontend.yaml)
0004
0005
0006 Visit working display:
0007
0008 https://eic.github.io/firebird/
0009
0010
0011 ## Development server
0012
0013 Run `ng serve` in `firebird-ng` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
0014
0015 # Firebird Data Exchange format
0016
0017 Data exchange is both JSON and Javascript object compatible.
0018
0019 It starts with version, any custom origin info and a list of entries.
0020 In HENP physics `entry` may correspond to `event` data.
0021
0022 ```json
0023 {
0024 "version": "0.01",
0025 "origin": {any custom origin info here"},
0026 "entries": [
0027 entry1, entry2, ...
0028 ]
0029 }
0030 ```
0031
0032 - **version** - is JSON schema version
0033 - **origin** - designed for any general custom info such as original file name,
0034 timestamp, simulation software version, etc.
0035 - **entries** - list of entries/events. The format is below.
0036
0037 ## Entry format
0038
0039 Entry is an object with `id` and `components` properties.
0040 By design components represent different hits, tracks, vertices, collections, etc.
0041 While can be any arbitary data, that will be further rendered by the frontend.
0042
0043 ```json
0044 {
0045 "id": "entry number or unique string",
0046 "components": [
0047
0048 ...
0049
0050 ]
0051 }
0052 ```
0053
0054 requrired fields are `id` and `components`.
0055
0056
0057 ## Component format
0058
0059 - "name": unique string id
0060 - "type": string with type (depends on what component will be used in the frontend to render it)
0061 - "originType": optional string with type of origin, e.g. "edm4eic::TrackerHitData",
0062 - all other fields are depend on "type"
0063
0064 So far example of exchange format looks like (only required fields are used here):
0065
0066 ```json
0067 {
0068 "version": "0.01",
0069 "entries": [
0070 {
0071 "id": "event 0",
0072 "components": [
0073 {
0074 "name": "BarrelVertexHits",
0075 "type": "HitBox",
0076 ...,
0077 },
0078 ...
0079 ]
0080 },
0081 ...
0082 ]
0083 }
0084 ```
0085
0086 ## HitBox component
0087
0088 ```json
0089 {
0090 "pos": [1, 2, 3],
0091 "dim": [10, 10, 1],
0092 "t": [4, 1],
0093 "ed": [0.001, 0.0001]
0094 }
0095 ```
0096 Hit has
0097
0098 - "pos": position [mm] (x, y, z),
0099 - "dim": box dimensions [mm] (dx, dy, dz),
0100 - "t": time information [ns] (time, err_time),
0101 - "ed": energy deposit with error [GeV] (edep, err_edep)
0102
0103 ## TypeScript Event Model
0104
0105
0106 The Firebird Data Exchange model provides a structured way to serialize and deserialize
0107 event data. This model is implemented in TypeScript and designed to be extensible,
0108 allowing users to add their own custom components without modifying the core parsing logic.
0109
0110 The implementation consists of several TypeScript classes and interfaces that mirror the data exchange
0111 format and provide methods for serialization and deserialization.
0112
0113 - **DataExchange** class - Represents the entire data exchange object.
0114 - **Entry** class - Represents an individual event entry.
0115 - **EntryComponent** abstract class - A base class representing a generic entry component. Described below.
0116
0117 It Typescript Firebird Data Exchange often referenced as Dex (Data EXchange). E.g.
0118 `toDexObject`, `fromDexObject`. `DexObject` is a JS object, that if serialized to JSON
0119 would correspond a part of DataExchangeFormat. E.g. Dex HitBox will have `pos`, `dim` etc.
0120
0121 We can put it differently. In general JSON format is very close to object definition in JS => TS.
0122 But despite that, Firebird JSON format is just a data exchange layer and when deserialized from
0123 JSON is not designed to be a 100% a convenient to work with JS data structure.
0124 More over, it lacks some methods and abstractions, that our domain data-model should have,
0125 such as links between event model and three.js rendering tree objects.
0126
0127 Summarizing:
0128
0129 - Firebird Data Exchange - is JSON schema shaping data exchange between backend and frontend
0130 - DexObject - JSON parsed to JS object
0131 - TypeScript event model - Frontend set of classes mimicking DexObject structure but designed
0132 to be convenient in terms of the frontend API
0133
0134
0135 ### EntryComponent machinery
0136
0137 Different collection of objects such as hits, tracks, vertexes, etc.
0138 that firebird can work with are represented as various event or Entry Component-s.
0139 Each type derive from EntryComponent and registered in a system.
0140 Then corresponding Painters classes know how to render/paint them, there are rules how
0141 to display them in tables, etc.
0142
0143 - **EntryComponent** An abstract class representing a generic entry component.
0144 - Contains common properties:
0145 - `name`: Unique identifier.
0146 - `type`: Component type (used for determining the appropriate factory).
0147 - `originType`: Optional string indicating the origin type.
0148 - Declares an abstract method `toDexObject()` that must be implemented by subclasses.
0149
0150 - **EntryComponentFactory Interface**: Defines a factory for creating `EntryComponent`
0151 instances from Dex objects - deserialized data.
0152 - **Component Registry**: A mapping of component types to their corresponding factories.
0153 - Functions:
0154 - `registerComponentFactory(factory: EntryComponentFactory)`: Registers a new factory.
0155 - `getComponentFactory(type: string)`: Retrieves a factory based on the component type.
0156
0157
0158 ## Extending the Model
0159
0160 ### Adding a New Component Type
0161
0162 To add a new component type, follow these steps:
0163
0164 1. **Create a New Component Class**: Extend `EntryComponent` and implement the `toDexObject()` method.
0165
0166 ```typescript
0167 export class CustomComponent extends EntryComponent {
0168 static type = 'CustomType';
0169 // Define additional properties
0170
0171 constructor(name: string, /* additional parameters */, originType?: string) {
0172 super(name, CustomComponent.type, originType);
0173 // Initialize additional properties
0174 }
0175
0176 toDexObject(): any {
0177 return {
0178 name: this.name,
0179 type: this.type,
0180 originType: this.originType,
0181 // Serialize additional properties
0182 };
0183 }
0184 }
0185 ```
0186
0187 2. **Create a Factory for the Component**: Implement `EntryComponentFactory` for your component.
0188
0189 ```typescript
0190 export class CustomComponentFactory implements EntryComponentFactory {
0191 type: string = CustomComponent.type;
0192
0193 fromDexObject(obj: any): EntryComponent {
0194 const name = obj["name"];
0195 // Extract additional properties
0196 const originType = obj["originType"];
0197
0198 // Validate required fields
0199 if (!name /* || missing other required fields */) {
0200 throw new Error("Missing required fields in CustomComponent");
0201 }
0202
0203 return new CustomComponent(name, /* additional parameters */, originType);
0204 }
0205 }
0206 ```
0207
0208 3. **Register the Factory**: Use the `registerComponentFactory()` function to register your component factory.
0209
0210 ```typescript
0211 // Register the custom component factory
0212 registerComponentFactory(new CustomComponentFactory());
0213 ```
0214
0215 4. **Update JSON Parsing Logic**: No need to modify existing parsing logic. The registry will dynamically resolve the new component type.
0216