Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MNT Move shared eLog code to separate module #187

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
94 changes: 2 additions & 92 deletions summaries/BeamlineSummaryPlots_mfx.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,97 +33,7 @@
from smalldata_tools.SmallDataAna_psana import SmallDataAna_psana as sdaps
from smalldata_tools.utilities import image_from_dxy
from smalldata_tools.utilities import rebin

def getElogBasicAuth(exp: str) -> HTTPBasicAuth:
"""Return an authentication object for the eLog API for an opr account.

This method will only work for active experiments. "opr" accounts are
removed from the authorized users list after the experiment ends.

Paramters
---------
exp (str) Experiment name (to determine operator username).

Returns
-------
http_auth (HTTPBasicAuth) Authentication for eLog API.
"""
opr_name: str = f"{exp[:3]}opr"
hostname: str = socket.gethostname()
if hostname.find('sdf') >= 0:
auth_path: str = "/sdf/group/lcls/ds/tools/forElogPost.txt"
else:
auth_path: str = f"/cds/home/opr/{opr_name}/forElogPost.txt"

with open(auth_path, "r") as f:
pw: str = f.readline()[:-1]

return HTTPBasicAuth(username=opr_name, password=pw)

def postElogMsg(
exp: str,
msg: str,
*,
tag: Optional[str] = "",
title: Optional[str] = "",
files: list = []
) -> None:
"""Post a new message to the eLog. Adapted from `elog` package.

Parameters
----------
exp (str) Experiment name.
msg (str) Body of the eLog post.
tag (str) Optional. A tag to include for the post.
title (str) Optional. A title for the eLog post.
files (list) Optional. Either a list of paths (str) to files (figures) to
include with the eLog post, OR, a list of 2-tuples of strings of the
form (`path`, `description`).
"""
post_files: list = []
for f in files:
if isinstance(f, str):
desc: str = os.path.basename(f)
formatted_file: tuple = (
"files",
(desc, open(f, "rb")),
mimetypes.guess_type(f)[0]
)
elif isinstance(f, tuple) or isinstance(f, list):
formatted_file: tuple = (
"files",
(f[1], open(f[0], "rb")),
mimetypes.guess_type(f[0])[0]
)
else:
logger.debug(f"Can't parse file {f} for eLog attachment. Skipping.")
continue
post_files.append(formatted_file)

post: dict = {}
post['log_text'] = msg
if tag:
post['log_tags'] = tag
if title:
post['log_title'] = title

http_auth: HTTPBasicAuth = getElogBasicAuth(exp)
base_url: str = "https://pswww.slac.stanford.edu/ws-auth/lgbk/lgbk"
post_url: str = f"{base_url}/{exp}/ws/new_elog_entry"

params: dict = {'url': post_url, 'data': post, 'auth': http_auth}
if post_files:
params.update({'files': post_files})

resp: requests.models.Response = requests.post(**params)

if resp.status_code >= 300:
logger.debug(
f"Error when posting to eLog: HTTP status code {resp.status_code}"
)

if not resp.json()['success']:
logger.debug(f"Error when posting to eLog: {resp.json()['error_msg']}")
from summaries.elog_utilities import *

def postDetectorDamageMsg(
detectors: list,
Expand Down Expand Up @@ -168,7 +78,7 @@ def postDetectorDamageMsg(
"<td><b><center>Missing/Damaged Events</center></b></td>"
"<td><b><center>Percentage Missing/Damaged</center></b></td></tr>"
)

post_msg: bool = False

for det_name in detectors:
Expand Down
147 changes: 3 additions & 144 deletions summaries/PedestalPlot.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@
import argparse
import sys
import logging
import requests
from pathlib import Path
from requests.auth import HTTPBasicAuth
import socket
from typing import Optional
import mimetypes

from summaries.elog_utilities import *
try:
basestring
except NameError:
Expand Down Expand Up @@ -111,23 +109,6 @@
####
# helper functions
####
def postRunTable(runtable_data):
ws_url = args.url + "/run_control/{0}/ws/add_run_params".format(args.experiment)
print('URL:',ws_url)
user=args.experiment[:3]+'opr'
elogPostFile='/cds/home/opr/%s/forElogPost.txt'%user
hostname=socket.gethostname()
if hostname.find('sdf')>=0:
elogPostFile='/sdf/group/lcls/ds/tools/forElogPost.txt'
with open(elogPostFile,'r') as reader:
answer = reader.readline()
r = requests.post(ws_url, params={"run_num": args.run}, json=runtable_data, \
auth=HTTPBasicAuth(args.experiment[:3]+'opr', answer[:-1]))
#we might need to use this for non=current expetiments. Currently does not work in ARP
#krbheaders = KerberosTicket("HTTP@" + urlparse(ws_url).hostname).getAuthHeaders()
#r = requests.post(ws_url, headers=krbheaders, params={"run_num": args.run}, json=runtable_data)
print(r)

def statusStats(det_name, printme=False, request_run=None):
det = psana.Detector(det_name)
if request_run:
Expand Down Expand Up @@ -162,128 +143,6 @@ def statusStats(det_name, printme=False, request_run=None):
print(k,v)
return statusStatDict

def getKerberosAuthHeaders() -> dict: ...

def getElogBasicAuth(exp: str) -> HTTPBasicAuth:
"""Return an authentication object for the eLog API for an opr account.

This method will only work for active experiments. "opr" accounts are
removed from the authorized users list after the experiment ends.

Paramters
---------
exp (str) Experiment name (to determine operator username).

Returns
-------
http_auth (HTTPBasicAuth) Authentication for eLog API.
"""
opr_name: str = f"{exp[:3]}opr"
hostname: str = socket.gethostname()
if hostname.find('sdf') >= 0:
auth_path: str = "/sdf/group/lcls/ds/tools/forElogPost.txt"
else:
auth_path: str = f"/cds/home/opr/{opr_name}/forElogPost.txt"

with open(auth_path, "r") as f:
pw: str = f.readline()[:-1]

return HTTPBasicAuth(username=opr_name, password=pw)

def getRunsWithTag(
exp: str,
tag: str,
http_auth: Optional[HTTPBasicAuth] = None
) -> list:
"""Return a list of runs tagged with a specific `tag`.

Parameters
----------
exp (str) Experiment name.
tag (str) Tag to match against run tags.
http_auth (HTTPBasicAuth) Authentication for eLog API.

Returns
-------
tagged_runs (list[int]) List of runs with the specified tag. Empty if none
were found or there was a communication error.
"""
base_url: str = "https://pswww.slac.stanford.edu/ws-auth/lgbk/lgbk"
tag_url: str = f"{base_url}/{exp}/ws/get_runs_with_tag?tag={tag}"
http_auth: HTTPBasicAuth = http_auth or getElogBasicAuth(exp)
resp: requests.models.Response = requests.get(tag_url, auth=http_auth)

tagged_runs: list = []
if resp.json()['success']:
tagged_runs = resp.json()['value']

return tagged_runs

def postElogMsg(
exp: str,
msg: str,
*,
tag: Optional[str] = "",
title: Optional[str] = "",
files: list = []
) -> None:
"""Post a new message to the eLog. Adapted from `elog` package.

Parameters
----------
exp (str) Experiment name.
msg (str) Body of the eLog post.
tag (str) Optional. A tag to include for the post.
title (str) Optional. A title for the eLog post.
files (list) Optional. Either a list of paths (str) to files (figures) to
include with the eLog post, OR, a list of 2-tuples of strings of the
form (`path`, `description`).
"""
post_files: list = []
for f in files:
if isinstance(f, str):
desc: str = os.path.basename(f)
formatted_file: tuple = (
"files",
(desc, open(f, "rb")),
mimetypes.guess_type(f)[0]
)
elif isinstance(f, tuple) or isinstance(f, list):
formatted_file: tuple = (
"files",
(f[1], open(f[0], "rb")),
mimetypes.guess_type(f[0])[0]
)
else:
logger.debug(f"Can't parse file {f} for eLog attachment. Skipping.")
continue
post_files.append(formatted_file)

post: dict = {}
post['log_text'] = msg
if tag:
post['log_tags'] = tag
if title:
post['log_title'] = title

http_auth: HTTPBasicAuth = getElogBasicAuth(exp)
base_url: str = "https://pswww.slac.stanford.edu/ws-auth/lgbk/lgbk"
post_url: str = f"{base_url}/{exp}/ws/new_elog_entry"

params: dict = {'url': post_url, 'data': post, 'auth': http_auth}
if post_files:
params.update({'files': post_files})

resp: requests.models.Response = requests.post(**params)

if resp.status_code >= 300:
logger.debug(
f"Error when posting to eLog: HTTP status code {resp.status_code}"
)

if not resp.json()['success']:
logger.debug(f"Error when posting to eLog: {resp.json()['error_msg']}")

def postBadPixMsg(
detectors: list,
exp: str,
Expand Down Expand Up @@ -749,7 +608,7 @@ def plotPedestals(expname='mfxc00118', run=364, nosave_elog=False, make_ped_imgs
print('Made Directory to save data:', elogDir)
tabs.save(('%s/report.html'%elogDir))

postRunTable(runTableData)
postRunTable(args.experiment, args.run, runTableData)

return tabs

Expand Down
Loading