Skip to content

Create a new device class for tcavs #261

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

Open
wants to merge 30 commits into
base: main
Choose a base branch
from

Conversation

phys-cgarnier
Copy link
Collaborator

@phys-cgarnier phys-cgarnier commented Apr 18, 2025

TCAV Device class:
Changed generator.py to include extract_tcav function. Also implemented advanced filtering in extract devices. You can pass an unpacked dictionary that is organized by {field_name: expected value}
For example :
additional_filter_constraints = {"Engineering Name": "TRANS_DEFL"}
Added relevant fields to metadata.py

@phys-cgarnier phys-cgarnier linked an issue Apr 18, 2025 that may be closed by this pull request
@phys-cgarnier phys-cgarnier changed the title 254 create a new device class for tcavs Create a new device class for tcavs Apr 22, 2025
Copy link
Collaborator

@eloise-nebula eloise-nebula left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Chris, looks consistent with our other device classes. I found a bunch of places where pydantic validation could replace your manual validation. This device is unique because its configuration depends on its mode_config, but I think that's handled well here. Once we figure out the validation stuff.

def set_mode_config_option(self):
mode_config_options = self.PVs.mode_configs.get_ctrlvars(timeout=1)
if mode_config_options:
[
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fewer lines to write this for loop as:

for i, option in enumerate(mode_config_options["enum_strs"]):
    self._mode_config_options.update({option: i})

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure I can do that, I was trying to make this as close to a match to magnet.py as possible but I can clean it up.

super(TCAVControlInformation, self).__init__(*args, **kwargs)

def set_mode_config_option(self):
mode_config_options = self.PVs.mode_configs.get_ctrlvars(timeout=1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this code error out if get_ctrlvars times out? What's the use case for a TCAV without mode_config_options?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe (although am unable to confirm at this time), that you cannot or should not be setting other pvs in the tcav while TCAV:DIAG0:11:MODECFG is in the Disable state. The use case would then be just read only for the TCAV PVs

options = [options_to_check]
for option in options:
if option not in self.controls_information.mode_config_options:
print(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think an error here would be more appropriate. As it stands, the check_options decorator doesn't do anything to communicate to the code that something went wrong.


def decorated(self, *args, **kwargs):
if self.mode_config == "Disable":
print("Unable to perform action, TCAV is in Disabled state")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another place where an error might be better than a print statement.


@amp_set.setter
@check_state
def amp_set(self, amplitude):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pydantic lets you validate function arguments with function annotations like so:

def amp_set(self, amplitude: float):

The if statement shouldn't be necessary.

@amp_fbenb.setter
@check_state
def amp_fbenb(self, state: Union[str, int]):
if not isinstance(state, str) or not isinstance(state, int):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pydantic should already be validating this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, the expected type is actually an enum_str, I couldn't get the validation to work how I thought I could.
Unless I made the properties pydantic objects

@phase_fbenb.setter
@check_state
def phase_fbenb(self, state: Union[str, int]):
if not isinstance(state, str) or not isinstance(state, int):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another place where pydantic covers function validation.

@amp_fbst.setter
@check_state
def amp_fbst(self, state: Union[str, int]):
if not isinstance(state, str) or not isinstance(state, int):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

@phase_fbst.setter
@check_state
def phase_fbst(self, state: Union[str, int]):
if not isinstance(state, str) or not isinstance(state, int):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.


@l_eff.setter
def l_eff(self, length):
if not isinstance(length, float):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pydantic validation could replace this.

controls_information: SerializeAsAny[TCAVControlInformation]
metadata: SerializeAsAny[TCAVMetadata]

def __init__(self, *args, **kwargs):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need an __init__ function when using Pydantic

Copy link
Collaborator

@kabanaty kabanaty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good in general. Some cleanup to be done with implementing Pydantic validation in some of the TCAV properties.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create a new device class for TCAVs
3 participants