Public Access
add type hints to data classes and fix get_ydata override conflict
- signature-only type hints for ADC_Result, MeasurementResult, Accumulation, and the Drawable base class (x: ndarray | list, y: list) - get_ydata now takes channel: int = 0 across the hierarchy (Drawable, Accumulation, MeasurementResult, Error_Result), fixing the LSP violation flagged by pyrefly - widen _XArray alias to ndarray | list: internal copy constructors pass self.x[:] which is that union - add hinted files to pyrefly project-includes pyrefly errors in the covered files drop from 102 to 74; the rest is PyTables stub noise and pre-existing latent bugs left for separate fixes. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
1 parent
e5472484cb
commit
c797aeb387
6 files changed
+174
-135
No files matched your search
@@ -58,6 +58,9 @@ version = {attr = "damaris.__version__"}
|
|||||||
project-includes = [
|
project-includes = [
|
||||||
"src/damaris/experiments/Experiment.py",
|
"src/damaris/experiments/Experiment.py",
|
||||||
"src/damaris/experiments/dac.py",
|
"src/damaris/experiments/dac.py",
|
||||||
|
"src/damaris/data/ADC_Result.py",
|
||||||
|
"src/damaris/data/MeasurementResult.py",
|
||||||
|
"src/damaris/data/Accumulation.py",
|
||||||
]
|
]
|
||||||
search-path = ["src"]
|
search-path = ["src"]
|
||||||
python-version = "3.11"
|
python-version = "3.11"
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# -*- coding: iso-8859-1 -*-
|
# -*- coding: iso-8859-1 -*-
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from .Resultable import Resultable
|
from .Resultable import Resultable
|
||||||
from .Drawable import Drawable
|
from .Drawable import Drawable
|
||||||
from .Signalpath import Signalpath
|
from .Signalpath import Signalpath
|
||||||
@@ -9,7 +11,13 @@ import numpy
|
|||||||
import sys
|
import sys
|
||||||
import datetime
|
import datetime
|
||||||
import tables
|
import tables
|
||||||
|
from typing import IO
|
||||||
from scipy.signal import filtfilt, remez
|
from scipy.signal import filtfilt, remez
|
||||||
|
|
||||||
|
_XArray = numpy.ndarray | list
|
||||||
|
_YChannels = list[numpy.ndarray]
|
||||||
|
_IndexList = list[tuple[int, int]]
|
||||||
|
_Description = dict[str, str]
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# #
|
# #
|
||||||
# Name: Class ADC_Result #
|
# Name: Class ADC_Result #
|
||||||
@@ -39,7 +47,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
sampling_rate: Sampling frequency of the ADC data.
|
sampling_rate: Sampling frequency of the ADC data.
|
||||||
job_id: identifier for the job that generated this result.
|
job_id: identifier for the job that generated this result.
|
||||||
"""
|
"""
|
||||||
def __init__(self, x = None, y:list = None, index = None, sampl_freq = None, desc = None, job_id = None, job_date = None):
|
def __init__(self, x: _XArray | None = None, y: _YChannels | None = None, index: _IndexList | None = None, sampl_freq: float | None = None, desc: _Description | None = None, job_id: int | None = None, job_date: datetime.datetime | None = None):
|
||||||
Resultable.__init__(self)
|
Resultable.__init__(self)
|
||||||
Drawable.__init__(self)
|
Drawable.__init__(self)
|
||||||
|
|
||||||
@@ -87,7 +95,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
raise ValueError("Wrong usage of __init__!")
|
raise ValueError("Wrong usage of __init__!")
|
||||||
|
|
||||||
|
|
||||||
def create_data_space(self, channels, samples):
|
def create_data_space(self, channels: int, samples: int) -> None:
|
||||||
"Initialises the internal data-structures"
|
"Initialises the internal data-structures"
|
||||||
|
|
||||||
if self.contains_data():
|
if self.contains_data():
|
||||||
@@ -104,12 +112,12 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
self.cont_data = True
|
self.cont_data = True
|
||||||
|
|
||||||
|
|
||||||
def contains_data(self):
|
def contains_data(self) -> bool:
|
||||||
"""Returns true if ADC_Result contains data. (-> create_data_space() was called)"""
|
"""Returns true if ADC_Result contains data. (-> create_data_space() was called)"""
|
||||||
return self.cont_data
|
return self.cont_data
|
||||||
|
|
||||||
|
|
||||||
def check_clipping(self, bit_depth=None):
|
def check_clipping(self, bit_depth: int | None = None) -> bool:
|
||||||
"""
|
"""
|
||||||
Check if any data in y is clipped.
|
Check if any data in y is clipped.
|
||||||
For a 14-bit ADC, clipping occurs at 2**13 (8192) or 2**13-1 (8191).
|
For a 14-bit ADC, clipping occurs at 2**13 (8192) or 2**13-1 (8191).
|
||||||
@@ -147,7 +155,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
return self.is_clipped
|
return self.is_clipped
|
||||||
|
|
||||||
|
|
||||||
def lowpass(self, cutoff, numtaps=None):
|
def lowpass(self, cutoff: float, numtaps: int | None = None) -> ADC_Result:
|
||||||
"""
|
"""
|
||||||
Apply a zero-phase lowpass FIR filter to all channels.
|
Apply a zero-phase lowpass FIR filter to all channels.
|
||||||
|
|
||||||
@@ -239,7 +247,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def add_sample_space(self, samples):
|
def add_sample_space(self, samples: int) -> None:
|
||||||
"Adds space for n samples, where n can also be negative (deletes space). New space is filled up with \"0\""
|
"Adds space for n samples, where n can also be negative (deletes space). New space is filled up with \"0\""
|
||||||
|
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
@@ -259,7 +267,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
|
|
||||||
def get_result_by_index(self, index):
|
def get_result_by_index(self, index: int) -> ADC_Result:
|
||||||
|
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
@@ -281,33 +289,33 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def get_sampling_rate(self):
|
def get_sampling_rate(self) -> float:
|
||||||
"""Returns the samplingfrequency"""
|
"""Returns the samplingfrequency"""
|
||||||
return self.sampling_rate + 0
|
return self.sampling_rate + 0
|
||||||
|
|
||||||
|
|
||||||
def set_sampling_rate(self, hz):
|
def set_sampling_rate(self, hz: float) -> None:
|
||||||
"""Sets the samplingfrequency in hz"""
|
"""Sets the samplingfrequency in hz"""
|
||||||
self.sampling_rate = float(hz)
|
self.sampling_rate = float(hz)
|
||||||
|
|
||||||
|
|
||||||
def get_nChannels(self):
|
def get_nChannels(self) -> int:
|
||||||
"""Gets the number of channels"""
|
"""Gets the number of channels"""
|
||||||
return self.nChannels + 0
|
return self.nChannels + 0
|
||||||
|
|
||||||
def set_nChannels(self, channels):
|
def set_nChannels(self, channels: int) -> None:
|
||||||
"""Sets the number of channels"""
|
"""Sets the number of channels"""
|
||||||
self.nChannels = int(channels)
|
self.nChannels = int(channels)
|
||||||
|
|
||||||
|
|
||||||
def get_index_bounds(self, index):
|
def get_index_bounds(self, index: int) -> tuple[int, int]:
|
||||||
"Returns a tuple with (start, end) of the wanted result"
|
"Returns a tuple with (start, end) of the wanted result"
|
||||||
return self.index[index]
|
return self.index[index]
|
||||||
|
|
||||||
def uses_statistics(self):
|
def uses_statistics(self) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def write_to_csv(self, destination=sys.stdout, delimiter=" "):
|
def write_to_csv(self, destination: str | IO[str] = sys.stdout, delimiter: str = " ") -> None:
|
||||||
"""
|
"""
|
||||||
writes the data to a file or to sys.stdout
|
writes the data to a file or to sys.stdout
|
||||||
destination can be a file or a filename
|
destination can be a file or a filename
|
||||||
@@ -319,7 +327,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
self._write_to_csv_dest(destination, delimiter)
|
self._write_to_csv_dest(destination, delimiter)
|
||||||
|
|
||||||
def _write_to_csv_dest(self, dest, delimiter):
|
def _write_to_csv_dest(self, dest: IO[str], delimiter: str) -> None:
|
||||||
dest.write("# adc_result\n")
|
dest.write("# adc_result\n")
|
||||||
dest.write("# t y0 y1 ...\n")
|
dest.write("# t y0 y1 ...\n")
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
@@ -335,7 +343,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
finally:
|
finally:
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
def write_to_simpson(self, destination=sys.stdout, delimiter=" "):
|
def write_to_simpson(self, destination: str | IO[str] = sys.stdout, delimiter: str = " ") -> None:
|
||||||
"""
|
"""
|
||||||
writes the data to a text file or sys.stdout in Simpson format,
|
writes the data to a text file or sys.stdout in Simpson format,
|
||||||
for further processing with the NMRnotebook software;
|
for further processing with the NMRnotebook software;
|
||||||
@@ -347,7 +355,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
self._write_to_simpson_dest(destination, delimiter)
|
self._write_to_simpson_dest(destination, delimiter)
|
||||||
|
|
||||||
def _write_to_simpson_dest(self, dest, delimiter):
|
def _write_to_simpson_dest(self, dest: IO[str], delimiter: str) -> None:
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
xdata=self.get_xdata()
|
xdata=self.get_xdata()
|
||||||
@@ -366,7 +374,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
finally:
|
finally:
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
def write_to_hdf(self, hdffile, where, name, title, complib=None, complevel=None):
|
def write_to_hdf(self, hdffile: tables.File, where: str, name: str, title: str, complib: str | None = None, complevel: int | None = None) -> None:
|
||||||
accu_group=hdffile.create_group(where=where,name=name,title=title)
|
accu_group=hdffile.create_group(where=where,name=name,title=title)
|
||||||
accu_group._v_attrs.damaris_type="ADC_Result"
|
accu_group._v_attrs.damaris_type="ADC_Result"
|
||||||
if self.contains_data():
|
if self.contains_data():
|
||||||
@@ -463,13 +471,13 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
|
|
||||||
# Ueberladen von Operatoren und Built-Ins -------------------------------------------------------
|
# Ueberladen von Operatoren und Built-Ins -------------------------------------------------------
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self) -> int:
|
||||||
"Redefining len(ADC_Result obj), returns the number of samples in one channel and 0 without data"
|
"Redefining len(ADC_Result obj), returns the number of samples in one channel and 0 without data"
|
||||||
if len(self.y)>0:
|
if len(self.y)>0:
|
||||||
return len(self.y[0])
|
return len(self.y[0])
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
"""
|
"""
|
||||||
writes job meta data and data to string returned
|
writes job meta data and data to string returned
|
||||||
"""
|
"""
|
||||||
@@ -486,12 +494,12 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
|
|
||||||
return tmp_string
|
return tmp_string
|
||||||
|
|
||||||
def _copy_metadata(self, r):
|
def _copy_metadata(self, r: ADC_Result) -> None:
|
||||||
"Copy channel metadata (nChannels, is_clipped) from self to the new result r"
|
"Copy channel metadata (nChannels, is_clipped) from self to the new result r"
|
||||||
r.nChannels = self.nChannels
|
r.nChannels = self.nChannels
|
||||||
r.is_clipped = self.is_clipped
|
r.is_clipped = self.is_clipped
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other: int | float) -> ADC_Result:
|
||||||
"Redefining self + other (scalar)"
|
"Redefining self + other (scalar)"
|
||||||
if isinstance(other, int) or isinstance(other, float):
|
if isinstance(other, int) or isinstance(other, float):
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
@@ -509,12 +517,12 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __radd__(self, other):
|
def __radd__(self, other: int | float) -> ADC_Result:
|
||||||
"Redefining other (scalar) + self"
|
"Redefining other (scalar) + self"
|
||||||
return self.__add__(other)
|
return self.__add__(other)
|
||||||
|
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other: int | float) -> ADC_Result:
|
||||||
"Redefining self - other (scalar)"
|
"Redefining self - other (scalar)"
|
||||||
if isinstance(other, int) or isinstance(other, float):
|
if isinstance(other, int) or isinstance(other, float):
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
@@ -532,7 +540,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __rsub__(self, other):
|
def __rsub__(self, other: int | float) -> ADC_Result:
|
||||||
"Redefining other (scalar) - self"
|
"Redefining other (scalar) - self"
|
||||||
if isinstance(other, int) or isinstance(other, float):
|
if isinstance(other, int) or isinstance(other, float):
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
@@ -550,7 +558,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other: int | float) -> ADC_Result:
|
||||||
"Redefining self * other (scalar)"
|
"Redefining self * other (scalar)"
|
||||||
if isinstance(other, int) or isinstance(other, float):
|
if isinstance(other, int) or isinstance(other, float):
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
@@ -567,12 +575,12 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
raise ValueError(f"ValueError: Cannot multiply \"{other.__class__}\" to ADC-Result!")
|
raise ValueError(f"ValueError: Cannot multiply \"{other.__class__}\" to ADC-Result!")
|
||||||
|
|
||||||
|
|
||||||
def __rmul__(self, other):
|
def __rmul__(self, other: int | float) -> ADC_Result:
|
||||||
"Redefining other (scalar) * self"
|
"Redefining other (scalar) * self"
|
||||||
return self.__mul__(other)
|
return self.__mul__(other)
|
||||||
|
|
||||||
|
|
||||||
def __pow__(self, other):
|
def __pow__(self, other: int | float) -> ADC_Result:
|
||||||
"Redefining self ** other (scalar)"
|
"Redefining self ** other (scalar)"
|
||||||
if isinstance(other, int) or isinstance(other, float):
|
if isinstance(other, int) or isinstance(other, float):
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
@@ -588,7 +596,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
raise ValueError(f"ValueError: Cannot power raise \"{other.__class__}\" to ADC-Result!")
|
raise ValueError(f"ValueError: Cannot power raise \"{other.__class__}\" to ADC-Result!")
|
||||||
|
|
||||||
def __truediv__(self, other):
|
def __truediv__(self, other: int | float) -> ADC_Result:
|
||||||
"Redefining self / other (scalar)"
|
"Redefining self / other (scalar)"
|
||||||
if isinstance(other, int) or isinstance(other, float):
|
if isinstance(other, int) or isinstance(other, float):
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
@@ -603,7 +611,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to ADC-Result!")
|
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to ADC-Result!")
|
||||||
|
|
||||||
def __rtruediv__(self, other):
|
def __rtruediv__(self, other: int | float) -> ADC_Result:
|
||||||
"Redefining other (scalar) / self"
|
"Redefining other (scalar) / self"
|
||||||
if isinstance(other, int) or isinstance(other, float):
|
if isinstance(other, int) or isinstance(other, float):
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
@@ -617,14 +625,14 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to ADC-Result!")
|
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to ADC-Result!")
|
||||||
|
|
||||||
def __floordiv__(self, other):
|
def __floordiv__(self, other: int) -> ADC_Result:
|
||||||
"Redefining self // other (scalar)"
|
"Redefining self // other (scalar)"
|
||||||
if isinstance(other, float):
|
if isinstance(other, float):
|
||||||
raise ValueError("ValueError: Cannot use floor division (//) on floats! Use \"/\" instead of \"//\"! ")
|
raise ValueError("ValueError: Cannot use floor division (//) on floats! Use \"/\" instead of \"//\"! ")
|
||||||
|
|
||||||
if isinstance(other, int):
|
if isinstance(other, int):
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
tmp_y = []
|
tmp_y: list[numpy.ndarray] = []
|
||||||
for i in range(self.get_number_of_channels()):
|
for i in range(self.get_number_of_channels()):
|
||||||
tmp_y.append(numpy.array(self.y[i], dtype="float32") // other)
|
tmp_y.append(numpy.array(self.y[i], dtype="float32") // other)
|
||||||
r = ADC_Result(x = self.x[:], y = tmp_y, index = self.index[:], sampl_freq = self.sampling_rate, desc = self.description, job_id = self.job_id, job_date = self.job_date)
|
r = ADC_Result(x = self.x[:], y = tmp_y, index = self.index[:], sampl_freq = self.sampling_rate, desc = self.description, job_id = self.job_id, job_date = self.job_date)
|
||||||
@@ -634,14 +642,14 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to ADC-Result!")
|
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to ADC-Result!")
|
||||||
|
|
||||||
def __rfloordiv__(self, other):
|
def __rfloordiv__(self, other: int) -> ADC_Result:
|
||||||
"Redefining other (scalar) // self"
|
"Redefining other (scalar) // self"
|
||||||
if isinstance(other, float):
|
if isinstance(other, float):
|
||||||
raise ValueError("ValueError: Cannot use floor division (//) on floats! Use \"/\" instead of \"//\"! ")
|
raise ValueError("ValueError: Cannot use floor division (//) on floats! Use \"/\" instead of \"//\"! ")
|
||||||
|
|
||||||
if isinstance(other, int):
|
if isinstance(other, int):
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
tmp_y = []
|
tmp_y: list[numpy.ndarray] = []
|
||||||
for i in range(self.get_number_of_channels()):
|
for i in range(self.get_number_of_channels()):
|
||||||
tmp_y.append(other // numpy.array(self.y[i], dtype="float32"))
|
tmp_y.append(other // numpy.array(self.y[i], dtype="float32"))
|
||||||
r = ADC_Result(x = self.x[:], y = tmp_y, index = self.index[:], sampl_freq = self.sampling_rate, desc = self.description, job_id = self.job_id, job_date = self.job_date)
|
r = ADC_Result(x = self.x[:], y = tmp_y, index = self.index[:], sampl_freq = self.sampling_rate, desc = self.description, job_id = self.job_id, job_date = self.job_date)
|
||||||
@@ -652,7 +660,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to ADC-Result!")
|
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to ADC-Result!")
|
||||||
|
|
||||||
|
|
||||||
def __neg__(self):
|
def __neg__(self) -> ADC_Result:
|
||||||
"Redefining -self"
|
"Redefining -self"
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
tmp_y = []
|
tmp_y = []
|
||||||
@@ -666,7 +674,7 @@ class ADC_Result(Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def read_from_hdf(hdf_node):
|
def read_from_hdf(hdf_node: object) -> ADC_Result | None:
|
||||||
"""
|
"""
|
||||||
read accumulation data from HDF node and return it.
|
read accumulation data from HDF node and return it.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -25,6 +25,12 @@ import datetime # added by Oleg Petrov
|
|||||||
import ctypes # added by Oleg Petrov
|
import ctypes # added by Oleg Petrov
|
||||||
import struct # added by Oleg Petrov
|
import struct # added by Oleg Petrov
|
||||||
import os # added by Oleg Petrov
|
import os # added by Oleg Petrov
|
||||||
|
from typing import IO
|
||||||
|
|
||||||
|
_XArray = numpy.ndarray | list
|
||||||
|
_YChannels = list[numpy.ndarray]
|
||||||
|
_IndexList = list[tuple[int, int]]
|
||||||
|
_Description = dict[str, str]
|
||||||
|
|
||||||
|
|
||||||
class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
||||||
@@ -50,7 +56,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
x (list): The x-axis data points.
|
x (list): The x-axis data points.
|
||||||
y (list): The y-axis data points.
|
y (list): The y-axis data points.
|
||||||
"""
|
"""
|
||||||
def __init__(self, x = None, y = None, y_2 = None, n = None, index = None, sampl_freq = None, error = False):
|
def __init__(self, x: _XArray | None = None, y: _YChannels | None = None, y_2: _YChannels | numpy.ndarray | None = None, n: int | None = None, index: _IndexList | None = None, sampl_freq: float | None = None, error: bool = False) -> None:
|
||||||
Errorable.__init__(self)
|
Errorable.__init__(self)
|
||||||
Drawable.__init__(self)
|
Drawable.__init__(self)
|
||||||
|
|
||||||
@@ -102,7 +108,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Wrong usage of __init__!")
|
raise ValueError("Wrong usage of __init__!")
|
||||||
|
|
||||||
def _copy_provenance(self, r):
|
def _copy_provenance(self, r: "Accumulation") -> None:
|
||||||
r.is_clipped = self.is_clipped
|
r.is_clipped = self.is_clipped
|
||||||
r.job_id = self.job_id
|
r.job_id = self.job_id
|
||||||
r.job_ids = self.job_ids.copy()
|
r.job_ids = self.job_ids.copy()
|
||||||
@@ -110,7 +116,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
if self.common_descriptions is not None:
|
if self.common_descriptions is not None:
|
||||||
r.common_descriptions = self.common_descriptions.copy()
|
r.common_descriptions = self.common_descriptions.copy()
|
||||||
|
|
||||||
def get_accu_by_index(self, index: int):
|
def get_accu_by_index(self, index: int) -> "Accumulation":
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
start = self.index[index][0]
|
start = self.index[index][0]
|
||||||
@@ -138,13 +144,13 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
self.lock.release()
|
self.lock.release()
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def get_result_by_index(self, index):
|
def get_result_by_index(self, index: int) -> "Accumulation":
|
||||||
return self.get_accu_by_index(index)
|
return self.get_accu_by_index(index)
|
||||||
|
|
||||||
def get_Result_by_index(self, index):
|
def get_Result_by_index(self, index: int) -> "Accumulation":
|
||||||
return self.get_accu_by_index(index)
|
return self.get_accu_by_index(index)
|
||||||
|
|
||||||
def get_ysquare(self, channel):
|
def get_ysquare(self, channel: int) -> numpy.ndarray | None:
|
||||||
if self.uses_statistics():
|
if self.uses_statistics():
|
||||||
try:
|
try:
|
||||||
return self.y_square[channel]
|
return self.y_square[channel]
|
||||||
@@ -172,7 +178,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
|
|
||||||
# external interface --------------------------------------------------------------------
|
# external interface --------------------------------------------------------------------
|
||||||
|
|
||||||
def get_yerr(self, channel):
|
def get_yerr(self, channel: int) -> numpy.ndarray | list:
|
||||||
"""
|
"""
|
||||||
return error (std.dev/sqrt(n)) of mean
|
return error (std.dev/sqrt(n)) of mean
|
||||||
"""
|
"""
|
||||||
@@ -196,7 +202,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
# sample standard deviation / sqrt(n)
|
# sample standard deviation / sqrt(n)
|
||||||
return numpy.nan_to_num(numpy.sqrt(variance_over_n))
|
return numpy.nan_to_num(numpy.sqrt(variance_over_n))
|
||||||
|
|
||||||
def get_ydata(self, channel):
|
def get_ydata(self, channel: int = 0) -> numpy.ndarray | list:
|
||||||
"""
|
"""
|
||||||
return mean data
|
return mean data
|
||||||
"""
|
"""
|
||||||
@@ -214,7 +220,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
return tmp_y
|
return tmp_y
|
||||||
|
|
||||||
|
|
||||||
def get_ymin(self):
|
def get_ymin(self) -> float|int:
|
||||||
if not self.contains_data():
|
if not self.contains_data():
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -249,10 +255,10 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
self.lock.release()
|
self.lock.release()
|
||||||
return max(tmp_max)
|
return max(tmp_max)
|
||||||
|
|
||||||
def get_job_id(self) -> int:
|
def get_job_id(self) -> int | None:
|
||||||
return self.job_id # modified by Oleg Petrov
|
return self.job_id # modified by Oleg Petrov
|
||||||
|
|
||||||
def write_to_csv(self, destination=sys.stdout, delimiter=" "):
|
def write_to_csv(self, destination: str | IO[str] = sys.stdout, delimiter: str = " ") -> None:
|
||||||
"""
|
"""
|
||||||
writes the data to a file.
|
writes the data to a file.
|
||||||
destination can be a filehandle or a filename, default sys.stdout
|
destination can be a filehandle or a filename, default sys.stdout
|
||||||
@@ -263,7 +269,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
self._write_to_csv_dest(destination, delimiter)
|
self._write_to_csv_dest(destination, delimiter)
|
||||||
|
|
||||||
def _write_to_csv_dest(self, dest, delimiter):
|
def _write_to_csv_dest(self, dest: IO[str], delimiter: str) -> None:
|
||||||
dest.write("# accumulation %d\n"%self.n)
|
dest.write("# accumulation %d\n"%self.n)
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
@@ -296,7 +302,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
# ------------- added by Oleg Petrov, 14 Feb 2012 ----------------------
|
# ------------- added by Oleg Petrov, 14 Feb 2012 ----------------------
|
||||||
def write_to_simpson(self, destination=sys.stdout, delimiter=" ", frequency=100e6):
|
def write_to_simpson(self, destination: str | IO[str] = sys.stdout, delimiter: str = " ", frequency: float = 100e6) -> None:
|
||||||
"""
|
"""
|
||||||
writes the data to a text file or sys.stdout in Simpson format,
|
writes the data to a text file or sys.stdout in Simpson format,
|
||||||
for further processing with the NMRnotebook software;
|
for further processing with the NMRnotebook software;
|
||||||
@@ -308,7 +314,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
self._write_to_simpson_dest(destination, delimiter, frequency)
|
self._write_to_simpson_dest(destination, delimiter, frequency)
|
||||||
|
|
||||||
def _write_to_simpson_dest(self, dest, delimiter, frequency):
|
def _write_to_simpson_dest(self, dest: IO[str], delimiter: str, frequency: float) -> None:
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
xdata=self.get_xdata()
|
xdata=self.get_xdata()
|
||||||
@@ -329,11 +335,11 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
# ------------- added by Oleg Petrov, 10 Sep 2013 -----------------------
|
# ------------- added by Oleg Petrov, 10 Sep 2013 -----------------------
|
||||||
def write_to_tecmag(self, destination=sys.stdout, nrecords=1,\
|
def write_to_tecmag(self, destination = sys.stdout, nrecords: int = 1,\
|
||||||
frequency=100.,\
|
frequency: float = 100.,\
|
||||||
last_delay = 1.,\
|
last_delay: float = 1.,\
|
||||||
receiver_phase=0.,\
|
receiver_phase: float = 0.,\
|
||||||
nucleus='1H'):
|
nucleus: str = '1H') -> None:
|
||||||
"""
|
"""
|
||||||
writes the data to a binary file in TecMag format;
|
writes the data to a binary file in TecMag format;
|
||||||
destination can be a file object or a filename;
|
destination can be a file object or a filename;
|
||||||
@@ -456,7 +462,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
|
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
|
|
||||||
def write_to_hdf(self, hdffile, where, name, title, complib=None, complevel=None):
|
def write_to_hdf(self, hdffile: tables.File, where: str, name: str, title: str, complib: str | None = None, complevel: int | None = None) -> None:
|
||||||
"""
|
"""
|
||||||
Write the accumulation data to an HDF5 file.
|
Write the accumulation data to an HDF5 file.
|
||||||
|
|
||||||
@@ -617,7 +623,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
return tmp_string
|
return tmp_string
|
||||||
|
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other: "int | float | ADC_Result | Accumulation | None") -> "Accumulation":
|
||||||
"""
|
"""
|
||||||
Redefining self + other
|
Redefining self + other
|
||||||
We define this for different types of other:
|
We define this for different types of other:
|
||||||
@@ -801,22 +807,22 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("can not add "+repr(type(other))+" to Accumulation")
|
raise ValueError("can not add "+repr(type(other))+" to Accumulation")
|
||||||
|
|
||||||
def __radd__(self, other):
|
def __radd__(self, other: "int | float | ADC_Result | Accumulation | None") -> "Accumulation":
|
||||||
"""Redefining other + self"""
|
"""Redefining other + self"""
|
||||||
return self.__add__(other)
|
return self.__add__(other)
|
||||||
|
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other: "int | float | ADC_Result | Accumulation") -> "Accumulation":
|
||||||
"""Redefining self - other"""
|
"""Redefining self - other"""
|
||||||
return self.__add__(-other)
|
return self.__add__(-other)
|
||||||
|
|
||||||
|
|
||||||
def __rsub__(self, other):
|
def __rsub__(self, other: "int | float | ADC_Result | Accumulation") -> "Accumulation":
|
||||||
"""Redefining other - self"""
|
"""Redefining other - self"""
|
||||||
return (-self) + other
|
return (-self) + other
|
||||||
|
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other: int | float) -> "Accumulation":
|
||||||
"""Redefining self * other (scalar)"""
|
"""Redefining self * other (scalar)"""
|
||||||
if isinstance(other, (int, float)):
|
if isinstance(other, (int, float)):
|
||||||
if not self.contains_data():
|
if not self.contains_data():
|
||||||
@@ -843,11 +849,11 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
raise ValueError(f"ValueError: Cannot multiply \"{other.__class__}\" to Accumulation!")
|
raise ValueError(f"ValueError: Cannot multiply \"{other.__class__}\" to Accumulation!")
|
||||||
|
|
||||||
def __rmul__(self, other):
|
def __rmul__(self, other: int | float) -> "Accumulation":
|
||||||
"""Redefining other (scalar) * self"""
|
"""Redefining other (scalar) * self"""
|
||||||
return self.__mul__(other)
|
return self.__mul__(other)
|
||||||
|
|
||||||
def __imul__(self, other):
|
def __imul__(self, other: int | float) -> "Accumulation":
|
||||||
"""Redefining self *= other (scalar)"""
|
"""Redefining self *= other (scalar)"""
|
||||||
if isinstance(other, (int, float)):
|
if isinstance(other, (int, float)):
|
||||||
if not self.contains_data():
|
if not self.contains_data():
|
||||||
@@ -862,7 +868,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
raise ValueError(f"ValueError: Cannot multiply \"{other.__class__}\" to Accumulation!")
|
raise ValueError(f"ValueError: Cannot multiply \"{other.__class__}\" to Accumulation!")
|
||||||
|
|
||||||
def __truediv__(self, other):
|
def __truediv__(self, other: int | float) -> "Accumulation":
|
||||||
"""Redefining self / other (scalar)"""
|
"""Redefining self / other (scalar)"""
|
||||||
if isinstance(other, (int, float)):
|
if isinstance(other, (int, float)):
|
||||||
if not self.contains_data():
|
if not self.contains_data():
|
||||||
@@ -889,7 +895,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to Accumulation!")
|
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to Accumulation!")
|
||||||
|
|
||||||
def __itruediv__(self, other):
|
def __itruediv__(self, other: int | float) -> "Accumulation":
|
||||||
"""Redefining self /= other (scalar)"""
|
"""Redefining self /= other (scalar)"""
|
||||||
if isinstance(other, (int, float)):
|
if isinstance(other, (int, float)):
|
||||||
if not self.contains_data():
|
if not self.contains_data():
|
||||||
@@ -904,7 +910,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to Accumulation!")
|
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to Accumulation!")
|
||||||
|
|
||||||
def __floordiv__(self, other):
|
def __floordiv__(self, other: int) -> "Accumulation":
|
||||||
"""Redefining self // other (scalar)"""
|
"""Redefining self // other (scalar)"""
|
||||||
if isinstance(other, float):
|
if isinstance(other, float):
|
||||||
raise ValueError("ValueError: Cannot use floor division (//) on floats! Use \"/\" instead of \"//\"! ")
|
raise ValueError("ValueError: Cannot use floor division (//) on floats! Use \"/\" instead of \"//\"! ")
|
||||||
@@ -913,7 +919,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
if not self.contains_data():
|
if not self.contains_data():
|
||||||
raise ValueError("Accumulation: You cant divide an empty accumulation")
|
raise ValueError("Accumulation: You cant divide an empty accumulation")
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
tmp_y = []
|
tmp_y: list[numpy.ndarray] = []
|
||||||
for i in range(self.get_number_of_channels()):
|
for i in range(self.get_number_of_channels()):
|
||||||
tmp_y.append(self.y[i] // other)
|
tmp_y.append(self.y[i] // other)
|
||||||
|
|
||||||
@@ -929,7 +935,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
else:
|
else:
|
||||||
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to Accumulation!")
|
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to Accumulation!")
|
||||||
|
|
||||||
def __ifloordiv__(self, other):
|
def __ifloordiv__(self, other: int) -> "Accumulation":
|
||||||
"""Redefining self //= other (scalar)"""
|
"""Redefining self //= other (scalar)"""
|
||||||
if isinstance(other, float):
|
if isinstance(other, float):
|
||||||
raise ValueError("ValueError: Cannot use floor division (//) on floats! Use \"/\" instead of \"//\"! ")
|
raise ValueError("ValueError: Cannot use floor division (//) on floats! Use \"/\" instead of \"//\"! ")
|
||||||
@@ -950,7 +956,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to Accumulation!")
|
raise ValueError(f"ValueError: Cannot divide \"{other.__class__}\" to Accumulation!")
|
||||||
|
|
||||||
|
|
||||||
def __iadd__(self, other):
|
def __iadd__(self, other: "int | float | ADC_Result | Accumulation | None") -> "Accumulation":
|
||||||
"""Redefining self += other"""
|
"""Redefining self += other"""
|
||||||
# Float or int
|
# Float or int
|
||||||
if isinstance(other, int) or isinstance(other, float):
|
if isinstance(other, int) or isinstance(other, float):
|
||||||
@@ -1123,12 +1129,12 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
raise ValueError("can not add "+repr(type(other))+" to Accumulation")
|
raise ValueError("can not add "+repr(type(other))+" to Accumulation")
|
||||||
|
|
||||||
|
|
||||||
def __isub__(self, other):
|
def __isub__(self, other: "int | float | ADC_Result | Accumulation") -> "Accumulation":
|
||||||
"""Redefining self -= other"""
|
"""Redefining self -= other"""
|
||||||
return self.__iadd__(-other)
|
return self.__iadd__(-other)
|
||||||
|
|
||||||
|
|
||||||
def __neg__(self):
|
def __neg__(self) -> "Accumulation":
|
||||||
"""Redefining -self"""
|
"""Redefining -self"""
|
||||||
|
|
||||||
if not self.contains_data():
|
if not self.contains_data():
|
||||||
@@ -1149,7 +1155,7 @@ class Accumulation(Errorable, Drawable, DamarisFFT, Signalpath):
|
|||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def read_from_hdf(hdf_node):
|
def read_from_hdf(hdf_node: object) -> "Accumulation | None":
|
||||||
"""
|
"""
|
||||||
read accumulation data from HDF node and return it.
|
read accumulation data from HDF node and return it.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# -*- coding: iso-8859-1 -*-
|
# -*- coding: iso-8859-1 -*-
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# #
|
# #
|
||||||
# Name: Class Drawable #
|
# Name: Class Drawable #
|
||||||
@@ -8,23 +10,26 @@
|
|||||||
# #
|
# #
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
|
import numpy
|
||||||
|
|
||||||
|
|
||||||
class Drawable:
|
class Drawable:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
# Will be set correctly in one of the subclasses
|
# Will be set correctly in one of the subclasses
|
||||||
self.x = []
|
self.x: numpy.ndarray | list = []
|
||||||
self.y = []
|
self.y: list = []
|
||||||
|
|
||||||
self.styles = { }
|
self.styles: dict = { }
|
||||||
|
|
||||||
self.xlabel = None
|
self.xlabel: str | None = None
|
||||||
self.ylabel = None
|
self.ylabel: str | None = None
|
||||||
|
|
||||||
self.title = None
|
self.title: str | None = None
|
||||||
|
|
||||||
self.legend = { }
|
self.legend: dict = { }
|
||||||
|
|
||||||
self.text = {}
|
self.text: dict = {}
|
||||||
|
|
||||||
self.xmin = 0
|
self.xmin = 0
|
||||||
self.xmax = 0
|
self.xmax = 0
|
||||||
@@ -32,12 +37,12 @@ class Drawable:
|
|||||||
self.ymax = 0
|
self.ymax = 0
|
||||||
|
|
||||||
|
|
||||||
def get_xdata(self):
|
def get_xdata(self) -> numpy.ndarray | list:
|
||||||
"Returns a reference to the x-Plotdata (array)"
|
"Returns a reference to the x-Plotdata (array)"
|
||||||
return self.x
|
return self.x
|
||||||
|
|
||||||
|
|
||||||
def set_xdata(self, pos, value):
|
def set_xdata(self, pos: int, value: float) -> None:
|
||||||
"Sets a point in x"
|
"Sets a point in x"
|
||||||
try:
|
try:
|
||||||
self.x[pos] = value
|
self.x[pos] = value
|
||||||
@@ -45,7 +50,7 @@ class Drawable:
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def get_ydata(self, channel):
|
def get_ydata(self, channel: int = 0) -> numpy.ndarray | list:
|
||||||
"Returns the y-Plotdata of channel n (array)"
|
"Returns the y-Plotdata of channel n (array)"
|
||||||
try:
|
try:
|
||||||
return self.y[channel]
|
return self.y[channel]
|
||||||
@@ -53,51 +58,52 @@ class Drawable:
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def set_ydata(self, channel, pos, value):
|
def set_ydata(self, channel: int, pos: int, value: float) -> None:
|
||||||
"Sets a point in y"
|
"Sets a point in y"
|
||||||
try:
|
try:
|
||||||
self.y[channel][pos] = value
|
self.y[channel][pos] = value
|
||||||
except:
|
except:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def get_number_of_channels(self):
|
|
||||||
|
def get_number_of_channels(self) -> int:
|
||||||
"Returns the number of channels in y"
|
"Returns the number of channels in y"
|
||||||
return len(self.y)
|
return len(self.y)
|
||||||
|
|
||||||
|
|
||||||
def get_style(self):
|
def get_style(self) -> dict:
|
||||||
"Returns a reference to plot-styles (dictionary)"
|
"Returns a reference to plot-styles (dictionary)"
|
||||||
return self.styles
|
return self.styles
|
||||||
|
|
||||||
|
|
||||||
def set_style(self, channel, value):
|
def set_style(self, channel: int | str, value: object) -> None:
|
||||||
"Sets a channel to a certain plot-style"
|
"Sets a channel to a certain plot-style"
|
||||||
if channel in self.styles:
|
if channel in self.styles:
|
||||||
print("Drawable Warning: Style key \"%s\" will be overwritten with \"%s\"" % (str(channel), str(value)))
|
print("Drawable Warning: Style key \"%s\" will be overwritten with \"%s\"" % (str(channel), str(value)))
|
||||||
self.styles[channel] = str(value)
|
self.styles[channel] = str(value)
|
||||||
|
|
||||||
|
|
||||||
def get_xlabel(self):
|
def get_xlabel(self) -> str | None:
|
||||||
"Returns the label for the x-axis"
|
"Returns the label for the x-axis"
|
||||||
return self.xlabel
|
return self.xlabel
|
||||||
|
|
||||||
|
|
||||||
def set_xlabel(self, label):
|
def set_xlabel(self, label: object) -> None:
|
||||||
"Sets the label for the x-axis"
|
"Sets the label for the x-axis"
|
||||||
self.xlabel = str(label)
|
self.xlabel = str(label)
|
||||||
|
|
||||||
|
|
||||||
def get_ylabel(self):
|
def get_ylabel(self) -> str | None:
|
||||||
"Gets the label for the y-axis"
|
"Gets the label for the y-axis"
|
||||||
return self.ylabel
|
return self.ylabel
|
||||||
|
|
||||||
|
|
||||||
def set_ylabel(self, label):
|
def set_ylabel(self, label: object) -> None:
|
||||||
"Sets the label for the y-axis"
|
"Sets the label for the y-axis"
|
||||||
self.ylabel = str(label)
|
self.ylabel = str(label)
|
||||||
|
|
||||||
|
|
||||||
def get_text(self, index):
|
def get_text(self, index: int | str) -> str | None:
|
||||||
"Returns labels to be plotted (List)"
|
"Returns labels to be plotted (List)"
|
||||||
if index in self.text:
|
if index in self.text:
|
||||||
return self.text[index]
|
return self.text[index]
|
||||||
@@ -105,61 +111,68 @@ class Drawable:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def set_text(self, index, text):
|
def set_text(self, index: int | str, text: object) -> None:
|
||||||
"Sets labels to be plotted "
|
"Sets labels to be plotted "
|
||||||
self.text[index] = str(text)
|
self.text[index] = str(text)
|
||||||
|
|
||||||
|
|
||||||
def get_title(self):
|
def get_title(self) -> str | None:
|
||||||
"Returns the title of the plot"
|
"Returns the title of the plot"
|
||||||
return self.title
|
return self.title
|
||||||
|
|
||||||
|
|
||||||
def set_title(self, title):
|
def set_title(self, title: object) -> None:
|
||||||
"Sets the title of the plot"
|
"Sets the title of the plot"
|
||||||
self.title = str(title)
|
self.title = str(title)
|
||||||
|
|
||||||
|
|
||||||
def get_legend(self):
|
def get_legend(self) -> dict:
|
||||||
"Returns the legend of the plot (Dictionary)"
|
"Returns the legend of the plot (Dictionary)"
|
||||||
return self.legend
|
return self.legend
|
||||||
|
|
||||||
|
|
||||||
def set_legend(self, channel, value):
|
def set_legend(self, channel: int | str, value: object) -> None:
|
||||||
"Sets the legend of the plot"
|
"Sets the legend of the plot"
|
||||||
if channel in self.legend:
|
if channel in self.legend:
|
||||||
print("Drawable Warning: Legend key \"%s\" will be overwritten with \"%s\"" % (str(channel), str(value)))
|
print("Drawable Warning: Legend key \"%s\" will be overwritten with \"%s\"" % (str(channel), str(value)))
|
||||||
self.legend[channel] = str(value)
|
self.legend[channel] = str(value)
|
||||||
|
|
||||||
def get_xmin(self):
|
|
||||||
|
def get_xmin(self) -> float:
|
||||||
"Returns minimun of x"
|
"Returns minimun of x"
|
||||||
return self.x.min()
|
return self.x.min()
|
||||||
|
|
||||||
def get_xminpos(self):
|
|
||||||
|
def get_xminpos(self) -> float:
|
||||||
"Returns smallest positive value of x"
|
"Returns smallest positive value of x"
|
||||||
mask = self.x > 0
|
mask = self.x > 0
|
||||||
return self.x[mask].min()
|
return self.x[mask].min()
|
||||||
|
|
||||||
def set_xmin(self, xmin):
|
|
||||||
|
def set_xmin(self, xmin: float) -> None:
|
||||||
"Sets minimum of x"
|
"Sets minimum of x"
|
||||||
self.xmin = xmin
|
self.xmin = xmin
|
||||||
|
|
||||||
def get_xmax(self):
|
|
||||||
|
def get_xmax(self) -> float:
|
||||||
"Returns maximum of x"
|
"Returns maximum of x"
|
||||||
return self.x.max()
|
return self.x.max()
|
||||||
|
|
||||||
def set_xmax(self, xmax):
|
|
||||||
|
def set_xmax(self, xmax: float) -> None:
|
||||||
"Sets maximum of x"
|
"Sets maximum of x"
|
||||||
self.xmax = xmax
|
self.xmax = xmax
|
||||||
|
|
||||||
def get_ymin(self):
|
|
||||||
|
def get_ymin(self) -> float | int:
|
||||||
"Returns minimum of y"
|
"Returns minimum of y"
|
||||||
if isinstance(self.y, list):
|
if isinstance(self.y, list):
|
||||||
return min([yarr.min() for yarr in self.y])
|
return min([yarr.min() for yarr in self.y])
|
||||||
else:
|
else:
|
||||||
return self.y.min()
|
return self.y.min()
|
||||||
|
|
||||||
def get_yminpos(self):
|
|
||||||
|
def get_yminpos(self) -> float | int:
|
||||||
"Returns smallest positive value of y"
|
"Returns smallest positive value of y"
|
||||||
if isinstance(self.y, list):
|
if isinstance(self.y, list):
|
||||||
ymins = []
|
ymins = []
|
||||||
@@ -172,17 +185,20 @@ class Drawable:
|
|||||||
ymin = self.y[mask].min()
|
ymin = self.y[mask].min()
|
||||||
return ymin
|
return ymin
|
||||||
|
|
||||||
def set_ymin(self, ymin):
|
|
||||||
|
def set_ymin(self, ymin: float) -> None:
|
||||||
"Sets minimum of y"
|
"Sets minimum of y"
|
||||||
self.ymin = ymin
|
self.ymin = ymin
|
||||||
|
|
||||||
def get_ymax(self):
|
|
||||||
|
def get_ymax(self) -> float | int:
|
||||||
"Returns maximimum of y"
|
"Returns maximimum of y"
|
||||||
if isinstance(self.y, list):
|
if isinstance(self.y, list):
|
||||||
return max([yarr.max() for yarr in self.y])
|
return max([yarr.max() for yarr in self.y])
|
||||||
else:
|
else:
|
||||||
return self.y.max()
|
return self.y.max()
|
||||||
|
|
||||||
def set_ymax(self, ymax):
|
|
||||||
|
def set_ymax(self, ymax: float) -> None:
|
||||||
"Sets maximum of y"
|
"Sets maximum of y"
|
||||||
self.ymax = ymax
|
self.ymax = ymax
|
||||||
@@ -46,7 +46,7 @@ class Error_Result(Resultable, Drawable):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# Nothing to plot
|
# Nothing to plot
|
||||||
def get_ydata(self):
|
def get_ydata(self, channel=0):
|
||||||
return [0.0]
|
return [0.0]
|
||||||
|
|
||||||
# Nothing to plot
|
# Nothing to plot
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import sys
|
|||||||
import tables
|
import tables
|
||||||
import numpy
|
import numpy
|
||||||
import collections
|
import collections
|
||||||
|
from typing import IO
|
||||||
from . import Drawable
|
from . import Drawable
|
||||||
|
|
||||||
## provide gaussian statistics for a series of measured data points
|
## provide gaussian statistics for a series of measured data points
|
||||||
@@ -12,7 +13,7 @@ from . import Drawable
|
|||||||
# internally it keeps the sum, the sum of squares and the number of data points
|
# internally it keeps the sum, the sum of squares and the number of data points
|
||||||
class AccumulatedValue:
|
class AccumulatedValue:
|
||||||
|
|
||||||
def __init__(self, mean=None, mean_err=None, n=None):
|
def __init__(self, mean: float | None = None, mean_err: float | None = None, n: int | None = None):
|
||||||
"""
|
"""
|
||||||
one value with std. deviation
|
one value with std. deviation
|
||||||
can be initialized by:
|
can be initialized by:
|
||||||
@@ -42,7 +43,7 @@ class AccumulatedValue:
|
|||||||
self.y=float(mean)*self.n
|
self.y=float(mean)*self.n
|
||||||
self.y2=float(mean_err)**2*n*(n-1.0)+float(mean)**2*n
|
self.y2=float(mean_err)**2*n*(n-1.0)+float(mean)**2*n
|
||||||
|
|
||||||
def __add__(self,y):
|
def __add__(self, y: "AccumulatedValue | float") -> "AccumulatedValue":
|
||||||
new_one=AccumulatedValue()
|
new_one=AccumulatedValue()
|
||||||
if isinstance(y, AccumulatedValue):
|
if isinstance(y, AccumulatedValue):
|
||||||
new_one.y=self.y+y.y
|
new_one.y=self.y+y.y
|
||||||
@@ -54,7 +55,7 @@ class AccumulatedValue:
|
|||||||
new_one.n=self.n+1
|
new_one.n=self.n+1
|
||||||
return new_one
|
return new_one
|
||||||
|
|
||||||
def __iadd__(self,y):
|
def __iadd__(self, y: "AccumulatedValue | float") -> "AccumulatedValue":
|
||||||
if isinstance(y, AccumulatedValue):
|
if isinstance(y, AccumulatedValue):
|
||||||
self.y+=y.y
|
self.y+=y.y
|
||||||
self.y2+=y.y2
|
self.y2+=y.y2
|
||||||
@@ -65,14 +66,14 @@ class AccumulatedValue:
|
|||||||
self.n+=1
|
self.n+=1
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def copy(self):
|
def copy(self) -> "AccumulatedValue":
|
||||||
a=AccumulatedValue()
|
a=AccumulatedValue()
|
||||||
a.y=self.y
|
a.y=self.y
|
||||||
a.y2=self.y2
|
a.y2=self.y2
|
||||||
a.n=self.n
|
a.n=self.n
|
||||||
return a
|
return a
|
||||||
|
|
||||||
def mean(self):
|
def mean(self) -> float | None:
|
||||||
"""
|
"""
|
||||||
returns the mean of all added/accumulated values
|
returns the mean of all added/accumulated values
|
||||||
"""
|
"""
|
||||||
@@ -81,7 +82,7 @@ class AccumulatedValue:
|
|||||||
else:
|
else:
|
||||||
return self.y/self.n
|
return self.y/self.n
|
||||||
|
|
||||||
def sigma(self):
|
def sigma(self) -> float | None:
|
||||||
"""
|
"""
|
||||||
returns the standard deviation added/accumulated values
|
returns the standard deviation added/accumulated values
|
||||||
"""
|
"""
|
||||||
@@ -97,7 +98,7 @@ class AccumulatedValue:
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def mean_error(self):
|
def mean_error(self) -> float | None:
|
||||||
"""
|
"""
|
||||||
returns the mean's error (=std.dev/sqrt(n)) of all added/accumulated values
|
returns the mean's error (=std.dev/sqrt(n)) of all added/accumulated values
|
||||||
"""
|
"""
|
||||||
@@ -113,7 +114,7 @@ class AccumulatedValue:
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
if self.n==0:
|
if self.n==0:
|
||||||
return "no value"
|
return "no value"
|
||||||
elif self.n==1:
|
elif self.n==1:
|
||||||
@@ -121,12 +122,12 @@ class AccumulatedValue:
|
|||||||
else:
|
else:
|
||||||
return "%g +/- %g (%d accumulations)"%(self.mean(),self.mean_error(),self.n)
|
return "%g +/- %g (%d accumulations)"%(self.mean(),self.mean_error(),self.n)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return str(self)
|
return str(self)
|
||||||
|
|
||||||
class MeasurementResult(Drawable.Drawable, collections.UserDict):
|
class MeasurementResult(Drawable.Drawable, collections.UserDict):
|
||||||
|
|
||||||
def __init__(self, quantity_name):
|
def __init__(self, quantity_name: str) -> None:
|
||||||
"""
|
"""
|
||||||
convenient accumulation and interface to plot functions
|
convenient accumulation and interface to plot functions
|
||||||
|
|
||||||
@@ -138,7 +139,7 @@ class MeasurementResult(Drawable.Drawable, collections.UserDict):
|
|||||||
self.lock = threading.RLock()
|
self.lock = threading.RLock()
|
||||||
|
|
||||||
# get the selected item, if it does not exist, create an empty one
|
# get the selected item, if it does not exist, create an empty one
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key: float) -> "AccumulatedValue":
|
||||||
if key not in self:
|
if key not in self:
|
||||||
a=AccumulatedValue()
|
a=AccumulatedValue()
|
||||||
self.data[float(key)]=a
|
self.data[float(key)]=a
|
||||||
@@ -146,14 +147,14 @@ class MeasurementResult(Drawable.Drawable, collections.UserDict):
|
|||||||
else:
|
else:
|
||||||
return self.data[float(key)]
|
return self.data[float(key)]
|
||||||
|
|
||||||
def __setitem__(self,key,value):
|
def __setitem__(self,key: float,item: "AccumulatedValue | float")-> None:
|
||||||
if not isinstance(value, AccumulatedValue):
|
if not isinstance(item, AccumulatedValue):
|
||||||
value=AccumulatedValue(float(value))
|
item=AccumulatedValue(float(item))
|
||||||
return collections.UserDict.__setitem__(self,
|
return collections.UserDict.__setitem__(self,
|
||||||
float(key),
|
float(key),
|
||||||
value)
|
item)
|
||||||
|
|
||||||
def __add__(self, right_value):
|
def __add__(self, right_value: int) -> "MeasurementResult":
|
||||||
if right_value==0:
|
if right_value==0:
|
||||||
new_one=MeasurementResult(self.quantity_name)
|
new_one=MeasurementResult(self.quantity_name)
|
||||||
for key in self.data:
|
for key in self.data:
|
||||||
@@ -162,10 +163,10 @@ class MeasurementResult(Drawable.Drawable, collections.UserDict):
|
|||||||
else:
|
else:
|
||||||
raise Exception("not implemented")
|
raise Exception("not implemented")
|
||||||
|
|
||||||
def get_title(self):
|
def get_title(self) -> str:
|
||||||
return self.quantity_name
|
return self.quantity_name
|
||||||
|
|
||||||
def get_xdata(self):
|
def get_xdata(self) -> numpy.ndarray:
|
||||||
"""
|
"""
|
||||||
sorted array of all dictionary entries without Accumulated Value objects with n==0
|
sorted array of all dictionary entries without Accumulated Value objects with n==0
|
||||||
"""
|
"""
|
||||||
@@ -174,32 +175,37 @@ class MeasurementResult(Drawable.Drawable, collections.UserDict):
|
|||||||
keys.sort()
|
keys.sort()
|
||||||
return keys
|
return keys
|
||||||
|
|
||||||
def get_ydata(self):
|
def get_ydata(self, channel: int = 0) -> numpy.ndarray:
|
||||||
|
"""
|
||||||
|
y data (mean values); the channel argument is accepted for
|
||||||
|
compatibility with the Drawable interface, MeasurementResult
|
||||||
|
is single-channel
|
||||||
|
"""
|
||||||
return self.get_xydata()[1]
|
return self.get_xydata()[1]
|
||||||
|
|
||||||
def get_xydata(self):
|
def get_xydata(self) -> list[numpy.ndarray]:
|
||||||
k=self.get_xdata()
|
k=self.get_xdata()
|
||||||
v=numpy.array([self.data[key].mean() for key in k], dtype="float64")
|
v=numpy.array([self.data[key].mean() for key in k], dtype="float64")
|
||||||
return [k,v]
|
return [k,v]
|
||||||
|
|
||||||
def get_errorplotdata(self):
|
def get_errorplotdata(self) -> list[numpy.ndarray]:
|
||||||
k=self.get_xdata()
|
k=self.get_xdata()
|
||||||
v=numpy.array([self.data[key].mean() for key in k], dtype="float64")
|
v=numpy.array([self.data[key].mean() for key in k], dtype="float64")
|
||||||
e=numpy.array([self.data[key].mean_error() for key in k], dtype="float64")
|
e=numpy.array([self.data[key].mean_error() for key in k], dtype="float64")
|
||||||
return [k,v,e]
|
return [k,v,e]
|
||||||
|
|
||||||
def get_lineplotdata(self):
|
def get_lineplotdata(self) -> list[numpy.ndarray]:
|
||||||
k=self.get_xdata()
|
k=self.get_xdata()
|
||||||
v=numpy.array(self.y, dtype="float64")
|
v=numpy.array(self.y, dtype="float64")
|
||||||
return [k, v]
|
return [k, v]
|
||||||
|
|
||||||
def uses_statistics(self):
|
def uses_statistics(self) -> bool:
|
||||||
"""
|
"""
|
||||||
drawable interface method returns True
|
drawable interface method returns True
|
||||||
"""
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def write_to_csv(self,destination=sys.stdout, delimiter=" "):
|
def write_to_csv(self,destination: str | IO[str] = sys.stdout, delimiter: str = " ") -> None:
|
||||||
"""
|
"""
|
||||||
writes the data to a file or to sys.stdout
|
writes the data to a file or to sys.stdout
|
||||||
destination can be a file or a filename
|
destination can be a file or a filename
|
||||||
@@ -211,7 +217,7 @@ class MeasurementResult(Drawable.Drawable, collections.UserDict):
|
|||||||
else:
|
else:
|
||||||
self._write_to_csv_dest(destination, delimiter)
|
self._write_to_csv_dest(destination, delimiter)
|
||||||
|
|
||||||
def _write_to_csv_dest(self, dest, delimiter):
|
def _write_to_csv_dest(self, dest: IO[str], delimiter: str) -> None:
|
||||||
dest.write("# quantity:"+str(self.quantity_name)+"\n")
|
dest.write("# quantity:"+str(self.quantity_name)+"\n")
|
||||||
dest.write("# x y ysigma n\n")
|
dest.write("# x y ysigma n\n")
|
||||||
for x in self.get_xdata():
|
for x in self.get_xdata():
|
||||||
@@ -228,7 +234,7 @@ class MeasurementResult(Drawable.Drawable, collections.UserDict):
|
|||||||
y.n))
|
y.n))
|
||||||
|
|
||||||
|
|
||||||
def write_to_hdf(self, hdffile, where, name, title, complib=None, complevel=None):
|
def write_to_hdf(self, hdffile: tables.File, where: str, name: str, title: str, complib: str | None = None, complevel: int | None = None) -> None:
|
||||||
h5_table_format= {
|
h5_table_format= {
|
||||||
"x" : tables.Float32Col(),
|
"x" : tables.Float32Col(),
|
||||||
"y" : tables.Float32Col(),
|
"y" : tables.Float32Col(),
|
||||||
@@ -271,7 +277,7 @@ class MeasurementResult(Drawable.Drawable, collections.UserDict):
|
|||||||
mr_table.flush()
|
mr_table.flush()
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
def read_from_hdf(hdf_node):
|
def read_from_hdf(hdf_node: object) -> "MeasurementResult | None":
|
||||||
"""
|
"""
|
||||||
reads a MeasurementResult object from the hdf_node
|
reads a MeasurementResult object from the hdf_node
|
||||||
or None if the node is not suitable
|
or None if the node is not suitable
|
||||||
|
|||||||
Reference in new issue
Block a user