diff --git a/src/cristallina/uscan.py b/src/cristallina/uscan.py index d4c0fe5..e2dc67b 100644 --- a/src/cristallina/uscan.py +++ b/src/cristallina/uscan.py @@ -1,47 +1,120 @@ -from sfdata import SFScanInfo -import sfdata.utils +import json +import time +from pathlib import Path + +from sfdata.utils import print_skip_warning, json_load, adjust_shape +from sfdata.ign import remove_ignored_filetypes_scan +from sfdata import SFDataFiles, SFScanInfo from partialjson.json_parser import JSONParser -class UnfinishedScan(SFScanInfo): +class UnfinishedScanInfo(SFScanInfo): """ - Represents an unfinished scan from SwissFEL data, mimicking a finished SFScanInfo. It tries - to parse a partial JSON file and extract the scan information. + Represents an unfinished scan from SwissFEL data, mimicking a finished SFScanInfo. It allows to iterate + over already available scan steps and waits for new data if the scan is still ongoing. + + If the scan is already finished, it behaves like a regular SFScanInfo. Args: - fname (str): The filename of the JSON file to be processed for scan information. + fname (str): The filepath of the JSON file to be processed for scan information (e.g. scan.json). + refresh_interval (int): Time in seconds to wait before checking for new data again. Default is 10 seconds. """ - def __init__(self, fname): + def __init__(self, fname, refresh_interval=10): self.fname = fname - self.fs = sfdata.utils.FileStatus(fname) + self.finished = False + self.refresh_interval = refresh_interval + if is_finished_scan(fname): + # simple case, it is a finished scan and our parent can handle it + super().__init__(fname) + self.finished = True + else: + # try to parse it as a partial JSON file + self._parse_partial_json(fname) + + def _parse_partial_json(self, fname): with open(fname) as f: content = f.read() - parser = JSONParser() - + + parser = JSONParser() self.info = info = parser.parse(content) + + # we try to extract as much information as possible, + # leaving missing parts out if not available + fnames = info.get("scan_files", []) + self.files = remove_ignored_filetypes_scan(fnames) + + self.parameters = info.get("scan_parameters", []) + + values = info.get("scan_values", []) + readbacks = info.get("scan_readbacks", []) + + # filter for empty values which can occur in the partial json parsing + values = [vals for vals in values if vals] + readbacks = [rb for rb in readbacks if rb] + self.values = adjust_shape(values) + self.readbacks = adjust_shape(readbacks) - self.files = info["scan_files"] + def __iter__(self): + if self.finished: + return super().__iter__() - try: - self.parameters = info["scan_parameters"] - except KeyError: - self.parameters = None + return self._generate_data() - try: - values = info["scan_values"] - values = [v for v in values if v] - except KeyError: - values = None + def _generate_data(self): + """Generator that yields scan data as it becomes available during the scan.""" + yielded_count = 0 + + while True: + self._parse_partial_json(self.fname) - try: - readbacks = info["scan_readbacks"] - readbacks = [r for r in readbacks if r] - except KeyError: - readbacks = None + # Check if we have new files to yield + while self.files and len(self.files) > yielded_count: + fns = self.files[yielded_count] + + if not files_available_on_disk(fns): + time.sleep(self.refresh_interval) + continue # Wait and recheck - self.values = sfdata.utils.adjust_shape(values) - self.readbacks = sfdata.utils.adjust_shape(readbacks) + yielded_count += 1 + + try: + with SFDataFiles(*fns) as data: + yield data + except Exception as exc: + # TODO: Think about what could go wrong here and deal with it more specifically + sn = f"step {yielded_count - 1} {fns}" + print_skip_warning(exc, sn) + continue # Try next file + + if is_finished_scan(self.fname) and (yielded_count >= len(self.files)): + return # Scan is finished, and we yielded all available files, stop iteration + + # Wait before checking again + time.sleep(self.refresh_interval) + + +def is_finished_scan(fname): + """ If the scan.json file is complete, valid and the files are on the disk the scan is finished. + This does not cover the case where a scan is interrupted and continued later. + + It also relies on the behavior of RA that the scan.json is only fully written at the end of the scan.""" + try: + content = json_load(fname) + files = [file for step in content['scan_files'] for file in step] + # Check if all files are available on disk + if not files_available_on_disk(set(files)): + return False + except json.JSONDecodeError: + return False + return True + + +def files_available_on_disk(fnames): + """Check if all files for this step are available on disk and contain some data.""" + if all(Path(fn).exists() for fn in fnames): + return all(Path(fn).stat().st_size > 0 for fn in fnames) + return False \ No newline at end of file diff --git a/tests/data/scans/scan1.json b/tests/data/scans/scan1.json new file mode 100644 index 0000000..c52a6b3 --- /dev/null +++ b/tests/data/scans/scan1.json @@ -0,0 +1,108 @@ +{ + "pulseIds": [ + [ + 25378283898, + 25378283908 + ], + [ + 25378284929, + 25378284939 + ], + [ + 25378285957, + 25378285967 + ], + [ + 25378286993, + 25378287003 + ], + [ + 25378288023, + 25378288033 + ], + [ + 25378289052, + 25378289062 + ] + ], + "scan_files": [ + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.JF20T01V01.h5" + ] + ], + "scan_parameters": { + "Id": [ + "DUMMY" + ], + "conversion_factor": [ + 1 + ], + "name": [ + "Dummy" + ], + "offset": [ + 0 + ], + "scan_name": "test_slow_acquisition", + "units": [ + "au" + ] + }, + "scan_readbacks": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + 3.0 + ], + [ + 4.0 + ], + [ + 5.0 + ] + ], + "scan_readbacks_raw": [ + [ + 0.0 + ], + [ \ No newline at end of file diff --git a/tests/data/scans/scan2.json b/tests/data/scans/scan2.json new file mode 100644 index 0000000..aab7953 --- /dev/null +++ b/tests/data/scans/scan2.json @@ -0,0 +1,128 @@ +{ + "pulseIds": [ + [ + 25378283898, + 25378283908 + ], + [ + 25378284929, + 25378284939 + ], + [ + 25378285957, + 25378285967 + ], + [ + 25378286993, + 25378287003 + ], + [ + 25378288023, + 25378288033 + ], + [ + 25378289052, + 25378289062 + ], + [ + 25378290082, + 25378290092 + ] + ], + "scan_files": [ + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.JF20T01V01.h5" + ] + ], + "scan_parameters": { + "Id": [ + "DUMMY" + ], + "conversion_factor": [ + 1 + ], + "name": [ + "Dummy" + ], + "offset": [ + 0 + ], + "scan_name": "test_slow_acquisition", + "units": [ + "au" + ] + }, + "scan_readbacks": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + 3.0 + ], + [ + 4.0 + ], + [ + 5.0 + ], + [ + 6.0 + ] + ], + "scan_readbacks_raw": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + \ No newline at end of file diff --git a/tests/data/scans/scan3.json b/tests/data/scans/scan3.json new file mode 100644 index 0000000..5671ac2 --- /dev/null +++ b/tests/data/scans/scan3.json @@ -0,0 +1,148 @@ +{ + "pulseIds": [ + [ + 25378283898, + 25378283908 + ], + [ + 25378284929, + 25378284939 + ], + [ + 25378285957, + 25378285967 + ], + [ + 25378286993, + 25378287003 + ], + [ + 25378288023, + 25378288033 + ], + [ + 25378289052, + 25378289062 + ], + [ + 25378290082, + 25378290092 + ], + [ + 25378291117, + 25378291127 + ] + ], + "scan_files": [ + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.JF20T01V01.h5" + ] + ], + "scan_parameters": { + "Id": [ + "DUMMY" + ], + "conversion_factor": [ + 1 + ], + "name": [ + "Dummy" + ], + "offset": [ + 0 + ], + "scan_name": "test_slow_acquisition", + "units": [ + "au" + ] + }, + "scan_readbacks": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + 3.0 + ], + [ + 4.0 + ], + [ + 5.0 + ], + [ + 6.0 + ], + [ + 7.0 + ] + ], + "scan_readbacks_raw": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + 3.0 + ], + [ + 4.0 + ], + [ + 5.0 + \ No newline at end of file diff --git a/tests/data/scans/scan4.json b/tests/data/scans/scan4.json new file mode 100644 index 0000000..3bbd106 --- /dev/null +++ b/tests/data/scans/scan4.json @@ -0,0 +1,328 @@ +{ + "pulseIds": [ + [ + 25378283898, + 25378283908 + ], + [ + 25378284929, + 25378284939 + ], + [ + 25378285957, + 25378285967 + ], + [ + 25378286993, + 25378287003 + ], + [ + 25378288023, + 25378288033 + ], + [ + 25378289052, + 25378289062 + ], + [ + 25378290082, + 25378290092 + ], + [ + 25378291117, + 25378291127 + ], + [ + 25378292146, + 25378292156 + ], + [ + 25378293176, + 25378293186 + ], + [ + 25378294206, + 25378294216 + ], + [ + 25378295236, + 25378295246 + ], + [ + 25378296272, + 25378296282 + ], + [ + 25378297301, + 25378297311 + ], + [ + 25378298330, + 25378298340 + ], + [ + 25378299359, + 25378299369 + ], + [ + 25378300389, + 25378300399 + ] + ], + "scan_files": [ + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0009.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0009.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0009.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0009.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0010.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0010.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0010.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0010.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0011.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0011.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0011.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0011.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0012.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0012.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0012.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0012.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0013.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0013.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0013.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0013.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0014.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0014.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0014.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0014.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0015.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0015.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0015.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0015.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0016.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0016.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0016.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0016.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0017.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0017.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0017.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0017.JF20T01V01.h5" + ] + ], + "scan_parameters": { + "Id": [ + "DUMMY" + ], + "conversion_factor": [ + 1 + ], + "name": [ + "Dummy" + ], + "offset": [ + 0 + ], + "scan_name": "test_slow_acquisition", + "units": [ + "au" + ] + }, + "scan_readbacks": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + 3.0 + ], + [ + 4.0 + ], + [ + 5.0 + ], + [ + 6.0 + ], + [ + 7.0 + ], + [ + 8.0 + ], + [ + 9.0 + ], + [ + 10.0 + ], + [ + 11.0 + ], + [ + 12.0 + ], + [ + 13.0 + ], + [ + 14.0 + ], + [ + 15.0 + ], + [ + 16.0 + ] + ], + "scan_readbacks_raw": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + 3.0 + ], + [ + 4.0 + ], + [ + 5.0 + ], + [ + 6.0 + ], + [ + 7.0 + ], + [ + 8.0 + ], + [ + 9.0 + ], + [ + 10.0 + ], + [ + 11.0 + ], + [ + 12.0 + ], + [ + 13.0 + ], + [ + 14.0 + ], + [ + 15.0 + ], + [ + 16.0 + ] + ], + "scan_step_info": [ + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [] + ], + "scan_values": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + \ No newline at end of file diff --git a/tests/data/scans/scan5.json b/tests/data/scans/scan5.json new file mode 100644 index 0000000..8e446ae --- /dev/null +++ b/tests/data/scans/scan5.json @@ -0,0 +1,368 @@ +{ + "pulseIds": [ + [ + 25378283898, + 25378283908 + ], + [ + 25378284929, + 25378284939 + ], + [ + 25378285957, + 25378285967 + ], + [ + 25378286993, + 25378287003 + ], + [ + 25378288023, + 25378288033 + ], + [ + 25378289052, + 25378289062 + ], + [ + 25378290082, + 25378290092 + ], + [ + 25378291117, + 25378291127 + ], + [ + 25378292146, + 25378292156 + ], + [ + 25378293176, + 25378293186 + ], + [ + 25378294206, + 25378294216 + ], + [ + 25378295236, + 25378295246 + ], + [ + 25378296272, + 25378296282 + ], + [ + 25378297301, + 25378297311 + ], + [ + 25378298330, + 25378298340 + ], + [ + 25378299359, + 25378299369 + ], + [ + 25378300389, + 25378300399 + ], + [ + 25378301425, + 25378301435 + ], + [ + 25378302455, + 25378302465 + ] + ], + "scan_files": [ + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0009.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0009.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0009.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0009.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0010.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0010.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0010.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0010.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0011.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0011.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0011.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0011.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0012.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0012.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0012.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0012.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0013.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0013.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0013.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0013.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0014.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0014.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0014.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0014.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0015.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0015.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0015.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0015.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0016.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0016.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0016.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0016.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0017.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0017.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0017.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0017.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0018.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0018.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0018.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0018.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0019.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0019.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0019.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0019.JF20T01V01.h5" + ] + ], + "scan_parameters": { + "Id": [ + "DUMMY" + ], + "conversion_factor": [ + 1 + ], + "name": [ + "Dummy" + ], + "offset": [ + 0 + ], + "scan_name": "test_slow_acquisition", + "units": [ + "au" + ] + }, + "scan_readbacks": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + 3.0 + ], + [ + 4.0 + ], + [ + 5.0 + ], + [ + 6.0 + ], + [ + 7.0 + ], + [ + 8.0 + ], + [ + 9.0 + ], + [ + 10.0 + ], + [ + 11.0 + ], + [ + 12.0 + ], + [ + 13.0 + ], + [ + 14.0 + ], + [ + 15.0 + ], + [ + 16.0 + ], + [ + 17.0 + ], + [ + 18.0 + ] + ], + "scan_readbacks_raw": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + 3.0 + ], + [ + 4.0 + ], + [ + 5.0 + ], + [ + 6.0 + ], + [ + 7.0 + ], + [ + 8.0 + ], + [ + 9.0 + ], + [ + 10.0 + ], + [ + 11.0 + ], + [ + 12.0 + ], + [ + 13.0 + ], + [ + 14.0 + ], + [ + 15.0 + ], + [ + 16.0 + ], + [ + 17.0 + ], + [ + 18.0 + ] + ], + "scan_step_info": [ + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [] + ], + "scan_values": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + 3.0 + ], + [ + 4.0 + \ No newline at end of file diff --git a/tests/data/scans/scan_finished.json b/tests/data/scans/scan_finished.json new file mode 100644 index 0000000..5d730ba --- /dev/null +++ b/tests/data/scans/scan_finished.json @@ -0,0 +1,452 @@ +{ + "pulseIds": [ + [ + 25378283898, + 25378283908 + ], + [ + 25378284929, + 25378284939 + ], + [ + 25378285957, + 25378285967 + ], + [ + 25378286993, + 25378287003 + ], + [ + 25378288023, + 25378288033 + ], + [ + 25378289052, + 25378289062 + ], + [ + 25378290082, + 25378290092 + ], + [ + 25378291117, + 25378291127 + ], + [ + 25378292146, + 25378292156 + ], + [ + 25378293176, + 25378293186 + ], + [ + 25378294206, + 25378294216 + ], + [ + 25378295236, + 25378295246 + ], + [ + 25378296272, + 25378296282 + ], + [ + 25378297301, + 25378297311 + ], + [ + 25378298330, + 25378298340 + ], + [ + 25378299359, + 25378299369 + ], + [ + 25378300389, + 25378300399 + ], + [ + 25378301425, + 25378301435 + ], + [ + 25378302455, + 25378302465 + ], + [ + 25378303485, + 25378303495 + ], + [ + 25378304515, + 25378304525 + ] + ], + "scan_files": [ + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0001.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0002.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0003.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0004.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0005.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0006.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0007.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0008.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0009.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0009.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0009.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0009.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0010.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0010.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0010.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0010.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0011.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0011.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0011.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0011.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0012.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0012.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0012.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0012.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0013.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0013.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0013.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0013.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0014.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0014.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0014.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0014.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0015.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0015.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0015.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0015.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0016.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0016.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0016.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0016.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0017.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0017.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0017.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0017.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0018.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0018.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0018.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0018.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0019.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0019.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0019.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0019.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0020.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0020.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0020.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0020.JF20T01V01.h5" + ], + [ + "/sf/cristallina/data/p19150/raw/run0531/data/acq0021.PVDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0021.BSDATA.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0021.JF16T03V02.h5", + "/sf/cristallina/data/p19150/raw/run0531/data/acq0021.JF20T01V01.h5" + ] + ], + "scan_parameters": { + "Id": [ + "DUMMY" + ], + "conversion_factor": [ + 1 + ], + "name": [ + "Dummy" + ], + "offset": [ + 0 + ], + "scan_name": "test_slow_acquisition", + "units": [ + "au" + ] + }, + "scan_readbacks": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + 3.0 + ], + [ + 4.0 + ], + [ + 5.0 + ], + [ + 6.0 + ], + [ + 7.0 + ], + [ + 8.0 + ], + [ + 9.0 + ], + [ + 10.0 + ], + [ + 11.0 + ], + [ + 12.0 + ], + [ + 13.0 + ], + [ + 14.0 + ], + [ + 15.0 + ], + [ + 16.0 + ], + [ + 17.0 + ], + [ + 18.0 + ], + [ + 19.0 + ], + [ + 20.0 + ] + ], + "scan_readbacks_raw": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + 3.0 + ], + [ + 4.0 + ], + [ + 5.0 + ], + [ + 6.0 + ], + [ + 7.0 + ], + [ + 8.0 + ], + [ + 9.0 + ], + [ + 10.0 + ], + [ + 11.0 + ], + [ + 12.0 + ], + [ + 13.0 + ], + [ + 14.0 + ], + [ + 15.0 + ], + [ + 16.0 + ], + [ + 17.0 + ], + [ + 18.0 + ], + [ + 19.0 + ], + [ + 20.0 + ] + ], + "scan_step_info": [ + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [], + [] + ], + "scan_values": [ + [ + 0.0 + ], + [ + 1.0 + ], + [ + 2.0 + ], + [ + 3.0 + ], + [ + 4.0 + ], + [ + 5.0 + ], + [ + 6.0 + ], + [ + 7.0 + ], + [ + 8.0 + ], + [ + 9.0 + ], + [ + 10.0 + ], + [ + 11.0 + ], + [ + 12.0 + ], + [ + 13.0 + ], + [ + 14.0 + ], + [ + 15.0 + ], + [ + 16.0 + ], + [ + 17.0 + ], + [ + 18.0 + ], + [ + 19.0 + ], + [ + 20.0 + ] + ] +} \ No newline at end of file