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

Block properties: allow variable expressions for enum fields #6870

Open
eltos opened this issue Sep 27, 2023 · 12 comments · May be fixed by #6991
Open

Block properties: allow variable expressions for enum fields #6870

eltos opened this issue Sep 27, 2023 · 12 comments · May be fixed by #6991

Comments

@eltos
Copy link
Contributor

eltos commented Sep 27, 2023

Feature Description

Block properties with dtype: enum are the only properties which can not be controlled dynamically by variables or expressions.
The drop-down menu for enums simply does not allow entering variables names.

Take the File source as an example:
Here "Repeat" is even runtime-adjustable, but because it is not possible to assign it via a variable, there is no way to actually change it at runtime, nor can it be exposed as a parameter if used inside a hier block.

-   id: repeat
    label: Repeat
    dtype: enum
    default: 'True'
    options: ['True', 'False']
    option_labels: ['Yes', 'No']

grafik

It would be good to have the ability to enter expressions, similar to how it is done for other types which have option_labels defined, for example File sink:

-   id: unbuffered
    label: Unbuffered
    dtype: bool
    default: 'False'
    options: ['False', 'True']
    option_labels: ['Off', 'On']

grafik

In this very specific example, one could also change enum to bool, but this feature request is about a general way to solve this constraint.

As a nice side effect, this would also allow creating type-dynamic hier blocks by controlling the blocks "Type" parameter (which is an enum) via a common variable that could be exposed as a (non-runtime adjustable) hier-block parameter.

Feature Urgency

high (impacts broad portion of ecosystem)

More Information

For simplicity, it should also be possible to use the string representation of the enum to select it via the variable, e.g. for the "repeat" parameter above, a string variable with values "True", "False", "Yes" or "No" would be valid (not sure if case-sensitivity should be enforced).

/label GRC

@martinling
Copy link

martinling commented Dec 5, 2023

Here's a real-world use case where the lack of this feature is extremely painful.

I've just published a DVB-S2 receiver test flowgraph which outputs three adjacent signals.

Generating a DVB-S2 signal requires a series of 7 different specialised blocks, but because of the way the protocol works, all of these blocks need to know the main modulation and coding parameters. And they're all configured as enums.

So if, for instance you want to change the code rate from 1/2 to 1/4 in this flowgraph, you need to change it by hand on 21 different blocks:

dvbs2_rx_test

@AsriFox
Copy link
Contributor

AsriFox commented Dec 5, 2023

I agree! I have encountered the DVB-S2 enum problem as well.
Fortunately, in GRC all values are basically strings interpreted by Python / Mako templates. It means we can do workarounds in block definitions (.block.yml) like this:

parameters:
- id: constellation
  label: Signal Constellation
  dtype: string
  default: MOD_QPSK
  options: [ MOD_QPSK, MOD_8PSK ]
  option_labels: [ 'QPSK', '8PSK' ]

templates:
  imports: from gnuradio import dtv
  make: dtv.dvbs2_modulator_bc(dtv.FECFRAME_NORMAL, dtv.${rate}, dtv.${constellation}, dtv.INTERPOLATION_OFF)

Because dtype is string, you can input variable names and even python expressions in this field. This also works when dtype is set to int or bool.
Unfortunately, there are no checks against options when interpreting values - they just get passed into templates as strings.

@martinling
Copy link

@AsriFox thanks but I don't really see how this helps in practice.

I want some non-experts to be able to clone the repository that contains that flowgraph and use it. I don't want them to need to edit their GNU Radio installation to do so.

Is there some way to apply this trick using some sort of flowgraph-local block definitions? Maybe with a hierarchical block or something?

@AsriFox
Copy link
Contributor

AsriFox commented Dec 5, 2023

Yes. Drop dvbs2wrapper_modulator_bc.block.yml in ~/.grc_gnuradio and try opening dvbs2wrapper_example.grc in GNURadio Companion.
dvbs2wrapper.zip
Other blocks can be wrapped similarly. Note that string doesn't support option_attributes, so all comparisons are manual.

@martinling
Copy link

Thanks @AsriFox, that's indeed a useful trick, but it's definitely not a substitute for properly implementing this feature.

Thinking a bit more about it, just having the ability to set an enum field to a variable expression isn't really sufficient to make this work nicely, there's some related things needed too:

  • It should be possible to create a variable with a specific enum type, such that you can use a dropdown when editing the variable block to select the value. It would probably be best to make this a separate Enum Variable block, since it would work a bit differently to a regular Variable block. You'd need to be able to choose a specific enum type for it.

  • There ought to be some QT GUI block that does the same thing, so that you can switch enum values in a running flowgraph.

@marcusmueller
Copy link
Member

marcusmueller commented Dec 5, 2023

@martinling @AsriFox bit of architectural cross-inspiration here: Blocks in GNU Radio's tree are of different vintages and development focuses. If we were to add such a block today, we'd recommend to not solve this (solely) through variables with callbacks (which, as implemented, is an extremely Python+GRC approach to things), but expect it to have a message input through which such settings can be easily done from other elements of the flowgraph, including other blocks.

Anyways, this (and most blocks) won't have a message input in the short term, so, bit of a moot point, but maybe an inspiration should this progress at some point to a situation where anyone sees themselves writing a block.

Regarding:

There ought to be some QT GUI block that does the same thing, so that you can switch enum values in a running flowgraph.

Have a variable that's just a python tuple of all valid values, say with ID choices.
Use the Qt GUI chooser with, say, ID choice_index, to select an integer [0, len(choices)[. In the block you're using these choices, you do choices[choice_index] :)

@dkozel
Copy link
Contributor

dkozel commented Dec 5, 2023

If we wanted to make this change I believe the only alteration would be changing line 38 to use EnumEntryParam rather than EnumParam.

elif dtype == 'enum':
input_widget_cls = ParamWidgets.EnumParam
elif self.options:
input_widget_cls = ParamWidgets.EnumEntryParam

@AsriFox
Copy link
Contributor

AsriFox commented Dec 5, 2023

@marcusmueller I think the main issue is the (in)ability to bind block parameters of type enum to external variables. It's useful for changing parameters of many blocks at once, like in the DVB-S2 example. My string workaround provides that ability, but loses enum's strict set of options and the convenience of option_attributes.
I do have an idea for a solution, inspired by the StrictYAML schemas.

@dkozel
Copy link
Contributor

dkozel commented Dec 5, 2023

Changing to using EnumEntryParam is the start of an answer, but doesn't actually work. Entering a variable or python expression is not evaluated and value silently switches back to the default enum choice on closing the block properties. Also I have a bug where I have to click the field twice to select the text entry box for the EnumEntryParam. I think this entry type is broken, fixing it properly would be good and I agree that being able to programmatically set an enum property is an obvious and desirable feature.

@AsriFox If you have an idea of how to having a way of passing in a programmatic value for the enum while both preserving the type safety and making the UI clear about whether a static value from the dropdown of valid enum values or a dynamic variable or equation has been entered that would be great to hear.

@marcusmueller Agreed, messages and/or tags are a great solution for changing at runtime, but supporting the use of variables for enum fields is just taking the existing functionality of all other parameter data types and extending it to enums. Making design patterns/features work more universally and consistently seems a straightforward improvement.

@martinling
Copy link

Have a variable that's just a python tuple of all valid values, say with ID choices. Use the Qt GUI chooser with, say, ID choice_index, to select an integer [0, len(choices)[. In the block you're using these choices, you do choices[choice_index] :)

This is a nice idea in principle, but have you seen the number of coding and modulation options for DVB-S2? 😢

@martinling
Copy link

In my particular use case, an enum variable block is exactly what's desired. Changing these settings at runtime is not very practical, since changing the modulation and coding parameters changes the maximum stream rate, and then you need to produce different video data. Which currently requires manual experimentation to find the right encoder settings.

@AsriFox
Copy link
Contributor

AsriFox commented Dec 5, 2023

@martinling DVB-S2 parameters have a unique problem: there is a lot of them, and not all of them are compatible with one another. For example, there are only three code rates for FECFRAME_MEDIUM, but they are in the same dtv.dvb_code_rate enum. A Python solution to this exact problem is used in Igor Freire's DVB-S2 receiver. If you install that OOT, you will be able to use it in GRC.

AsriFox added a commit to AsriFox/gnuradio that referenced this issue Dec 5, 2023
Fixes gnuradio#6870

Signed-off-by: AsriFox <asrifox@yandex.ru>
AsriFox added a commit to AsriFox/gnuradio that referenced this issue Dec 5, 2023
Fixes gnuradio#6870

Signed-off-by: AsriFox <asrifox@yandex.ru>
@AsriFox AsriFox linked a pull request Dec 5, 2023 that will close this issue
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants