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

draft: sketched out SO interface CI workflow. #798

Draft
wants to merge 5 commits into
base: main
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
15 changes: 15 additions & 0 deletions .github/workflows/interface_ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

name: interface-ci
on: [pull_request]

jobs:
check-so-interface:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./tests/ci
steps:
- name: Check out the repository to the runner
uses: actions/checkout@v4
- name: Check SO interface spec
run: python ./check_so_interface.py
Binary file added tests/.DS_Store
Binary file not shown.
250 changes: 250 additions & 0 deletions tests/ci/check_so_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
import ast
# functions and their arguments to check
# specified here: https://www.overleaf.com/project/5e837cac9659910001e5f71e
# could move this to a file
#to complete: work on functions and arguments to check file and spec_args dictionary

#Files that need to be checked: smurf_tune, smurf_command, smurf_util, smurf_noise, smurf_iv
#python/pysmurf/client/util/smurf_util.py
#python/pysmurf/client/command/smurf_command.py
#python/pysmurf/client/debug/smurf_noise.py
#python/pysmurf/client/debug/smurf_iv.py
interface = {
"python/pysmurf/client/tune/smurf_tune.py": { # file
"SmurfTuneMixin": { # class
"find_freq": [], # function and args
}
},
"python/pysmurf/client/command/smurf_command.py": {
"SmurfCommandMixin": {
"set_stream_enable": []
}
},
"python/pysmurf/client/util/smurf_util.py": {
"SmurfUtilMixin": {
"which_on": []
}
},
"python/pysmurf/client/debug/smurf_iv.py": {
"SmurfIVMixin": {
"run_iv": []
}
},
"python/pysmurf/client/debug/smurf_noise.py": {
"SmurfNoiseMixin": {
"take_noise_psd" : []
}
}
}

spec_args = {
"setup": [

],
"set_amplifier_bias": [

],
"set_cryo_card_ps_en": [

],
"which_on": [

],
"band_off": [

],
"channel_off": [

],
"full_band_resp": [

],
"find_freq": [

],
"setup_notches": [

],
"run_serial_gradient_descent": [

],
"run_serial_eta_scan": [

],
"plot_tune_summary": [

],
"tracking_setup": [

],
"set_amplitude_scale_array": [

],
"set_tes_bias_bipolar_array": [

],
"set_tes_bias_high_current": [

],
"set_tes_bias_low_current": [

],
"set_mode_dc" "set_mode_ac": [

],
"flux_ramp_setup": [

],
"set_stream_enable": [

],
"take_stream_data": [

],
"take_noise_psd": [

],
"stream_data_on": [

],
"stream_data_off": [

],
"read_stream_data": [

],
"set_downsample_filter": [

],
"run_iv": [

],
"analyze_iv": [

]
}
freeze = {}

with open('tests/ci/frozen_functions.py', 'r') as fh: #opens file "fname", in read mode 'r', to be used in code as "fh"
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

what is going to be stored in this file? Is it a pseudo-python representation of the objects/methods structure that define the interface?

frozen = ast.parse(fh.read())
for node in ast.walk(frozen):
if isinstance(node, ast.FunctionDef) and node.name in spec_args.keys():
freeze.update({node.name: node})
print("FROZEN")
Copy link
Collaborator

Choose a reason for hiding this comment

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

There's a lot of these print checks I put along the way to debug, and visualize the flow of my code. I haven't deleted them yet because I wanted to keep them in here to remember good places/dictionaries and lists to check in my code for future debugging. A final version of this code will definitely have these removed.

print(freeze.items())
"""
*** ==> I found this function in smurf_tune.py
frozen functions list:

SETUP FUNCTIONS
setup
set_amplifier_bias #smurf_command
set_cryo_card_ps_en #smurf_command
which_on #smurf_util
band_off #smurf_util
channel_off #smurf_util

TUNING FUNCTIONS
full_band_resp ***
find_freq ***
setup_notches ***
run_serial_gradient_descent #smurf_command
run_serial_eta_scan #smurf_command
plot_tune_summary ***
tracking_setup ***
set_amplitude_scale_array #smurf_command

TES/FLUX RAMP FUNCTIONS
set_tes_bias_bipolar_array #smurf_util
set_tes_bias_high_current #smurf_util
set_tes_bias_low_current #smurft_util
set_mode_dc #smurf_util
set_mode_ac #smurf_util
flux_ramp_setup ***

DATA ACQUISITION FUNCTIONS
set_stream_enable #smurf_command
take_stream_data #smurf_util
take_noise_psd #smurf_noise
stream_data_on #smurf_util
stream_data_off #surf_util
read_stream_data #smurf_util
set_downsample_filter #smurf_util

IV FUNCTIONS
run_iv #smurf_iv
analyze_iv #smurf_iv

DATA OUTPUTS TO DISK
tune files generated when new resonators are found
channel mapping file format
.dat noise files - generated by take_stream_data
iv_files - generated by run_iv"

"""
def compare_args(found, freeze):
#print(freeze.values())
for func_name, func_node in found.items():
if func_name not in freeze:
print(func_name + " not in specified functions")
continue

spec_func = freeze[func_name]
#print(freeze[func_name])
if spec_func == []:
print("waht")

# Handle the case where spec_func is a list
if isinstance(spec_func, list):
if len(spec_func) == 0:
print(f"No specification for {func_name}")
continue
spec_func = spec_func[0] # Assume the function is the first item in the list

# Extract arguments from the AST node
found_args = [arg.arg for arg in func_node.args.args]
#print(found_args)
found_defaults = [ast.unparse(d) if d else None for d in func_node.args.defaults]
#print(found_defaults)

# Extract arguments from the spec function
spec_args_list = [arg.arg for arg in spec_func.args.args]
spec_defaults = [ast.unparse(d) if d else None for d in spec_func.args.defaults]

# Compare arguments
if found_args != spec_args_list:
print(f"Mismatch in arguments for function {func_name}")
print(f"Found: {found_args}")
print(f"Expected: {spec_args_list}")
return False

# Compare default values
if found_defaults != spec_defaults:
print(f"Mismatch in default values for function {func_name}")
print(f"Found: {found_defaults}")
print(f"Expected: {spec_defaults}")
return False

return True

if __name__ == "__main__": #if this is the main thing being run
for fname, spec in interface.items(): #loop over file names "fname" as keys and "spec" as values in dictionary called "interface"
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

currently interface is not defined

with open(fname, 'r') as fh: #opens file "fname", in read mode 'r', to be used in code as "fh"
tree = ast.parse(fh.read()) #parsing contents of file into abstract syntax tree
notfound = []
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

these two lines don't need to be in the context manager

found = {}
dump = ast.dump(tree)
for node in ast.walk(tree):
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the first layer in the tree is usually going to be made up of ClassDef objects (though not always), which in turn contain FunctionDef's. The original sketch had a check for this.

if isinstance(node, ast.FunctionDef) and node.name in spec_args.keys():
found.update({node.name: node})
for key in spec_args:
if key not in found:
notfound.append(key)
#print("FOUND:")
#print(found.items())
#print("NOT FOUND:")
#print(notfound)
#compare arguments
assert compare_args(found, freeze)
#print(ast.dump(found.get('find_freq')))
pass
Loading
Loading