Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PREFECT_LOGGING_EXTRA_LOGGERS=bluesky_tiled_plugins.validator
TILED_RETRY_ATTEMPTS=3
128 changes: 117 additions & 11 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ __pycache__/

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
Expand All @@ -20,10 +19,12 @@ lib64/
parts/
sdist/
var/
venv/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
Expand All @@ -38,31 +39,139 @@ pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Sphinx documentation
docs/build/
docs/source/generated/
# Flask stuff:
instance/
.webassets-cache

# pytest
.pytest_cache/
# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# Ruff stuff:
.ruff_cache/

# PyPI configuration file
.pypirc

# Editor files
#mac
.DS_Store
Expand All @@ -78,9 +187,6 @@ target/
#vscode
.vscode/*

#Ipython Notebook
.ipynb_checkpoints

#file extensions
#
*.h5
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/prefix-dev/pixi:0.57.0
FROM ghcr.io/prefix-dev/pixi:0.71.3

ENV TZ="America/New_York"

Expand All @@ -7,6 +7,7 @@ RUN apt-get -y update && \

COPY pixi.toml .
COPY pixi.lock .
COPY .env .
# use `--locked` to ensure the lockfile is up to date with pixi.toml
RUN pixi install --locked
# create the shell-hook bash script to activate the environment
Expand Down
64 changes: 46 additions & 18 deletions data_validation.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,56 @@
import time
import os
import time as ttime

from dotenv import load_dotenv
from prefect import flow, get_run_logger, task
from export_tools import initialize_tiled_client
from tiled.client import from_uri

BEAMLINE_OR_ENDSTATION = "ucal"


def get_api_key_from_env():
with open("/srv/container.secret", "r") as secrets:
load_dotenv(stream=secrets)
api_key = os.environ["TILED_API_KEY"]
return api_key


@task(retries=2, retry_delay_seconds=10)
def read_all_streams(uid, beamline_acronym="ucal"):
logger = get_run_logger()
catalog = initialize_tiled_client(beamline_acronym)
run = catalog[uid]
def get_catalog(api_key=None):
if not api_key:
api_key = get_api_key_from_env()
catalog = from_uri("https://tiled.nsls2.bnl.gov", api_key=api_key)[
f"{BEAMLINE_OR_ENDSTATION}/raw"
]
return catalog


@task(retries=2, retry_delay_seconds=10)
def get_run(uid, api_key=None):
if not api_key:
api_key = get_api_key_from_env()
cl = from_uri("https://tiled.nsls2.bnl.gov", api_key=api_key)
run = cl[f"{BEAMLINE_OR_ENDSTATION}/raw"][uid]
return run


logger.info(f"Validating uid {run.start['uid']}")
start_time = time.monotonic()
for stream in run:
@task(retries=2, retry_delay_seconds=10)
def read_stream(run, stream):
return run[stream].read()


@flow
def data_validation(uid, api_key=None, dry_run=False):
logger = get_run_logger()
logger.info(f"Validating uid {uid}")
start_time = ttime.monotonic()
run_client = get_run(uid, api_key=api_key)
for stream in run_client:
logger.info(f"{stream}:")
stream_start_time = time.monotonic()
stream_data = run[stream].read()
stream_elapsed_time = time.monotonic() - stream_start_time
stream_start_time = ttime.monotonic()
stream_data = read_stream(run_client, stream) # noqa: F841
stream_elapsed_time = ttime.monotonic() - stream_start_time
logger.info(f"{stream} elapsed_time = {stream_elapsed_time}")
logger.info(f"{stream} nbytes = {stream_data.nbytes:_}")
elapsed_time = time.monotonic() - start_time
elapsed_time = ttime.monotonic() - start_time
logger.info(f"{elapsed_time = }")


@flow
def general_data_validation(uid, beamline_acronym="ucal"):
read_all_streams(uid, beamline_acronym)
30 changes: 19 additions & 11 deletions end_of_run_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import os
from export_to_xdi import exportToXDI
from export_to_hdf5 import exportToHDF5
from export_tools import get_proposal_path, initialize_tiled_client
from data_validation import get_run
from export_tools import get_proposal_path
import datetime


Expand All @@ -28,28 +29,35 @@ def create_export_path(export_path):


@task(retries=2, retry_delay_seconds=10)
def export_all_streams(uid, beamline_acronym="ucal"):
def export_all_streams(uid, api_key=None, dry_run=False):
logger = get_run_logger()
catalog = initialize_tiled_client(beamline_acronym)
run = catalog[uid]
run = get_run(uid, api_key=api_key)

base_export_path = get_export_path(run)
logger.info(f"Generating Export for uid {run.start['uid']}")
logger.info(f"Export Data to {base_export_path}")
create_export_path(base_export_path)
if not dry_run:
create_export_path(base_export_path)

logger.info("Exporting XDI")
xdi_export_path = join(base_export_path, "xdi")
create_export_path(xdi_export_path)
exportToXDI(xdi_export_path, run)
if not dry_run:
create_export_path(xdi_export_path)
exportToXDI(xdi_export_path, run)
else:
logger.info(f"dry_run: not exporting to {xdi_export_path}")
logger.info("Exporting HDF5")
hdf5_export_path = join(base_export_path, "hdf5")
create_export_path(hdf5_export_path)
exportToHDF5(hdf5_export_path, run)
if not dry_run:
create_export_path(hdf5_export_path)
exportToHDF5(hdf5_export_path, run)
else:
logger.info(f"dry_run: not exporting to {hdf5_export_path}")
# logger.info("Exporting Athena")
# if not dry_run:
# exportToAthena(export_path, run)


@flow
def general_data_export(uid, beamline_acronym="ucal"):
export_all_streams(uid, beamline_acronym)
def general_data_export(uid, api_key=None, dry_run=False):
export_all_streams(uid, api_key=api_key, dry_run=dry_run)
Loading
Loading