fix ar
2 changed files+12−7
python/ephys_compression_tests/algorithms/ans/__init__.pymodified+2−2View file
@@ -318,7 +318,7 @@ for a in algorithm_dicts_base:
318318 return reconstructed
319319 algorithm_dicts.append({
320320 "name": a["name"] + f"-ar{order}",
321- "version": a["version"] + f".2",
321+ "version": a["version"] + f".3",
322322 "encode": encode0_ar,
323323 "decode": decode0_ar,
324324 "description": a["description"] + f" with auto-regressive prediction encoding of order {order}",
@@ -361,7 +361,7 @@ for ar_order in [2, 8]:
361361 return decode0_ar_lossy
362362 algorithm_dicts.append({
363363 "name": f"ans-ar{ar_order}-lossy-tol{tolerance}",
364- "version": "11",
364+ "version": "12",
365365 "encode": make_encode_ar_lossy(),
366366 "decode": make_decode_ar_lossy(),
367367 "description": f"ANS with lossy auto-regressive prediction encoding of order {ar_order} and tolerance {tolerance}",
python/ephys_compression_tests/algorithms/ans/ar_numba.pymodified+10−5View file
@@ -26,7 +26,12 @@ def _fit_ar_model_channel(channel_data: np.ndarray, k: int, subsample_factor: in
2626
2727 # Determine subsampling stride
2828 max_samples = n - k
29- stride = max(1, max_samples // min_samples, subsample_factor)
29+ # Use subsample_factor, but ensure we don't skip so much that we get fewer than min_samples
30+ if subsample_factor * min_samples > max_samples:
31+ # If subsample_factor would give us too few samples, reduce stride
32+ stride = max(1, max_samples // min_samples)
33+ else:
34+ stride = max(1, subsample_factor)
3035
3136 # Number of samples we'll actually use
3237 n_samples = (max_samples + stride - 1) // stride
@@ -41,7 +46,7 @@ def _fit_ar_model_channel(channel_data: np.ndarray, k: int, subsample_factor: in
4146 if sample_idx >= n_samples:
4247 break
4348 for i in range(k):
44- X[sample_idx, i] = np.float32(channel_data[t - k + i])
49+ X[sample_idx, i] = np.float32(channel_data[t - 1 - i])
4550 y[sample_idx] = np.float32(channel_data[t])
4651 sample_idx += 1
4752
@@ -122,7 +127,7 @@ def _compute_residuals_jit(data: np.ndarray, coefficients: np.ndarray,
122127 # Predict from previous k samples
123128 predicted = np.float32(0.0)
124129 for i in range(k):
125- predicted += coef[i] * np.float32(data[t - k + i, ch])
130+ predicted += coef[i] * np.float32(data[t - 1 - i, ch])
126131
127132 # Residual = actual - predicted (rounded)
128133 residuals[t, ch] = data[t, ch] - np.int16(np.round(predicted))
@@ -154,7 +159,7 @@ def _compute_residuals_lossy_jit(data: np.ndarray, coefficients: np.ndarray,
154159 # Predict from previous k reconstructed samples
155160 predicted = np.float32(0.0)
156161 for i in range(k):
157- predicted += coef[i] * np.float32(reconstructed[t - k + i, ch])
162+ predicted += coef[i] * np.float32(reconstructed[t - 1 - i, ch])
158163
159164 prediction_int = np.int16(np.round(predicted))
160165
@@ -226,7 +231,7 @@ def _reconstruct_from_residuals_jit(residuals: np.ndarray, coefficients: np.ndar
226231 # Predict from previous k reconstructed samples
227232 predicted = np.float32(0.0)
228233 for i in range(k):
229- predicted += coef[i] * np.float32(reconstructed[t - k + i, ch])
234+ predicted += coef[i] * np.float32(reconstructed[t - 1 - i, ch])
230235
231236 # Reconstruct: actual = predicted (rounded) + residual
232237 reconstructed[t, ch] = np.int16(np.round(predicted)) + residuals[t, ch]