Waveform of strings no longer works
Closed this issue · 3 comments
This:
labels = builder.WaveformOut(
"ENUM:LABELS", initial_value=[b"ZERO", b"ONE", b"MANY"]
)
used to give a waveform with FTVL
of STRING
under pythonSoftIOC 3.2, but now it gives:
Traceback (most recent call last):
File "/dls/science/users/tmc43/common/python/PandABlocks-client/pandablocks/ioc/ioc.py", line 1490, in create_record
self, record_name, field_info, str_vals
File "/dls/science/users/tmc43/common/python/PandABlocks-client/pandablocks/ioc/ioc.py", line 943, in _make_bit_mux
initial_value=[b"ZERO", b"ONE", b"MANY"]
File "/scratch/tmc43/pipenv/PandABlocks-client-0xhNhEPE/lib/python3.7/site-packages/softioc/builder.py", line 226, in WaveformOut
_waveform(value, fields)
File "/scratch/tmc43/pipenv/PandABlocks-client-0xhNhEPE/lib/python3.7/site-packages/softioc/builder.py", line 215, in _waveform
fields['FTVL'] = NumpyDtypeToDbf[datatype.name]
KeyError: 'bytes32'
Interesting regression. Do you feel like bisecting it? Unfortunately 3.2 is quite a long way back, it may be simpler to reimplement the functionality!
I didn't realise that arrays of strings actually worked.
I'm investigating it now. There has been a large amount of changes in this area unfortunately. I'll see what I can do.
I've found most of the missing pieces from the 3.2 -> 4.* change that broke this:
The mapping between types changed rather a lot. The old NumpyCharCodeToDbr
mapping was replaced by NumpyDtypeToDbf
(and other bits). Adding this mapping: 'bytes32': 'STRING'
means we can initialize a Waveform of the given form without error, but caget
'ing it doesn't work right.
The second major change is WaveformBase._write_value
. Previously there was a call to numpy.require()
using a saved dtype
(inferred earlier in the initialisation process) that was set to "S40" i.e. an EPICS string. That conversion step just doesn't exist anymore. Hacking it by just adding this line at the beginning of the method: value = numpy.require(value, dtype=numpy.dtype('S40'))
makes everything almost work:
>>> caget("AAA:AAA")
ca_array(['ZERO', '', ''], dtype='<U4')
I haven't yet worked out why elements 1 and 2 are now empty. And I'm not sure what the proper fix of the _write_value
method is, but it's nearly there.