Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
183 commits
Select commit Hold shift + click to select a range
afc8e97
Create spectrometer_telecommunicator class
Oli-Jones475 Jun 12, 2026
81a2347
Add query methods to SpecTel class
Oli-Jones475 Jun 12, 2026
9e48ada
Add basic interaction methods
Oli-Jones475 Jun 12, 2026
412bd41
Add scan reading methods to SpecTel class
Oli-Jones475 Jun 12, 2026
57a2ef0
Change bind call to connect
Oli-Jones475 Jun 12, 2026
5b6eda6
Clear connection message from socket
Oli-Jones475 Jun 12, 2026
dfad9fb
Check for ack and remove trailing text on response
Oli-Jones475 Jun 12, 2026
8531c1e
Create a method to extract response body
Oli-Jones475 Jun 12, 2026
4a6f1a8
Fix small typo in byte delimeter
Oli-Jones475 Jun 12, 2026
887d5c0
Use += instead of join for appending bytes
Oli-Jones475 Jun 12, 2026
ca3ae71
Add fastcs dependency
Oli-Jones475 Jun 12, 2026
086b045
Make controller class for flame
Oli-Jones475 Jun 12, 2026
fa95e3a
Launch fastcs IOC from main
Oli-Jones475 Jun 12, 2026
87fabdc
Set integration time properly
Oli-Jones475 Jun 12, 2026
3761e10
Create spec tel object in controller
Oli-Jones475 Jun 12, 2026
9232d05
Override controller connect method
Oli-Jones475 Jun 12, 2026
9a5c9dd
Add scan data attribute
Oli-Jones475 Jun 12, 2026
fa158ba
Fix bug in set_integration_time method
Oli-Jones475 Jun 15, 2026
bcab506
Add scan trigger
Oli-Jones475 Jun 15, 2026
9317abc
Move spec_tel_obj from ref to IO
Oli-Jones475 Jun 15, 2026
ac80458
Fix raw response delimeter bug
Oli-Jones475 Jun 15, 2026
ad7554c
Change scan trigger attribute to command
Oli-Jones475 Jun 15, 2026
1367da8
Add attribute for acquisition period
Oli-Jones475 Jun 22, 2026
2dce362
Add attribute for total images
Oli-Jones475 Jun 22, 2026
d768d34
Add acquire data command
Oli-Jones475 Jun 22, 2026
9189da7
Sync scans properly
Oli-Jones475 Jun 22, 2026
9f26386
Sync scans properly
Oli-Jones475 Jun 23, 2026
f9cbf66
Extend default acquisition period
Oli-Jones475 Jun 23, 2026
5170b1d
Fix bug in waiting schedule
Oli-Jones475 Jun 23, 2026
067683b
Write scan data to a text file
Oli-Jones475 Jun 23, 2026
193d309
Added screen generation
Oli-Jones475 Jun 24, 2026
92d2467
Fix PV RBV not matching
Oli-Jones475 Jun 24, 2026
42163cd
Add docstrings to spectrometer_telecommunicator
Oli-Jones475 Jun 24, 2026
b7881ad
Add exceptions to connect method
Oli-Jones475 Jun 24, 2026
6e27b27
Raise exception when socket object does not exist
Oli-Jones475 Jun 24, 2026
a5b33a9
Configure FastCS logging
Oli-Jones475 Jun 24, 2026
296d6f6
Add logging to _extract_response() method
Oli-Jones475 Jun 24, 2026
4644aa4
Raise UnexpectedResponseError s
Oli-Jones475 Jun 24, 2026
72cea8c
Handle unexpected responses in controller
Oli-Jones475 Jun 24, 2026
0bb2876
Log scan schedule warning
Oli-Jones475 Jun 24, 2026
47c7a08
Add docstrings
Oli-Jones475 Jun 24, 2026
7ab47a7
Set constant for scan data length
Oli-Jones475 Jun 24, 2026
3e42726
Add Numpy and H5py as dependencies
Oli-Jones475 Jun 25, 2026
86a08f5
Start hdf5_file_builder class
Oli-Jones475 Jun 25, 2026
4570594
Fill body of create_hdf5_file method
Oli-Jones475 Jun 25, 2026
7d01940
Implement group methods
Oli-Jones475 Jun 25, 2026
cb5399f
Create dummy attribute classes
Oli-Jones475 Jun 26, 2026
7f46414
Change attribute ref structure
Oli-Jones475 Jun 26, 2026
70fb0ec
Move controller attributes to their own file
Oli-Jones475 Jun 26, 2026
fa5b0c2
Add pvs for file save location
Oli-Jones475 Jun 26, 2026
e46dfb8
Use hdf5 builder class
Oli-Jones475 Jun 26, 2026
e9c1437
Add pvs for title, sample name and id
Oli-Jones475 Jun 26, 2026
c4fa480
Add docstrings to flame_controller_attributes
Oli-Jones475 Jun 26, 2026
c625b47
Create dummy_spectrometer class
Oli-Jones475 Jun 15, 2026
f167dce
Make dummy_spectrometer use asyncio
Oli-Jones475 Jun 15, 2026
3cef06c
Fix constant recieval bug
Oli-Jones475 Jun 15, 2026
2b8f8ae
Send spectrometer initial message from dummy
Oli-Jones475 Jun 15, 2026
6d379ce
Create basic connection test
Oli-Jones475 Jun 15, 2026
a2c18e4
Implement basic request handling for dummy
Oli-Jones475 Jun 15, 2026
dc82e90
Tidy dummy_spectrometer
Oli-Jones475 Jun 22, 2026
511198e
Add methods for basic commands
Oli-Jones475 Jun 22, 2026
140077a
Add methods for basic spectromoter functionality
Oli-Jones475 Jun 22, 2026
e3f9c34
Add method to set scan data
Oli-Jones475 Jun 22, 2026
2aa44b3
Make method to respond in chunks
Oli-Jones475 Jun 22, 2026
deaf719
Fix method to set integration time
Oli-Jones475 Jun 22, 2026
c64eacf
Add docstrings and private variables
Oli-Jones475 Jun 22, 2026
1451327
Ensure last value of new scan is different to last
Oli-Jones475 Jun 22, 2026
fde13a8
Write component tests for basic functionalities
Oli-Jones475 Jun 22, 2026
3a7a1f4
Fix bug in intialising last_scan_data
Oli-Jones475 Jun 22, 2026
a28b54d
Make test file for file building tests
Oli-Jones475 Jun 26, 2026
9da4e92
Write structure tests for file builder
Oli-Jones475 Jun 26, 2026
d76a941
Add pytest-asyncio as a dependency
Oli-Jones475 Jun 26, 2026
8f17acf
Fix bug with dtype intialisation
Oli-Jones475 Jun 26, 2026
e8a0c03
Fix bug in attribute adding in file builder
Oli-Jones475 Jun 26, 2026
ac5987d
Fix misnamed dataset
Oli-Jones475 Jun 26, 2026
eb2889f
Fix bug of not using kwarg data
Oli-Jones475 Jun 26, 2026
88861a2
Fix misnaming bugs
Oli-Jones475 Jun 26, 2026
c52a8dc
Cleanup file fixture in file builder
Oli-Jones475 Jun 26, 2026
d2319e4
Add potential error for spectel connect method
Oli-Jones475 Jun 29, 2026
6b7a0c5
Add tests for spec tel conenction going wrong
Oli-Jones475 Jun 29, 2026
1cbea83
Added timeout to spectel socket
Oli-Jones475 Jun 29, 2026
c433efa
Add invalid response test
Oli-Jones475 Jun 29, 2026
ec191d6
Fix bad socket test
Oli-Jones475 Jun 29, 2026
2f0399c
Remove unecessary socket sends
Oli-Jones475 Jun 29, 2026
ad9012b
Correct parameter
Oli-Jones475 Jun 29, 2026
d869d06
Unprivate fields
Oli-Jones475 Jun 29, 2026
c85615d
Start flame_controller_test file
Oli-Jones475 Jun 29, 2026
875f8c5
Add bind option to dummy_spectrometer
Oli-Jones475 Jun 29, 2026
5971f11
Remove UI options
Oli-Jones475 Jun 29, 2026
7b3210e
Add caput test
Oli-Jones475 Jun 29, 2026
cf5a607
Add test for scan data command
Oli-Jones475 Jun 29, 2026
432b7be
Add data acquisition test
Oli-Jones475 Jun 29, 2026
2e60545
Create dummy file builder class
Oli-Jones475 Jun 30, 2026
28a8894
Test acquire data file creation
Oli-Jones475 Jun 30, 2026
36b34cb
Create test for acquiring data after chaning args
Oli-Jones475 Jun 30, 2026
6d4c44e
Fix acquire data tests
Oli-Jones475 Jun 30, 2026
0daa4d6
Raise error when calling spec_tels connect twice
Oli-Jones475 Jun 30, 2026
2f1ac55
Add error options to spec tel overwrite
Oli-Jones475 Jun 30, 2026
136bc3b
Fix acquisition parameter change test
Oli-Jones475 Jun 30, 2026
bfbc382
Add keyword arguments to creation function
Oli-Jones475 Jun 30, 2026
42b55aa
Add note for future tests
Oli-Jones475 Jun 30, 2026
2c6e346
Remove connected pointer
Oli-Jones475 Jun 30, 2026
df83762
Rewrite replace_spec_tel_methods note
Oli-Jones475 Jun 30, 2026
4218200
Fix timing tests
Oli-Jones475 Jun 30, 2026
800592d
Add temporary file directory to tests
Oli-Jones475 Jun 30, 2026
ab27855
Add tests to test exceptions
Oli-Jones475 Jun 30, 2026
2807842
Covnert spectrometer_telecommunicator to async
Oli-Jones475 Jul 1, 2026
6511567
Fix controller spec_tel calls
Oli-Jones475 Jul 1, 2026
b7815b1
Fix tests
Oli-Jones475 Jul 1, 2026
3a3e1ab
Added timeouts to socket methods
Oli-Jones475 Jul 1, 2026
ee7419e
Add log tests for acquiring data
Oli-Jones475 Jul 1, 2026
5fcf8cb
Create interruption test
Oli-Jones475 Jul 1, 2026
5cd0596
Fix typo
Oli-Jones475 Jul 1, 2026
784c05f
Add constants to file_builder_test
Oli-Jones475 Jul 2, 2026
8553b46
Remove acquire data command
Oli-Jones475 Jul 2, 2026
57cb734
Add capture attribute
Oli-Jones475 Jul 2, 2026
457c45f
Rename filepath and name pvs
Oli-Jones475 Jul 2, 2026
38ccdc5
Remove unecessary attributes
Oli-Jones475 Jul 2, 2026
7a8dbc8
Re-write methods for file builder
Oli-Jones475 Jul 2, 2026
47e369c
Add other attributes to data section
Oli-Jones475 Jul 2, 2026
94e60e2
Set wavelengths in h5 file
Oli-Jones475 Jul 2, 2026
637383d
Make capture switch method
Oli-Jones475 Jul 2, 2026
d251451
Append data to file when capturing
Oli-Jones475 Jul 2, 2026
e807594
Re-write file_builder_test
Oli-Jones475 Jul 3, 2026
02d3b20
Fix controller arguments
Oli-Jones475 Jul 3, 2026
9dd14be
Fix arguments in tests
Oli-Jones475 Jul 3, 2026
e3b0a05
Pv names changed
Oli-Jones475 Jul 8, 2026
130197c
Make to do list for source code
Oli-Jones475 Jul 3, 2026
e3b0ea8
Write to do list for tests
Oli-Jones475 Jul 3, 2026
9807524
Update README
Oli-Jones475 Jul 3, 2026
843dc7b
Merge send query methods
Oli-Jones475 Jul 8, 2026
35172d2
Added parameters
Oli-Jones475 Jul 8, 2026
63b0150
Todo file updated
Oli-Jones475 Jul 8, 2026
1941270
Tidy hdf5_file_builder file
Oli-Jones475 Jul 8, 2026
9c2cd8b
Changed names to lowercase
Oli-Jones475 Jul 8, 2026
00c0150
Add units attribute for wavelengths dataset
Oli-Jones475 Jul 8, 2026
7f0a86e
Add instrument group to h5 file
Oli-Jones475 Jul 8, 2026
abec17c
Docstrings added to hdf5_file_builder
Oli-Jones475 Jul 8, 2026
938463b
Add exceptions
Oli-Jones475 Jul 8, 2026
5b66543
Change hdf5_file_builder to file_builder
Oli-Jones475 Jul 8, 2026
541b476
Update todo lists
Oli-Jones475 Jul 8, 2026
f8f537a
Update docstrings
Oli-Jones475 Jul 8, 2026
1b9b933
Switch some lines
Oli-Jones475 Jul 8, 2026
53ae035
Add kwargs for wavlengths and scan data length
Oli-Jones475 Jul 8, 2026
ebc909f
Remand attribute IOs and Refs
Oli-Jones475 Jul 8, 2026
5cad0da
Create controller_and_mock_objects function
Oli-Jones475 Jul 9, 2026
beeb790
Re-write test_set_integration_time
Oli-Jones475 Jul 9, 2026
fd3143b
Re-write test_scan_data_command
Oli-Jones475 Jul 9, 2026
8b58462
Re-write flame_controller_test
Oli-Jones475 Jul 9, 2026
446bbcb
Re-write more tests
Oli-Jones475 Jul 9, 2026
e352b1d
Fix bug in error message
Oli-Jones475 Jul 9, 2026
53e8c75
Re-write test bad scan
Oli-Jones475 Jul 9, 2026
5d9de6a
Remove todo comment
Oli-Jones475 Jul 10, 2026
7825e90
Add docstrings to flame_controller_test
Oli-Jones475 Jul 10, 2026
86584b7
Replace magic numbers with constants
Oli-Jones475 Jul 10, 2026
be51005
Write test for file building
Oli-Jones475 Jul 10, 2026
0421bbb
Update Todo
Oli-Jones475 Jul 10, 2026
0e26057
Change handle_request architecture
Oli-Jones475 Jul 10, 2026
358c691
Add delay to scan responses
Oli-Jones475 Jul 10, 2026
ba04689
Update todo
Oli-Jones475 Jul 10, 2026
1cf700c
Fix bug
Oli-Jones475 Jul 10, 2026
ec08a13
Changed spec_tel_coroutine to a context manager
Oli-Jones475 Jul 10, 2026
0ba528f
Increase default timeout time
Oli-Jones475 Jul 10, 2026
5527ff2
Update todo list
Oli-Jones475 Jul 10, 2026
a966b15
Remove dummy_hdf5_file_builder
Oli-Jones475 Jul 10, 2026
814db97
Fix bug with string dtype
Oli-Jones475 Jul 10, 2026
ea8d231
Update structure test
Oli-Jones475 Jul 10, 2026
d6cf547
Update test values test
Oli-Jones475 Jul 10, 2026
9fd76c0
Added filebuilder fixture
Oli-Jones475 Jul 10, 2026
f82294a
Write test for making multiple files
Oli-Jones475 Jul 10, 2026
9992c8b
Add OpenFileException to file_builder
Oli-Jones475 Jul 10, 2026
ff7d972
Added tests for all exceptions
Oli-Jones475 Jul 10, 2026
683d196
update todo list
Oli-Jones475 Jul 10, 2026
1c1f9c7
Fix tmp_path bug
Oli-Jones475 Jul 10, 2026
2638fae
Fix basic scan data bug
Oli-Jones475 Jul 10, 2026
6944e3e
Update Title
Oli-Jones475 Jul 20, 2026
43e3cd8
Add cli arguments for ip and port
Oli-Jones475 Jul 20, 2026
a49c894
Add epics opi directory to container
Oli-Jones475 Jul 20, 2026
e5c2037
Change file path for fastcs gui
Oli-Jones475 Jul 20, 2026
371e226
Add mount path cli argument
Oli-Jones475 Jul 20, 2026
30d98a9
Remove annoying test
Oli-Jones475 Jul 20, 2026
3cb4fb1
Fix file builder tests
Oli-Jones475 Jul 20, 2026
4828fd8
Remove required keywork for positional arguments
Oli-Jones475 Jul 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ COPY --from=build /python /python
COPY --from=build /app/.venv /app/.venv
ENV PATH=/app/.venv/bin:$PATH

# Make directory to run inside and generate bob files
RUN mkdir -p /epics/opi

WORKDIR /epics/opi

# change this entrypoint if it is not the same as the repo
ENTRYPOINT ["fastcsflame"]
CMD ["--version"]
42 changes: 25 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,37 @@

# fastcsflame

EPICS driver for the OceanOptics flame mini spectrometer
EPICS driver for the OceanOptics Flame mini spectrometer

This is where you should write a short paragraph that describes what your module does,
how it does it, and why people should use it.
When started, the script connects to a spectrometer at a specific IP and port and interacts with it using the TelNet protocol. An IOC for interacting with this device is started. This allows users to interact with the device using channel access (controller name is FLAME) or through a Phoebus UI (opi files are generated in the opi directory). Users can create a file holding collected data by starting the a capture period (set Capture to 1). This will create a h5 file at the location specified by the FilePath PV with the value of the FileName PV as its name. Every time the Scan command is run scan data from the device will be added to this file. To end the capture period set Capture to 0 again. This will close the file and future scans will not be added.

What | Where
:---: | :---:
Source | <https://github.com//fastcsflame>
Docker | `docker run ghcr.io//fastcsflame:latest`
Releases | <https://github.com//fastcsflame/releases>
Source | <https://gitlab.diamond.ac.uk/controls/containers/beamline/fastcs-flame>

This is where you should put some images or code snippets that illustrate
some relevant examples. If it is a library then you might put some
introductory code here:
# PVs of the Flame IOC
- IntegrationTime
- LastScanData
- Scan
- FilePath
- FileName
- Capture

```python
from fastcsflame import __version__
Start the IOC:
`fastcsflame`
(in future this will have options for the address and port to communicate to the device on)

print(f"Hello fastcsflame {__version__}")
```
Set integration time to 10:
`caput FLAME:IntegrationTime 10`

Or if it is a commandline tool then you might put some example commands here:
Get the data from the last scan:
`caget FLAME:LastScanData`

```
python -m fastcsflame --version
```
Trigger a scan on the Flame:
`caput FLAME:Scan 1`

Start the capture period (creates the h5 file)
`caput FLAME:Capture 1`

Stop the capture period (closes the h5 file, allowing users to view it)
`caput FLAME:Capture 0`
9 changes: 7 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ classifiers = [
"Programming Language :: Python :: 3.14",
]
description = "EPICS driver for the OceanOptics flame mini spectrometer"
dependencies = [] # Add project dependencies here, e.g. ["click", "numpy"]
dependencies = [
"fastcs[epicsca]",
"h5py",
"numpy",
] # Add project dependencies here, e.g. ["click", "numpy"]
dynamic = ["version"]
license.file = "LICENSE"
readme = "README.md"
Expand All @@ -25,6 +29,7 @@ dev = [
"pre-commit",
"pyright",
"pytest",
"pytest-asyncio",
"pytest-cov",
"ruff",
"tox-uv",
Expand All @@ -46,7 +51,7 @@ version_file = "src/fastcsflame/_version.py"

[tool.pyright]
typeCheckingMode = "standard"
reportMissingImports = false # Ignore missing stubs in imported modules
reportMissingImports = false # Ignore missing stubs in imported modules

[tool.pytest.ini_options]
# Run pytest with all our checkers, and don't spam us with massive tracebacks on error
Expand Down
27 changes: 27 additions & 0 deletions src/fastcsflame/TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# To Do list

## SpectrometerTelecommunicator

### Big Things
- Accept ascii communications from the device
- Maybe make a message queue so we dont send message that talk over each other and wait for each others responses
(At the moment this should be handled for us by FastCS)

### Small Things
- Interpret metadata from scan messages more, dont just disregard it

## Hdf5FileBuilder
Sorted

## FlameControllerAttributes

### Big Things
- Combine DummyBoolIO and DummyStrIO into one class that uses generics
(Same for Refs)

## FlameController
Looks fine??

## __main__
- Add CLI arguments for Controller arguments
- Change title
46 changes: 45 additions & 1 deletion src/fastcsflame/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

from argparse import ArgumentParser
from collections.abc import Sequence
from pathlib import Path

from fastcs.launch import FastCS
from fastcs.logging import configure_logging
from fastcs.transports.epics import EpicsGUIOptions
from fastcs.transports.epics.ca import EpicsCATransport

from fastcsflame.flame_controller import FlameController

from . import __version__

Expand All @@ -11,13 +19,49 @@
def main(args: Sequence[str] | None = None) -> None:
"""Argument parser for the CLI."""
parser = ArgumentParser()
parser.add_argument(
"ip",
type=str,
help="IP Address of the terminal server (or other device) "
"the flame spectrometer is connect to",
)
parser.add_argument(
"port",
type=int,
help="The port of the terminal server (or other device) "
"the flame spectrometer is connected to",
)
parser.add_argument(
"mount-path",
type=str,
help="The path in the container to the mounted filesystem for saving data",
)
parser.add_argument(
"-v",
"--version",
action="version",
version=__version__,
)
parser.parse_args(args)
arguments_object = parser.parse_args(args)

configure_logging()

gui_options = EpicsGUIOptions(
output_dir=Path("epics/opi"), title="Flame Spectrometer Controller"
)
epics_ca = EpicsCATransport(gui=gui_options)

flame_controller = FlameController(
arguments_object.ip,
arguments_object.port,
mount_path="/dls/science/b21",
default_file_name="data",
)
flame_controller.set_path(["FLAME"])

fastcs = FastCS(flame_controller, [epics_ca])

fastcs.run()


if __name__ == "__main__":
Expand Down
173 changes: 173 additions & 0 deletions src/fastcsflame/file_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import h5py
import numpy as np
from numpy.typing import NDArray

STRING_DTYPE = h5py.string_dtype(encoding="utf-8")


class NoOpenFileError(Exception):
pass


class OpenFileError(Exception):
pass


class ScanLengthError(Exception):
pass


class FileBuilder:
"""
Builds h5 files containing data collected from the Flame
"""

_wavelengths: NDArray[np.float64]
_mount_path: str
file: h5py.File | None = None
scans_added: int = 0

def __init__(self, mount_path: str, wavelengths: NDArray[np.float64]):
"""
wavelengths: An array of wavelength values in nanometers
Represents wavelengths of intensity data points collected by flame
Should be the same length as the scan data collected by flame
"""
self.mount_path = mount_path
self._wavelengths = wavelengths

def create_file(self, file_path: str, file_name: str, auto_close=False):
"""
Creates and structures an h5 file for Flame data
file_path: Where to create the file
Both relative and absolute file paths are valid
Do not include final /
file_name: What to call the file
Do not include extension
auto_close: If this object already has an open file it closes it and does not
raise an exception
raises:
OpenFileError
When this object already has an open file and auto_close is false
If a h5 file exist at the file_path location with a matching name it will
be replaced without warning
This method may be called multiple times from this class to create multiple
files
"""
if self.file is not None:
if auto_close:
self.file.close()
else:
raise OpenFileError(
"Close previously created file before creating a new file"
)

self.file = h5py.File(f"{self.mount_path}{file_path}/{file_name}.h5", "w")

entry_group = self.file.create_group("entry")

self._create_data_group(entry_group)
self._create_instrument_group(entry_group)

def _create_data_group(self, parent_group: h5py.Group):
"""
Creates and structures the data group of the h5 file
parent_group: Group to create the data group under
"""
data_group = parent_group.create_group("data")

# Dataset starts empty but will have scan data added to it as scans are taken
# maxshape with first argument None allows this
data_group.create_dataset(
"data",
shape=(0, len(self._wavelengths)),
dtype=np.int64,
chunks=True,
maxshape=(None, len(self._wavelengths)),
)

data_group.attrs["axes"] = "Scan x Wavelength"
data_group.attrs["signal"] = "Intensity"

wavelength_axis = data_group.create_dataset(
"wavelength_axis", data=self._wavelengths
)
wavelength_axis.attrs["long_name"] = "Wavelength"
wavelength_axis.attrs["units"] = "nm"

self.scans_added = 0

def _create_instrument_group(self, parent_group: h5py.Group):
"""
Creates and structures the instrument group of the h5 file
parent_group: Group to create the instrument group under
"""
instrument_group = parent_group.create_group("instrument")

instrument_group.create_dataset(
"make",
data=np.array(["Flame Miniature Spectrometer"], dtype=STRING_DTYPE),
)
instrument_group.create_dataset(
"model", data=np.array(["FLAME-S"], dtype=STRING_DTYPE)
)
instrument_group.create_dataset(
"manufacturer", data=np.array(["OceanOptics"], dtype=STRING_DTYPE)
)

def add_scan(self, data: NDArray[np.int64]):
"""
Adds scan data to the last created h5 file
data: Scan data from the flame
raises:
NoOpenFileError
When no file has been created or the previously created file was closed
FileNotFoundError
When the scan data dataset couldnt be found in the h5 file
ScanLengthError
When scan data length does not match wavelength array length
"""

if self.file is None:
raise NoOpenFileError(
"No file has been created or last created file was closed.\n"
"Nowhere to add scan to"
)

dataset_path = "entry/data/data"
dataset = self.file[dataset_path]
if not isinstance(dataset, h5py.Dataset):
raise FileNotFoundError(
f"Could not find dataset in h5 file at: {dataset_path}"
)

if self._wavelengths.shape[0] != data.shape[0]:
raise ScanLengthError(
"Scan data length does not match wavelength array length.\n"
f"Scan data length: {data.shape[0]} \n"
f"Wavelength array length: {self._wavelengths.shape[0]} \n"
"Could not add data to file"
)

# Adds an extra space for the new scan data
dataset.resize(self.scans_added + 1, axis=0)
# Places new scan data at the end of the array
dataset[self.scans_added] = data

self.scans_added += 1

def close_file(self):
"""
Closes last created h5 file
raises:
NoOpenFileError
When no file has been created or the previously created file was closed
"""
if self.file is None:
raise NoOpenFileError(
"No file has been created or last created file was closed.\n"
"No file to close"
)

self.file.close()
self.file = None
Loading
Loading