Public Access
script for release added, pyrefly checks are fixed for now
This commit is contained in:
1 parent
428af30c30
commit
dda8ae7df0
6 files changed
+179
-89
No files matched your search
@@ -22,13 +22,25 @@ jobs:
|
|||||||
- name: Install Node.js and git
|
- name: Install Node.js and git
|
||||||
run: |
|
run: |
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get -y install nodejs git lsb-release jq
|
apt-get -y install nodejs git lsb-release jq devscripts
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
github-server-url: https://gitea.pkm.physik.tu-darmstadt.de
|
github-server-url: https://gitea.pkm.physik.tu-darmstadt.de
|
||||||
|
|
||||||
|
- name: Set package version from release tag
|
||||||
|
if: startsWith(gitea.ref, 'refs/tags/v')
|
||||||
|
env:
|
||||||
|
TAG: ${{ gitea.ref_name }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
VERSION="${TAG#v}"
|
||||||
|
if [ "$(dpkg-parsechangelog --show-field Version)" != "$VERSION" ]; then
|
||||||
|
dch --newversion "$VERSION" --distribution stable --force-distribution --noquery "Release $TAG"
|
||||||
|
fi
|
||||||
|
sed -i -E "s/^(__version__ = \")([^\"]+)(\")$/\1${VERSION}\3/" src/damaris/__init__.py
|
||||||
|
|
||||||
- name: Install build dependencies
|
- name: Install build dependencies
|
||||||
run: bash requirements.debian
|
run: bash requirements.debian
|
||||||
|
|
||||||
|
|||||||
Executable
+65
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 VERSION (for example: 0.30)"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ ${1:-} == "-h" || ${1:-} == "--help" ]]; then
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $# -ne 1 || ! $1 =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]]; then
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
version=$1
|
||||||
|
tag="v$version"
|
||||||
|
root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||||
|
cd "$root"
|
||||||
|
|
||||||
|
if [[ -n $(git status --porcelain) ]]; then
|
||||||
|
echo "Release requires a clean working tree." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then
|
||||||
|
echo "Tag $tag already exists." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
command -v dch >/dev/null || { echo "Install devscripts to use dch." >&2; exit 1; }
|
||||||
|
command -v dpkg-parsechangelog >/dev/null || { echo "Install dpkg-dev to use dpkg-parsechangelog." >&2; exit 1; }
|
||||||
|
|
||||||
|
current_version=$(dpkg-parsechangelog --show-field Version)
|
||||||
|
if [[ $current_version == "$version" ]]; then
|
||||||
|
echo "debian/changelog already has version $version." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
dch --newversion "$version" --distribution stable --force-distribution
|
||||||
|
sed -i "s/^__version__ = .*/__version__ = \"$version\"/" src/damaris/__init__.py
|
||||||
|
|
||||||
|
if [[ $(dpkg-parsechangelog --show-field Version) != "$version" ]] ||
|
||||||
|
[[ $(sed -n 's/^__version__ = "\([^"]*\)"$/\1/p' src/damaris/__init__.py) != "$version" ]]; then
|
||||||
|
echo "Release version did not update consistently; inspect the changelog and package version." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "About to commit the version bump and create tag $tag."
|
||||||
|
read -r -p "Continue? [y/N] " answer
|
||||||
|
if [[ ! $answer =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Release preparation stopped; version and changelog edits were kept."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git add debian/changelog src/damaris/__init__.py
|
||||||
|
git commit -m "Release $tag"
|
||||||
|
git tag -a "$tag" -m "Release $tag"
|
||||||
|
|
||||||
|
echo "Created local release tag $tag. Push the commit and tag to start the package workflow."
|
||||||
|
echo " git push origin HEAD"
|
||||||
|
echo " git push origin $tag"
|
||||||
@@ -12,13 +12,14 @@ import numpy
|
|||||||
import sys
|
import sys
|
||||||
import datetime
|
import datetime
|
||||||
import tables
|
import tables
|
||||||
from typing import IO
|
from typing import IO, Any, Literal, cast
|
||||||
from scipy.signal import filtfilt, remez
|
from scipy.signal import filtfilt, remez
|
||||||
|
|
||||||
_XArray = numpy.ndarray | list
|
_XArray = numpy.ndarray | list
|
||||||
_YChannels = list[numpy.ndarray]
|
_YChannels = list[numpy.ndarray]
|
||||||
_IndexList = list[tuple[int, int]]
|
_IndexList = list[tuple[int, int]]
|
||||||
_Description = dict[str, str]
|
_Description = dict[str, str]
|
||||||
|
_CompressionLibrary = Literal["blosc", "blosc2", "bzip2", "lzo", "zlib"]
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# #
|
# #
|
||||||
# Name: Class ADC_Result #
|
# Name: Class ADC_Result #
|
||||||
@@ -377,13 +378,14 @@ class ADC_Result(MeasurementData, Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
|
|
||||||
def write_to_hdf(self, hdffile: tables.File, where: str, name: str, title: str, complib: str | None = None, complevel: int | None = None) -> 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"
|
attrs = cast(Any, accu_group._v_attrs)
|
||||||
|
attrs.damaris_type="ADC_Result"
|
||||||
if self.contains_data():
|
if self.contains_data():
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
# save time stamps
|
# save time stamps
|
||||||
if "job_date" in dir(self) and self.job_date is not None:
|
if "job_date" in dir(self) and self.job_date is not None:
|
||||||
accu_group._v_attrs.time="%04d%02d%02d %02d:%02d:%02d.%03d"%(self.job_date.year,
|
attrs.time="%04d%02d%02d %02d:%02d:%02d.%03d"%(self.job_date.year,
|
||||||
self.job_date.month,
|
self.job_date.month,
|
||||||
self.job_date.day,
|
self.job_date.day,
|
||||||
self.job_date.hour,
|
self.job_date.hour,
|
||||||
@@ -393,15 +395,17 @@ class ADC_Result(MeasurementData, Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
|
|
||||||
if self.description is not None:
|
if self.description is not None:
|
||||||
for (key,value) in self.description.items():
|
for (key,value) in self.description.items():
|
||||||
accu_group._v_attrs.__setattr__("description_"+key,str(value))
|
attrs.__setattr__("description_"+key,str(value))
|
||||||
accu_group._v_attrs.__setattr__("sampling_rate",self.sampling_rate)
|
attrs.__setattr__("sampling_rate",self.sampling_rate)
|
||||||
|
|
||||||
# save interval information
|
# save interval information
|
||||||
filter=None
|
filter=None
|
||||||
if complib is not None:
|
if complib is not None:
|
||||||
if complevel is None:
|
if complevel is None:
|
||||||
complevel=9
|
complevel=9
|
||||||
filter=tables.Filters(complevel=complevel,complib=complib,shuffle=1)
|
filter=tables.Filters(complevel=complevel,
|
||||||
|
complib=cast(_CompressionLibrary, complib),
|
||||||
|
shuffle=True)
|
||||||
|
|
||||||
index_table=hdffile.create_table(where=accu_group,
|
index_table=hdffile.create_table(where=accu_group,
|
||||||
name="indices",
|
name="indices",
|
||||||
@@ -414,7 +418,7 @@ class ADC_Result(MeasurementData, Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
expectedrows=len(self.index))
|
expectedrows=len(self.index))
|
||||||
index_table.flavor="numpy"
|
index_table.flavor="numpy"
|
||||||
# save channel data
|
# save channel data
|
||||||
new_row=index_table.row
|
new_row = cast(Any, index_table.row)
|
||||||
for i in range(len(self.index)):
|
for i in range(len(self.index)):
|
||||||
new_row["start"]=self.index[i][0]
|
new_row["start"]=self.index[i][0]
|
||||||
new_row["dwelltime"]=1.0/self.sampling_rate
|
new_row["dwelltime"]=1.0/self.sampling_rate
|
||||||
@@ -436,27 +440,14 @@ class ADC_Result(MeasurementData, Resultable, Drawable, DamarisFFT, Signalpath):
|
|||||||
# save data
|
# save data
|
||||||
time_slice_data=None
|
time_slice_data=None
|
||||||
if filter is not None:
|
if filter is not None:
|
||||||
chunkshape = numpy.shape(timedata)
|
chunkshape = (min(timedata.shape[0], 1024 * 8), timedata.shape[1])
|
||||||
if len(chunkshape) <= 1:
|
time_slice_data=hdffile.create_carray(accu_group,
|
||||||
chunkshape = (min(chunkshape[0],1024*8),)
|
name="adc_data",
|
||||||
else:
|
shape=timedata.shape,
|
||||||
chunkshape = (min(chunkshape[0],1024*8), chunkshape[1])
|
chunkshape=chunkshape,
|
||||||
if tables.__version__[0]=="1":
|
atom=tables.Int16Atom(),
|
||||||
time_slice_data=hdffile.create_carray(accu_group,
|
filters=filter,
|
||||||
name="adc_data",
|
title="adc data")
|
||||||
shape=timedata.shape,
|
|
||||||
atom=tables.Int16Atom(shape=chunkshape,
|
|
||||||
flavor="numpy"),
|
|
||||||
filters=filter,
|
|
||||||
title="adc data")
|
|
||||||
else:
|
|
||||||
time_slice_data=hdffile.create_carray(accu_group,
|
|
||||||
name="adc_data",
|
|
||||||
shape=timedata.shape,
|
|
||||||
chunkshape=chunkshape,
|
|
||||||
atom=tables.Int16Atom(),
|
|
||||||
filters=filter,
|
|
||||||
title="adc data")
|
|
||||||
time_slice_data[:]=timedata
|
time_slice_data[:]=timedata
|
||||||
else:
|
else:
|
||||||
time_slice_data=hdffile.create_array(accu_group,
|
time_slice_data=hdffile.create_array(accu_group,
|
||||||
@@ -684,7 +675,8 @@ def read_from_hdf(hdf_node: object) -> ADC_Result | None:
|
|||||||
if not isinstance(hdf_node, tables.Group):
|
if not isinstance(hdf_node, tables.Group):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if hdf_node._v_attrs.damaris_type!="ADC_Result":
|
attrs = cast(Any, hdf_node._v_attrs)
|
||||||
|
if attrs.damaris_type!="ADC_Result":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not (hdf_node.__contains__("indices") and hdf_node.__contains__("adc_data")):
|
if not (hdf_node.__contains__("indices") and hdf_node.__contains__("adc_data")):
|
||||||
@@ -696,12 +688,12 @@ def read_from_hdf(hdf_node: object) -> ADC_Result | None:
|
|||||||
adc.set_title(hdf_node._v_title)
|
adc.set_title(hdf_node._v_title)
|
||||||
# populate description dictionary
|
# populate description dictionary
|
||||||
adc.description={}
|
adc.description={}
|
||||||
for attrname in hdf_node._v_attrs._v_attrnamesuser:
|
for attrname in attrs._v_attrnamesuser:
|
||||||
if attrname.startswith("description_"):
|
if attrname.startswith("description_"):
|
||||||
adc.description[attrname[12:]]=hdf_node._v_attrs.__getattr__(attrname)
|
adc.description[attrname[12:]]=attrs.__getattr__(attrname)
|
||||||
|
|
||||||
if "time" in dir(hdf_node._v_attrs):
|
if "time" in dir(attrs):
|
||||||
timestring=hdf_node._v_attrs.__getattr__("time")
|
timestring=attrs.__getattr__("time")
|
||||||
adc.job_date=datetime.datetime(int(timestring[:4]), # year
|
adc.job_date=datetime.datetime(int(timestring[:4]), # year
|
||||||
int(timestring[4:6]), # month
|
int(timestring[4:6]), # month
|
||||||
int(timestring[6:8]), # day
|
int(timestring[6:8]), # day
|
||||||
|
|||||||
@@ -26,12 +26,13 @@ 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
|
from typing import IO, Any, Literal, cast
|
||||||
|
|
||||||
_XArray = numpy.ndarray | list
|
_XArray = numpy.ndarray | list
|
||||||
_YChannels = list[numpy.ndarray]
|
_YChannels = list[numpy.ndarray]
|
||||||
_IndexList = list[tuple[int, int]]
|
_IndexList = list[tuple[int, int]]
|
||||||
_Description = dict[str, str]
|
_Description = dict[str, str]
|
||||||
|
_CompressionLibrary = Literal["blosc", "blosc2", "bzip2", "lzo", "zlib"]
|
||||||
|
|
||||||
|
|
||||||
class Accumulation(MeasurementData, Errorable, Drawable, DamarisFFT, Signalpath):
|
class Accumulation(MeasurementData, Errorable, Drawable, DamarisFFT, Signalpath):
|
||||||
@@ -307,7 +308,7 @@ class Accumulation(MeasurementData, Errorable, Drawable, DamarisFFT, Signalpath)
|
|||||||
for i in range(len(xdata)):
|
for i in range(len(xdata)):
|
||||||
dest.write("%e"%xdata[i])
|
dest.write("%e"%xdata[i])
|
||||||
for j in range(ch_no):
|
for j in range(ch_no):
|
||||||
if self.use_error:
|
if self.use_error and yerr is not None:
|
||||||
dest.write("%s%e%s%e"%(delimiter, ydata[j][i], delimiter, yerr[j][i]))
|
dest.write("%s%e%s%e"%(delimiter, ydata[j][i], delimiter, yerr[j][i]))
|
||||||
else:
|
else:
|
||||||
dest.write("%s%e"%(delimiter,ydata[j][i]))
|
dest.write("%s%e"%(delimiter,ydata[j][i]))
|
||||||
@@ -358,7 +359,7 @@ class Accumulation(MeasurementData, 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: int = 1,\
|
def write_to_tecmag(self, destination: str | IO[bytes] = sys.stdout.buffer, nrecords: int = 1,\
|
||||||
frequency: float = 100.,\
|
frequency: float = 100.,\
|
||||||
last_delay: float = 1.,\
|
last_delay: float = 1.,\
|
||||||
receiver_phase: float = 0.,\
|
receiver_phase: float = 0.,\
|
||||||
@@ -388,8 +389,8 @@ class Accumulation(MeasurementData, Errorable, Drawable, DamarisFFT, Signalpath)
|
|||||||
else:
|
else:
|
||||||
record = (self.job_id/self.n)%nrecords + 1
|
record = (self.job_id/self.n)%nrecords + 1
|
||||||
|
|
||||||
the_destination=destination
|
the_destination: IO[bytes] | None = None
|
||||||
if type(destination) in (str,):
|
if isinstance(destination, str):
|
||||||
if record == 1 and os.path.exists(destination):
|
if record == 1 and os.path.exists(destination):
|
||||||
os.rename(destination, os.path.dirname(destination)+'/~'+os.path.basename(destination))
|
os.rename(destination, os.path.dirname(destination)+'/~'+os.path.basename(destination))
|
||||||
|
|
||||||
@@ -420,7 +421,10 @@ class Accumulation(MeasurementData, Errorable, Drawable, DamarisFFT, Signalpath)
|
|||||||
data = data.flatten()
|
data = data.flatten()
|
||||||
|
|
||||||
if record == 1:
|
if record == 1:
|
||||||
the_destination=open(destination, "wb")
|
if isinstance(destination, str):
|
||||||
|
the_destination = open(destination, "wb")
|
||||||
|
else:
|
||||||
|
the_destination = destination
|
||||||
|
|
||||||
# allocate space for all records in advance:
|
# allocate space for all records in advance:
|
||||||
buff = ctypes.create_string_buffer(1056+data_offset+2068)
|
buff = ctypes.create_string_buffer(1056+data_offset+2068)
|
||||||
@@ -481,20 +485,24 @@ class Accumulation(MeasurementData, Errorable, Drawable, DamarisFFT, Signalpath)
|
|||||||
struct.pack_into('4s', buff, 1056+data_offset+2060, 'PSEQ') # 'PSEQ' tag 658476
|
struct.pack_into('4s', buff, 1056+data_offset+2060, 'PSEQ') # 'PSEQ' tag 658476
|
||||||
struct.pack_into('?', buff, 1056+data_offset+2064, False) # BOOLean 658480
|
struct.pack_into('?', buff, 1056+data_offset+2064, False) # BOOLean 658480
|
||||||
|
|
||||||
the_destination.write(buff)
|
the_destination.write(buff.raw)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
the_destination=open(destination, "rb+")
|
if isinstance(destination, str):
|
||||||
|
the_destination = open(destination, "rb+")
|
||||||
|
else:
|
||||||
|
the_destination = destination
|
||||||
buff = ctypes.create_string_buffer(4*2*npts[0])
|
buff = ctypes.create_string_buffer(4*2*npts[0])
|
||||||
struct.pack_into('%sf' % (2*npts[0]), buff, 0, *data)
|
struct.pack_into('%sf' % (2*npts[0]), buff, 0, *data)
|
||||||
|
|
||||||
the_destination.seek(1056+4*2*npts[0]*(record-1))
|
the_destination.seek(1056+4*2*npts[0]*(record-1))
|
||||||
the_destination.write(buff)
|
the_destination.write(buff.raw)
|
||||||
|
|
||||||
the_destination = None
|
|
||||||
ydata=None
|
ydata=None
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
if isinstance(destination, str) and the_destination is not None:
|
||||||
|
the_destination.close()
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
@@ -518,25 +526,28 @@ class Accumulation(MeasurementData, Errorable, Drawable, DamarisFFT, Signalpath)
|
|||||||
:param complevel: compression level.
|
:param complevel: compression level.
|
||||||
"""
|
"""
|
||||||
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="Accumulation"
|
attrs = cast(Any, accu_group._v_attrs)
|
||||||
|
attrs.damaris_type="Accumulation"
|
||||||
if self.contains_data():
|
if self.contains_data():
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
# save time stamps
|
# save time stamps
|
||||||
if self.time_period is not None and len(self.time_period)>0:
|
if self.time_period is not None and len(self.time_period)>0:
|
||||||
accu_group._v_attrs.earliest_time = self.time_period[0].isoformat(sep=' ', timespec='milliseconds')
|
attrs.earliest_time = self.time_period[0].isoformat(sep=' ', timespec='milliseconds')
|
||||||
accu_group._v_attrs.oldest_time = self.time_period[1].isoformat(sep=' ', timespec='milliseconds')
|
attrs.oldest_time = self.time_period[1].isoformat(sep=' ', timespec='milliseconds')
|
||||||
if self.common_descriptions is not None:
|
if self.common_descriptions is not None:
|
||||||
for (key,value) in self.common_descriptions.items():
|
for (key,value) in self.common_descriptions.items():
|
||||||
accu_group._v_attrs.__setattr__("description_"+key,str(value))
|
attrs.__setattr__("description_"+key,str(value))
|
||||||
accu_group._v_attrs.__setattr__("sampling_rate",self.sampling_rate)
|
attrs.__setattr__("sampling_rate",self.sampling_rate)
|
||||||
|
|
||||||
|
|
||||||
filter=None
|
filter=None
|
||||||
if complib is not None:
|
if complib is not None:
|
||||||
if complevel is None:
|
if complevel is None:
|
||||||
complevel=3
|
complevel=3
|
||||||
filter=tables.Filters(complevel=complevel,complib=complib,shuffle=1)
|
filter=tables.Filters(complevel=complevel,
|
||||||
|
complib=cast(_CompressionLibrary, complib),
|
||||||
|
shuffle=True)
|
||||||
|
|
||||||
# save interval information
|
# save interval information
|
||||||
# start save index_table
|
# start save index_table
|
||||||
@@ -553,7 +564,7 @@ class Accumulation(MeasurementData, Errorable, Drawable, DamarisFFT, Signalpath)
|
|||||||
expectedrows=len(self.index))
|
expectedrows=len(self.index))
|
||||||
index_table.flavor="numpy"
|
index_table.flavor="numpy"
|
||||||
# save interval data
|
# save interval data
|
||||||
new_row=index_table.row
|
new_row = cast(Any, index_table.row)
|
||||||
for i in range(len(self.index)):
|
for i in range(len(self.index)):
|
||||||
new_row["start"]=self.index[i][0]
|
new_row["start"]=self.index[i][0]
|
||||||
new_row["dwelltime"]=1.0/self.sampling_rate
|
new_row["dwelltime"]=1.0/self.sampling_rate
|
||||||
@@ -574,7 +585,7 @@ class Accumulation(MeasurementData, Errorable, Drawable, DamarisFFT, Signalpath)
|
|||||||
title="job_ids used for accumulation",
|
title="job_ids used for accumulation",
|
||||||
filters=filter,
|
filters=filter,
|
||||||
expectedrows=len(self.job_ids))
|
expectedrows=len(self.job_ids))
|
||||||
new_row=jobid_table.row
|
new_row = cast(Any, jobid_table.row)
|
||||||
for i,job_id in enumerate(self.job_ids):
|
for i,job_id in enumerate(self.job_ids):
|
||||||
new_row["job_date"] = self.job_ids[job_id].isoformat(timespec='milliseconds')
|
new_row["job_date"] = self.job_ids[job_id].isoformat(timespec='milliseconds')
|
||||||
new_row["job_id"]=job_id
|
new_row["job_id"]=job_id
|
||||||
@@ -595,27 +606,14 @@ class Accumulation(MeasurementData, Errorable, Drawable, DamarisFFT, Signalpath)
|
|||||||
# save data
|
# save data
|
||||||
time_slice_data=None
|
time_slice_data=None
|
||||||
if filter is not None:
|
if filter is not None:
|
||||||
chunkshape=timedata.shape
|
chunkshape = (min(timedata.shape[0], 1024 * 8), timedata.shape[1])
|
||||||
if len(chunkshape) <= 1:
|
time_slice_data=hdffile.create_carray(accu_group,
|
||||||
chunkshape = (min(chunkshape[0],1024*8),)
|
name="accu_data",
|
||||||
else:
|
shape=timedata.shape,
|
||||||
chunkshape = (min(chunkshape[0],1024*8), chunkshape[1])
|
chunkshape=chunkshape,
|
||||||
if tables.__version__[0]=="1":
|
atom=tables.Float32Atom(),
|
||||||
time_slice_data=hdffile.create_carray(accu_group,
|
filters=filter,
|
||||||
name="accu_data",
|
title="accu data")
|
||||||
shape=timedata.shape,
|
|
||||||
atom=tables.Float32Atom(shape=chunkshape,
|
|
||||||
flavor="numpy"),
|
|
||||||
filters=filter,
|
|
||||||
title="accu data")
|
|
||||||
else:
|
|
||||||
time_slice_data=hdffile.create_carray(accu_group,
|
|
||||||
name="accu_data",
|
|
||||||
shape=timedata.shape,
|
|
||||||
chunkshape=chunkshape,
|
|
||||||
atom=tables.Float32Atom(),
|
|
||||||
filters=filter,
|
|
||||||
title="accu data")
|
|
||||||
|
|
||||||
time_slice_data[:]=timedata
|
time_slice_data[:]=timedata
|
||||||
else:
|
else:
|
||||||
@@ -1111,7 +1109,8 @@ class Accumulation(MeasurementData, Errorable, Drawable, DamarisFFT, Signalpath)
|
|||||||
self.set_title(self.__title_pattern % self.n)
|
self.set_title(self.__title_pattern % self.n)
|
||||||
if hasattr(other, "is_clipped"):
|
if hasattr(other, "is_clipped"):
|
||||||
self.is_clipped = other.is_clipped
|
self.is_clipped = other.is_clipped
|
||||||
self.common_descriptions=other.common_descriptions.copy()
|
self.common_descriptions = (other.common_descriptions.copy()
|
||||||
|
if other.common_descriptions is not None else None)
|
||||||
self.time_period=other.time_period[:] if other.time_period is not None else None
|
self.time_period=other.time_period[:] if other.time_period is not None else None
|
||||||
self.job_id = other.job_id # added by Oleg Petrov
|
self.job_id = other.job_id # added by Oleg Petrov
|
||||||
self.job_ids.update(other.job_ids)
|
self.job_ids.update(other.job_ids)
|
||||||
@@ -1213,7 +1212,8 @@ def read_from_hdf(hdf_node: object) -> "Accumulation | None":
|
|||||||
if not isinstance(hdf_node, tables.Group):
|
if not isinstance(hdf_node, tables.Group):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if hdf_node._v_attrs.damaris_type!="Accumulation":
|
attrs = cast(Any, hdf_node._v_attrs)
|
||||||
|
if attrs.damaris_type!="Accumulation":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not (hdf_node.__contains__("indices") and hdf_node.__contains__("accu_data")):
|
if not (hdf_node.__contains__("indices") and hdf_node.__contains__("accu_data")):
|
||||||
@@ -1224,13 +1224,13 @@ def read_from_hdf(hdf_node: object) -> "Accumulation | None":
|
|||||||
|
|
||||||
# populate description dictionary
|
# populate description dictionary
|
||||||
accu.common_descriptions={}
|
accu.common_descriptions={}
|
||||||
for attrname in hdf_node._v_attrs._v_attrnamesuser:
|
for attrname in attrs._v_attrnamesuser:
|
||||||
if attrname.startswith("description_"):
|
if attrname.startswith("description_"):
|
||||||
accu.common_descriptions[attrname[12:]]=hdf_node._v_attrs.__getattr__(attrname)
|
accu.common_descriptions[attrname[12:]]=attrs.__getattr__(attrname)
|
||||||
|
|
||||||
earliest_time=None
|
earliest_time=None
|
||||||
if "earliest_time" in dir(hdf_node._v_attrs):
|
if "earliest_time" in dir(attrs):
|
||||||
timestring=hdf_node._v_attrs.__getattr__("earliest_time")
|
timestring=attrs.__getattr__("earliest_time")
|
||||||
# Handle both formats: "20260705 19:13:59.162" and "2026-07-05 19:13:59.162"
|
# Handle both formats: "20260705 19:13:59.162" and "2026-07-05 19:13:59.162"
|
||||||
if '-' in timestring:
|
if '-' in timestring:
|
||||||
# New format: "2026-07-05 19:13:59.162"
|
# New format: "2026-07-05 19:13:59.162"
|
||||||
@@ -1261,8 +1261,8 @@ def read_from_hdf(hdf_node: object) -> "Accumulation | None":
|
|||||||
)
|
)
|
||||||
|
|
||||||
oldest_time=None
|
oldest_time=None
|
||||||
if "oldest_time" in dir(hdf_node._v_attrs):
|
if "oldest_time" in dir(attrs):
|
||||||
timestring=hdf_node._v_attrs.__getattr__("oldest_time")
|
timestring=attrs.__getattr__("oldest_time")
|
||||||
# Handle both formats: "20260705 19:13:59.162" and "2026-07-05 19:13:59.162"
|
# Handle both formats: "20260705 19:13:59.162" and "2026-07-05 19:13:59.162"
|
||||||
if '-' in timestring:
|
if '-' in timestring:
|
||||||
# New format: "2026-07-05 19:13:59.162"
|
# New format: "2026-07-05 19:13:59.162"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import sys
|
|||||||
import tables
|
import tables
|
||||||
import numpy
|
import numpy
|
||||||
import collections
|
import collections
|
||||||
from typing import IO
|
from typing import IO, Any, Literal, cast
|
||||||
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
|
||||||
@@ -31,7 +31,10 @@ class AccumulatedValue:
|
|||||||
self.y2=self.y**2
|
self.y2=self.y**2
|
||||||
self.n=1
|
self.n=1
|
||||||
elif mean_err is None:
|
elif mean_err is None:
|
||||||
self.n=max(1, int(n))
|
if n is None:
|
||||||
|
self.n=1
|
||||||
|
else:
|
||||||
|
self.n=max(1, n)
|
||||||
self.y=float(mean)*self.n
|
self.y=float(mean)*self.n
|
||||||
self.y2=(float(mean)**2)*self.n
|
self.y2=(float(mean)**2)*self.n
|
||||||
elif n is None:
|
elif n is None:
|
||||||
@@ -240,7 +243,9 @@ class MeasurementResult(Drawable.Drawable, collections.UserDict):
|
|||||||
if complib is not None:
|
if complib is not None:
|
||||||
if complevel is None:
|
if complevel is None:
|
||||||
complevel=9
|
complevel=9
|
||||||
filter=tables.Filters(complevel=complevel,complib=complib,shuffle=1)
|
filter=tables.Filters(complevel=complevel,
|
||||||
|
complib=cast(Literal["blosc", "blosc2", "bzip2", "lzo", "zlib"], complib),
|
||||||
|
shuffle=True)
|
||||||
|
|
||||||
mr_table=hdffile.create_table(where=where,name=name,
|
mr_table=hdffile.create_table(where=where,name=name,
|
||||||
description=h5_table_format,
|
description=h5_table_format,
|
||||||
@@ -248,11 +253,12 @@ class MeasurementResult(Drawable.Drawable, collections.UserDict):
|
|||||||
filters=filter,
|
filters=filter,
|
||||||
expectedrows=len(self))
|
expectedrows=len(self))
|
||||||
mr_table.flavor="numpy"
|
mr_table.flavor="numpy"
|
||||||
mr_table.attrs.damaris_type="MeasurementResult"
|
attrs = cast(Any, mr_table.attrs)
|
||||||
|
attrs.damaris_type="MeasurementResult"
|
||||||
self.lock.acquire()
|
self.lock.acquire()
|
||||||
try:
|
try:
|
||||||
mr_table.attrs.quantity_name=self.quantity_name
|
attrs.quantity_name=self.quantity_name
|
||||||
row=mr_table.row
|
row = cast(Any, mr_table.row)
|
||||||
xdata=self.get_xdata()
|
xdata=self.get_xdata()
|
||||||
if xdata.shape[0]!=0:
|
if xdata.shape[0]!=0:
|
||||||
for x in xdata:
|
for x in xdata:
|
||||||
@@ -276,10 +282,11 @@ def read_from_hdf(hdf_node: object) -> "MeasurementResult | None":
|
|||||||
if not isinstance(hdf_node, tables.Table):
|
if not isinstance(hdf_node, tables.Table):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if hdf_node._v_attrs.damaris_type!="MeasurementResult":
|
attrs = cast(Any, hdf_node._v_attrs)
|
||||||
|
if attrs.damaris_type!="MeasurementResult":
|
||||||
return None
|
return None
|
||||||
|
|
||||||
mr=MeasurementResult(hdf_node._v_attrs.quantity_name)
|
mr=MeasurementResult(attrs.quantity_name)
|
||||||
for r in hdf_node.iterrows():
|
for r in hdf_node.iterrows():
|
||||||
mr[r["x"]]=AccumulatedValue(r["y"],r["y_err"],r["n"])
|
mr[r["x"]]=AccumulatedValue(r["y"],r["y_err"],r["n"])
|
||||||
|
|
||||||
|
|||||||
@@ -360,6 +360,20 @@ class TestAccumulation(unittest.TestCase):
|
|||||||
r *= 2
|
r *= 2
|
||||||
np.testing.assert_array_equal(accu.y[0], np.array([10, 20, 30], dtype="float32"))
|
np.testing.assert_array_equal(accu.y[0], np.array([10, 20, 30], dtype="float32"))
|
||||||
|
|
||||||
|
def test_empty_iadd_accumulation_without_common_descriptions(self):
|
||||||
|
"""An accumulation without common descriptions can be copied in-place."""
|
||||||
|
other = Accumulation(x=np.array([0.0, 1.0]),
|
||||||
|
y=[np.array([10.0, 20.0])],
|
||||||
|
n=1,
|
||||||
|
index=[(0, 1)],
|
||||||
|
sampl_freq=1000.0)
|
||||||
|
accu = Accumulation()
|
||||||
|
|
||||||
|
accu += other
|
||||||
|
|
||||||
|
self.assertIsNone(accu.common_descriptions)
|
||||||
|
np.testing.assert_array_equal(accu.y[0], other.y[0])
|
||||||
|
|
||||||
def test_accumulation_plus_accumulation_keeps_both_job_ids(self):
|
def test_accumulation_plus_accumulation_keeps_both_job_ids(self):
|
||||||
"""accu1 + accu2 must keep the provenance of both operands."""
|
"""accu1 + accu2 must keep the provenance of both operands."""
|
||||||
adc1 = self.create_adc_result()
|
adc1 = self.create_adc_result()
|
||||||
|
|||||||
Reference in new issue
Block a user