Source code for functionalizer.filters.implementations.touch

"""Filters reducing touches."""

import numpy as np
import pandas as pd
from pyspark.sql import functions as F

import sparkmanager as sm
from functionalizer.filters import DatasetOperation
from functionalizer.utils import get_logger

from . import add_random_column

logger = get_logger(__name__)


_KEY_TOUCH = 0x202


[docs] class TouchReductionFilter(DatasetOperation): """Filter touches based on a simple probability. Defined in the recipe as `TouchReduction`, restrict connections according to the `survival_rate` defined. """ def __init__(self, recipe, source, target): """Initilize the filter by parsing the recipe. The rules stored in the recipe are loaded in their abstract form, concretization will happen with the acctual circuit. """ super().__init__(recipe, source, target) self.survival = recipe.get("touch_reduction.survival_rate") self.seed = recipe.get("seed") logger.info("Using seed %d for trimming touches", self.seed)
[docs] def apply(self, circuit): """Actually reduce the touches of the circuit.""" touches = add_random_column(circuit.df, "touch_rand", self.seed, _KEY_TOUCH) return touches.where(F.col("touch_rand") <= F.lit(self.survival)).drop("touch_rand")
[docs] class TouchRulesFilter(DatasetOperation): """Filter touches based on recipe rules. Defined in the recipe as `TouchRules`, restrict connections between mtypes and types (dendrite/soma). Any touches not allowed are removed. This filter is deterministic. """ _checkpoint = True def __init__(self, recipe, source, target): """Initilize the filter by parsing the recipe. The rules stored in the recipe are loaded in their abstract form, concretization will happen with the acctual circuit. """ super().__init__(recipe, source, target) self.columns, self.rules = recipe.as_matrix("touch_rules") self.unset_value = len(recipe.get("touch_rules"))
[docs] def apply(self, circuit): """Filter the circuit edges according to the touch rules.""" fail_column = F.lit(0) for col, factor in zip(self.columns, self.rules.shape): fail_column *= factor fail_column += F.col(col) rules = sm.createDataFrame( pd.DataFrame({"fail": np.nonzero(self.rules.flatten() == self.unset_value)[0]}) ) # For each neuron we require: # - preMType # - postMType # - preBranchType # - postBranchType # # The first four fields are properties of the neurons, part of # neuronDF, while postBranchType is a property if the touch, # historically checked by the index of the target neuron # section (0->soma) touches = circuit.df if not hasattr(circuit.df, "efferent_section_type") or not hasattr( circuit.df, "afferent_section_type" ): raise RuntimeError("TouchRules need [ae]fferent_section_type") return ( touches.withColumn("fail", fail_column) .join(F.broadcast(rules), "fail", "left_anti") .drop("fail") )