Skip to content

pybes3

besio

open(file, **kwargs)

Alias for uproot.open.

Returns:

Type Description
Any

The uproot file object.

Warning

This function is deprecated and will be removed in future versions. Use uproot.open instread.

Source code in src/pybes3/besio/__init__.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def open(file: str, **kwargs: object) -> Any:
    """
    Alias for `uproot.open`.

    Returns:
        The uproot file object.

    Warning:
        This function is deprecated and will be removed in future versions.
        Use `uproot.open` instread.
    """
    # TODO: Remove this in the future.
    warn(
        "`pybes3.open` is deprecated and will be removed in future versions. "
        "Use `uproot.open` instead.",
        DeprecationWarning,
        stacklevel=2,
    )
    return uproot.open(file, **kwargs)

concatenate(files, expressions=None, cut=None, **kwargs)

Alias for uproot.concatenate.

Returns:

Type Description
Any

The concatenated array.

Warning

This function is deprecated and will be removed in future versions. Use uproot.concatenate instread.

Source code in src/pybes3/besio/__init__.py
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def concatenate(
    files: str | list[str],
    expressions: str | list[str] | None = None,
    cut: str | None = None,
    **kwargs: object,
) -> Any:
    """
    Alias for `uproot.concatenate`.

    Returns:
        The concatenated array.

    Warning:
        This function is deprecated and will be removed in future versions.
        Use `uproot.concatenate` instread.
    """
    # TODO: Remove this in the future.
    warn(
        "`pybes3.concatenate` is deprecated and will be removed in future versions. "
        "Use `uproot.concatenate` instead.",
        DeprecationWarning,
        stacklevel=2,
    )
    return uproot.concatenate(files, expressions, cut, **kwargs)

open_raw(file)

Open a raw binary file.

Parameters:

Name Type Description Default
file str

The file to open.

required

Returns:

Type Description
RawBinaryReader

The raw binary reader.

Source code in src/pybes3/besio/__init__.py
60
61
62
63
64
65
66
67
68
69
70
def open_raw(file: str) -> RawBinaryReader:
    """
    Open a raw binary file.

    Parameters:
        file (str): The file to open.

    Returns:
        (RawBinaryReader): The raw binary reader.
    """
    return RawBinaryReader(file)

concatenate_raw(files, *, entry_start=0, entry_stop=-1, filter_name=None, verbose=False)

Concatenate multiple raw binary files into ak.Array

Parameters:

Name Type Description Default
files str | Path | list[str | Path]

files to be read.

required
entry_start int

The starting entry to read. Defaults to 0.

0
entry_stop int

The stopping entry to read. Defaults to -1, which means read until the end.

-1
filter_name Union[str, list, None]

A filter to select specific fields to read. Defaults to None, which means read all fields.

None
verbose bool

Show reading process. Defaults to False.

False

Returns:

Type Description
Array

Concatenated raw data array.

Source code in src/pybes3/besio/raw_io.py
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
def concatenate(
    files: str | Path | list[str | Path],
    *,
    entry_start: int = 0,
    entry_stop: int = -1,
    filter_name: Union[str, list, None] = None,
    verbose: bool = False,
) -> ak.Array:
    """
    Concatenate multiple raw binary files into `ak.Array`

    Parameters:
        files (str | Path | list[str | Path]): files to be read.
        entry_start (int, optional): The starting entry to read. Defaults to 0.
        entry_stop (int, optional): The stopping entry to read. Defaults to -1, which means read until the end.
        filter_name (Union[str, list, None], optional): A filter to select specific fields to read. Defaults to `None`, which means read all fields.
        verbose (bool, optional): Show reading process. Defaults to `False`.

    Returns:
        Concatenated raw data array.
    """
    if not isinstance(files, list):
        files = glob.glob(files, recursive=True)

    files = [str(Path(file).resolve()) for file in files if _is_raw(file)]

    if len(files) == 0:
        raise ValueError("No valid raw files found")

    n_cum_entries = 0
    readers_with_entry_range: list[tuple[RawBinaryReader, int, int]] = []
    for file in files:
        reader = RawBinaryReader(file)

        if n_cum_entries + reader.entries < entry_start:
            n_cum_entries += reader.entries
            continue

        entry_start_for_reader = None
        entry_stop_for_reader = None

        # entry_start for this reader
        if n_cum_entries < entry_start and n_cum_entries + reader.entries >= entry_start:
            entry_start_for_reader = entry_start - n_cum_entries
        else:
            entry_start_for_reader = 0

        # entry_stop for this reader
        if entry_stop < 0:
            entry_stop_for_reader = -1
        elif n_cum_entries <= entry_stop and n_cum_entries + reader.entries > entry_stop:
            entry_stop_for_reader = entry_stop - n_cum_entries
        else:
            entry_stop_for_reader = -1

        readers_with_entry_range.append(
            (reader, entry_start_for_reader, entry_stop_for_reader)
        )

        n_cum_entries += reader.entries
        if entry_stop >= 0 and n_cum_entries >= entry_stop:
            break

    try:
        res = []
        n_cum_read = 0
        for reader, entry_start_for_reader, entry_stop_for_reader in readers_with_entry_range:
            n_read = (
                entry_stop_for_reader - entry_start_for_reader
                if entry_stop_for_reader >= 0
                else reader.entries - entry_start_for_reader
            )

            if verbose:
                print(
                    f"Reading file {reader.path}: {n_cum_read} -> {n_cum_read + n_read} entries ...",
                )

            res.append(
                reader.arrays(
                    entry_start=entry_start_for_reader,
                    entry_stop=entry_stop_for_reader,
                    filter_name=filter_name,
                )
            )

            n_cum_read += n_read
    finally:
        for reader, _, _ in readers_with_entry_range:
            reader.close()

    if len(res) == 0:
        return ak.Array([])

    return ak.concatenate(res)

detectors

emc_gid_to_center_x(gid)

Convert EMC gid to x coordinate of the crystal's center.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required

Returns:

Type Description
FloatLike

The x coordinate of the crystal's center.

Source code in src/pybes3/detectors/emc.py
260
261
262
263
264
265
266
267
268
269
270
271
@nb.vectorize(cache=True)
def emc_gid_to_center_x(gid: IntLike) -> FloatLike:
    """
    Convert EMC gid to x coordinate of the crystal's center.

    Parameters:
        gid: The gid of the crystal.

    Returns:
        The x coordinate of the crystal's center.
    """
    return _center_x[gid]

emc_gid_to_center_y(gid)

Convert EMC gid to y coordinate of the crystal's center.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required

Returns:

Type Description
FloatLike

The y coordinate of the crystal's center.

Source code in src/pybes3/detectors/emc.py
274
275
276
277
278
279
280
281
282
283
284
285
@nb.vectorize(cache=True)
def emc_gid_to_center_y(gid: IntLike) -> FloatLike:
    """
    Convert EMC gid to y coordinate of the crystal's center.

    Parameters:
        gid: The gid of the crystal.

    Returns:
        The y coordinate of the crystal's center.
    """
    return _center_y[gid]

emc_gid_to_center_z(gid)

Convert EMC gid to z coordinate of the crystal's center.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required

Returns:

Type Description
FloatLike

The z coordinate of the crystal's center.

Source code in src/pybes3/detectors/emc.py
288
289
290
291
292
293
294
295
296
297
298
299
@nb.vectorize(cache=True)
def emc_gid_to_center_z(gid: IntLike) -> FloatLike:
    """
    Convert EMC gid to z coordinate of the crystal's center.

    Parameters:
        gid: The gid of the crystal.

    Returns:
        The z coordinate of the crystal's center.
    """
    return _center_z[gid]

emc_gid_to_front_center_x(gid)

Convert EMC gid to x coordinate of the crystal's front center.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required

Returns:

Type Description
FloatLike

The x coordinate of the crystal's front center.

Source code in src/pybes3/detectors/emc.py
302
303
304
305
306
307
308
309
310
311
312
313
@nb.vectorize(cache=True)
def emc_gid_to_front_center_x(gid: IntLike) -> FloatLike:
    """
    Convert EMC gid to x coordinate of the crystal's front center.

    Parameters:
        gid: The gid of the crystal.

    Returns:
        The x coordinate of the crystal's front center.
    """
    return _front_center_x[gid]

emc_gid_to_front_center_y(gid)

Convert EMC gid to y coordinate of the crystal's front center.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required

Returns:

Type Description
FloatLike

The y coordinate of the crystal's front center.

Source code in src/pybes3/detectors/emc.py
316
317
318
319
320
321
322
323
324
325
326
327
@nb.vectorize(cache=True)
def emc_gid_to_front_center_y(gid: IntLike) -> FloatLike:
    """
    Convert EMC gid to y coordinate of the crystal's front center.

    Parameters:
        gid: The gid of the crystal.

    Returns:
        The y coordinate of the crystal's front center.
    """
    return _front_center_y[gid]

emc_gid_to_front_center_z(gid)

Convert EMC gid to z coordinate of the crystal's front center.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required

Returns:

Type Description
FloatLike

The z coordinate of the crystal's front center.

Source code in src/pybes3/detectors/emc.py
330
331
332
333
334
335
336
337
338
339
340
341
@nb.vectorize(cache=True)
def emc_gid_to_front_center_z(gid: IntLike) -> FloatLike:
    """
    Convert EMC gid to z coordinate of the crystal's front center.

    Parameters:
        gid: The gid of the crystal.

    Returns:
        The z coordinate of the crystal's front center.
    """
    return _front_center_z[gid]

emc_gid_to_part(gid)

Convert EMC gid to part.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required

Returns:

Type Description
IntLike

The part number of the crystal.

Source code in src/pybes3/detectors/emc.py
173
174
175
176
177
178
179
180
181
182
183
184
@nb.vectorize(cache=True)
def emc_gid_to_part(gid: IntLike) -> IntLike:
    """
    Convert EMC gid to part.

    Parameters:
        gid: The gid of the crystal.

    Returns:
        The part number of the crystal.
    """
    return _part[gid]

emc_gid_to_phi(gid)

Convert EMC gid to phi.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required

Returns:

Type Description
IntLike

The phi number of the crystal.

Source code in src/pybes3/detectors/emc.py
201
202
203
204
205
206
207
208
209
210
211
212
@nb.vectorize(cache=True)
def emc_gid_to_phi(gid: IntLike) -> IntLike:
    """
    Convert EMC gid to phi.

    Parameters:
        gid: The gid of the crystal.

    Returns:
        The phi number of the crystal.
    """
    return _phi[gid]

emc_gid_to_point_x(gid, point)

Convert EMC gid to x coordinate of the point.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required
point IntLike

The point number, 0-7.

required

Returns:

Type Description
FloatLike

The x coordinate of the point.

Source code in src/pybes3/detectors/emc.py
215
216
217
218
219
220
221
222
223
224
225
226
227
@nb.vectorize(cache=True)
def emc_gid_to_point_x(gid: IntLike, point: IntLike) -> FloatLike:
    """
    Convert EMC gid to x coordinate of the point.

    Parameters:
        gid: The gid of the crystal.
        point: The point number, 0-7.

    Returns:
        The x coordinate of the point.
    """
    return _points_x[gid, point]

emc_gid_to_point_y(gid, point)

Convert EMC gid to y coordinate of the point.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required
point IntLike

The point number, 0-7.

required

Returns:

Type Description
FloatLike

The y coordinate of the point.

Source code in src/pybes3/detectors/emc.py
230
231
232
233
234
235
236
237
238
239
240
241
242
@nb.vectorize(cache=True)
def emc_gid_to_point_y(gid: IntLike, point: IntLike) -> FloatLike:
    """
    Convert EMC gid to y coordinate of the point.

    Parameters:
        gid: The gid of the crystal.
        point: The point number, 0-7.

    Returns:
        The y coordinate of the point.
    """
    return _points_y[gid, point]

emc_gid_to_point_z(gid, point)

Convert EMC gid to z coordinate of the point.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required
point IntLike

The point number, 0-7.

required

Returns:

Type Description
FloatLike

The z coordinate of the point.

Source code in src/pybes3/detectors/emc.py
245
246
247
248
249
250
251
252
253
254
255
256
257
@nb.vectorize(cache=True)
def emc_gid_to_point_z(gid: IntLike, point: IntLike) -> FloatLike:
    """
    Convert EMC gid to z coordinate of the point.

    Parameters:
        gid: The gid of the crystal.
        point: The point number, 0-7.

    Returns:
        The z coordinate of the point.
    """
    return _points_z[gid, point]

emc_gid_to_theta(gid)

Convert EMC gid to theta.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required

Returns:

Type Description
IntLike

The theta number of the crystal.

Source code in src/pybes3/detectors/emc.py
187
188
189
190
191
192
193
194
195
196
197
198
@nb.vectorize(cache=True)
def emc_gid_to_theta(gid: IntLike) -> IntLike:
    """
    Convert EMC gid to theta.

    Parameters:
        gid: The gid of the crystal.

    Returns:
        The theta number of the crystal.
    """
    return _theta[gid]

get_emc_geom_table(library='np')

Get EMC crystal position table.

Parameters:

Name Type Description Default
library Literal['np', 'ak', 'pd']

The library to return the data in. Choose from 'ak', 'np', 'pd'.

'np'

Returns:

Type Description
Array | dict[str, ndarray] | DataFrame

The EMC crystal position table.

Raises:

Type Description
ValueError

If the library is not 'ak', 'np', or 'pd'.

ImportError

If the library is 'pd' but pandas is not installed.

Source code in src/pybes3/detectors/emc.py
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
def get_emc_geom_table(library: Literal["np", "ak", "pd"] = "np"):
    """
    Get EMC crystal position table.

    Parameters:
        library: The library to return the data in. Choose from 'ak', 'np', 'pd'.

    Returns:
        (ak.Array | dict[str, np.ndarray] | pd.DataFrame): The EMC crystal position table.

    Raises:
        ValueError: If the library is not 'ak', 'np', or 'pd'.
        ImportError: If the library is 'pd' but pandas is not installed.
    """
    cp: dict[str, np.ndarray] = {k: v.copy() for k, v in _emc_geom.items()}

    res: dict[str, np.ndarray] = {}

    for k in [
        "gid",
        "center_x",
        "center_y",
        "center_z",
        "front_center_x",
        "front_center_y",
        "front_center_z",
    ]:
        res[k] = cp[k]

    # flatten crystal points
    for i in range(8):
        res[f"points_x_{i}"] = cp["points_x"][:, i]
        res[f"points_y_{i}"] = cp["points_y"][:, i]
        res[f"points_z_{i}"] = cp["points_z"][:, i]

    if library == "ak":
        return ak.Array(res)
    elif library == "np":
        return res
    elif library == "pd":
        try:
            import pandas as pd  # type: ignore
        except ImportError:
            raise ImportError("Pandas is not installed. Run `pip install pandas`.")
        return pd.DataFrame(res)
    else:
        raise ValueError(f"Invalid library {library}. Choose from 'ak', 'np', 'pd'.")

get_emc_crystal_position(library='np')

Deprecated

This function is deprecated, use get_emc_geom_table instead.

Source code in src/pybes3/detectors/emc.py
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def get_emc_crystal_position(library: Literal["np", "ak", "pd"] = "np"):
    """
    !!! warning "Deprecated"
        This function is deprecated, use `get_emc_geom_table` instead.
    """
    import warnings

    warnings.warn(
        "get_emc_crystal_position is deprecated, use get_emc_geom_table instead.",
        DeprecationWarning,
        stacklevel=2,
    )

    return get_emc_geom_table(library)

get_emc_gid(part, theta, phi)

Get EMC gid of given part, theta, and phi.

  • part 0: 0-479
    • theta 0: 0-63
    • theta 1: 64-127
    • theta 2: 128-207
    • theta 3: 208-287
    • theta 4: 288-383
    • theta 5: 384-479
  • part 1: 480-5759 (theta 0-47)
  • part 2: 5760-6239
    • theta 5: 5760-5855 (96)
    • theta 4: 5856-5951 (96)
    • theta 3: 5952-6031 (80)
    • theta 2: 6032-6111 (80)
    • theta 1: 6112-6175 (64)
    • theta 0: 6176-6239 (64)

Parameters:

Name Type Description Default
part IntLike

part number

required
theta IntLike

theta number

required
phi IntLike

phi number

required

Returns:

Name Type Description
index IntLike

EMC index

Source code in src/pybes3/detectors/emc.py
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
@nb.vectorize(cache=True)
def get_emc_gid(part: IntLike, theta: IntLike, phi: IntLike) -> IntLike:
    """
    Get EMC gid of given part, theta, and phi.

    - part 0: 0-479
        - theta 0: 0-63
        - theta 1: 64-127
        - theta 2: 128-207
        - theta 3: 208-287
        - theta 4: 288-383
        - theta 5: 384-479
    - part 1: 480-5759 (theta 0-47)
    - part 2: 5760-6239
        - theta 5: 5760-5855 (96)
        - theta 4: 5856-5951 (96)
        - theta 3: 5952-6031 (80)
        - theta 2: 6032-6111 (80)
        - theta 1: 6112-6175 (64)
        - theta 0: 6176-6239 (64)

    Parameters:
        part: part number
        theta: theta number
        phi: phi number

    Returns:
        index: EMC index
    """
    if part == 0:
        res = 0
        if theta == 0 or theta == 1:
            return theta * ENDCAP_PHI_01 + phi

        res += 2 * ENDCAP_PHI_01
        if theta == 2 or theta == 3:
            return res + (theta - 2) * ENDCAP_PHI_23 + phi

        res += 2 * ENDCAP_PHI_23
        if theta == 4 or theta == 5:
            return res + (theta - 4) * ENDCAP_PHI_45 + phi

    if part == 1:
        return ENDCAP_CRYSTALS + theta * BARREL_PHI + phi

    if part == 2:
        res = ENDCAP_CRYSTALS + BARREL_CRYSTALS

        if theta == 4 or theta == 5:
            return res + (5 - theta) * ENDCAP_PHI_45 + phi

        res += 2 * ENDCAP_PHI_45
        if theta == 2 or theta == 3:
            return res + (3 - theta) * ENDCAP_PHI_23 + phi

        res += 2 * ENDCAP_PHI_23
        if theta == 0 or theta == 1:
            return res + (1 - theta) * ENDCAP_PHI_01 + phi

    raise ValueError(f"Unsupported part: {part}")

get_mdc_gid(layer, wire)

Get MDC gid of given layer and wire.

Parameters:

Name Type Description Default
layer IntLike

The layer number.

required
wire IntLike

The wire number.

required

Returns:

Type Description
IntLike

The gid of the wire.

Source code in src/pybes3/detectors/mdc.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
@nb.vectorize(cache=True)
def get_mdc_gid(layer: IntLike, wire: IntLike) -> IntLike:
    """
    Get MDC gid of given layer and wire.

    Parameters:
        layer: The layer number.
        wire: The wire number.

    Returns:
        The gid of the wire.
    """
    return _layer_start_gid[layer] + wire

get_mdc_geom_table(library='np')

Get the MDC wire position table.

Parameters:

Name Type Description Default
library Literal['np', 'ak', 'pd']

The library to return the data in. Choose from 'ak', 'np', 'pd'.

'np'

Returns:

Type Description
Array | dict[str, ndarray] | DataFrame

The MDC wire position table.

Raises:

Type Description
ValueError

If the library is not 'ak', 'np', or 'pd'.

ImportError

If the library is 'pd' but pandas is not installed.

Source code in src/pybes3/detectors/mdc.py
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def get_mdc_geom_table(library: Literal["np", "ak", "pd"] = "np"):
    """
    Get the MDC wire position table.

    Parameters:
        library: The library to return the data in. Choose from 'ak', 'np', 'pd'.

    Returns:
        (ak.Array | dict[str, np.ndarray] | pd.DataFrame): The MDC wire position table.

    Raises:
        ValueError: If the library is not 'ak', 'np', or 'pd'.
        ImportError: If the library is 'pd' but pandas is not installed.
    """
    cp: dict[str, np.ndarray] = {k: v.copy() for k, v in _mdc_geom_table.items()}

    if library == "ak":
        return ak.Array(cp)
    elif library == "np":
        return cp
    elif library == "pd":
        try:
            import pandas as pd  # type: ignore
        except ImportError:
            raise ImportError("Pandas is not installed. Run `pip install pandas`.")
        return pd.DataFrame(cp)
    else:
        raise ValueError(f"Invalid library {library}. Choose from 'ak', 'np', 'pd'.")

get_mdc_wire_position(library='np')

Deprecated

This function is deprecated, use get_mdc_geom_table instead.

Source code in src/pybes3/detectors/mdc.py
72
73
74
75
76
77
78
79
80
81
82
83
84
85
def get_mdc_wire_position(library: Literal["np", "ak", "pd"] = "np"):
    """
    !!! warning "Deprecated"
        This function is deprecated, use `get_mdc_geom_table` instead.
    """
    import warnings

    warnings.warn(
        "get_mdc_wire_position is deprecated, use get_mdc_geom_table instead.",
        DeprecationWarning,
        stacklevel=2,
    )

    return get_mdc_geom_table(library)

mdc_gid_to_east_x(gid)

Convert gid to east_x (cm).

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required

Returns:

Type Description
FloatLike

The east_x (cm) of the wire.

Source code in src/pybes3/detectors/mdc.py
246
247
248
249
250
251
252
253
254
255
256
257
@nb.vectorize(cache=True)
def mdc_gid_to_east_x(gid: IntLike) -> FloatLike:
    """
    Convert gid to east_x (cm).

    Parameters:
        gid: The gid of the wire.

    Returns:
        The east_x (cm) of the wire.
    """
    return _east_x[gid]

mdc_gid_to_east_y(gid)

Convert gid to east_y (cm).

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required

Returns:

Type Description
FloatLike

The east_y (cm) of the wire.

Source code in src/pybes3/detectors/mdc.py
260
261
262
263
264
265
266
267
268
269
270
271
@nb.vectorize(cache=True)
def mdc_gid_to_east_y(gid: IntLike) -> FloatLike:
    """
    Convert gid to east_y (cm).

    Parameters:
        gid: The gid of the wire.

    Returns:
        The east_y (cm) of the wire.
    """
    return _east_y[gid]

mdc_gid_to_east_z(gid)

Convert gid to east_z (cm).

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required

Returns:

Type Description
FloatLike

The east_z (cm) of the wire.

Source code in src/pybes3/detectors/mdc.py
274
275
276
277
278
279
280
281
282
283
284
285
@nb.vectorize(cache=True)
def mdc_gid_to_east_z(gid: IntLike) -> FloatLike:
    """
    Convert gid to east_z (cm).

    Parameters:
        gid: The gid of the wire.

    Returns:
        The east_z (cm) of the wire.
    """
    return _east_z[gid]

mdc_gid_to_is_stereo(gid)

Convert gid to is_stereo.

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required

Returns:

Type Description
BoolLike

The is_stereo of the wire.

Source code in src/pybes3/detectors/mdc.py
190
191
192
193
194
195
196
197
198
199
200
201
@nb.vectorize(cache=True)
def mdc_gid_to_is_stereo(gid: IntLike) -> BoolLike:
    """
    Convert gid to is_stereo.

    Parameters:
        gid: The gid of the wire.

    Returns:
        The is_stereo of the wire.
    """
    return _is_stereo[gid]

mdc_gid_to_layer(gid)

Convert gid to layer.

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required

Returns:

Type Description
IntLike

The layer number of the wire.

Source code in src/pybes3/detectors/mdc.py
131
132
133
134
135
136
137
138
139
140
141
142
@nb.vectorize(cache=True)
def mdc_gid_to_layer(gid: IntLike) -> IntLike:
    """
    Convert gid to layer.

    Parameters:
        gid: The gid of the wire.

    Returns:
        The layer number of the wire.
    """
    return _layer[gid]

mdc_gid_to_stereo(gid)

Convert gid to stereo. 0 for axial, -1 for stereo that phi_west < phi_east, 1 for stereo that phi_west > phi_east.

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required

Returns:

Type Description
IntLike

The stereo of the wire.

Source code in src/pybes3/detectors/mdc.py
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
@nb.vectorize(cache=True)
def mdc_gid_to_stereo(gid: IntLike) -> IntLike:
    """
    Convert gid to stereo.
    `0` for `axial`,
    `-1` for stereo that `phi_west < phi_east`,
    `1` for stereo that `phi_west > phi_east`.

    Parameters:
        gid: The gid of the wire.

    Returns:
        The stereo of the wire.
    """
    return _stereo[gid]

mdc_gid_to_superlayer(gid)

Convert gid to superlayer.

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required

Returns:

Type Description
IntLike

The superlayer number of the wire.

Source code in src/pybes3/detectors/mdc.py
103
104
105
106
107
108
109
110
111
112
113
114
@nb.vectorize(cache=True)
def mdc_gid_to_superlayer(gid: IntLike) -> IntLike:
    """
    Convert gid to superlayer.

    Parameters:
        gid: The gid of the wire.

    Returns:
        The superlayer number of the wire.
    """
    return _superlayer[gid]

mdc_gid_to_west_x(gid)

Convert gid to west_x (cm).

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required

Returns:

Type Description
FloatLike

The west_x (cm) of the wire.

Source code in src/pybes3/detectors/mdc.py
204
205
206
207
208
209
210
211
212
213
214
215
@nb.vectorize(cache=True)
def mdc_gid_to_west_x(gid: IntLike) -> FloatLike:
    """
    Convert gid to west_x (cm).

    Parameters:
        gid: The gid of the wire.

    Returns:
        The west_x (cm) of the wire.
    """
    return _west_x[gid]

mdc_gid_to_west_y(gid)

Convert gid to west_y (cm).

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required

Returns:

Type Description
FloatLike

The west_y (cm) of the wire.

Source code in src/pybes3/detectors/mdc.py
218
219
220
221
222
223
224
225
226
227
228
229
@nb.vectorize(cache=True)
def mdc_gid_to_west_y(gid: IntLike) -> FloatLike:
    """
    Convert gid to west_y (cm).

    Parameters:
        gid: The gid of the wire.

    Returns:
        The west_y (cm) of the wire.
    """
    return _west_y[gid]

mdc_gid_to_west_z(gid)

Convert gid to west_z (cm).

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required

Returns:

Type Description
FloatLike

The west_z (cm) of the wire.

Source code in src/pybes3/detectors/mdc.py
232
233
234
235
236
237
238
239
240
241
242
243
@nb.vectorize(cache=True)
def mdc_gid_to_west_z(gid: IntLike) -> FloatLike:
    """
    Convert gid to west_z (cm).

    Parameters:
        gid: The gid of the wire.

    Returns:
        The west_z (cm) of the wire.
    """
    return _west_z[gid]

mdc_gid_to_wire(gid)

Convert gid to wire.

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required

Returns:

Type Description
IntLike

The wire number of the wire.

Source code in src/pybes3/detectors/mdc.py
145
146
147
148
149
150
151
152
153
154
155
156
@nb.vectorize(cache=True)
def mdc_gid_to_wire(gid: IntLike) -> IntLike:
    """
    Convert gid to wire.

    Parameters:
        gid: The gid of the wire.

    Returns:
        The wire number of the wire.
    """
    return _wire[gid]

mdc_gid_z_to_x(gid, z)

Get the x (cm) position of the wire at z (cm).

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required
z FloatLike

The z (cm) position.

required

Returns:

Type Description
FloatLike

The x (cm) position of the wire at z (cm).

Source code in src/pybes3/detectors/mdc.py
288
289
290
291
292
293
294
295
296
297
298
299
300
@nb.vectorize(cache=True)
def mdc_gid_z_to_x(gid: IntLike, z: FloatLike) -> FloatLike:
    """
    Get the x (cm) position of the wire at z (cm).

    Parameters:
        gid: The gid of the wire.
        z: The z (cm) position.

    Returns:
        The x (cm) position of the wire at z (cm).
    """
    return _west_x[gid] + _dx_dz[gid] * (z - _west_z[gid])

mdc_gid_z_to_y(gid, z)

Get the y (cm) position of the wire at z (cm).

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required
z FloatLike

The z (cm) position.

required

Returns:

Type Description
FloatLike

The y (cm) position of the wire at z (cm).

Source code in src/pybes3/detectors/mdc.py
303
304
305
306
307
308
309
310
311
312
313
314
315
@nb.vectorize(cache=True)
def mdc_gid_z_to_y(gid: IntLike, z: FloatLike) -> FloatLike:
    """
    Get the y (cm) position of the wire at z (cm).

    Parameters:
        gid: The gid of the wire.
        z: The z (cm) position.

    Returns:
        The y (cm) position of the wire at z (cm).
    """
    return _west_y[gid] + _dy_dz[gid] * (z - _west_z[gid])

mdc_layer_to_is_stereo(layer)

Convert layer to is_stereo.

Parameters:

Name Type Description Default
layer IntLike

The layer number.

required

Returns:

Type Description
BoolLike

The is_stereo of the layer.

Source code in src/pybes3/detectors/mdc.py
176
177
178
179
180
181
182
183
184
185
186
187
@nb.vectorize(cache=True)
def mdc_layer_to_is_stereo(layer: IntLike) -> BoolLike:
    """
    Convert layer to is_stereo.

    Parameters:
        layer: The layer number.

    Returns:
        The is_stereo of the layer.
    """
    return _is_layer_stereo[layer]

mdc_layer_to_superlayer(layer)

Convert layer to superlayer.

Parameters:

Name Type Description Default
layer IntLike

The layer number.

required

Returns:

Type Description
IntLike

The superlayer number of the layer.

Source code in src/pybes3/detectors/mdc.py
117
118
119
120
121
122
123
124
125
126
127
128
@nb.vectorize(cache=True)
def mdc_layer_to_superlayer(layer: IntLike) -> IntLike:
    """
    Convert layer to superlayer.

    Parameters:
        layer: The layer number.

    Returns:
        The superlayer number of the layer.
    """
    return np.digitize(layer, _superlayer_splits, right=False) - 1

parse_emc_gid(gid, geometry=False)

Parse the gid of EMC crystals. "gid" is the global ID of the crystal, ranges from 0 to 6239. When gid is an ak.Array, the result is an ak.Array, otherwise it is a dict.

Keys of the output:

  • gid: Global ID of the crystal.
  • part: Part number, 0 for endcap0, 1 for barrel, 2 for endcap1.
  • theta: Theta number.
  • phi: Phi number.

Optional keys of the output when geometry is True:

  • front_center_x: x position of the front center of the crystal.
  • front_center_y: y position of the front center of the crystal.
  • front_center_z: z position of the front center of the crystal.
  • center_x: x position of the center of the crystal.
  • center_y: y position of the center of the crystal.
  • center_z: z position of the center of the crystal.

Info

The 8 points of the crystal will not be returned here. If you need the 8 points of the crystal, use emc_gid_to_point_x, emc_gid_to_point_y and emc_gid_to_point_z.

Parameters:

Name Type Description Default
gid IntLike

The gid of the crystal.

required
geometry bool

Whether to include the geometry information.

False

Returns:

Type Description
Array | dict[str, Any]

The parsed result.

Source code in src/pybes3/detectors/emc.py
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
def parse_emc_gid(gid: IntLike, geometry: bool = False) -> ak.Array | dict[str, Any]:
    """
    Parse the gid of EMC crystals. "gid" is the global ID of the crystal, ranges from 0 to 6239.
    When `gid` is an `ak.Array`, the result is an `ak.Array`, otherwise it is a `dict`.

    Keys of the output:

    - `gid`: Global ID of the crystal.
    - `part`: Part number, 0 for endcap0, 1 for barrel, 2 for endcap1.
    - `theta`: Theta number.
    - `phi`: Phi number.

    Optional keys of the output when `geometry` is `True`:

    - `front_center_x`: x position of the front center of the crystal.
    - `front_center_y`: y position of the front center of the crystal.
    - `front_center_z`: z position of the front center of the crystal.
    - `center_x`: x position of the center of the crystal.
    - `center_y`: y position of the center of the crystal.
    - `center_z`: z position of the center of the crystal.

    !!! info
        The 8 points of the crystal will not be returned here.
        If you need the 8 points of the crystal, use `emc_gid_to_point_x`, `emc_gid_to_point_y`
        and `emc_gid_to_point_z`.

    Parameters:
        gid: The gid of the crystal.
        geometry: Whether to include the geometry information.

    Returns:
        The parsed result.
    """
    part = emc_gid_to_part(gid)
    theta = emc_gid_to_theta(gid)
    phi = emc_gid_to_phi(gid)

    res = {"gid": gid, "part": part, "theta": theta, "phi": phi}

    if geometry:
        res["front_center_x"] = emc_gid_to_front_center_x(gid)
        res["front_center_y"] = emc_gid_to_front_center_y(gid)
        res["front_center_z"] = emc_gid_to_front_center_z(gid)
        res["center_x"] = emc_gid_to_center_x(gid)
        res["center_y"] = emc_gid_to_center_y(gid)
        res["center_z"] = emc_gid_to_center_z(gid)

    if isinstance(gid, ak.Array):
        return ak.zip(res)
    else:
        return res

parse_mdc_gid(gid, geometry=False)

Parse the gid of MDC wires. "gid" is the global ID of the wire, ranges from 0 to 6795. When gid is an ak.Array, the result is an ak.Array, otherwise it is a dict.

Keys of the output:

  • gid: Global ID of the wire.
  • layer: Layer number.
  • wire: Local wire number.
  • stereo: Stereo type. 0 for axial, -1 for phi_west < phi_east, 1 for phi_west > phi_east.
  • is_stereo: Whether the wire is a stereo wire.
  • superlayer: Superlayer number.

Optional keys of the output when geometry is True:

  • mid_x: x position of the wire at z=0.
  • mid_y: y position of the wire at z=0.
  • west_x: x position of the west end of the wire.
  • west_y: y position of the west end of the wire.
  • west_z: z position of the west end of the wire.
  • east_x: x position of the east end of the wire.
  • east_y: y position of the east end of the wire.
  • east_z: z position of the east end of the wire.

Parameters:

Name Type Description Default
gid IntLike

The gid of the wire.

required
geometry bool

Whether to include the geometry information.

False

Returns:

Type Description
Array | dict[str, Any]

The parsed result.

Source code in src/pybes3/detectors/mdc.py
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
def parse_mdc_gid(gid: IntLike, geometry: bool = False) -> ak.Array | dict[str, Any]:
    """
    Parse the gid of MDC wires. "gid" is the global ID of the wire, ranges from 0 to 6795.
    When `gid` is an `ak.Array`, the result is an `ak.Array`, otherwise it is a `dict`.

    Keys of the output:

    - `gid`: Global ID of the wire.
    - `layer`: Layer number.
    - `wire`: Local wire number.
    - `stereo`: Stereo type. 0 for axial, -1 for `phi_west < phi_east`, 1 for `phi_west > phi_east`.
    - `is_stereo`: Whether the wire is a stereo wire.
    - `superlayer`: Superlayer number.

    Optional keys of the output when `geometry` is `True`:

    - `mid_x`: x position of the wire at `z=0`.
    - `mid_y`: y position of the wire at `z=0`.
    - `west_x`: x position of the west end of the wire.
    - `west_y`: y position of the west end of the wire.
    - `west_z`: z position of the west end of the wire.
    - `east_x`: x position of the east end of the wire.
    - `east_y`: y position of the east end of the wire.
    - `east_z`: z position of the east end of the wire.

    Parameters:
        gid: The gid of the wire.
        geometry: Whether to include the geometry information.

    Returns:
        The parsed result.
    """
    layer = mdc_gid_to_layer(gid)
    wire = mdc_gid_to_wire(gid)

    res = {
        "gid": gid,
        "layer": layer,
        "wire": wire,
        "stereo": mdc_gid_to_stereo(gid),
        "is_stereo": mdc_gid_to_is_stereo(gid),
        "superlayer": mdc_gid_to_superlayer(gid),
    }

    if geometry:
        west_x = mdc_gid_to_west_x(gid)
        west_y = mdc_gid_to_west_y(gid)
        east_x = mdc_gid_to_east_x(gid)
        east_y = mdc_gid_to_east_y(gid)
        res["mid_x"] = (west_x + east_x) / 2
        res["mid_y"] = (west_y + east_y) / 2
        res["west_x"] = west_x
        res["west_y"] = west_y
        res["west_z"] = mdc_gid_to_west_z(gid)
        res["east_x"] = east_x
        res["east_y"] = east_y
        res["east_z"] = mdc_gid_to_east_z(gid)

    if isinstance(gid, ak.Array):
        return ak.zip(res)
    else:
        return res

cgem_gid_to_is_vstrip(gid)

Check whether a CGEM gid corresponds to a v-strip.

Parameters:

Name Type Description Default
gid IntLike

The gid of the strip.

required

Returns:

Type Description
BoolLike

True if the strip is a v-strip, otherwise False.

Source code in src/pybes3/detectors/cgem.py
157
158
159
160
161
162
163
164
165
166
167
def cgem_gid_to_is_vstrip(gid: IntLike) -> BoolLike:
    """
    Check whether a CGEM gid corresponds to a v-strip.

    Parameters:
        gid: The gid of the strip.

    Returns:
        True if the strip is a v-strip, otherwise False.
    """
    return cgem_gid_to_strip_type(gid) == V_STRIP_TYPE

cgem_gid_to_is_xstrip(gid)

Check whether a CGEM gid corresponds to an x-strip.

Parameters:

Name Type Description Default
gid IntLike

The gid of the strip.

required

Returns:

Type Description
BoolLike

True if the strip is an x-strip, otherwise False.

Source code in src/pybes3/detectors/cgem.py
144
145
146
147
148
149
150
151
152
153
154
def cgem_gid_to_is_xstrip(gid: IntLike) -> BoolLike:
    """
    Check whether a CGEM gid corresponds to an x-strip.

    Parameters:
        gid: The gid of the strip.

    Returns:
        True if the strip is an x-strip, otherwise False.
    """
    return cgem_gid_to_strip_type(gid) == X_STRIP_TYPE

cgem_gid_to_layer(gid)

Convert CGEM gid to layer.

Parameters:

Name Type Description Default
gid IntLike

The gid of the strip.

required

Returns:

Type Description
IntLike

The layer number of the strip.

Source code in src/pybes3/detectors/cgem.py
88
89
90
91
92
93
94
95
96
97
98
99
@nb.vectorize(cache=True)
def cgem_gid_to_layer(gid: IntLike) -> IntLike:
    """
    Convert CGEM gid to layer.

    Parameters:
        gid: The gid of the strip.

    Returns:
        The layer number of the strip.
    """
    return _layer[gid]

cgem_gid_to_sheet(gid)

Convert CGEM gid to sheet.

Parameters:

Name Type Description Default
gid IntLike

The gid of the strip.

required

Returns:

Type Description
IntLike

The sheet number of the strip.

Source code in src/pybes3/detectors/cgem.py
102
103
104
105
106
107
108
109
110
111
112
113
@nb.vectorize(cache=True)
def cgem_gid_to_sheet(gid: IntLike) -> IntLike:
    """
    Convert CGEM gid to sheet.

    Parameters:
        gid: The gid of the strip.

    Returns:
        The sheet number of the strip.
    """
    return _sheet[gid]

cgem_gid_to_strip(gid)

Convert CGEM gid to strip number.

Parameters:

Name Type Description Default
gid IntLike

The gid of the strip.

required

Returns:

Type Description
IntLike

The strip number within the corresponding strip type.

Source code in src/pybes3/detectors/cgem.py
130
131
132
133
134
135
136
137
138
139
140
141
@nb.vectorize(cache=True)
def cgem_gid_to_strip(gid: IntLike) -> IntLike:
    """
    Convert CGEM gid to strip number.

    Parameters:
        gid: The gid of the strip.

    Returns:
        The strip number within the corresponding strip type.
    """
    return _strip[gid]

cgem_gid_to_strip_type(gid)

Convert CGEM gid to strip type.

Parameters:

Name Type Description Default
gid IntLike

The gid of the strip.

required

Returns:

Type Description
IntLike

The strip type of the strip, 0 for x-strip and 1 for v-strip.

Source code in src/pybes3/detectors/cgem.py
116
117
118
119
120
121
122
123
124
125
126
127
@nb.vectorize(cache=True)
def cgem_gid_to_strip_type(gid: IntLike) -> IntLike:
    """
    Convert CGEM gid to strip type.

    Parameters:
        gid: The gid of the strip.

    Returns:
        The strip type of the strip, 0 for x-strip and 1 for v-strip.
    """
    return _strip_type[gid]

get_cgem_gid(layer, sheet, strip_type, strip)

Get CGEM gid of given layer, sheet, strip_type and strip.

Parameters:

Name Type Description Default
layer IntLike

The layer number, 0-2.

required
sheet IntLike

The sheet number within the layer.

required
strip_type IntLike

The strip type, 0 for x-strip and 1 for v-strip.

required
strip IntLike

The strip number within the strip type.

required

Returns:

Type Description
IntLike

The global strip ID of the CGEM strip, ranging from 0 to 9896.

Source code in src/pybes3/detectors/cgem.py
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
@nb.vectorize(cache=True)
def get_cgem_gid(
    layer: IntLike, sheet: IntLike, strip_type: IntLike, strip: IntLike
) -> IntLike:
    """
    Get CGEM gid of given layer, sheet, strip_type and strip.

    Parameters:
        layer: The layer number, 0-2.
        sheet: The sheet number within the layer.
        strip_type: The strip type, 0 for x-strip and 1 for v-strip.
        strip: The strip number within the strip type.

    Returns:
        The global strip ID of the CGEM strip, ranging from 0 to 9896.
    """
    gid = (N_SHEETS[:layer] * (N_XSTRIPS[:layer] + N_VSTRIPS[:layer])).sum()
    gid += sheet * (N_XSTRIPS[layer] + N_VSTRIPS[layer])
    gid += strip_type * N_XSTRIPS[layer]
    gid += strip
    return gid

parse_cgem_gid(gid)

Parse CGEM gid into layer, sheet, strip type and strip number.

Parameters:

Name Type Description Default
gid IntLike

The gid of the strip.

required

Returns:

Type Description
Array | dict[str, Any]

If gid is a ak.Array, returns an ak.Array with fields "layer", "sheet", "strip_type",

Array | dict[str, Any]

"strip", "is_xstrip" and "is_vstrip".

Array | dict[str, Any]

Otherwise, returns a dictionary with keys "layer", "sheet", "strip_type", "strip",

Array | dict[str, Any]

"is_xstrip" and "is_vstrip".

Source code in src/pybes3/detectors/cgem.py
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
def parse_cgem_gid(gid: IntLike) -> ak.Array | dict[str, Any]:
    """
    Parse CGEM gid into layer, sheet, strip type and strip number.

    Parameters:
        gid: The gid of the strip.

    Returns:
        If gid is a ak.Array, returns an ak.Array with fields "layer", "sheet", "strip_type",
        "strip", "is_xstrip" and "is_vstrip".
        Otherwise, returns a dictionary with keys "layer", "sheet", "strip_type", "strip",
        "is_xstrip" and "is_vstrip".
    """
    layer = cgem_gid_to_layer(gid)
    sheet = cgem_gid_to_sheet(gid)
    strip_type = cgem_gid_to_strip_type(gid)
    strip = cgem_gid_to_strip(gid)

    res = {
        "layer": layer,
        "sheet": sheet,
        "strip_type": strip_type,
        "strip": strip,
        "is_xstrip": strip_type == X_STRIP_TYPE,
        "is_vstrip": strip_type == V_STRIP_TYPE,
    }

    if isinstance(gid, ak.Array):
        return ak.zip(res)
    else:
        return res

get_tof_gid(part, layer_or_module, phi_or_strip)

Get TOF gid of given part, layer_or_module and phi_or_strip.

Parameters:

Name Type Description Default
part IntLike

The part of the TOF, 0-2 for scintillator, 3-4 for MRPC.

required
layer_or_module IntLike

The layer (for scintillator) or module (for MRPC) number, starting from 0.

required
phi_or_strip IntLike

The phi (for scintillator) or strip (for MRPC) number, starting from 0.

required

Returns:

Type Description
IntLike

The global strip ID of the TOF strip, ranging from 0 to 1135.

Source code in src/pybes3/detectors/tof.py
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@nb.vectorize(cache=True)
def get_tof_gid(part: IntLike, layer_or_module: IntLike, phi_or_strip: IntLike) -> IntLike:
    """
    Get TOF gid of given part, layer_or_module and phi_or_strip.

    Parameters:
        part: The part of the TOF, 0-2 for scintillator, 3-4 for MRPC.
        layer_or_module: The layer (for scintillator) or module (for MRPC) number, starting from 0.
        phi_or_strip: The phi (for scintillator) or strip (for MRPC) number, starting from 0.

    Returns:
        The global strip ID of the TOF strip, ranging from 0 to 1135.
    """
    gid = (N_LAYER_OR_MODULE[:part] * N_PHI_OR_STRIP[:part]).sum()
    gid += layer_or_module * N_PHI_OR_STRIP[part]
    gid += phi_or_strip
    return gid

parse_tof_gid(gid)

Parse TOF gid into part, layer_or_module and phi_or_strip.

Parameters:

Name Type Description Default
gid IntLike

The global strip ID of the TOF strip, ranging from 0 to 1135.

required

Returns:

Type Description
Array | dict[str, Any]

If gid is a ak.Array, returns an ak.Array with fields "part", "layer_or_module" and "phi_or_strip".

Array | dict[str, Any]

Otherwise, returns a dictionary with keys "part", "layer_or_module" and "phi_or_strip".

Source code in src/pybes3/detectors/tof.py
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def parse_tof_gid(gid: IntLike) -> ak.Array | dict[str, Any]:
    """
    Parse TOF gid into part, layer_or_module and phi_or_strip.

    Parameters:
        gid: The global strip ID of the TOF strip, ranging from 0 to 1135.

    Returns:
        If gid is a ak.Array, returns an ak.Array with fields "part", "layer_or_module" and "phi_or_strip".
        Otherwise, returns a dictionary with keys "part", "layer_or_module" and "phi_or_strip".
    """
    part = tof_gid_to_part(gid)
    layer_or_module = tof_gid_to_layer_or_module(gid)
    phi_or_strip = tof_gid_to_phi_or_strip(gid)

    res = {
        "part": part,
        "layer_or_module": layer_or_module,
        "phi_or_strip": phi_or_strip,
    }

    if isinstance(gid, ak.Array):
        return ak.zip(res)
    else:
        return res

tof_gid_to_layer_or_module(gid)

Get TOF layer_or_module from gid.

Source code in src/pybes3/detectors/tof.py
72
73
74
75
@nb.vectorize(cache=True)
def tof_gid_to_layer_or_module(gid: IntLike) -> IntLike:
    """Get TOF layer_or_module from gid."""
    return _layer_or_module[gid]

tof_gid_to_part(gid)

Get TOF part from gid.

Source code in src/pybes3/detectors/tof.py
66
67
68
69
@nb.vectorize(cache=True)
def tof_gid_to_part(gid: IntLike) -> IntLike:
    """Get TOF part from gid."""
    return _part[gid]

tof_gid_to_phi_or_strip(gid)

Get TOF phi_or_strip from gid.

Source code in src/pybes3/detectors/tof.py
78
79
80
81
@nb.vectorize(cache=True)
def tof_gid_to_phi_or_strip(gid: IntLike) -> IntLike:
    """Get TOF phi_or_strip from gid."""
    return _phi_or_strip[gid]

tracks

HelixObject

Source code in src/pybes3/helix.py
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
class HelixObject:
    def __init__(
        self,
        dr: float,
        phi0: float,
        kappa: float,
        dz: float,
        tanl: float,
        *,
        error: np.ndarray = None,
        pivot: TypeObjPosition = (0, 0, 0),
    ):
        self.dr = float(dr)
        self.phi0 = float(phi0)
        self.kappa = float(kappa)
        self.dz = float(dz)
        self.tanl = float(tanl)
        self.error = error
        self.pivot = _regularize_obj_position(pivot)

    @property
    def radius(self) -> float:
        """
        Circular radius of the helix (in cm).
        """
        return 1000 / 2.99792458 / np.abs(self.kappa)

    @property
    def momentum(self) -> vector.MomentumObject3D:
        """
        Momentum of the helix as a 3D vector.
        Note that the momentum is relative to the pivot, so once the pivot is changed,
        the momentum will also change accordingly.
        """
        pt = 1 / abs(self.kappa)
        pz = pt * self.tanl
        phi = (self.phi0 + np.pi / 2) % (2 * np.pi)
        return vector.obj(pt=pt, phi=phi, pz=pz)

    @property
    def position(self) -> vector.VectorObject3D:
        return vector.VectorObject3D(
            x=self.dr * math.cos(self.phi0),
            y=self.dr * math.sin(self.phi0),
            z=self.dz,
        )

    @property
    def charge(self) -> int:
        """
        Returns the charge of the helix.
        """
        return 1 if self.kappa > 1e-10 else -1 if self.kappa < -1e-10 else 0

    def change_pivot(self, *args):
        """
        Change the pivot point of the helix.
        The transformation refers to `Helix` class in `BOSS`.
        """
        # transform helix parameters
        r = self.radius

        old_dr = self.dr
        old_phi0 = self.phi0
        old_dz = self.dz
        tanl = self.tanl
        kappa = self.kappa

        old_pivot = self.pivot
        new_pivot = _regularize_obj_position(args)

        new_dr, new_phi0, new_dz, new_error = _change_pivot(
            r=r,
            old_dr=old_dr,
            old_phi0=old_phi0,
            old_dz=old_dz,
            kappa=kappa,
            tanl=tanl,
            old_error=self.error,
            old_pivot=old_pivot,
            new_pivot=new_pivot,
        )

        return HelixObject(
            dr=new_dr,
            phi0=new_phi0,
            kappa=kappa,
            dz=new_dz,
            tanl=tanl,
            error=new_error,
            pivot=new_pivot,
        )

    def __repr__(self) -> str:
        return f"Bes3Helix(dr={self.dr:.3f}, phi0={self.phi0:.3f}, kappa={self.kappa:.3f}, tanl={self.tanl:.3f}, dz={self.dz:.3f})"

    def isclose(
        self,
        other: "HelixObject",
        *,
        rtol: float = 1e-5,
        atol: float = 1e-8,
        equal_nan: bool = False,
    ) -> bool:
        if xor(
            (self.error is not None),
            (other.error is not None),
        ):
            warnings.warn(
                "One of the helix records has an error matrix, but the other does not. "
                "Ignoring error matrix for isclose check.",
                UserWarning,
            )

        return _obj_isclose(self, other, rtol=rtol, atol=atol, equal_nan=equal_nan)

radius property

Circular radius of the helix (in cm).

momentum property

Momentum of the helix as a 3D vector. Note that the momentum is relative to the pivot, so once the pivot is changed, the momentum will also change accordingly.

charge property

Returns the charge of the helix.

change_pivot(*args)

Change the pivot point of the helix. The transformation refers to Helix class in BOSS.

Source code in src/pybes3/helix.py
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
def change_pivot(self, *args):
    """
    Change the pivot point of the helix.
    The transformation refers to `Helix` class in `BOSS`.
    """
    # transform helix parameters
    r = self.radius

    old_dr = self.dr
    old_phi0 = self.phi0
    old_dz = self.dz
    tanl = self.tanl
    kappa = self.kappa

    old_pivot = self.pivot
    new_pivot = _regularize_obj_position(args)

    new_dr, new_phi0, new_dz, new_error = _change_pivot(
        r=r,
        old_dr=old_dr,
        old_phi0=old_phi0,
        old_dz=old_dz,
        kappa=kappa,
        tanl=tanl,
        old_error=self.error,
        old_pivot=old_pivot,
        new_pivot=new_pivot,
    )

    return HelixObject(
        dr=new_dr,
        phi0=new_phi0,
        kappa=kappa,
        dz=new_dz,
        tanl=tanl,
        error=new_error,
        pivot=new_pivot,
    )

dr_phi0_to_x(dr, phi0)

Convert helix parameters to x location.

Parameters:

Name Type Description Default
dr float

helix[0] parameter, dr.

required
phi0 float

helix[1] parameter, phi0.

required

Returns:

Type Description
FloatLike

x location of the helix.

Source code in src/pybes3/helix.py
473
474
475
476
477
478
479
480
481
482
483
484
485
@nb.vectorize(cache=True)
def dr_phi0_to_x(dr: FloatLike, phi0: FloatLike) -> FloatLike:
    """
    Convert helix parameters to x location.

    Parameters:
        dr (float): helix[0] parameter, dr.
        phi0 (float): helix[1] parameter, phi0.

    Returns:
        x location of the helix.
    """
    return dr * np.cos(phi0)

dr_phi0_to_y(dr, phi0)

Convert helix parameters to y location.

Parameters:

Name Type Description Default
dr FloatLike

helix[0] parameter, dr.

required
phi0 FloatLike

helix[1] parameter, phi0.

required

Returns:

Type Description
FloatLike

y location of the helix.

Source code in src/pybes3/helix.py
488
489
490
491
492
493
494
495
496
497
498
499
500
@nb.vectorize(cache=True)
def dr_phi0_to_y(dr: FloatLike, phi0: FloatLike) -> FloatLike:
    """
    Convert helix parameters to y location.

    Parameters:
        dr: helix[0] parameter, dr.
        phi0: helix[1] parameter, phi0.

    Returns:
        y location of the helix.
    """
    return dr * np.sin(phi0)

helix_awk(*args, **kwargs)

helix_awk(
    helix: ak.Array,
    error: ak.Array | None = None,
    pivot: TypeAwkPosition = (0, 0, 0),
) -> HelixAwkwardArray
helix_awk(
    *,
    dr: ak.Array,
    phi0: ak.Array,
    kappa: ak.Array,
    dz: ak.Array,
    tanl: ak.Array,
    error: ak.Array | None = None,
    pivot: TypeAwkPosition = (0, 0, 0),
) -> HelixAwkwardArray
helix_awk(
    *,
    momentum: ak.Array,
    position: ak.Array,
    charge: Literal[-1, 1] | ak.Array,
    error: ak.Array | None = None,
    pivot: TypeAwkPosition = (0, 0, 0),
) -> HelixAwkwardArray
Source code in src/pybes3/helix.py
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
def helix_awk(*args, **kwargs) -> HelixAwkwardArray:
    # Use a sentinel to distinguish "not provided" from an explicit None
    error = _SENTINEL
    pivot = _SENTINEL

    if len(args) > 0:
        helix = args[0]

        if len(args) > 1:
            error = args[1]
            if "error" in kwargs:
                raise ValueError("Cannot pass both helix and error as positional arguments.")

        if len(args) > 2:
            pivot = args[2]
            if "pivot" in kwargs:
                raise ValueError("Cannot pass both helix and pivot as positional arguments.")

        dr = helix[..., 0]
        phi0 = helix[..., 1]
        kappa = helix[..., 2]
        dz = helix[..., 3]
        tanl = helix[..., 4]

    elif "helix" in kwargs:
        helix = kwargs.pop("helix")

        dr = helix[..., 0]
        phi0 = helix[..., 1]
        kappa = helix[..., 2]
        dz = helix[..., 3]
        tanl = helix[..., 4]

    elif "dr" in kwargs:
        dr = kwargs.pop("dr")
        phi0 = kwargs.pop("phi0")
        kappa = kwargs.pop("kappa")
        dz = kwargs.pop("dz")
        tanl = kwargs.pop("tanl")

    else:
        momentum = kwargs.pop("momentum")
        position = kwargs.pop("position")
        charge = kwargs.pop("charge")

        pivot = kwargs.pop("pivot", (0, 0, 0))
        if not isinstance(pivot, ak.Array):
            pivot = _regularize_obj_position(pivot)

        # compute helix parameters
        kappa = charge / momentum.pt
        phi0 = (momentum.phi - np.pi / 2) % (2 * np.pi)

        dist = (position - pivot).to_2D()
        dr = _fix_dr_sign(dist.rho, phi0, dist.phi)

        dz = position.z - pivot.z
        tanl = momentum.pz / momentum.pt

    # Only pop from kwargs if not already set via positional args
    if error is _SENTINEL:
        error = kwargs.pop("error", None)
    if pivot is _SENTINEL:
        pivot = kwargs.pop("pivot", (0, 0, 0))

    if not isinstance(pivot, ak.Array):
        pivot = _regularize_obj_position(pivot)

        x0 = ak.ones_like(dr) * pivot.x
        y0 = ak.ones_like(dr) * pivot.y
        z0 = ak.ones_like(dr) * pivot.z
        pivot = ak.zip({"x": x0, "y": y0, "z": z0}, with_name="Vector3D")

    res_dict = {
        "dr": dr,
        "phi0": phi0,
        "kappa": kappa,
        "dz": dz,
        "tanl": tanl,
        "pivot": pivot,
    }

    if error is not None:
        res_dict["error"] = error

    _check_kwargs_used_up(kwargs)

    raw_shape = _extract_index(dr.layout)
    return ak.zip(res_dict, depth_limit=len(raw_shape) + 1, with_name="Bes3Helix")

helix_obj(*args, **kwargs)

helix_obj(
    dr: float,
    phi0: float,
    kappa: float,
    dz: float,
    tanl: float,
    *,
    error: np.ndarray | None = None,
    pivot: TypeObjPosition = (0, 0, 0),
) -> HelixObject
helix_obj(
    *,
    params: tuple[float, float, float, float, float],
    error: np.ndarray | None = None,
    pivot: TypeObjPosition = (0, 0, 0),
) -> HelixObject
helix_obj(
    *,
    momentum: TypeObjMomentum,
    position: TypeObjPosition,
    charge: Literal[-1, 1],
    error: np.ndarray | None = None,
    pivot: TypeObjPosition = (0, 0, 0),
) -> HelixObject
Source code in src/pybes3/helix.py
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
def helix_obj(*args, **kwargs) -> HelixObject:
    pivot = _regularize_obj_position(kwargs.pop("pivot", (0, 0, 0)))

    error = kwargs.pop("error", None)
    if isinstance(error, ak.Array):
        error = error.to_numpy()

    # given helix parameters as positional arguments
    if len(args) > 0:
        _check_kwargs_used_up(kwargs)
        return HelixObject(*args, error=error, pivot=pivot)

    # given helix parameters as keyword arguments
    if "dr" in kwargs:
        dr = kwargs.pop("dr")
        phi0 = kwargs.pop("phi0")
        kappa = kwargs.pop("kappa")
        dz = kwargs.pop("dz")
        tanl = kwargs.pop("tanl")

        _check_kwargs_used_up(kwargs)
        return HelixObject(
            dr=dr, phi0=phi0, kappa=kappa, dz=dz, tanl=tanl, pivot=pivot, error=error
        )

    # given helix parameters as a tuple
    if "params" in kwargs:
        params = kwargs.pop("params")
        if len(params) != 5:
            raise ValueError("params must be a tuple of 5 elements")

        _check_kwargs_used_up(kwargs)
        return HelixObject(*params, pivot=pivot, error=error)

    # given momentum, position and charge
    charge: Literal[-1, 1] = int(kwargs.pop("charge"))
    assert charge in (-1, 1), "Charge must be either -1 or 1"

    momentum = _regularize_obj_momentum(kwargs.pop("momentum"))
    position = _regularize_obj_position(kwargs.pop("position"))

    # compute helix parameters
    kappa = charge / momentum.pt
    phi0 = (momentum.phi - np.pi / 2) % (2 * np.pi)

    dist = (position - pivot).to_2D()
    dr = dist.rho
    if not np.isclose(dist.phi % (2 * np.pi), phi0):
        dr *= -1

    dz = position.z - pivot.z
    tanl = momentum.pz / momentum.pt

    _check_kwargs_used_up(kwargs)
    return HelixObject(
        dr=dr,
        phi0=phi0,
        kappa=kappa,
        dz=dz,
        tanl=tanl,
        pivot=pivot,
        error=error,
    )

kappa_to_charge(kappa)

Convert helix parameter to charge.

Parameters:

Name Type Description Default
kappa FloatLike

helix[2] parameter, kappa.

required

Returns:

Type Description
IntLike

charge of the helix.

Source code in src/pybes3/helix.py
531
532
533
534
535
536
537
538
539
540
541
542
@nb.vectorize(cache=True)
def kappa_to_charge(kappa: FloatLike) -> IntLike:
    """
    Convert helix parameter to charge.

    Parameters:
        kappa: helix[2] parameter, kappa.

    Returns:
        charge of the helix.
    """
    return 1 if kappa > 1e-10 else -1 if kappa < -1e-10 else 0

kappa_to_pt(kappa)

Convert helix parameter to pt.

Parameters:

Name Type Description Default
kappa FloatLike

helix[2] parameter, kappa.

required

Returns:

Type Description
FloatLike

pt of the helix.

Source code in src/pybes3/helix.py
517
518
519
520
521
522
523
524
525
526
527
528
@nb.vectorize(cache=True)
def kappa_to_pt(kappa: FloatLike) -> FloatLike:
    """
    Convert helix parameter to pt.

    Parameters:
        kappa: helix[2] parameter, kappa.

    Returns:
        pt of the helix.
    """
    return 1 / np.abs(kappa)

kappa_to_radius(kappa)

Convert helix parameter kappa to circular radius.

Parameters:

Name Type Description Default
kappa FloatLike

helix[2] parameter, kappa.

required

Returns:

Type Description
FloatLike

circular radius of the helix in cm.

Source code in src/pybes3/helix.py
545
546
547
548
549
550
551
552
553
554
555
556
@nb.vectorize(cache=True)
def kappa_to_radius(kappa: FloatLike) -> FloatLike:
    """
    Convert helix parameter kappa to circular radius.

    Parameters:
        kappa: helix[2] parameter, kappa.

    Returns:
        circular radius of the helix in cm.
    """
    return 1000 / 2.99792458 / np.abs(kappa)

phi0_to_phi(phi0)

Convert helix parameter phi0 to momentum phi.

Parameters:

Name Type Description Default
phi0 FloatLike

helix[1] parameter, phi0.

required

Returns:

Type Description
FloatLike

phi of the momentum vector.

Source code in src/pybes3/helix.py
503
504
505
506
507
508
509
510
511
512
513
514
@nb.vectorize(cache=True)
def phi0_to_phi(phi0: FloatLike) -> FloatLike:
    """
    Convert helix parameter phi0 to momentum phi.

    Parameters:
        phi0: helix[1] parameter, phi0.

    Returns:
        phi of the momentum vector.
    """
    return (phi0 + np.pi / 2) % (2 * np.pi)