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

Add "now" subcommand, as requested #32

Merged
merged 2 commits into from
Dec 17, 2024
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
211 changes: 128 additions & 83 deletions apsbss/apsbss.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@

EXAMPLES::

apsbss current
apsbss esaf 226319
apsbss proposal 66083 2020-2 9-ID-B,C
apsbss now 19-ID-D
apsbss esaf 276575
apsbss proposal 1010753 2024-3 12-ID-B

.. rubric:: Application
.. autosummary::

~cmd_esaf
~cmd_list
~cmd_now
~cmd_proposal
~cmd_report
~cmd_runs
~get_options
~main
Expand All @@ -30,10 +30,12 @@

~connect_epics
~epicsClear
~epicsReport
~epicsSetup
~epicsUpdate
"""

import datetime
import logging
import os
import sys
Expand Down Expand Up @@ -107,6 +109,65 @@ def epicsClear(prefix):
bss.status_msg.put("Done")


def epicsReport(args):
"""
Subcommand ``report``: EPICS PVs: report the PV values.

PARAMETERS

args
*obj* :
Object returned by ``argparse``
"""
bss = connect_epics(args.prefix)
print(bss._table(length=30))


def epicsSetup(prefix, beamline, run=None):
"""
Define the beamline name and APS run in the EPICS database.
Connect with the EPICS database instance.

PARAMETERS

prefix
*str* :
EPICS PV prefix
beamline
*str* :
Name of beam line (as defined by the BSS)
run
*str* :
Name of APS run (as defined by the BSS).
optional: default is current APS run name.
"""
bss = connect_epics(prefix)

run = run or server.current_run
sector = int(beamline.split("-")[0])
logger.debug(
"setup EPICS %s %s run=%s sector=%s",
prefix,
beamline,
run,
sector,
)

bss.status_msg.wait_for_connection()
bss.status_msg.put("clear PVs ...")

bss.wait_for_connection()
bss.clear()

bss.status_msg.put("write PVs ...")
bss.esaf.aps_run.put(run)
bss.proposal.beamline_name.put(beamline)
bss.esaf.sector.put(str(sector))
bss.status_msg.put("Done")

return bss


def epicsUpdate(prefix):
"""
Update EPICS database instance with current ESAF & proposal info.
Expand Down Expand Up @@ -179,13 +240,13 @@ def epicsUpdate(prefix):
proposal = server.proposal(proposal_id, beamline, run)

bss.status_msg.put("set Proposal PVs ...")
bss.proposal.end_date.put(str(proposal.endTime))
bss.proposal.end_date_timestamp.put(round(proposal.endTime.timestamp()))
bss.proposal.end_date.put(str(proposal.endDate))
bss.proposal.end_date_timestamp.put(round(proposal.endDate.timestamp()))
bss.proposal.mail_in_flag.put(proposal.mail_in)
bss.proposal.proprietary_flag.put(proposal.proprietary)
bss.proposal.raw.put(yaml.dump(proposal))
bss.proposal.start_date.put(str(proposal.startTime))
bss.proposal.start_date_timestamp.put(round(proposal.startTime.timestamp()))
bss.proposal.start_date.put(str(proposal.startDate))
bss.proposal.start_date_timestamp.put(round(proposal.startDate.timestamp()))
bss.proposal.submitted_date.put(str(proposal.submittedDate))
bss.proposal.submitted_date_timestamp.put(round(proposal.submittedDate.timestamp()))
bss.proposal.title.put(proposal.title)
Expand All @@ -211,51 +272,6 @@ def epicsUpdate(prefix):
bss.status_msg.put("Done")


def epicsSetup(prefix, beamline, run=None):
"""
Define the beamline name and APS run in the EPICS database.
Connect with the EPICS database instance.

PARAMETERS

prefix
*str* :
EPICS PV prefix
beamline
*str* :
Name of beam line (as defined by the BSS)
run
*str* :
Name of APS run (as defined by the BSS).
optional: default is current APS run name.
"""
bss = connect_epics(prefix)

run = run or server.current_run
sector = int(beamline.split("-")[0])
logger.debug(
"setup EPICS %s %s run=%s sector=%s",
prefix,
beamline,
run,
sector,
)

bss.status_msg.wait_for_connection()
bss.status_msg.put("clear PVs ...")

bss.wait_for_connection()
bss.clear()

bss.status_msg.put("write PVs ...")
bss.esaf.aps_run.put(run)
bss.proposal.beamline_name.put(beamline)
bss.esaf.sector.put(str(sector))
bss.status_msg.put("Done")

return bss


def get_options():
"""Handle command line arguments."""
global parser
Expand Down Expand Up @@ -317,6 +333,12 @@ def get_options():
)
p_sub.add_argument("beamlineName", type=str, help="Beamline name")

p_sub = subcommand.add_parser(
"now",
help="print information of proposals & ESAFs running now",
)
p_sub.add_argument("beamlineName", type=str, help="Beamline name")

p_sub = subcommand.add_parser(
"proposal",
help="print specific proposal for beamline and run",
Expand Down Expand Up @@ -347,7 +369,7 @@ def get_options():

def cmd_esaf(args):
"""
Handle ``esaf`` command.
Subcommand ``esaf``: print list of beamlines.

PARAMETERS

Expand All @@ -364,7 +386,7 @@ def cmd_esaf(args):

def cmd_list(args):
"""
Handle ``list`` command.
Subcommand ``list``: print proposals and ESAFs for beamline and run

PARAMETERS

Expand All @@ -374,52 +396,78 @@ def cmd_list(args):

New in release 1.3.9
"""
run = str(args.run).strip().lower()
sector = int(args.beamlineName.split("-")[0])
beamline = args.beamlineName
runs = server.parse_runs_arg(str(args.run).strip().lower())
sector = int(beamline.split("-")[0])

logger.debug("run: %s", run)
logger.debug("run(s): %s", runs)

print(f"Proposal(s): beam line {args.beamlineName}, run: {args.run}")
print(server._proposal_table(args.beamlineName, args.run))
for run in sorted(runs, reverse=True):
esafs = server.esafs(sector, run)
proposals = server.proposals(beamline, run)

print(f"ESAF(s): sector {sector}, run: {args.run}")
print(server._esaf_table(sector, args.run))
print(f"Proposal(s): beam line {beamline}, run(s): {', '.join(runs)}")
print(server.proposal_table(proposals))

print(f"ESAF(s): sector {sector}, run(s): {', '.join(runs)}")
print(server.esaf_table(esafs))

def cmd_proposal(args):

def cmd_now(args):
"""
Handle ``proposal`` command.
Subcommand ``now``: print information of proposals & ESAFs running now.

PARAMETERS

args
*obj* :
Object returned by ``argparse``

New in release 2.0.0
"""
try:
proposal = server.proposal(args.proposalId, args.beamlineName, args.run)
print(yaml.dump(proposal.to_dict()))
except Exception as reason:
print(f"Exception: {reason}")
beamline = args.beamlineName
targetDate = datetime.datetime.now().astimezone()
run = server.find_run(targetDate)
sector = beamline.split("-")[0]
esafs = [
esaf
for esaf in server.esafs(sector, run)
# formatting comment
if esaf.startDate <= targetDate <= esaf.endDate
]
props = {
prop.proposal_id: prop
for prop in server.proposals(beamline, run).values()
if prop.startDate <= targetDate <= prop.endDate
}

print(f"Proposal(s): beam line {beamline}, {targetDate}")
print(server.proposal_table(props))

print(f"ESAF(s): sector {sector}, {targetDate}")
print(server.esaf_table(esafs))


def cmd_report(args):
def cmd_proposal(args):
"""
Handle ``report`` command.
Subcommand ``proposal``: print specific proposal for beamline and run.

PARAMETERS

args
*obj* :
Object returned by ``argparse``
"""
bss = connect_epics(args.prefix)
print(bss._table(length=30))
try:
proposal = server.proposal(args.proposalId, args.beamlineName, args.run)
print(yaml.dump(proposal.to_dict()))
except Exception as reason:
print(f"Exception: {reason}")


def cmd_runs(args):
"""
Handle ``runs`` command.
Subcommand ``runs``: print APS run names.

PARAMETERS

Expand All @@ -432,16 +480,10 @@ def cmd_runs(args):
table.labels = "run start end".split()

def sorter(run):
return run["startTime"]
return run.startDate

for run in sorted(server._runs.values(), key=sorter, reverse=args.ascending):
table.addRow(
(
run["name"],
run["startTime"],
run["endTime"],
)
)
table.addRow((str(run), run.startDate, run.endDate))
print(str(table))
else:
printColumns(server.runs)
Expand All @@ -465,6 +507,9 @@ def main():
elif args.subcommand == "list":
cmd_list(args)

elif args.subcommand == "now":
cmd_now(args)

elif args.subcommand == "proposal":
cmd_proposal(args)

Expand All @@ -475,7 +520,7 @@ def main():
epicsUpdate(args.prefix)

elif args.subcommand == "report":
cmd_report(args)
epicsReport(args)

else:
parser.print_usage()
Expand Down
11 changes: 2 additions & 9 deletions apsbss/bss_dm.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

from .core import DM_APS_DB_WEB_SERVICE_URL
from .core import ProposalBase
from .core import Run
from .core import ScheduleInterfaceBase
from .core import iso2dt

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -76,12 +76,5 @@ def proposals(self, beamline, run) -> dict:
def _runs(self) -> list:
"""List of details of all known runs."""
if "listRuns" not in self._cache:
self._cache["listRuns"] = [
{
"name": run["name"],
"startTime": iso2dt(run["startTime"]),
"endTime": iso2dt(run["endTime"]),
}
for run in self.api.listRuns()
]
self._cache["listRuns"] = [Run(run) for run in self.api.listRuns()]
return self._cache["listRuns"]
Loading
Loading