Spatial Analysis Utilities

Spatial Analysis Utilities for Neural Data

This module provides comprehensive spatial analysis tools for neural data, particularly for analyzing place cells, grid cells, and other spatially-modulated neurons.

Key functionality: - Place field detection and analysis - Grid score computation - Spatial information metrics - Position decoding - Speed/direction filtering - High-level spatial analysis pipelines

Utilities for spatial data visualization and evaluation metrics.

Note

Place cell detection: Use driada.intense (MI-based analysis with shuffle-based significance testing) for principled place cell detection.

extract_place_fields() is EXPERIMENTAL and uses arbitrary thresholds. It’s provided for quick visualization only, not scientific analysis.

Warning

Removed in v1.0: analyze_spatial_coding() and filter_by_speed() have been removed. Use INTENSE for place cell detection and analysis.

Visualization Utilities

Core functions for creating spatial visualizations:

driada.utils.spatial.compute_occupancy_map(positions, fps=1.0, arena_bounds=None, bin_size=0.025, min_occupancy=0.1, smooth_sigma=None)[source]

Compute 2D occupancy map from position data.

Parameters:
  • positions (np.ndarray, shape (n_samples, 2)) – X, Y positions over time

  • fps (float) – Frames per second (sampling frequency). Default 1.0 assumes one frame per second.

  • arena_bounds (tuple of tuples, optional) – ((x_min, x_max), (y_min, y_max)). If None, inferred from data

  • bin_size (float) – Size of spatial bins in same units as positions

  • min_occupancy (float) – Minimum occupancy time (seconds) for valid bins

  • smooth_sigma (float, optional) – Gaussian smoothing sigma in bins. If None, no smoothing

Return type:

Tuple[ndarray, ndarray, ndarray]

Returns:

  • occupancy_map (np.ndarray) – 2D occupancy map in seconds

  • x_edges (np.ndarray) – X bin edges

  • y_edges (np.ndarray) – Y bin edges

Raises:

ValueError – If positions is not 2D or fps is non-positive

Examples

>>> positions = np.random.rand(1000, 2)  # 1000 frames
>>> # With 30 fps recording
>>> occ_map, x_edges, y_edges = compute_occupancy_map(positions, fps=30.0)
>>> # occ_map contains time in seconds per bin

Compute time spent in each spatial bin. Use for trajectory occupancy maps.

driada.utils.spatial.compute_rate_map(neural_signal, positions, occupancy_map, x_edges, y_edges, fps=1.0, smooth_sigma=1.5)[source]

Compute firing rate map from neural signal and positions.

Parameters:
  • neural_signal (np.ndarray) – Neural signal (e.g., calcium fluorescence, firing rates, spike counts)

  • positions (np.ndarray, shape (n_samples, 2)) – X, Y positions corresponding to neural signal

  • occupancy_map (np.ndarray) – 2D occupancy map in seconds from compute_occupancy_map

  • x_edges (np.ndarray) – X bin edges from compute_occupancy_map

  • y_edges (np.ndarray) – Y bin edges from compute_occupancy_map

  • fps (float) – Frames per second (sampling frequency). Must match the fps used in compute_occupancy_map.

  • smooth_sigma (float, optional) – Gaussian smoothing sigma in bins

Returns:

rate_map – 2D activity map (mean signal per spatial bin)

Return type:

np.ndarray

Raises:

ValueError – If positions shape doesn’t match neural_signal length or fps is non-positive

Examples

>>> # Generate sample data
>>> import numpy as np
>>> positions = np.random.rand(1000, 2)  # 1000 frames of 2D positions
>>> neural_signal = np.random.rand(1000)  # Corresponding neural activity
>>> # Compute occupancy first
>>> occ_map, x_edges, y_edges = compute_occupancy_map(positions, fps=30.0)
>>> # Then compute rate map
>>> rate_map = compute_rate_map(neural_signal, positions, occ_map,
...                            x_edges, y_edges, fps=30.0)

Compute firing rate as a function of position. Use for place field visualization.

Spatial Information Metrics

Evaluation metrics for spatial coding:

driada.utils.spatial.compute_spatial_information_rate(rate_map, occupancy_map)[source]

Compute spatial information rate (bits/spike).

Implements Skaggs et al. (1993) spatial information metric.

Parameters:
  • rate_map (np.ndarray) – 2D firing rate map

  • occupancy_map (np.ndarray) – 2D occupancy map in seconds (time spent in each bin)

Returns:

spatial_info – Spatial information in bits/spike. Returns 0 if mean rate is 0.

Return type:

float

Notes

Forces non-negative result. Uses log2 for bits.

Examples

>>> import numpy as np
>>> positions = np.random.rand(1000, 2)
>>> signal = np.random.rand(1000)  # Neural signal
>>> occ_map, x_edges, y_edges = compute_occupancy_map(positions, fps=30.0)
>>> rate_map = compute_rate_map(signal, positions, occ_map, x_edges, y_edges, fps=30.0)
>>> si = compute_spatial_information_rate(rate_map, occ_map)

Skaggs et al. (1993) spatial information metric in bits/spike. Measures how much information about position is conveyed by each spike.

driada.utils.spatial.compute_spatial_information(neural_activity, positions, logger=None)[source]

Compute mutual information between neural activity and spatial position.

Parameters:
  • neural_activity (array-like or TimeSeries) – Neural activity data. If np.ndarray, shape (n_neurons, n_samples) or (n_samples,)

  • positions (array-like or TimeSeries) – Spatial position data (X, Y). If np.ndarray, shape (n_samples, 2)

  • logger (logging.Logger, optional) – Logger for debugging

Returns:

metrics – Spatial information metrics: - mi_x: MI with X position - mi_y: MI with Y position - mi_total: MI with 2D position

Return type:

dict

Raises:
  • ValueError – If positions is not 2D or shape mismatch

  • ImportError – If required information theory packages are not available

Notes

Uses Gaussian-Copula MI (gcmi) estimator.

Examples

>>> import numpy as np
>>> # Create sample data: 5 neurons, 500 time points
>>> neural_data = np.random.rand(5, 500)
>>> positions = np.random.rand(500, 2)
>>> mi_metrics = compute_spatial_information(neural_data, positions)
>>> print(f"MI with position: {mi_metrics['mi_total']:.3f} bits")  
MI with position: ... bits

Mutual information between neural activity and position. Returns MI for X, Y, and total 2D position.

driada.utils.spatial.compute_spatial_decoding_accuracy(neural_activity, positions, test_size=0.5, n_estimators=20, max_depth=3, min_samples_leaf=50, random_state=42, logger=None)[source]

Compute position decoding accuracy from neural activity.

Parameters:
  • neural_activity (np.ndarray, shape (n_neurons, n_samples)) – Neural activity matrix

  • positions (np.ndarray, shape (n_samples, 2)) – True X, Y positions

  • test_size (float) – Fraction of data for testing

  • n_estimators (int) – Number of trees in random forest

  • max_depth (int) – Maximum tree depth

  • min_samples_leaf (int) – Minimum samples per leaf

  • random_state (int) – Random seed for reproducibility

  • logger (logging.Logger, optional) – Logger for debugging

Returns:

metrics – Decoding accuracy metrics: - r2_x: R² score for X position - r2_y: R² score for Y position - r2_avg: Average R² score - mse: Mean squared error

Return type:

dict

Raises:

ValueError – If shape mismatch between neural_activity and positions

Notes

Forces non-negative R² scores. Uses all CPU cores.

Examples

>>> import numpy as np
>>> # Create sample data: 10 neurons, 1000 time points
>>> neural_data = np.random.rand(10, 1000)
>>> positions = np.random.rand(1000, 2)
>>> metrics = compute_spatial_decoding_accuracy(neural_data, positions)
>>> print(f"Decoding R²: {metrics['r2_avg']:.3f}")  
Decoding R²: ...

ML-based position decoding from neural activity. Uses Random Forest regression to predict position from population activity.

Metrics Wrapper

driada.utils.spatial.compute_spatial_metrics(neural_activity, positions, metrics=None, **kwargs)[source]

Compute selected spatial metrics (decoding and information only).

Note

Place field detection (extract_place_fields) is experimental and not included in this function. Use INTENSE for principled place cell detection.

Parameters:
  • neural_activity (np.ndarray, shape (n_neurons, n_samples)) – Neural activity data

  • positions (np.ndarray, shape (n_samples, 2)) – Position data

  • metrics (list of str, optional) – Metrics to compute. If None, computes all. Options: ‘decoding’, ‘information’ (Removed: ‘place_fields’ - use INTENSE instead)

  • **kwargs – Additional arguments passed to analysis functions (e.g., fps, logger, test_size)

Returns:

results – Computed metrics based on requested analyses

Return type:

dict

Raises:

ValueError – If invalid metric name provided or ‘place_fields’ requested

Examples

>>> # Compute only decoding accuracy
>>> import numpy as np
>>> neural_data = np.random.rand(15, 2000)  # 15 neurons, 2000 samples
>>> positions = np.random.rand(2000, 2)
>>> results = compute_spatial_metrics(neural_data, positions,
...                                  metrics=['decoding'])
>>> # Compute all metrics
>>> import numpy as np
>>> neural_data = np.random.rand(15, 2000)
>>> positions = np.random.rand(2000, 2)
>>> results = compute_spatial_metrics(neural_data, positions)

Compute multiple spatial metrics (decoding and information). Place field detection removed - use INTENSE instead.

Experimental Functions

Warning

The following function is EXPERIMENTAL and uses arbitrary thresholds. For scientific analysis, use INTENSE for principled place cell detection.

driada.utils.spatial.extract_place_fields(rate_map, min_peak_rate=1.0, min_field_size=9, peak_to_mean_ratio=1.5)[source]

Extract place fields from a rate map using threshold-based detection.

Warning

This function is EXPERIMENTAL and uses arbitrary thresholds. For scientific analysis, use INTENSE (MI-based detection with shuffle-based significance testing).

This function is provided for quick visualization purposes only (e.g., “roughly where are the place fields for plotting?”). It should NOT be used for quantitative analysis.

Parameters:
  • rate_map (np.ndarray) – 2D firing rate map

  • min_peak_rate (float) – Minimum peak firing rate for valid place field

  • min_field_size (int) – Minimum number of contiguous bins for valid field

  • peak_to_mean_ratio (float) – Minimum ratio of peak to mean rate in field

Returns:

place_fields – List of place fields with properties: - peak_rate: Peak firing rate - center: (x, y) indices of field center - size: Number of bins in field - mean_rate: Mean rate within field

Return type:

list of dict

Raises:

ValueError – If input parameters are invalid

Notes

Uses 8-connectivity for contiguous region detection.

Experimental function - thresholds are not data-driven. Use compute_cell_feat_significance() from INTENSE for principled detection.

Examples

>>> rate_map = np.random.rand(40, 40)
>>> fields = extract_place_fields(rate_map, min_peak_rate=0.8)

EXPERIMENTAL: Threshold-based place field detection for visualization only. Uses arbitrary parameters (min_peak_rate, min_field_size, peak_to_mean_ratio). For quantitative analysis, use compute_cell_feat_significance() from INTENSE.