slsDetectorPackage/pyctbgui/tests/unit/test_npz_writer.py
Dhanya Thattil 5b61ff24bb
Dev/pyctbgui merge (#960)
* added empty c extension

* added rotation to the decoding

* added color map, options and findex

* minor

* move checks to before acquisition

* added pixel map based decoder

* cleanup

* no thread creation for single thread processing

* added rotation and test to compare

* allow high and low water mark for zmq (also buffer size) for fast readouts

* removed roatation during decoding

* added Transpose to image and invert Y False to invert it

* retains the zoomed state after the first image of gui, catch and display exception if no detector connected

* moved start frame to dockable widget, removed extra frame number label, moved current measurement also to dockable widget, hide frame plot entirely when showing patternviewer

* first image dependin on which plot

* remember settings of main window size and position, dockewidget if docked, its size and posisiotn as well, then update it next time the gui is opened

* change in comment

* using c decoder for moench 04 and matterhorn

* catch exception from invalid image from decoder

* clean up

* update row and col when choosing image type, neeeded to show values

* fix for previous PR

* disable resetting colormap values
keep the range selected for every new acquisition

* fix typos + tested on virtual matterhorn

* minor print

* refactored Slow ADCs Tab

* refactored DAC tab

* refactored power supplies

* refactored signals tab

* refactored transceiver tab

* fix typo

* fix typo2

* remove commented code

* delete commented code

* delete commented code

* delete commented signals code

* remove commented code for transceiver tab

* refactor adc tab

* refactor Pattern Tab

* Refactor transceivers tab (PR#5) (#118)

* refactored transceiver tab

* remove commented code for transceiver tab

---------

Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com>

* refactor adc tab (PR#6) (#119)


* refactor adc tab

* refactored Plot and Acquisition Tabs

* fix the regression issue

* restructure project files

* applying singleton and renaming tabs to services

* working install using pip

* applies singleton to tab classes and remove CI erros

* added pyzmq and pillow

* remove the singleton implementation and keep changes

* fix merge errors in mainWindow

* moved misplaced init file

* rename service to tab

* reorganize imports

* iterate over tabs

* reorder tabs

* add slowadc to the list

* saving changes (buggy)
power supply ui not showing in the gui

* split power supply tab

* fixed tests

* add hardcoded values to defines file

* fix error

* separate power supply

* fix errors for powerSuppliesTab

* split dacs

* split slow adcs

* split signals tab

* added tests for bit_utils

* add slowAdc class to defines

* split transceiver ui file

* split adc.ui

* split pattern ui file

* split plot and acquisition ui file

* added basic test for parsing bit names

* removed redundant code in read_alias_file

* fix dacs ui position

* testing for correct exception

* cmd and args at split

* group radio buttons

* fix comments from PR#1

* show legend

* added python version and dev requirements to setup.py

* fix dac issue

* moved _decoder into pkg

* added inplace build

* removed clear

* fixed dependencies

* make tests run without slsdet

* updated name of action

* define colcount

* fixed loading of alias file

* add yapf and ruff

* apply formatting

* fix E and F rules

* add more ruff rules

* change variable name

* squashing gh debugging commits and add pre-commit

* update label values to mv units

* add hook for yapf

* reconfigure yapf precommit hook

* add format and check_format to makefile

* change gh actions

* update readme

* added check_format

* WIP

* added linting in github action

* updated readme]

* add more control for color choice

* remove useless file

* fix un-updated line after refactoring Defines
BIT0_31_MASK is not found in Defines.signals

* visually improve the interface

* fix last commit

* add only selected plots for legend

* add hide legend button

* change hide legend to show legend
checkbox show legend is checked by default

* add support for saving in numpy

* solve conversations

* fix acq index offset

* fix browse button in pattern error

* fix other browse button errors

* finish tests and add usage.md

* remove buffer

* add file,numpy-like interface and tests

* remove useless .npy files

* subscriptible npz files

* remove useless files

* remove repetetive tests

* save changes

* add mode r+, add with support,remove logging

* remove offset of acqIndex between raw and numpy saving

* fix only saving last frame

* save signals of multiple devices

* add comments and move condition for clearer code

* fix bug when vieweing pattern file

* iterate over enabled and plotted plots

* add padestal substraction to transceiver and analog data

* init pedestal frames to detector.frames

* restore old exception

* add pedestal substraction for digital signals

* remove frames spinbox from plotTab

* remove comments and use str instead of Path

* avoid saving all frames

* correct exception and log error's trace

* add gui tests

* add waveform test

* add pedestal test

* refactor by using fixtures

* add tests for moench analog and pattern

* add pytest-qt to dependencies

* add save and load gui parameters

* remove nohup file

* fix old bug IndexError

* save plot type

* a

* handle canceling load, loading matterhorn pedestal for moench

* remove comparing .png files for pattern test

* save plot type

* red error on status bar when shape mismatch for loaded pedestal

* fix makefile and docstrings

* fix PRs conversation

* move code into different function

* fix wrong function names for power supply

* removed old ctbgui

* removed unnecessary files

---------

Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com>
Co-authored-by: Braham Bechir <braham_b@pc11979.psi.ch>
Co-authored-by: Bechir <bechir.braham@psi.ch>
Co-authored-by: Bechir <bechir.brahem420@gmail.com>
2024-09-10 16:00:04 +02:00

195 lines
7.0 KiB
Python

import filecmp
from pathlib import Path
import pytest
from pyctbgui.utils.numpyWriter.npy_writer import NumpyFileManager
import numpy as np
from pyctbgui.utils.numpyWriter.npz_writer import NpzFileWriter
@pytest.mark.parametrize('compressed', [True, False])
def test_incremental_npz(compressed, tmp_path):
arr1 = np.ones((10, 5, 5))
arr2 = np.zeros((10, 5, 5), dtype=np.int32)
arr3 = np.ones((10, 5, 5), dtype=np.float32)
with NpzFileWriter(tmp_path / 'tmp.npz', 'w', compress_file=compressed) as npz:
npz.writeArray('adc', arr1)
npz.writeArray('tx', arr2)
npz.writeArray('signal', arr3)
npzFile = np.load(tmp_path / 'tmp.npz')
assert sorted(npzFile.files) == sorted(('adc', 'tx', 'signal'))
assert np.array_equal(npzFile['adc'], np.ones((10, 5, 5)))
assert np.array_equal(npzFile['tx'], np.zeros((10, 5, 5), dtype=np.int32))
assert np.array_equal(npzFile['signal'], np.ones((10, 5, 5), dtype=np.float32))
if compressed:
np.savez_compressed(tmp_path / 'tmp2.npz', adc=arr1, tx=arr2, signal=arr3)
else:
np.savez(tmp_path / 'tmp2.npz', adc=arr1, tx=arr2, signal=arr3)
assert filecmp.cmp(tmp_path / 'tmp2.npz', tmp_path / 'tmp.npz')
@pytest.mark.parametrize('compressed', [True, False])
def test_zipping_npy_files(compressed, tmp_path):
data = {
'arr1': np.ones((10, 5, 5)),
'arr2': np.zeros((10, 5, 5), dtype=np.int32),
'arr3': np.ones((10, 5, 5), dtype=np.float32)
}
filePaths = [tmp_path / (file + '.npy') for file in data.keys()]
for file in data:
np.save(tmp_path / (file + '.npy'), data[file])
NpzFileWriter.zipNpyFiles(tmp_path / 'file.npz', filePaths, list(data.keys()), compressed=compressed)
npz = np.load(tmp_path / 'file.npz')
assert npz.files == list(data.keys())
for file in data:
assert np.array_equal(npz[file], data[file])
if compressed:
np.savez_compressed(tmp_path / 'numpy.npz', **data)
else:
np.savez(tmp_path / 'numpy.npz', **data)
numpyz = np.load(tmp_path / 'numpy.npz')
for file in data:
assert np.array_equal(numpyz[file], npz[file])
assert npz.files == numpyz.files
# different files :(
# for some reason numpy savez (most likely a trick with zipfile library) doesn't write the time
# of last modification
# assert filecmp.cmp(prefix / 'numpy.npz', prefix / 'file.npz')
@pytest.mark.parametrize('compressed', [True, False])
def test_npy_writer_with_zipfile_in_init(compressed, tmp_path):
npz = NpzFileWriter(tmp_path / 'tmp.npz', 'w', compress_file=compressed)
rng = np.random.default_rng(42)
arr = rng.random((8000, 5, 5))
npz.writeArray('adc', arr)
with npz.file.open('adc.npy', mode='r') as outfile:
npw = NumpyFileManager(outfile)
assert np.array_equal(npw.readFrames(720, 7999), arr[720:7999])
def test_compression(tmp_path):
arr = np.zeros((1000, 5, 5), dtype=np.int32)
with NpzFileWriter(tmp_path / 'tmp.npz', 'w', compress_file=True) as npz:
npz.writeArray('adc', arr)
np.savez(tmp_path / 'tmp2.npz', adc=arr)
assert Path(tmp_path / 'tmp2.npz').stat().st_size > Path(tmp_path / 'tmp.npz').stat().st_size
@pytest.mark.parametrize('compressed', [True, False])
@pytest.mark.parametrize('isPath', [True, False])
@pytest.mark.parametrize('deleteOriginals', [True, False])
def test_delete_files(compressed, isPath, deleteOriginals, tmp_path):
data = {
'arr1': np.ones((10, 5, 5)),
'arr2': np.zeros((10, 5, 5), dtype=np.int32),
'arr3': np.ones((10, 5, 5), dtype=np.float32)
}
filePaths = [tmp_path / (file + '.npy') for file in data.keys()]
for file in data:
np.save(tmp_path / (file + '.npy'), data[file])
path = tmp_path / 'file.npz'
path = str(path) if isPath else path
NpzFileWriter.zipNpyFiles(path,
filePaths,
list(data.keys()),
deleteOriginals=deleteOriginals,
compressed=compressed)
if deleteOriginals:
for file in filePaths:
assert not Path.exists(file)
else:
for file in filePaths:
assert Path.exists(file)
def test_npz_read_frames(tmp_path):
rng = np.random.default_rng(seed=42)
arr1 = rng.random((10, 5, 5))
with NpzFileWriter(tmp_path / 'tmp.npz', 'w') as npz:
npz.writeArray('adc', arr1)
with NpzFileWriter(tmp_path / 'tmp.npz', 'r') as npz:
frames = npz.readFrames('adc', 5, 8)
assert np.array_equal(frames, arr1[5:8])
def test_file_modes(tmp_path):
rng = np.random.default_rng(seed=42)
arr1 = rng.random((10, 5, 5))
# check reopening with mode w
with NpzFileWriter(tmp_path / 'tmp.npz', 'w') as npz:
npz.writeArray('adc', arr1)
with NpzFileWriter(tmp_path / 'tmp.npz', 'w') as npz:
assert npz.file.namelist() == []
# check reopening with mode x
with NpzFileWriter(tmp_path / 'tmp.npz', 'w') as npz:
npz.writeArray('adc', arr1)
with pytest.raises(FileExistsError):
with NpzFileWriter(tmp_path / 'tmp.npz', 'x'):
pass
# check reopening with mode r
with NpzFileWriter(tmp_path / 'tmp.npz', 'r') as npz:
assert np.array_equal(npz.readFrames('adc', 4, 6), arr1[4:6])
with pytest.raises(ValueError, match=r'write\(\) requires mode \'w\'\, \'x\'\, or \'a\''):
npz.writeArray('adc2', arr1)
@pytest.mark.filterwarnings('ignore::UserWarning')
def test_file_mode_a(tmp_path):
rng = np.random.default_rng(seed=42)
arr1 = rng.random((10, 5, 5))
# check reopening with mode a
with NpzFileWriter(tmp_path / 'tmp.npz', 'w') as npz:
npz.writeArray('adc', arr1)
with NpzFileWriter(tmp_path / 'tmp.npz', 'a') as npz:
npz.writeArray('adc2', arr1)
npz.writeArray('adc', arr1)
@pytest.mark.parametrize('compressed', [True, False])
def test_get_item(compressed, tmp_path):
rng = np.random.default_rng(seed=42)
arr1 = rng.random((10, 5, 5))
arr2 = rng.random((3, 2, 2))
# check reopening with mode a
npz = NpzFileWriter(tmp_path / 'tmp.npz', 'w', compress_file=compressed)
npz.writeArray('adc1', arr1)
npz.writeArray('adc2', arr2)
npz.writeArray('adc3', arr1)
assert np.array_equal(npz['adc1'].read(3), arr1[:3])
assert np.array_equal(npz['adc2'].read(1), arr2[:1])
assert np.array_equal(npz['adc2'].read(1), arr2[1:2])
assert np.array_equal(npz['adc2'].read(1), arr2[2:3])
assert np.array_equal(npz['adc1'].read(3), arr1[3:6])
assert np.array_equal(npz['adc1'].read(3), arr1[6:9])
@pytest.mark.parametrize('compressed', [True, False])
def test_namelist(compressed, tmp_path):
rng = np.random.default_rng(seed=42)
arr1 = rng.random((10, 5, 5))
arr2 = rng.random((3, 2, 2))
# check reopening with mode a
npz = NpzFileWriter(tmp_path / 'tmp.npz', 'w', compress_file=compressed)
npz.writeArray('adc1', arr1)
npz.writeArray('adc2', arr2)
npz.writeArray('adc3', arr1)
assert npz.namelist() == ['adc1', 'adc2', 'adc3']