Source code for pwspy.analysis.compilation._pws

# Copyright 2018-2020 Nick Anthony, Backman Biophotonics Lab, Northwestern University
#
# This file is part of PWSpy.
#
# PWSpy is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PWSpy is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PWSpy.  If not, see <https://www.gnu.org/licenses/>.

from __future__ import annotations
from dataclasses import dataclass
import typing as t_
import numpy as np

from ._abstract import AbstractCompilerSettings, AbstractRoiCompilationResults, AbstractRoiCompiler
from .. import warnings
from ...dataTypes import Roi
from ...dataTypes._other import RoiFile

if t_.TYPE_CHECKING:
    from ..pws import PWSAnalysisResults

# TODO Documentation


[docs]@dataclass class PWSCompilerSettings(AbstractCompilerSettings): """These settings determine which values should be processed during compilation""" reflectance: bool = False rms: bool = False polynomialRms: bool = False autoCorrelationSlope: bool = False rSquared: bool = False ld: bool = False opd: bool = False meanSigmaRatio: bool = False
[docs]@dataclass class PWSRoiCompilationResults(AbstractRoiCompilationResults): cellIdTag: str analysisName: str reflectance: float rms: float polynomialRms: float autoCorrelationSlope: float rSquared: float ld: float opd: np.ndarray opdIndex: np.ndarray # The x axis of a plot of opd varRatio: float #The ratio of signal variance of the Roi's mean spectra to the mean signal variance (rms^2) of the roiFile. should be between 0 and 1.
[docs]class PWSRoiCompiler(AbstractRoiCompiler): settings: PWSCompilerSettings # Just doing this to get accurate type hinting def __init__(self, settings: PWSCompilerSettings): super().__init__(settings)
[docs] def run(self, results: PWSAnalysisResults, roi: Roi) -> t_.Tuple[PWSRoiCompilationResults, t_.List[warnings.AnalysisWarning]]: warns = [] reflectance = self._avgOverRoi(roi, results.meanReflectance) if self.settings.reflectance else None rms = self._avgOverRoi(roi, results.rms) if self.settings.rms else None if self.settings.polynomialRms: try: polynomialRms = self._avgOverRoi(roi, results.polynomialRms) except KeyError: polynomialRms = None else: polynomialRms = None if self.settings.autoCorrelationSlope: try: autoCorrelationSlope = self._avgOverRoi(roi, results.autoCorrelationSlope, condition=np.logical_and(results.rSquared > 0.9, results.autoCorrelationSlope < 0)) except KeyError: autoCorrelationSlope = None else: autoCorrelationSlope = None if self.settings.rSquared: try: warns.append(warnings.checkRSquared(results.rSquared[roi.mask])) rSquared = self._avgOverRoi(roi, results.rSquared) except KeyError: rSquared = None else: rSquared = None if self.settings.ld: try: ld = self._avgOverRoi(roi, results.ld) except KeyError: ld = None else: ld = None if self.settings.opd: try: opd, opdIndex = results.opd opd = opd[roi.mask].mean(axis=0) except KeyError: opd = opdIndex = None else: opd = opdIndex = None if self.settings.meanSigmaRatio: try: spectra = results.reflectance.getMeanSpectra(roi)[0] meanRms = spectra.std() varRatio = meanRms**2 / (results.rms[roi.mask] ** 2).mean() warns.append(warnings.checkMeanSpectraRatio(varRatio)) except KeyError: varRatio = None else: varRatio = None results = PWSRoiCompilationResults( cellIdTag=results.imCubeIdTag, analysisName=results.analysisName, reflectance=reflectance, rms=rms, polynomialRms=polynomialRms, autoCorrelationSlope=autoCorrelationSlope, rSquared=rSquared, ld=ld, opd=opd, opdIndex=opdIndex, varRatio=varRatio) warns = [w for w in warns if w is not None] # Strip None from warns list return results, warns
@staticmethod def _avgOverRoi(roi: Roi, arr: np.ndarray, condition: np.ndarray = None) -> float: """Returns the average of arr over the ROI. if condition is provided then only value of arr where the condition is satisfied are included.""" assert len(arr.shape) == 2 if condition is not None: return arr[np.logical_and(roi.mask, condition)].mean() else: return arr[roi.mask].mean()