epics-base / p4p

Python bindings for the PVAccess network client and server.
BSD 3-Clause "New" or "Revised" License
27 stars 38 forks source link

Fix NTNDArray, add missing fields #23

Closed tynanford closed 5 years ago

tynanford commented 5 years ago

CS Studio was having issues with the current incomplete type definition for the NTNDArray. Added all the missing fields for the NTNDArray type and it resolved the display issue in CS Studio.

mdavidsaver commented 5 years ago

Can you be more specific about what additional fields cs-studio now requires? Also, can you provide a link to some code which is filling in the expanded structure? (I'm curious to see this in action)

My concern is about providing reasonable defaults for some of these fields. eg. dimension[].binning will default to 0, which isn't valid. Similarly, uncompressedSize and uncompressedSize should not be zero unless the image itself is empty. Would you have time to update p4p.nt.ndarray.NTNDArray.wrap() to fill in reasonable defaults?

I take it you are filling these definitions out based on http://epics-pvdata.sourceforge.net/alpha/normativeTypes/normativeTypes_20150316.html#ntndarray ?

@shroffk @brunoseivam fyi.

tynanford commented 5 years ago

Yes I have time to update the defaults in the wrap() method I will update the pull request.

I tested and found that the only new field that cs-studio requires was the bool reverse field in the dimension structure. This buildType method for the ndarray will work for displaying in cs-studio.

class NTNDArray(object):
    """Representation of an N-dimensional array with meta-data
    """
    Value = Value
    ntndarray = ntndarray

    @staticmethod
    def buildType(extra=[]):
        """Build type
        """
        return Type([
            ('value', 'v'),
            ('alarm', alarm),
            ('timeStamp', timeStamp),
            ('dimension', ('aS', None, [
                ('size', 'i'),
                ('reverse', '?'),   # New required field
            ])),
            ('attribute', ('aS', None, [
                ('name', 's'),
                ('value', 'v'),
            ])),
        ], id='epics:nt/NTNDArray:1.0')

And here is my test code to create the array which I am viewing in cs-studio

from p4p.nt import NTNDArray
from p4p.server import Server, StaticProvider
from p4p.server.thread import SharedPV
import numpy as np

class ArrayHandler:
    def put(pv, op):
        pv.post(op.value())
        op.done()  

provider = StaticProvider('arbitrary')

initial_data = np.arange(16)

ndarray_pv = SharedPV(handler=ArrayHandler(), nt=NTNDArray(), initial=initial_data)
provider.add('sample:array', ndarray_pv)

Server.forever(providers=[provider])
brunoseivam commented 5 years ago

I believe all non-optional fields (according to http://epics-pvdata.sourceforge.net/alpha/normativeTypes/normativeTypes_20150316.html#ntndarray) should be part of p4p's definition. I am not sure how to transparently handle things like compression, though.

tynanford commented 5 years ago

I added these defaults. What do you guys think? Also I wasn't sure what to put as a default for the codec field so I didn't add it yet.

        dataSize = value.nbytes

        return Value(self.type, {
            'value': value.flatten(),
            'compressedSize': dataSize,
            'uncompressedSize': dataSize,
            'uniqueId': 0,
            'timeStamp': {
                'secondsPastEpoch': S,
                'nanoseconds': NS * 1e9,
            },
            'attribute': [{'name': K, 'value': V} for K, V in attrib.items()],
            'dimension': [{'size': N,
                           'offset': 0,
                           'fullSize': N,
                           'binning': 1,
                           'reverse': False} for N in dims],
        })
mdavidsaver commented 5 years ago

Verified that the latest CSS/phoebus displays a gray scale image correctly, and added an example image server to help with future testing 7f356fa0fc832c2fef131ceef38a58322855efd2.

@shroffk