isgri 0.1.0__py3-none-any.whl → 0.3.0__py3-none-any.whl

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.
@@ -94,7 +94,7 @@ def default_pif_metadata():
94
94
  "SRC_DEC": None,
95
95
  "Source_Name": None,
96
96
  "cod": None,
97
- "No_Modules": 8,
97
+ "No_Modules": [1] * 8,
98
98
  }
99
99
 
100
100
 
isgri/utils/lightcurve.py CHANGED
@@ -29,7 +29,7 @@ class LightCurve:
29
29
  loc2ijd: Converts local time to IJD time.
30
30
  """
31
31
 
32
- def __init__(self, time, energies, gtis, dety, detz, pif, metadata):
32
+ def __init__(self, time, energies, gtis, dety, detz, weights, metadata):
33
33
  """
34
34
  Initialize LightCurve instance.
35
35
 
@@ -50,7 +50,7 @@ class LightCurve:
50
50
 
51
51
  self.dety = dety
52
52
  self.detz = detz
53
- self.pif = pif
53
+ self.weights = weights
54
54
  self.metadata = metadata
55
55
 
56
56
  @classmethod
@@ -71,16 +71,16 @@ class LightCurve:
71
71
  """
72
72
  events, gtis, metadata = load_isgri_events(events_path)
73
73
  if pif_path:
74
- events, pif, metadata_pif = load_isgri_pif(pif_path, events, pif_threshold, pif_extension)
74
+ events, weights, metadata_pif = load_isgri_pif(pif_path, events, pif_threshold, pif_extension)
75
75
  else:
76
- pif = np.ones(len(events))
76
+ weights = np.ones(len(events))
77
77
  metadata_pif = default_pif_metadata()
78
78
 
79
79
  metadata = merge_metadata(metadata, metadata_pif)
80
80
  time = events["TIME"]
81
81
  energies = events["ISGRI_ENERGY"]
82
82
  dety, detz = events["DETY"], events["DETZ"]
83
- return cls(time, energies, gtis, dety, detz, pif, metadata)
83
+ return cls(time, energies, gtis, dety, detz, weights, metadata)
84
84
 
85
85
  def rebin(self, binsize, emin, emax, local_time=True, custom_mask=None):
86
86
  """
@@ -116,10 +116,10 @@ class LightCurve:
116
116
  # Apply filters
117
117
  mask = self._create_event_mask(emin, emax, custom_mask)
118
118
  time_filtered = time[mask]
119
- pif_filtered = self.pif[mask]
119
+ weights_filtered = self.weights[mask]
120
120
 
121
121
  # Histogram
122
- counts, bin_edges = np.histogram(time_filtered, bins=bins, weights=pif_filtered)
122
+ counts, bin_edges = np.histogram(time_filtered, bins=bins, weights=weights_filtered)
123
123
  time_centers = bin_edges[:-1] + 0.5 * binsize_actual
124
124
 
125
125
  return time_centers, counts
@@ -208,7 +208,7 @@ class LightCurve:
208
208
  time_filtered = time[energy_mask]
209
209
  dety_filtered = self.dety[energy_mask]
210
210
  detz_filtered = self.detz[energy_mask]
211
- pif_filtered = self.pif[energy_mask]
211
+ weights_filtered = self.weights[energy_mask]
212
212
 
213
213
  # Compute module indices using digitize
214
214
  dety_bin = np.digitize(dety_filtered, DETY_BOUNDS) - 1 # 0 or 1
@@ -218,7 +218,7 @@ class LightCurve:
218
218
  counts = []
219
219
  for i in range(8):
220
220
  mask = module_idx == i
221
- counts.append(np.histogram(time_filtered[mask], bins=bins, weights=pif_filtered[mask])[0])
221
+ counts.append(np.histogram(time_filtered[mask], bins=bins, weights=weights_filtered[mask])[0])
222
222
 
223
223
  return times, counts
224
224
 
@@ -238,7 +238,7 @@ class LightCurve:
238
238
  float: The total counts in the specified range.
239
239
  """
240
240
  time = self.local_time if local_time else self.time
241
- return np.sum(self.pif[(time >= t1) & (time < t2) & (self.energies >= emin) & (self.energies < emax)])
241
+ return np.sum(self.weights[(time >= t1) & (time < t2) & (self.energies >= emin) & (self.energies < emax)])
242
242
 
243
243
  def ijd2loc(self, ijd_time):
244
244
  """
isgri/utils/quality.py CHANGED
@@ -62,7 +62,7 @@ class QualityMetrics:
62
62
  time, counts = self.lightcurve.rebin_by_modules(
63
63
  binsize=self.binsize, emin=self.emin, emax=self.emax, local_time=self.local_time
64
64
  )
65
- module_data = {"time": time, "counts": counts}
65
+ module_data = {"time": time, "counts": np.asarray(counts)}
66
66
  self.module_data = module_data
67
67
  return module_data
68
68
 
@@ -71,20 +71,36 @@ class QualityMetrics:
71
71
  Compute reduced chi-squared for count data.
72
72
 
73
73
  Args:
74
- counts (ndarray): Count array(s) to analyze.
75
- return_all (bool, optional): If True, returns chi-squared for each array. If False, returns mean. Defaults to False.
74
+ counts (ndarray): Count array(s) to analyze. Shape: (n_modules, n_bins) or (n_bins,)
75
+ return_all (bool, optional): If True, returns detailed results. If False, returns weighted mean. Defaults to False.
76
76
 
77
77
  Returns:
78
- float or ndarray: Reduced chi-squared value(s).
78
+ If return_all=False:
79
+ float: Weighted mean chi-squared (weighted by total counts per module)
80
+ If return_all=True:
81
+ tuple: (chi_squared, dof, no_counts) where:
82
+ - chi_squared: Raw chi-squared values per module
83
+ - dof: Degrees of freedom per module (n_bins - 1 excluding NaN)
84
+ - no_counts: Total counts per module
79
85
  """
80
86
  counts = np.asarray(counts)
81
87
  counts = np.where(counts == 0, np.nan, counts)
82
88
  mean_counts = np.nanmean(counts, axis=-1, keepdims=True)
83
89
  chi_squared = np.nansum((counts - mean_counts) ** 2 / mean_counts, axis=-1)
84
- dof = counts.shape[-1] - 1
90
+
91
+ # DOF = number of non-empty bins minus 1
92
+ nan_mask = ~np.isnan(counts)
93
+ dof = np.sum(nan_mask, axis=-1) - 1
94
+ no_counts = np.nansum(counts, axis=-1)
95
+
85
96
  if return_all:
86
- return chi_squared / dof
87
- return np.nanmean(chi_squared / dof)
97
+ return chi_squared, dof, no_counts
98
+
99
+ if np.sum(no_counts) == 0 or np.all(dof <= 0):
100
+ return np.nan
101
+
102
+ # Weight by total counts per module
103
+ return np.average(chi_squared / dof, weights=no_counts)
88
104
 
89
105
  def raw_chi_squared(self, counts=None, return_all=False):
90
106
  """
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: isgri
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: Python package for INTEGRAL IBIS/ISGRI lightcurve analysis
5
5
  Author: Dominik Patryk Pacholski
6
6
  License: MIT
7
7
  License-File: LICENSE
8
8
  Requires-Python: >=3.10
9
- Requires-Dist: astropy>=7.2.0
10
- Requires-Dist: numpy>=2.3.5
9
+ Requires-Dist: astropy
10
+ Requires-Dist: numpy
11
11
  Description-Content-Type: text/markdown
12
12
 
13
13
  # isgri
@@ -22,7 +22,7 @@ pip install isgri
22
22
 
23
23
  Or from source:
24
24
  ```bash
25
- git clone https://github.com/yourusername/isgri.git
25
+ git clone https://github.com/dominp/isgri.git
26
26
  cd isgri
27
27
  pip install -e .
28
28
  ```
@@ -49,6 +49,8 @@ qm = QualityMetrics(lc, binsize=1.0, emin=30, emax=300)
49
49
  chi = qm.raw_chi_squared()
50
50
  ```
51
51
 
52
+ **About PIF files:** PIF (Pixel Illumination Fraction) files contain per-pixel sensitivity maps generated by OSA task `ii_pif`. They weight events based on source position to improve signal-to-noise ratio. Using PIF files is recommended but optional.
53
+
52
54
  ## Features
53
55
 
54
56
  - Load ISGRI events and PIF files
@@ -60,5 +62,5 @@ chi = qm.raw_chi_squared()
60
62
 
61
63
  ## Documentation
62
64
 
63
- - **Tutorial**: See [demo/lightcurve_walkthrough.ipynb](demo/lightcurve_walkthrough.ipynb)
65
+ - **Tutorial**: - **Tutorial**: See [demo notebook](https://github.com/dominp/isgri/blob/main/demo/lightcurve_walkthrough.ipynb) on GitHub
64
66
  - **API docs**: All functions have docstrings - use `help(LightCurve)`
@@ -0,0 +1,11 @@
1
+ isgri/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ isgri/utils/__init__.py,sha256=H83Al7urc6LNW5KUzUBRdtRBUTahiZmkehKFiK90RrU,183
3
+ isgri/utils/file_loaders.py,sha256=HBQ-n-jFhcP1cxykemBFYTZ72ydJNQrZMUQTeZ2dSnw,5509
4
+ isgri/utils/lightcurve.py,sha256=VGRWcpOMnh8Rrbo-EETKAevhYYBZe55IuRQOw_cIfvY,10243
5
+ isgri/utils/pif.py,sha256=oxndfoZp-y9FO_TXcCP3dmesvh-sC7hAy2u_1YwGitw,1317
6
+ isgri/utils/quality.py,sha256=TZGXnao6hQ2STlI8S8JIfaldPAfdMORQJ0IH_rilFu4,7930
7
+ isgri/utils/time_conversion.py,sha256=47aTXn6cvi-LjOptDY2W-rjeF_PjthZer61VIsJqsro,908
8
+ isgri-0.3.0.dist-info/METADATA,sha256=MofiJhRbXTPhMNOQAtOSc4QmsYEIm8ckXayvr2LTIMQ,1767
9
+ isgri-0.3.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
10
+ isgri-0.3.0.dist-info/licenses/LICENSE,sha256=Q8oxmHR1cSnEXSHCjY3qeXMtupZI_1ZQZ1MBt4oeANE,1102
11
+ isgri-0.3.0.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- isgri/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- isgri/utils/__init__.py,sha256=H83Al7urc6LNW5KUzUBRdtRBUTahiZmkehKFiK90RrU,183
3
- isgri/utils/file_loaders.py,sha256=c0k7B4Uk1OfNKC_TkHtRbHuEeAu4lHxcbCoYLPuRw5E,5503
4
- isgri/utils/lightcurve.py,sha256=qhD5NvHnaSWPWaUh0nWXObj93f-ii6TQu92FIL7aznk,10191
5
- isgri/utils/pif.py,sha256=oxndfoZp-y9FO_TXcCP3dmesvh-sC7hAy2u_1YwGitw,1317
6
- isgri/utils/quality.py,sha256=vNOkIFOkOTP1FAy_1-t5Xvi38gp6UNgXJN3T-DtM8es,7209
7
- isgri/utils/time_conversion.py,sha256=47aTXn6cvi-LjOptDY2W-rjeF_PjthZer61VIsJqsro,908
8
- isgri-0.1.0.dist-info/METADATA,sha256=6rocF7iR95JEZnw51lyDBIIiBd8dp5wMBa8Q7xfJ4kE,1487
9
- isgri-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
10
- isgri-0.1.0.dist-info/licenses/LICENSE,sha256=Q8oxmHR1cSnEXSHCjY3qeXMtupZI_1ZQZ1MBt4oeANE,1102
11
- isgri-0.1.0.dist-info/RECORD,,
File without changes