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
25 changes: 24 additions & 1 deletion docs/tutorials/virtac_example.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ used by convention at Diamond for simulations) to avoid conflict with the same
PVs on the live machine.


## Start the virtual accelerator
## Starting the virtual accelerator

Once ATIP has been installed using pip or by running the docker image:

Expand Down Expand Up @@ -56,6 +56,29 @@ $ # or: . changeports 6064
In this new terminal you are then free to address the simulator as you would
the live machine, either through Pytac or by directly accessing the PVs.

## Command Line Options:

Usage::

virtac [-h] [--disable-emittance] [--enable-tfb] [--verbose] [ring_mode]

Positional arguments::

ring_mode The ring mode to be used, e.g., IO4 or DIAD

Optional arguments::

-h, --help show this help message and exit
-d, --disable-emittance
Disable the simulator's time-consuming emittance
calculation
-t, --enable-tfb Simulate extra dummy hardware to be used by the Tune
Feedback system
-v, --verbose Increase output and logging verbosity

N.B. The relatively slow emittance calculation is enabled by default, if the
virtac isn't as performant as your would like try disabling it using ``-d``.

## Feedback Records:

A number of PVs related to feedback systems are supported. These have been
Expand Down
26 changes: 17 additions & 9 deletions src/virtac/atip_ioc_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,29 @@
def parse_arguments():
"""Parse command line arguments sent to virtac"""
parser = argparse.ArgumentParser()
parser.add_argument("ring_mode", nargs="?", type=str, help="Ring mode name")
parser.add_argument(
"--disable-emittance",
"ring_mode",
nargs="?",
type=str,
help="The ring mode to be used, e.g., IO4 or DIAD",
)
parser.add_argument(
"-d",
help="disable the simulator's time-consuming emittance calculation",
"--disable-emittance",
help="Disable the simulator's time-consuming emittance calculation",
action="store_true",
)
parser.add_argument(
"--enable-tfb",
"-t",
help="simulate extra dummy hardware to be used by the Tune Feedback system",
"--enable-tfb",
help="Simulate extra dummy hardware to be used by the Tune Feedback system",
action="store_true",
)
parser.add_argument(
"--verbose", "-v", help="increase output verbosity", action="store_true"
"-v",
"--verbose",
help="Increase logging verbosity",
action="store_true",
)
return parser.parse_args()

Expand Down Expand Up @@ -66,7 +74,7 @@ def main():
DATADIR / ring_mode / "feedback.csv",
DATADIR / ring_mode / "mirrored.csv",
DATADIR / ring_mode / "tunefb.csv",
not args.disable_emittance,
args.disable_emittance,
)

# Warn if set to default EPICS port(s) as this will likely cause PV conflicts.
Expand Down Expand Up @@ -108,5 +116,5 @@ def main():
server.monitor_mirrored_pvs()
if args.enable_tfb:
server.setup_tune_feedback()

softioc.interactive_ioc(globals())
context = globals() | {"server": server}
softioc.interactive_ioc(context)
12 changes: 8 additions & 4 deletions src/virtac/atip_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ def _create_records(self, limits_csv, disable_emittance):
float(line["upper"]),
float(line["lower"]),
int(line["precision"]),
float(line["drive high"]),
float(line["drive low"]),
)

bend_in_record = None
Expand All @@ -190,8 +192,8 @@ def _create_records(self, limits_csv, disable_emittance):
field, units=pytac.ENG, data_source=pytac.SIM
)
get_pv = element.get_pv_name(field, pytac.RB)
upper, lower, precision = limits_dict.get(
get_pv, (None, None, None)
upper, lower, precision, drive_high, drive_low = limits_dict.get(
get_pv, (None, None, None, None, None)
)
builder.SetDeviceName(get_pv.split(":", 1)[0])
in_record = builder.aIn(
Expand All @@ -209,12 +211,14 @@ def _create_records(self, limits_csv, disable_emittance):
except HandleException:
self._rb_only_records.append(in_record)
else:
upper, lower, precision = limits_dict.get(
set_pv, (None, None, None)
upper, lower, precision, drive_high, drive_low = (
limits_dict.get(set_pv, (None, None, None, None, None))
)
builder.SetDeviceName(set_pv.split(":", 1)[0])
out_record = builder.aOut(
set_pv.split(":", 1)[1],
DRVH=drive_high,
DRVL=drive_low,
LOPR=lower,
HOPR=upper,
PREC=precision,
Expand Down
43 changes: 32 additions & 11 deletions src/virtac/create_csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,13 @@ def generate_bba_pvs(all_elements, symmetry):
data.append((elem.index, "bba_offset_x", pv_stem + ":CF:BBA_X_S", 0, "ao"))
data.append((elem.index, "bba_offset_y", pv_stem + ":CF:BBA_Y_S", 0, "ao"))
for cell in range(1, symmetry + 1):
cell = str(cell).zfill(2)
pv_stem = f"SR{cell}A-CS-FOFB-01"
padded_cell = str(cell).zfill(2)
pv_stem = f"SR{padded_cell}A-CS-FOFB-01"
# Waveform records
data.append(
(
cell,
f"cell_{cell}_excite_start_times",
f"cell_{padded_cell}_excite_start_times",
f"{pv_stem}:EXCITE:START_TIMES",
numpy.zeros(18),
"wfm",
Expand All @@ -112,7 +112,7 @@ def generate_bba_pvs(all_elements, symmetry):
data.append(
(
cell,
f"cell_{cell}_excite_amps",
f"cell_{padded_cell}_excite_amps",
f"{pv_stem}:EXCITE:AMPS",
numpy.zeros(18),
"wfm",
Expand All @@ -121,7 +121,7 @@ def generate_bba_pvs(all_elements, symmetry):
data.append(
(
cell,
f"cell_{cell}_excite_deltas",
f"cell_{padded_cell}_excite_deltas",
f"{pv_stem}:EXCITE:DELTAS",
numpy.zeros(18),
"wfm",
Expand All @@ -130,7 +130,7 @@ def generate_bba_pvs(all_elements, symmetry):
data.append(
(
cell,
f"cell_{cell}_excite_ticks",
f"cell_{padded_cell}_excite_ticks",
f"{pv_stem}:EXCITE:TICKS",
numpy.zeros(18),
"wfm",
Expand All @@ -140,7 +140,7 @@ def generate_bba_pvs(all_elements, symmetry):
data.append(
(
cell,
f"cell_{cell}_excite_prime",
f"cell_{padded_cell}_excite_prime",
f"{pv_stem}:EXCITE:PRIME",
0,
"ao",
Expand All @@ -157,13 +157,20 @@ def generate_pv_limits(lattice):
lattice (pytac.lattice.Lattice): The pytac lattice being used by the virtual
machine
"""
data = [("pv", "upper", "lower", "precision")]
data = [("pv", "upper", "lower", "precision", "drive high", "drive low")]
for element in lattice:
for field in element.get_fields()[pytac.SIM]:
pv = element.get_pv_name(field, pytac.RB)
ctrl = caget(pv, format=FORMAT_CTRL)
data.append(
(pv, ctrl.upper_ctrl_limit, ctrl.lower_ctrl_limit, ctrl.precision)
(
pv,
ctrl.upper_ctrl_limit,
ctrl.lower_ctrl_limit,
ctrl.precision,
ctrl.upper_disp_limit,
ctrl.lower_disp_limit,
)
)
try:
pv = element.get_pv_name(field, pytac.SP)
Expand All @@ -172,7 +179,14 @@ def generate_pv_limits(lattice):
else:
ctrl = caget(pv, format=FORMAT_CTRL)
data.append(
(pv, ctrl.upper_ctrl_limit, ctrl.lower_ctrl_limit, ctrl.precision)
(
pv,
ctrl.upper_ctrl_limit,
ctrl.lower_ctrl_limit,
ctrl.precision,
ctrl.upper_disp_limit,
ctrl.lower_disp_limit,
)
)
return data

Expand Down Expand Up @@ -347,9 +361,11 @@ def write_data_to_file(data, filename, ring_mode):
filepath = os.path.join(
os.path.abspath(os.path.dirname(__file__)), "data", ring_mode, filename
)
column_titles = data[0]
sorted_data = sorted(data[1:])
with open(filepath, "w", newline="") as file:
csv_writer = csv.writer(file)
csv_writer.writerows(data)
csv_writer.writerows([column_titles] + sorted_data)


def parse_arguments():
Expand Down Expand Up @@ -397,13 +413,18 @@ def parse_arguments():
args = parse_arguments()
lattice = atip.utils.loader(args.ring_mode)
all_elements = atip.utils.preload(lattice)
print("Creating feedback PVs CSV file.")
data = generate_feedback_pvs(all_elements, lattice)
write_data_to_file(data, args.feedback, args.ring_mode)
print("Creating BBA PVs CSV file.")
data = generate_bba_pvs(all_elements, lattice.symmetry)
write_data_to_file(data, args.bba, args.ring_mode)
print("Creating limits PVs CSV file.")
data = generate_pv_limits(lattice)
write_data_to_file(data, args.limits, args.ring_mode)
print("Creating mirrored PVs CSV file.")
data = generate_mirrored_pvs(lattice)
write_data_to_file(data, args.mirrored, args.ring_mode)
print("Creating tune PVs CSV file.")
data = generate_tune_pvs(lattice)
write_data_to_file(data, args.tune, args.ring_mode)
Loading
Loading