Skip to content

Commit

Permalink
Merge branch 'master' into clean
Browse files Browse the repository at this point in the history
  • Loading branch information
jlenain authored Oct 23, 2023
2 parents 267a188 + 134fd99 commit a0451c2
Show file tree
Hide file tree
Showing 15 changed files with 1,639 additions and 193 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Enable [pre-commit hooks](https://pre-commit.com/), which enforces adherence to
pre-commit install
```

Please follow the [same conventions as `ctapipe`](https://cta-observatory.github.io/ctapipe/getting_started/index.html#developing-a-new-feature-or-code-change) regarding settings of Git remotes for pull requests.
Please follow the [same conventions as `ctapipe`](https://ctapipe.readthedocs.io/en/latest/getting_started/) regarding settings of Git remotes, and how to contribute to the code with pull requests.

### Optional DIRAC support

Expand Down Expand Up @@ -110,8 +110,8 @@ or the [container alternative](#note-to-macos-users) as explained above.

All contribution are welcome.

Guidelines are the same as [ctapipe's ones](https://cta-observatory.github.io/ctapipe/development/index.html)
See [here](https://cta-observatory.github.io/ctapipe/development/pullrequests.html) how to make a pull request to contribute.
Guidelines are the same as [ctapipe's ones](https://ctapipe.readthedocs.io/en/latest/getting_started/)
See [here](https://ctapipe.readthedocs.io/en/latest/development/pullrequests.html#pullrequests) how to make a pull request to contribute.


## Report issue / Ask a question
Expand Down
146 changes: 91 additions & 55 deletions src/nectarchain/calibration/container/charge.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
from .utils import CtaPipeExtractor
from .waveforms import WaveformsContainer, WaveformsContainers


logging.basicConfig(format="%(asctime)s %(name)s %(levelname)s %(message)s")
log = logging.getLogger(__name__)
log.handlers = logging.getLogger("__main__").handlers


__all__ = ["ChargeContainer", "ChargeContainers"]


list_ctapipe_charge_extractor = [
"FullWaveformSum",
"FixedWindowSum",
Expand Down Expand Up @@ -61,7 +63,7 @@ def make_histo(charge, all_range, mask_broken_pix, _mask, hist_ma_data):
# print(f"hist_ma_data[0] = {hist_ma_data[0]}")
# print(f"mask_broken_pix = {mask_broken_pix}")

if not mask_broken_pix:
if not (mask_broken_pix):
# print("this pixel is not broken, let's continue computation")
hist, _charge = np.histogram(
charge,
Expand Down Expand Up @@ -123,11 +125,11 @@ def __init__(
self._nevents = nevents
self._npixels = npixels

self.ucts_timestamp = np.zeros(self.nevents, dtype=np.uint64)
self.ucts_busy_counter = np.zeros(self.nevents, dtype=np.uint16)
self.ucts_event_counter = np.zeros(self.nevents, dtype=np.uint16)
self.event_type = np.zeros(self.nevents, dtype=np.uint8)
self.event_id = np.zeros(self.nevents, dtype=np.uint16)
self.ucts_timestamp = np.zeros((self.nevents), dtype=np.uint64)
self.ucts_busy_counter = np.zeros((self.nevents), dtype=np.uint16)
self.ucts_event_counter = np.zeros((self.nevents), dtype=np.uint16)
self.event_type = np.zeros((self.nevents), dtype=np.uint8)
self.event_id = np.zeros((self.nevents), dtype=np.uint16)
self.trig_pattern_all = np.zeros(
(self.nevents, self.CAMERA.n_pixels, 4), dtype=bool
)
Expand All @@ -142,8 +144,8 @@ def from_waveforms(
"""create a new ChargeContainer from a WaveformsContainer
Args:
waveformContainer (WaveformsContainer): the waveforms
method (str, optional): Ctapipe ImageExtractor method. Defaults to
"FullWaveformSum".
method (str, optional): Ctapipe ImageExtractor method.
Defaults to "FullWaveformSum".
Returns:
chargeContainer : the ChargeContainer instance
Expand Down Expand Up @@ -180,11 +182,14 @@ def from_waveforms(

return chargeContainer

def write(self, path: Path, **kwargs):
def write(self, path: Path, start=None, end=None, block=None, **kwargs):
"""method to write in an output FITS file the ChargeContainer.
Args:
path (str): the directory where you want to save data
start (int): Start of event_id. Default is None.
end (int): End of event_id. Default is None.
block (int): Block number of SPE-WT scan. Default is None.
"""
suffix = kwargs.get("suffix", "")
if suffix != "":
Expand All @@ -193,49 +198,73 @@ def write(self, path: Path, **kwargs):
log.info(f"saving in {path}")
os.makedirs(path, exist_ok=True)

# table = Table(self.charge_hg)
# table.meta["pixels_id"] = self._pixels_id
# table.write(Path(path)/f"charge_hg_run{self.run_number}.ecsv",format='ascii.ecsv',overwrite=kwargs.get('overwrite',False))
#
# table = Table(self.charge_lg)
# table.meta["pixels_id"] = self._pixels_id
# table.write(Path(path)/f"charge_lg_run{self.run_number}.ecsv",format='ascii.ecsv',overwrite=kwargs.get('overwrite',False))
#
# table = Table(self.peak_hg)
# table.meta["pixels_id"] = self._pixels_id
# table.write(Path(path)/f"peak_hg_run{self.run_number}.ecsv",format='ascii.ecsv',overwrite=kwargs.get('overwrite',False))
#
# table = Table(self.peak_lg)
# table.meta["pixels_id"] = self._pixels_id
# table.write(Path(path)/f"peak_lg_run{self.run_number}.ecsv",format='ascii.ecsv',overwrite=kwargs.get('overwrite',False))

hdr = fits.Header()
hdr["RUN"] = self._run_number
hdr["NEVENTS"] = self.nevents
hdr["NPIXELS"] = self.npixels
hdr["COMMENT"] = (
f"The charge containeur for run {self._run_number} with {self._method}"
f" method : primary is the pixels id, then you can find HG charge, "
f"The charge containeur for run {self._run_number} with {self._method} "
f"method : primary is the pixels id, then you can find HG charge, "
f"LG charge, HG peak and LG peak, 2 last HDU are composed of event "
f"properties and trigger patern"
)

primary_hdu = fits.PrimaryHDU(self.pixels_id, header=hdr)
charge_hg_hdu = fits.ImageHDU(self.charge_hg, name="HG charge")
charge_lg_hdu = fits.ImageHDU(self.charge_lg, name="LG charge")
peak_hg_hdu = fits.ImageHDU(self.peak_hg, name="HG peak time")
peak_lg_hdu = fits.ImageHDU(self.peak_lg, name="LG peak time")
charge_hg_hdu = fits.ImageHDU(self.charge_hg[start:end], name="HG charge")
charge_lg_hdu = fits.ImageHDU(self.charge_lg[start:end], name="LG charge")
peak_hg_hdu = fits.ImageHDU(self.peak_hg[start:end], name="HG peak time")
peak_lg_hdu = fits.ImageHDU(self.peak_lg[start:end], name="LG peak time")

col1 = fits.Column(array=self.event_id, name="event_id", format="1I")
col2 = fits.Column(array=self.event_type, name="event_type", format="1I")
col1 = fits.Column(array=self.event_id[start:end], name="event_id", format="1J")
col2 = fits.Column(
array=self.event_type[start:end], name="event_type", format="1I"
)
col3 = fits.Column(
array=self.ucts_timestamp, name="ucts_timestamp", format="1K"
array=self.ucts_timestamp[start:end], name="ucts_timestamp", format="1K"
)
col4 = fits.Column(
array=self.ucts_busy_counter, name="ucts_busy_counter", format="1I"
array=self.ucts_busy_counter[start:end],
name="ucts_busy_counter",
format="1I",
)
col5 = fits.Column(
array=self.ucts_event_counter, name="ucts_event_counter", format="1I"
array=self.ucts_event_counter[start:end],
name="ucts_event_counter",
format="1I",
)
col6 = fits.Column(
array=self.multiplicity[start:end], name="multiplicity", format="1I"
)
col6 = fits.Column(array=self.multiplicity, name="multiplicity", format="1I")

coldefs = fits.ColDefs([col1, col2, col3, col4, col5, col6])
event_properties = fits.BinTableHDU.from_columns(
coldefs, name="event properties"
)

col1 = fits.Column(
array=self.trig_pattern_all,
array=self.trig_pattern_all[start:end],
name="trig_pattern_all",
format=f"{4 * self.CAMERA.n_pixels}L",
dim=f"({self.CAMERA.n_pixels},4)",
)
col2 = fits.Column(
array=self.trig_pattern,
array=self.trig_pattern[start:end],
name="trig_pattern",
format=f"{self.CAMERA.n_pixels}L",
)
Expand All @@ -255,7 +284,7 @@ def write(self, path: Path, **kwargs):
)
try:
hdul.writeto(
Path(path) / f"charge_run{self.run_number}{suffix}.fits",
Path(path) / f"charge_run{self.run_number}{suffix}_bloc_{block}.fits",
overwrite=kwargs.get("overwrite", False),
)
log.info(
Expand Down Expand Up @@ -329,8 +358,8 @@ def compute_charge(
Args:
waveformContainer (WaveformsContainer): the waveforms
channel (int): channel you want to compute charges
method (str, optional): ctapipe Image Extractor method method. Defaults
to "FullWaveformSum".
method (str, optional): ctapipe Image Extractor method method.
Defaults to "FullWaveformSum".
Raises:
ArgumentError: extraction method unknown
Expand Down Expand Up @@ -359,8 +388,8 @@ def compute_charge(
)

log.debug(
f"Extracting charges with method {method} and extractor_kwargs "
f"{extractor_kwargs}"
f"Extracting charges with method {method} and "
f"extractor_kwargs {extractor_kwargs}"
)
ImageExtractor = eval(method)(waveformContainer.subarray, **extractor_kwargs)

Expand Down Expand Up @@ -405,9 +434,9 @@ def histo_hg(self, n_bins: int = 1000, autoscale: bool = True) -> np.ndarray:
Args:
n_bins (int, optional): number of bins in charge (ADC counts).
Defaults to 1000.
Defaults to 1000.
autoscale (bool, optional): auto detect number of bins by pixels
(bin witdh = 1 ADC). Defaults to True.
(bin witdh = 1 ADC). Defaults to True.
Returns:
np.ndarray: masked array of charge histograms (histo,charge)
Expand All @@ -416,8 +445,8 @@ def histo_hg(self, n_bins: int = 1000, autoscale: bool = True) -> np.ndarray:
(self.charge_hg == self.charge_hg.mean(axis=0)).mean(axis=0), dtype=bool
)
log.debug(
f"there are {mask_broken_pix.sum()} broken pixels (charge stays at same "
f"level for each events)"
f"there are {mask_broken_pix.sum()} broken pixels "
f"(charge stays at same level for each events)"
)

if autoscale:
Expand All @@ -426,6 +455,10 @@ def histo_hg(self, n_bins: int = 1000, autoscale: bool = True) -> np.ndarray:
np.uint16(np.max(self.charge_hg.T[~mask_broken_pix].T)) + 1.5,
1,
)
# hist_ma = ma.masked_array(np.zeros((self.charge_hg.shape[1],
# all_range.shape[0]),dtype = np.uint16),
# mask=np.zeros((self.charge_hg.shape[1],
# all_range.shape[0]),dtype = bool))
charge_ma = ma.masked_array(
(
all_range.reshape(all_range.shape[0], 1)
Expand All @@ -437,12 +470,13 @@ def histo_hg(self, n_bins: int = 1000, autoscale: bool = True) -> np.ndarray:
)

broxen_pixels_mask = np.array(
[mask_broken_pix for _ in range(charge_ma.shape[1])]
[mask_broken_pix for i in range(charge_ma.shape[1])]
).T
# hist_ma.mask = new_data_mask.T
start = time.time()
_mask, hist_ma_data = make_histo(
self.charge_hg.T, all_range, mask_broken_pix
)
) # , charge_ma.data, charge_ma.mask, hist_ma.data, hist_ma.mask)
charge_ma.mask = np.logical_or(_mask, broxen_pixels_mask)
hist_ma = ma.masked_array(hist_ma_data, mask=charge_ma.mask)
log.debug(f"histogram hg computation time : {time.time() - start} sec")
Expand Down Expand Up @@ -488,8 +522,8 @@ def histo_lg(self, n_bins: int = 1000, autoscale: bool = True) -> np.ndarray:
(self.charge_lg == self.charge_lg.mean(axis=0)).mean(axis=0), dtype=bool
)
log.debug(
f"there are {mask_broken_pix.sum()} broken pixels (charge stays at same "
f"level for each events)"
f"there are {mask_broken_pix.sum()} broken pixels "
f"(charge stays at same level for each events)"
)

if autoscale:
Expand All @@ -509,7 +543,7 @@ def histo_lg(self, n_bins: int = 1000, autoscale: bool = True) -> np.ndarray:
)

broxen_pixels_mask = np.array(
[mask_broken_pix for _ in range(charge_ma.shape[1])]
[mask_broken_pix for i in range(charge_ma.shape[1])]
).T
# hist_ma.mask = new_data_mask.T
start = time.time()
Expand Down Expand Up @@ -546,13 +580,14 @@ def histo_lg(self, n_bins: int = 1000, autoscale: bool = True) -> np.ndarray:

def select_charge_hg(self, pixel_id: np.ndarray):
"""method to extract charge HG from a list of pixel ids
The output is the charge HG with a shape following the size of the input
pixel_id argument.
Pixel in pixel_id which are not present in the ChargeContaineur pixels_id are
skipped.
The output is the charge HG with a shape following the size
of the input pixel_id argument
Pixel in pixel_id which are not present in the
ChargeContaineur pixels_id are skipped
Args:
pixel_id (np.ndarray): array of pixel ids you want to extract the charge
pixel_id (np.ndarray): array of pixel ids you want to
extract the charge
Returns:
(np.ndarray): charge array in the order of specified pixel_id
Expand All @@ -562,8 +597,8 @@ def select_charge_hg(self, pixel_id: np.ndarray):
)
for pixel in pixel_id[~mask_contain_pixels_id]:
log.warning(
f"You asked for pixel_id {pixel} but it is not present in this "
f"ChargeContainer, skip this one"
f"You asked for pixel_id {pixel} but it is not present "
f"in this ChargeContainer, skip this one"
)
return np.array(
[
Expand All @@ -574,13 +609,14 @@ def select_charge_hg(self, pixel_id: np.ndarray):

def select_charge_lg(self, pixel_id: np.ndarray):
"""method to extract charge LG from a list of pixel ids
The output is the charge LG with a shape following the size of the input
pixel_id argument.
Pixel in pixel_id which are not present in the ChargeContaineur pixels_id are
skipped.
The output is the charge LG with a shape following the
size of the input pixel_id argument
Pixel in pixel_id which are not present in the ChargeContaineur
pixels_id are skipped
Args:
pixel_id (np.ndarray): array of pixel ids you want to extract the charge
pixel_id (np.ndarray): array of pixel ids you want to extract
the charge
Returns:
(np.ndarray): charge array in the order of specified pixel_id
Expand All @@ -590,8 +626,8 @@ def select_charge_lg(self, pixel_id: np.ndarray):
)
for pixel in pixel_id[~mask_contain_pixels_id]:
log.warning(
f"You asked for pixel_id {pixel} but it is not present in this "
f"ChargeContainer, skip this one"
f"You asked for pixel_id {pixel} but it is not "
f"present in this ChargeContainer, skip this one"
)
return np.array(
[
Expand Down Expand Up @@ -665,8 +701,8 @@ def write(self, path: str, **kwargs):

@staticmethod
def from_file(path: Path, run_number: int, **kwargs):
"""load ChargeContainers from FITS file previously written with
ChargeContainers.write() method
"""load ChargeContainers from FITS file previously written
with ChargeContainers.write() method
This method will search all the fits files corresponding to
{path}/charge_run{run_number}_*.fits scheme
Expand Down Expand Up @@ -695,8 +731,8 @@ def from_file(path: Path, run_number: int, **kwargs):

@property
def nChargeContainer(self):
"""getter giving the number of chargeContainer into the ChargeContainers
instance
"""getter giving the number of chargeContainer into the
ChargeContainers instance
Returns:
int: the number of chargeContainer
Expand Down
Loading

0 comments on commit a0451c2

Please sign in to comment.