legend-dataflow-scripts 0.4.0a2__tar.gz → 0.4.0a4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {legend_dataflow_scripts-0.4.0a2/src/legend_dataflow_scripts.egg-info → legend_dataflow_scripts-0.4.0a4}/PKG-INFO +1 -1
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4/src/legend_dataflow_scripts.egg-info}/PKG-INFO +1 -1
- legend_dataflow_scripts-0.4.0a4/src/legend_dataflow_scripts.egg-info/scm_version.json +8 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/_version.py +3 -3
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/dsp/dplms.py +3 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/dsp/eopt.py +3 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/dsp/evtsel.py +39 -10
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/dsp/nopt.py +3 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/dsp/pz.py +3 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/hit/aoe.py +4 -1
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/hit/ecal.py +8 -8
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/hit/lq.py +7 -2
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/hit/qc.py +3 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/tier/dsp.py +9 -6
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/utils/cfgtools.py +4 -2
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/workflow/pre_compile_catalog.py +6 -2
- legend_dataflow_scripts-0.4.0a2/src/legend_dataflow_scripts.egg-info/scm_version.json +0 -8
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/LICENSE +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/README.md +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/pyproject.toml +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/setup.cfg +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legend_dataflow_scripts.egg-info/SOURCES.txt +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legend_dataflow_scripts.egg-info/dependency_links.txt +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legend_dataflow_scripts.egg-info/entry_points.txt +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legend_dataflow_scripts.egg-info/not-zip-safe +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legend_dataflow_scripts.egg-info/requires.txt +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legend_dataflow_scripts.egg-info/scm_file_list.json +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legend_dataflow_scripts.egg-info/top_level.txt +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/__init__.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/__init__.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/__init__.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/dsp/__init__.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/dsp/svm.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/dsp/svm_build.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/par/geds/hit/__init__.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/tier/__init__.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/tier/hit.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/utils/__init__.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/utils/alias_table.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/utils/convert_np.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/utils/discharge.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/utils/files.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/utils/lgdo_utils.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/utils/log.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/utils/plot_dict.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/utils/pulser_removal.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/workflow/__init__.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/workflow/execenv.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/workflow/filedb.py +0 -0
- {legend_dataflow_scripts-0.4.0a2 → legend_dataflow_scripts-0.4.0a4}/src/legenddataflowscripts/workflow/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: legend-dataflow-scripts
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.0a4
|
|
4
4
|
Summary: Python package for the processing scripts for LEGEND-200 data
|
|
5
5
|
Author-email: George Marshall <ggmarsh@uw.edu>, Luigi Pertoldi <gipert@pm.me>
|
|
6
6
|
Maintainer: The LEGEND Collaboration
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: legend-dataflow-scripts
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.0a4
|
|
4
4
|
Summary: Python package for the processing scripts for LEGEND-200 data
|
|
5
5
|
Author-email: George Marshall <ggmarsh@uw.edu>, Luigi Pertoldi <gipert@pm.me>
|
|
6
6
|
Maintainer: The LEGEND Collaboration
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.4.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 4, 0, '
|
|
21
|
+
__version__ = version = '0.4.0a4'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 4, 0, 'a4')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'gc92695af3'
|
|
@@ -6,6 +6,7 @@ import time
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
8
|
import lh5
|
|
9
|
+
import matplotlib as mpl
|
|
9
10
|
import numpy as np
|
|
10
11
|
import pygama.math.distributions as pmd # noqa: F401
|
|
11
12
|
from dbetto.catalog import Props
|
|
@@ -25,6 +26,8 @@ from ....utils import (
|
|
|
25
26
|
take_table_rows,
|
|
26
27
|
)
|
|
27
28
|
|
|
29
|
+
mpl.use("agg") # no display needed; avoids X11 when DISPLAY is set
|
|
30
|
+
|
|
28
31
|
|
|
29
32
|
def par_geds_dsp_dplms() -> None:
|
|
30
33
|
"""Compute DPLMS optimal filter coefficients for HPGe detectors.
|
|
@@ -7,6 +7,7 @@ import warnings
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
|
|
9
9
|
import lh5
|
|
10
|
+
import matplotlib as mpl
|
|
10
11
|
import numpy as np
|
|
11
12
|
import pygama.pargen.energy_optimisation as om # noqa: F401
|
|
12
13
|
import sklearn.gaussian_process.kernels as ker
|
|
@@ -27,6 +28,8 @@ from ....utils import (
|
|
|
27
28
|
require_peaks_present,
|
|
28
29
|
)
|
|
29
30
|
|
|
31
|
+
mpl.use("agg") # no display needed; avoids X11 when DISPLAY is set
|
|
32
|
+
|
|
30
33
|
warnings.filterwarnings(action="ignore", category=RuntimeWarning)
|
|
31
34
|
try:
|
|
32
35
|
warnings.filterwarnings(action="ignore", category=np.exceptions.RankWarning)
|
|
@@ -133,6 +133,34 @@ def get_out_data(
|
|
|
133
133
|
return out_tbl, int(np.count_nonzero(final_mask))
|
|
134
134
|
|
|
135
135
|
|
|
136
|
+
def initial_bin_width(energy):
|
|
137
|
+
"""
|
|
138
|
+
Freedman-Diaconis starting bin width for the peak-finding histogram.
|
|
139
|
+
|
|
140
|
+
Parameters
|
|
141
|
+
----------
|
|
142
|
+
energy : numpy.ndarray
|
|
143
|
+
uncalibrated energies of the candidate events.
|
|
144
|
+
|
|
145
|
+
Returns
|
|
146
|
+
-------
|
|
147
|
+
float or None
|
|
148
|
+
bin width capped at 2 ADC, or ``None`` when the sample is degenerate
|
|
149
|
+
(fewer than two finite values, or no spread) and no histogram can be built.
|
|
150
|
+
"""
|
|
151
|
+
energy = energy[np.isfinite(energy)]
|
|
152
|
+
if len(energy) < 2:
|
|
153
|
+
return None
|
|
154
|
+
width = (
|
|
155
|
+
2
|
|
156
|
+
* (np.percentile(energy, 75) - np.percentile(energy, 25))
|
|
157
|
+
* len(energy) ** (-1 / 3)
|
|
158
|
+
)
|
|
159
|
+
if not width > 0:
|
|
160
|
+
return None
|
|
161
|
+
return min(width, 2)
|
|
162
|
+
|
|
163
|
+
|
|
136
164
|
def build_peak_dicts(peaks_kev, kev_widths, masks, log=None):
|
|
137
165
|
"""Build the per-peak accumulator state for the file x peak read loop.
|
|
138
166
|
|
|
@@ -455,16 +483,17 @@ def par_geds_dsp_evtsel() -> None:
|
|
|
455
483
|
)
|
|
456
484
|
energy = tb_out[energy_parameter].nda
|
|
457
485
|
|
|
458
|
-
init_bin_width = (
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
np.
|
|
462
|
-
|
|
486
|
+
init_bin_width = initial_bin_width(energy)
|
|
487
|
+
if init_bin_width is None: # too few events to histogram
|
|
488
|
+
msg = (
|
|
489
|
+
f"{peak}: only {np.isfinite(energy).sum()} "
|
|
490
|
+
"usable events, skipping peak"
|
|
463
491
|
)
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
492
|
+
log.warning(msg)
|
|
493
|
+
peak_dict["obj_buf"] = None
|
|
494
|
+
peak_dict["obj_buf_start"] = 0
|
|
495
|
+
peak_dict["idxs"] = None
|
|
496
|
+
continue
|
|
468
497
|
|
|
469
498
|
hist, bins, var = pgh.get_hist(
|
|
470
499
|
energy,
|
|
@@ -487,7 +516,7 @@ def par_geds_dsp_evtsel() -> None:
|
|
|
487
516
|
mu = peak_top_pars[0]
|
|
488
517
|
if mu > np.nanmax(bins) or mu < np.nanmin(bins):
|
|
489
518
|
raise ValueError
|
|
490
|
-
except
|
|
519
|
+
except (ValueError, TypeError, IndexError):
|
|
491
520
|
mu = np.nan
|
|
492
521
|
if mu is None or np.isnan(mu):
|
|
493
522
|
log.debug("Fit failed, using max guess")
|
|
@@ -6,6 +6,7 @@ import time
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
8
|
import lh5
|
|
9
|
+
import matplotlib as mpl
|
|
9
10
|
import numpy as np
|
|
10
11
|
import pygama.pargen.noise_optimization as pno
|
|
11
12
|
from dbetto.catalog import Props
|
|
@@ -20,6 +21,8 @@ from ....utils import (
|
|
|
20
21
|
require_config_keys,
|
|
21
22
|
)
|
|
22
23
|
|
|
24
|
+
mpl.use("agg") # no display needed; avoids X11 when DISPLAY is set
|
|
25
|
+
|
|
23
26
|
|
|
24
27
|
def par_geds_dsp_nopt() -> None:
|
|
25
28
|
"""Optimise DSP filter parameters for noise performance.
|
|
@@ -6,6 +6,7 @@ import pickle as pkl
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
8
|
import lh5
|
|
9
|
+
import matplotlib as mpl
|
|
9
10
|
import numpy as np
|
|
10
11
|
from dbetto.catalog import Props
|
|
11
12
|
from dspeed import build_dsp
|
|
@@ -24,6 +25,8 @@ from ....utils import (
|
|
|
24
25
|
take_table_rows,
|
|
25
26
|
)
|
|
26
27
|
|
|
28
|
+
mpl.use("agg") # no display needed; avoids X11 when DISPLAY is set
|
|
29
|
+
|
|
27
30
|
|
|
28
31
|
def par_geds_dsp_pz() -> None:
|
|
29
32
|
"""Determine the pole-zero (PZ) decay constant(s) for HPGe waveforms.
|
|
@@ -10,9 +10,10 @@ import time
|
|
|
10
10
|
import warnings
|
|
11
11
|
from pathlib import Path
|
|
12
12
|
|
|
13
|
+
import matplotlib as mpl
|
|
13
14
|
import numpy as np
|
|
14
15
|
from dbetto.catalog import Props
|
|
15
|
-
from pygama.pargen.AoE_cal import *
|
|
16
|
+
from pygama.pargen.AoE_cal import *
|
|
16
17
|
from pygama.pargen.AoE_cal import CalAoE
|
|
17
18
|
from pygama.pargen.utils import load_data
|
|
18
19
|
|
|
@@ -28,6 +29,8 @@ from ....utils import (
|
|
|
28
29
|
require_unique_suffixes,
|
|
29
30
|
)
|
|
30
31
|
|
|
32
|
+
mpl.use("agg") # no display needed; avoids X11 when DISPLAY is set
|
|
33
|
+
|
|
31
34
|
log = logging.getLogger(__name__)
|
|
32
35
|
|
|
33
36
|
warnings.filterwarnings(action="ignore", category=RuntimeWarning)
|
|
@@ -5,7 +5,7 @@ import copy
|
|
|
5
5
|
import inspect
|
|
6
6
|
import pickle as pkl
|
|
7
7
|
import warnings
|
|
8
|
-
from datetime import datetime
|
|
8
|
+
from datetime import UTC, datetime
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
|
|
11
11
|
import lh5
|
|
@@ -104,14 +104,14 @@ def plot_2614_timemap(
|
|
|
104
104
|
|
|
105
105
|
ticks, _ = plt.xticks()
|
|
106
106
|
plt.xlabel(
|
|
107
|
-
f"Time starting : {datetime.
|
|
107
|
+
f"Time starting : {datetime.fromtimestamp(ticks[0], tz=UTC).strftime('%d/%m/%y %H:%M')}"
|
|
108
108
|
)
|
|
109
109
|
plt.ylabel("Energy(keV)")
|
|
110
110
|
plt.ylim([erange[0], erange[1]])
|
|
111
111
|
|
|
112
112
|
plt.xticks(
|
|
113
113
|
ticks,
|
|
114
|
-
[datetime.
|
|
114
|
+
[datetime.fromtimestamp(tick, tz=UTC).strftime("%H:%M") for tick in ticks],
|
|
115
115
|
)
|
|
116
116
|
plt.close()
|
|
117
117
|
return fig
|
|
@@ -188,13 +188,13 @@ def plot_pulser_timemap(
|
|
|
188
188
|
plt.ylim([mean - n_spread * spread, mean + n_spread * spread])
|
|
189
189
|
ticks, _ = plt.xticks()
|
|
190
190
|
plt.xlabel(
|
|
191
|
-
f"Time starting : {datetime.
|
|
191
|
+
f"Time starting : {datetime.fromtimestamp(ticks[0], tz=UTC).strftime('%d/%m/%y %H:%M')}"
|
|
192
192
|
)
|
|
193
193
|
plt.ylabel("Energy(keV)")
|
|
194
194
|
|
|
195
195
|
plt.xticks(
|
|
196
196
|
ticks,
|
|
197
|
-
[datetime.
|
|
197
|
+
[datetime.fromtimestamp(tick, tz=UTC).strftime("%H:%M") for tick in ticks],
|
|
198
198
|
)
|
|
199
199
|
plt.close()
|
|
200
200
|
return fig
|
|
@@ -488,14 +488,14 @@ def plot_baseline_timemap(
|
|
|
488
488
|
|
|
489
489
|
ticks, _ = plt.xticks()
|
|
490
490
|
plt.xlabel(
|
|
491
|
-
f"Time starting : {datetime.
|
|
491
|
+
f"Time starting : {datetime.fromtimestamp(ticks[0], tz=UTC).strftime('%d/%m/%y %H:%M')}"
|
|
492
492
|
)
|
|
493
493
|
plt.ylabel("Baseline Value")
|
|
494
494
|
plt.ylim([mean - n_spread * spread, mean + n_spread * spread])
|
|
495
495
|
|
|
496
496
|
plt.xticks(
|
|
497
497
|
ticks,
|
|
498
|
-
[datetime.
|
|
498
|
+
[datetime.fromtimestamp(tick, tz=UTC).strftime("%H:%M") for tick in ticks],
|
|
499
499
|
)
|
|
500
500
|
plt.close()
|
|
501
501
|
return fig
|
|
@@ -683,7 +683,7 @@ def get_results_dict(ecal_class, data, cal_energy_param, selection_string):
|
|
|
683
683
|
|
|
684
684
|
pk_dict = results_dict["peak_parameters"]
|
|
685
685
|
|
|
686
|
-
for
|
|
686
|
+
for dic in pk_dict.values():
|
|
687
687
|
dic["function"] = dic["function"].name
|
|
688
688
|
dic["parameters"] = dic["parameters"].to_dict()
|
|
689
689
|
dic["uncertainties"] = dic["uncertainties"].to_dict()
|
|
@@ -9,12 +9,13 @@ import time
|
|
|
9
9
|
import warnings
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
|
+
import matplotlib as mpl
|
|
12
13
|
import numpy as np
|
|
13
14
|
import pandas as pd
|
|
14
15
|
from dbetto.catalog import Props
|
|
15
16
|
from pygama.math.distributions import gaussian
|
|
16
|
-
from pygama.pargen.AoE_cal import *
|
|
17
|
-
from pygama.pargen.lq_cal import *
|
|
17
|
+
from pygama.pargen.AoE_cal import *
|
|
18
|
+
from pygama.pargen.lq_cal import *
|
|
18
19
|
from pygama.pargen.lq_cal import LQCal
|
|
19
20
|
from pygama.pargen.utils import load_data
|
|
20
21
|
|
|
@@ -30,6 +31,8 @@ from ....utils import (
|
|
|
30
31
|
require_unique_suffixes,
|
|
31
32
|
)
|
|
32
33
|
|
|
34
|
+
mpl.use("agg") # no display needed; avoids X11 when DISPLAY is set
|
|
35
|
+
|
|
33
36
|
log = logging.getLogger(__name__)
|
|
34
37
|
warnings.filterwarnings(action="ignore", category=RuntimeWarning)
|
|
35
38
|
|
|
@@ -306,6 +309,8 @@ def run_lq_calibration(
|
|
|
306
309
|
][configs["cal_energy_param"]]["eres_linear"]
|
|
307
310
|
except KeyError:
|
|
308
311
|
lq_obj.eres_func = {}
|
|
312
|
+
for panel in getattr(lq_obj, "gauss_trends_hist", []):
|
|
313
|
+
panel.pop("model", None) # nested fit func, can't pickle
|
|
309
314
|
out_dicts[name] = out_dict
|
|
310
315
|
lq_objs[name] = copy.deepcopy(lq_obj)
|
|
311
316
|
lq_plot_dict[name] = copy.deepcopy(lq_plots)
|
|
@@ -9,6 +9,7 @@ import time
|
|
|
9
9
|
import warnings
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
|
+
import matplotlib as mpl
|
|
12
13
|
import numpy as np
|
|
13
14
|
from dbetto.catalog import Props
|
|
14
15
|
from lh5 import ls
|
|
@@ -28,6 +29,8 @@ from ....utils import (
|
|
|
28
29
|
prepare_output_paths,
|
|
29
30
|
)
|
|
30
31
|
|
|
32
|
+
mpl.use("agg") # no display needed; avoids X11 when DISPLAY is set
|
|
33
|
+
|
|
31
34
|
log = logging.getLogger(__name__)
|
|
32
35
|
warnings.filterwarnings(action="ignore", category=RuntimeWarning)
|
|
33
36
|
|
|
@@ -3,7 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import argparse
|
|
4
4
|
import time
|
|
5
5
|
import warnings
|
|
6
|
-
from
|
|
6
|
+
from concurrent.futures import ProcessPoolExecutor
|
|
7
|
+
from multiprocessing import get_context
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
|
|
9
10
|
import lh5
|
|
@@ -51,7 +52,7 @@ def build_dsp_wrapper(kwargs):
|
|
|
51
52
|
"""Unpack *kwargs* and delegate to :func:`dspeed.build_dsp`.
|
|
52
53
|
|
|
53
54
|
This thin wrapper exists so that a single-argument callable can be passed
|
|
54
|
-
to :meth:`
|
|
55
|
+
to :meth:`concurrent.futures.Executor.map`.
|
|
55
56
|
|
|
56
57
|
Parameters
|
|
57
58
|
----------
|
|
@@ -239,10 +240,12 @@ def build_tier_dsp() -> None:
|
|
|
239
240
|
}
|
|
240
241
|
process_kwargs_list.append(kwargs)
|
|
241
242
|
|
|
242
|
-
#
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
243
|
+
# fork pinned: default start method changes in py3.14
|
|
244
|
+
# a killed worker raises BrokenProcessPool here; Pool.map would hang forever
|
|
245
|
+
with ProcessPoolExecutor(
|
|
246
|
+
max_workers=args.n_processes, mp_context=get_context("fork")
|
|
247
|
+
) as pool:
|
|
248
|
+
list(pool.map(build_dsp_wrapper, process_kwargs_list))
|
|
246
249
|
|
|
247
250
|
# merge the DSPs
|
|
248
251
|
log.info("Merging DSPs")
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import copy
|
|
3
4
|
from collections.abc import Iterable, Mapping
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
|
|
@@ -133,14 +134,15 @@ def get_rule_config(configs_path, rule_name, timestamp, datatype):
|
|
|
133
134
|
|
|
134
135
|
Wraps ``TextDB(...).on(...)["snakemake_rules"][rule_name]`` so that a
|
|
135
136
|
missing key names the rule, timestamp, datatype and config path instead
|
|
136
|
-
of raising a bare :class:`KeyError`.
|
|
137
|
+
of raising a bare :class:`KeyError`. Returns a writable deep copy, since
|
|
138
|
+
``TextDB.on()`` results are shared and read-only.
|
|
137
139
|
"""
|
|
138
140
|
if not Path(configs_path).is_dir():
|
|
139
141
|
msg = f"config directory {configs_path} does not exist"
|
|
140
142
|
raise FileNotFoundError(msg)
|
|
141
143
|
configs = TextDB(configs_path, lazy=True).on(timestamp, category=datatype)
|
|
142
144
|
try:
|
|
143
|
-
return configs["snakemake_rules"][rule_name]
|
|
145
|
+
return copy.deepcopy(configs["snakemake_rules"][rule_name])
|
|
144
146
|
except KeyError as err:
|
|
145
147
|
msg = (
|
|
146
148
|
f"config resolved from {configs_path} for timestamp {timestamp} "
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import hashlib
|
|
4
|
+
import logging
|
|
4
5
|
import os
|
|
5
6
|
import pickle
|
|
6
7
|
import tempfile
|
|
@@ -11,6 +12,8 @@ from pathlib import Path
|
|
|
11
12
|
from dbetto import TextDB
|
|
12
13
|
from dbetto.catalog import Catalog
|
|
13
14
|
|
|
15
|
+
log = logging.getLogger(__name__)
|
|
16
|
+
|
|
14
17
|
|
|
15
18
|
def _content_digest(validity_path: Path) -> str:
|
|
16
19
|
"""Digest of the directory contents (relative path, mtime and size of
|
|
@@ -80,7 +83,7 @@ def pre_compile_catalog(validity_path: str | Path):
|
|
|
80
83
|
if isinstance(cached, Catalog):
|
|
81
84
|
return cached
|
|
82
85
|
except Exception: # unreadable pickle: rebuild below
|
|
83
|
-
|
|
86
|
+
log.debug("could not read catalog cache %s", cache_file, exc_info=True)
|
|
84
87
|
|
|
85
88
|
catalog = Catalog.read_from(validity_path / "validity.yaml")
|
|
86
89
|
entries = {}
|
|
@@ -108,6 +111,7 @@ def pre_compile_catalog(validity_path: str | Path):
|
|
|
108
111
|
Path(tmp_name).unlink(missing_ok=True)
|
|
109
112
|
raise
|
|
110
113
|
except Exception:
|
|
111
|
-
|
|
114
|
+
# caching is best-effort; a failed write must not break parsing
|
|
115
|
+
log.debug("could not write catalog cache %s", cache_file, exc_info=True)
|
|
112
116
|
|
|
113
117
|
return compiled
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|