Skip to content

baseUserAnalysis

Discover, register, and run SanPy user-analysis plugins.

Attributes¤

Classes¤

baseUserAnalysis ¤

Create a userAnalysis object after bAnalysis has been analyzed with the core analysis results.

Source code in sanpy/user_analysis/baseUserAnalysis.py
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
class baseUserAnalysis:
    """Create a userAnalysis object after bAnalysis has been analyzed with the core analysis results."""

    def __init__(self, ba: "sanpy.bAnalysis"):
        self._myAnalysis: sanpy.bAnalysis = ba

        self._userStatNames: list[str] = []

        self.defineUserStats()

    def _getUserStatNames(self) -> tuple[str, ...]:
        """Return internal names of results produced by this analysis."""
        return tuple(self._userStatNames)

    def defineUserStats(self):
        """Derived classes add each stat with addUserStat().

        See Also
        --------
        addUserStat
        """
        pass

    def addUserStat(
        self,
        humanName: str,
        internalName: str,
        *,
        showInPlotMenu: bool,
        isCategorical: bool,
        category: AnalysisResultCategory = AnalysisResultCategory.CUSTOM,
        valueType: str,
        default: Any,
        units: str,
        axisLabel: str,
        description: str,
    ) -> bool:
        """Register a user statistic for analysis and presentation.

        Args:
            humanName: Human-readable statistic name.
            internalName: Internal dataframe-column name without spaces or
                punctuation.
            showInPlotMenu: Whether X/Y statistic selectors show the result.
            isCategorical: Whether plots interpret values as discrete groups.
            category: Presentation category stored in the runtime result
                schema.
            valueType: Runtime value type name, such as ``"float"``.
            default: Default value for the result.
            units: Physical or logical units.
            axisLabel: Plot-axis label.
            description: Human-readable explanation.

        Returns:
            ``True`` when the definition was registered or was already
            registered identically; ``False`` when a conflicting definition
            was rejected.
        """
        from sanpy.bAnalysisResults import register_analysis_result

        registered = register_analysis_result(
            internalName,
            category=category,
            value_type=valueType,
            default=default,
            units=units,
            axis_label=axisLabel,
            show_in_plot_menu=showInPlotMenu,
            is_categorical=isCategorical,
            description=description,
        )
        if internalName not in self._userStatNames:
            self._userStatNames.append(internalName)
        return registered

    @property
    def ba(self):
        """Get the underlying [sanpy.bAnalysis][sanpy.bAnalysis] object"""
        return self._myAnalysis

    def getSweepX(self):
        """Get the x-axis of a recording."""
        return self.ba.fileLoader.sweepX

    def getSweepY(self):
        """Get the y-axis of a recording."""
        return self.ba.fileLoader.sweepY

    def getSweepC(self):
        """Get the DAC axis of a recording."""
        return self.ba.fileLoader.sweepC

    def getFilteredVm(self):
        return self.ba.fileLoader.sweepY_filtered

    def setSpikeValue(self, spikeIdx, theKey, theVal):
        """Set the value of a spike key.

        Parameters
        ----------
        spikeIdx : int
            The spike index , 0 based.
        theKey : str
            Name of the user defined internal name.
        theVal :
            The value for the key, can be almost any type like
            (float, int, bool, dict, list)

        Raises
        ------
        KeyError
            If theKey is not a key in analysis results.
        IndexError
            If spikeIdx is beyond number of spikes -1.
        """
        try:
            self.ba.spikeDict[spikeIdx][theKey] = theVal
        except (KeyError) as e:
            logger.error(f'User internal stat does not exist "{theKey}"')
        except (IndexError) as e:
            logger.error(
                f"spikeIdx {spikeIdx} is out of range, max value is {self.ba.numSpikes}"
            )

    def getSpikeValue(self, spikeIdx, theKey):
        """Get a single spike analysis result from key.

        Parameters
        ----------
        spikeIdx : int
            The spike index, 0 based.
        theKey : str
            Name of the analysis result defined internal name.

        Raises
        ------
        KeyError
            If theKey is not a key in analysis results.
        IndexError
            If spikeIdx is beyond number of spikes -1.
        """
        try:
            theRet = self.ba.spikeDict[spikeIdx][theKey]
            return theRet
        except KeyError as e:
            logger.error(f'User internal stat does not exist "{theKey}"')
        except IndexError as e:
            logger.error(
                f"spikeIdx {spikeIdx} is out of range, max value is {self.ba.numSpikes}"
            )

    def run(self):
        """Run user analysis. Calculate values for each new user stat."""

Attributes¤

ba property ¤

Get the underlying sanpy.bAnalysis object

Methods:¤

addUserStat(humanName, internalName, *, showInPlotMenu, isCategorical, category=AnalysisResultCategory.CUSTOM, valueType, default, units, axisLabel, description) ¤

Register a user statistic for analysis and presentation.

Args: humanName: Human-readable statistic name. internalName: Internal dataframe-column name without spaces or punctuation. showInPlotMenu: Whether X/Y statistic selectors show the result. isCategorical: Whether plots interpret values as discrete groups. category: Presentation category stored in the runtime result schema. valueType: Runtime value type name, such as "float". default: Default value for the result. units: Physical or logical units. axisLabel: Plot-axis label. description: Human-readable explanation.

Returns: True when the definition was registered or was already registered identically; False when a conflicting definition was rejected.

Source code in sanpy/user_analysis/baseUserAnalysis.py
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
def addUserStat(
    self,
    humanName: str,
    internalName: str,
    *,
    showInPlotMenu: bool,
    isCategorical: bool,
    category: AnalysisResultCategory = AnalysisResultCategory.CUSTOM,
    valueType: str,
    default: Any,
    units: str,
    axisLabel: str,
    description: str,
) -> bool:
    """Register a user statistic for analysis and presentation.

    Args:
        humanName: Human-readable statistic name.
        internalName: Internal dataframe-column name without spaces or
            punctuation.
        showInPlotMenu: Whether X/Y statistic selectors show the result.
        isCategorical: Whether plots interpret values as discrete groups.
        category: Presentation category stored in the runtime result
            schema.
        valueType: Runtime value type name, such as ``"float"``.
        default: Default value for the result.
        units: Physical or logical units.
        axisLabel: Plot-axis label.
        description: Human-readable explanation.

    Returns:
        ``True`` when the definition was registered or was already
        registered identically; ``False`` when a conflicting definition
        was rejected.
    """
    from sanpy.bAnalysisResults import register_analysis_result

    registered = register_analysis_result(
        internalName,
        category=category,
        value_type=valueType,
        default=default,
        units=units,
        axis_label=axisLabel,
        show_in_plot_menu=showInPlotMenu,
        is_categorical=isCategorical,
        description=description,
    )
    if internalName not in self._userStatNames:
        self._userStatNames.append(internalName)
    return registered
defineUserStats() ¤

Derived classes add each stat with addUserStat().

See Also

addUserStat

Source code in sanpy/user_analysis/baseUserAnalysis.py
203
204
205
206
207
208
209
210
def defineUserStats(self):
    """Derived classes add each stat with addUserStat().

    See Also
    --------
    addUserStat
    """
    pass
getSpikeValue(spikeIdx, theKey) ¤

Get a single spike analysis result from key.

Parameters:

Name Type Description Default
spikeIdx int

The spike index, 0 based.

required
theKey str

Name of the analysis result defined internal name.

required

Raises:

Type Description
KeyError

If theKey is not a key in analysis results.

IndexError

If spikeIdx is beyond number of spikes -1.

Source code in sanpy/user_analysis/baseUserAnalysis.py
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
def getSpikeValue(self, spikeIdx, theKey):
    """Get a single spike analysis result from key.

    Parameters
    ----------
    spikeIdx : int
        The spike index, 0 based.
    theKey : str
        Name of the analysis result defined internal name.

    Raises
    ------
    KeyError
        If theKey is not a key in analysis results.
    IndexError
        If spikeIdx is beyond number of spikes -1.
    """
    try:
        theRet = self.ba.spikeDict[spikeIdx][theKey]
        return theRet
    except KeyError as e:
        logger.error(f'User internal stat does not exist "{theKey}"')
    except IndexError as e:
        logger.error(
            f"spikeIdx {spikeIdx} is out of range, max value is {self.ba.numSpikes}"
        )
getSweepC() ¤

Get the DAC axis of a recording.

Source code in sanpy/user_analysis/baseUserAnalysis.py
277
278
279
def getSweepC(self):
    """Get the DAC axis of a recording."""
    return self.ba.fileLoader.sweepC
getSweepX() ¤

Get the x-axis of a recording.

Source code in sanpy/user_analysis/baseUserAnalysis.py
269
270
271
def getSweepX(self):
    """Get the x-axis of a recording."""
    return self.ba.fileLoader.sweepX
getSweepY() ¤

Get the y-axis of a recording.

Source code in sanpy/user_analysis/baseUserAnalysis.py
273
274
275
def getSweepY(self):
    """Get the y-axis of a recording."""
    return self.ba.fileLoader.sweepY
run() ¤

Run user analysis. Calculate values for each new user stat.

Source code in sanpy/user_analysis/baseUserAnalysis.py
340
341
def run(self):
    """Run user analysis. Calculate values for each new user stat."""
setSpikeValue(spikeIdx, theKey, theVal) ¤

Set the value of a spike key.

Parameters:

Name Type Description Default
spikeIdx int

The spike index , 0 based.

required
theKey str

Name of the user defined internal name.

required
theVal

The value for the key, can be almost any type like (float, int, bool, dict, list)

required

Raises:

Type Description
KeyError

If theKey is not a key in analysis results.

IndexError

If spikeIdx is beyond number of spikes -1.

Source code in sanpy/user_analysis/baseUserAnalysis.py
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
def setSpikeValue(self, spikeIdx, theKey, theVal):
    """Set the value of a spike key.

    Parameters
    ----------
    spikeIdx : int
        The spike index , 0 based.
    theKey : str
        Name of the user defined internal name.
    theVal :
        The value for the key, can be almost any type like
        (float, int, bool, dict, list)

    Raises
    ------
    KeyError
        If theKey is not a key in analysis results.
    IndexError
        If spikeIdx is beyond number of spikes -1.
    """
    try:
        self.ba.spikeDict[spikeIdx][theKey] = theVal
    except (KeyError) as e:
        logger.error(f'User internal stat does not exist "{theKey}"')
    except (IndexError) as e:
        logger.error(
            f"spikeIdx {spikeIdx} is out of range, max value is {self.ba.numSpikes}"
        )

Functions:¤

runAllUserAnalysis(ba, verbose=False) ¤

Run all user defined analysis.

Notes

Called at end of sanpy.bAnalysis.detect()

Source code in sanpy/user_analysis/baseUserAnalysis.py
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
def runAllUserAnalysis(ba, verbose=False):
    """Run all user defined analysis.

    Notes
    -----
    Called at end of sanpy.bAnalysis.detect()
    """

    # step through each
    objList = _getObjectList()  # list of dict

    if verbose:
        logger.info(f"objList: {objList}")
    for obj in objList:
        # instantiate and call run (will add values for stats
        # was this
        # userObj = obj(ba)
        # userObj.run()

        try:
            # instantiate a user object
            userObj = obj["constructor"](ba)

            # run the analysis
            userObj.run()  # run the analysis and append to actual ba object
        except Exception as e:
            logger.error(f"Exception in running user defined analysis: {e}")
            logger.error(traceback.format_exc())
All material is Copyright 2019-2026 Robert H. Cudmore