Skip to content

RFC: Embed our knowledge of VSFR types into the batch reader #49

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 1 commit into
base: master
Choose a base branch
from

Conversation

ckuethe
Copy link
Contributor

@ckuethe ckuethe commented May 5, 2025

Following on to #48 , I thought I might do some initial work on simplifying the batch_read_vsfrs() API. As best I can tell, radiacode transports all VSFRs as uint32le on the wire, no matter how many information-bearing bits they contain: a bool takes 32 bits, just like a float.

Conveniently, the SFR_FILE VS tells us which VSFR IDs are defined, and how to interpret them. It is fairly straightforward to parse the output of the commands() function which reads the SFR_FILE to produce a dict of format strings.

I updated batch_read_vsfrs() and its callers to omit the format argument, and just use the lookup dict to figure out what format to use.

As a quick test, the get_alarm_limits() function works correctly, as does the hand-rolled equivalent of energy_calib(): rc.batch_read_vsfrs([ CHN_TO_keV_A0, CHN_TO_keV_A1, CHN_TO_keV_A2])

Thoughs?

PS. here's the trashy script I used to generate the body of the lookup dict...

import iniconfig
import radiacode

cf = iniconfig.IniConfig('', data=radiacode.RadiaCode().commands())

for k in cf.sections:
    v = dict(cf[k].items())
    k = k.removeprefix('RC_').removeprefix('VSFR_')
    c = None
    if v.get('Type', "") == 'float':
        c = 'f'
    else:
        if v.get('Size', False) == '1':
            if v.get('Min', False) == '0' and v.get('Max', False) == '1':
                c = '3x?'
            else:
                c = '3xb' if v.get('Signed', False) == '1' else '3xB'
        elif v.get('Size', False) == '2':
            c = '2xh' if v.get('Signed', False) == '1' else '2xH'
        elif v.get('Size', False) == '4':
            c = 'i' if v.get('Signed', False) == '1' else 'I'

    print(f"\tVSFR.{k}: '{c}',")

As best I can tell, radiacode transports all VSFRs as uint32le on the wire,
no matter how many information-bearing bits they contain: a bool takes 32
bits, just like a float.

Conveniently, the SFR_FILE VS tells us which VSFR IDs are defined, and how
to interpret them. It is fairly straightforward to parse the output of the
`commands()` function which reads the `SFR_FILE` to produce a dict of format
strings.

Update `batch_read_vsfrs()` and its callers to omit the format argument,
and just use the lookup dict to figure out what format to use.

As an initial test, the `get_alarm_limits()` function works correctly, as
does the hand-rolled equivalent of `energy_calib()`:

`rc.batch_read_vsfrs( [ CHN_TO_keV_A0, CHN_TO_keV_A1, CHN_TO_keV_A2 ] )`

```
import iniconfig

cf = iniconfig.IniConfig('', data=radiacode.RadiaCode().commands())

for k in cf.sections:
    v = dict(cf[k].items())
    k = k.removeprefix('RC_').removeprefix('VSFR_')
    c = None
    if v.get('Type', "") == 'float':
        c = 'f'
    else:
        if v.get('Size', False) == '1':
            if v.get('Min', False) == '0' and v.get('Max', False) == '1':
                c = '3x?'
            else:
                c = '3xb' if v.get('Signed', False) == '1' else '3xB'
        elif v.get('Size', False) == '2':
            c = '2xh' if v.get('Signed', False) == '1' else '2xH'
        elif v.get('Size', False) == '4':
            c = 'i' if v.get('Signed', False) == '1' else 'I'

    print(f"\tVSFR.{k}: '{c}',")
```
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.

1 participant