ratal / mdfreader

Read Measurement Data Format (MDF) versions 3.x and 4.x file formats in python
Other
169 stars 74 forks source link

Unknown "signal_data_type" in mdf4reader.read_sdblock() #156

Closed rolfub closed 5 years ago

rolfub commented 5 years ago

Python version

Please write here the output of printing sys.version '2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)]'

Platform information

'Windows-10-10.0.16299'

Numpy version

'1.15.2'

mdfreader version

'2.7.8'

Description

Hello Aymeric,

I have a problem with an .mf4 file from CANoe (-> MDF Versionn 4.10) in the operation mdf4reader.read_sdblock().

Here is the output from a short debugging session:

signal_data_type = 10 (debug)

Traceback (most recent call last): File "C:\Users\rolfub\Desktop\CANoe\CANoetest.py", line 116, in file = mdfreader.mdf( "C:\Users\rolfub\Desktop\Cluster.mf4" ) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf.py", line 159, in init compression=compression) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdfreader.py", line 400, in read convertAfterRead, filterChannelNames, compression) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 1228, in read4 buf.read(channelSet, info, self.fileName) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 314, in read temp = temp.load(record, info, nameList=channelSet, sortedFlag=True, vlsd=True) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 457, in load sortedFlag=sortedFlag, vlsd=vlsd) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 125, in DATABlock parent_block['data'], parent_block['dz_org_data_length']) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 212, in read_sdblock buf.append(sdblock[pointer:pointer + VLSDLen].decode(channel_format).rstrip('\x00')) UnboundLocalError: local variable 'channel_format' referenced before assignment

I hope you can help me. I don't know what encoding I should define here.

Yours sincerely,

Rolf

ratal commented 5 years ago

signal_data_type = 10 means byte array type, possible -> no encoding I did not consider and encounter it so far and have no file to test it. But you can try the following:

def _read_sd_block(signal_data_type, sd_block, sd_block_length):
    """ Reads vlsd channel from its SD Block bytes

    Parameters
    ----------------
    signal_data_type : int

    sd_block : bytes
    SD Block bytes

    sd_block_length: int
    SD Block data length (header not included)

    Returns
    -----------
    array
    """
    pointer = 0
    buf = []
    if signal_data_type < 10:
        if signal_data_type == 6:
            channel_format = 'ISO8859'
        elif signal_data_type == 7:
            channel_format = 'utf-8'
        elif signal_data_type == 8:
            channel_format = '<utf-16'
        elif signal_data_type == 9:
            channel_format = '>utf-16'
        else:
            channel_format = 'utf-8'
        while pointer < sd_block_length:
            VLSDLen = structunpack('I', sd_block[pointer:pointer + 4])[0]  # length of data
            pointer += 4
            buf.append(sd_block[pointer:pointer + VLSDLen].decode(channel_format).rstrip('\x00'))
            pointer += VLSDLen
        buf = _equalize_string_length(buf)
    else:  # byte arrays or mime types
        while pointer < sd_block_length:
            VLSDLen = structunpack('I', sd_block[pointer:pointer + 4])[0]  # length of data
            pointer += 4
            buf.append(sd_block[pointer:pointer + VLSDLen])
            pointer += VLSDLen
        buf = _equalize_byte_length(buf)
    return array(buf)

def _equalize_string_length(buf):
    """ Makes all strings in a list having same length by appending spaces strings.

    Parameters
    ----------------
    buf : list of str

    Returns
    -----------
    list of str elements all having same length
    """
    max_len = len(max(buf, key=len))
    for i in range(len(buf)):  # resize string to same length, numpy constrain
        buf[i] = ''.join([buf[i], ' ' * (max_len - len(buf[i]))])
    return buf

def _equalize_byte_length(buf):
    """ Makes all bytes in a list having same length by appending null bytes.

    Parameters
    ----------------
    buf : list of bytes

    Returns
    -----------
    list of bytes all having same length
    """
    max_len = len(max(buf, key=len))
    for i in range(len(buf)):  # resize string to same length, numpy constrain
        buf[i] = buf[i].append('\x00' * (max_len - len(buf[i])))
    return buf

Most likely buggy, please feed back

rolfub commented 5 years ago

Hello Aymeric,

thank you for your solution!

Unfortunately I become the following traceback:

Traceback (most recent call last): File "C:\Users\rolfub\Desktop\CANoe\CANoetest.py", line 116, in file = mdfreader.mdf( "C:\Users\rolfub\Desktop\Cluster.mf4" ) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf.py", line 159, in init compression=compression) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdfreader.py", line 400, in read convertAfterRead, filterChannelNames, compression) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 1270, in read4 buf.read(channelSet, info, self.fileName) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 356, in read temp = temp.load(record, info, nameList=channelSet, sortedFlag=True, vlsd=True) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 499, in load sortedFlag=sortedFlag, vlsd=vlsd) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 125, in DATABlock parent_block['data'], parent_block['dz_org_data_length']) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 223, in read_sdblock buf = _equalize_byte_length(buf) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 257, in _equalize_byte_length buf[i] = buf[i].append('\x00' * (max_len - len(buf[i]))) AttributeError: 'str' object has no attribute 'append'

Yours sincerely,

Rolf

ratal commented 5 years ago

You can try the following:

    for i, element in enumerate(buf):  # resize string to same length, numpy constrain
        buf[i] = bytearray(element).extend(b'0' * (max_len - len(element))

but maybe you can avoid the call of _equalize_byte_length(buf) in _read_sd_block -> channel data should be a numpy array of type object. Better to equalize length as then numpy array will be considered with uint8 and could do some operations from it.

rolfub commented 5 years ago

Hello Aymeric,

here is the result of my test:

  1. with "buf = _equalize_byte_length(buf)" in _read_sd_block():

Traceback (most recent call last): File "C:\Users\rolfub\Desktop\CANoe\CANoetest.py", line 116, in file = mdfreader.mdf( "C:\Users\rolfub\Desktop\Cluster.mf4" ) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf.py", line 159, in init compression=compression) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdfreader.py", line 400, in read convertAfterRead, filterChannelNames, compression) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 1253, in read4 buf.read(channelSet, info, self.fileName) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 343, in read record[cn].name, temp) File "C:\Python27\lib\site-packages\numpy\lib\recfunctions.py", line 733, in rec_append_fields asrecarray=True, usemask=False) File "C:\Python27\lib\site-packages\numpy\lib\recfunctions.py", line 673, in append_fields data = [a.view([(name, a.dtype)]) for (name, a) in zip(names, data)] File "C:\Python27\lib\site-packages\numpy\core_internal.py", line 389, in _view_is_safe raise TypeError("Cannot change data-type for object array.") TypeError: Cannot change data-type for object array.

  1. without "buf = _equalize_byte_length(buf)" (commented out) in _read_sd_block(): There is no exception. I want to compare it with the values in CANoe tomorrow to be sure.

Yours sincerely,

Rolf

danielhrisca commented 5 years ago

@rolfub are you allowed to send a copy of your file with all the texts scrambled? This would make it usable just for debugging the internal structure and your data would be protected

rolfub commented 5 years ago

I want to but it isn't allowed. :-( I can only say that it is a CANoe 11 logging file. Instead of a BLF format I use the MDF4 format.

danielhrisca commented 5 years ago

Would it possible to make an argument to your superiors using this: Original: screenshot from 2018-11-08 17-33-33

Scrambled: screenshot from 2018-11-08 17-34-01

demo.zip

ratal commented 5 years ago

after _equalize_byte_length(buf), can you try putting return array(buf, dtype='B') ? What is type of channel when commentting _equalize_byte_length ? What is most convienient type for you ? (I guess object is unusable)

rolfub commented 5 years ago

Hello Aymeric,

sorry for the late answer. I have waited for a new CANoe-Logging file from my colleague for the test.

With "return array(buf, dtype='B')" I get the following exception: Traceback (most recent call last): File "C:\Users\rolfub\Desktop\CANoe\CANoe_test.py", line 116, in file = mdfreader.mdf( "C:\Users\rolfub\Desktop\MDF.mdf" ) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf.py", line 159, in init compression=compression) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdfreader.py", line 400, in read convertAfterRead, filterChannelNames, compression) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 1253, in read4 buf.read(channelSet, info, self.fileName) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 339, in read temp = temp.load(record, info, nameList=channelSet, sortedFlag=True, vlsd=True) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 482, in load sortedFlag=sortedFlag, vlsd=vlsd) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 125, in DATABlock parent_block['data'], parent_block['dz_org_data_length']) File "C:\Python27\lib\site-packages\mdfreader-2.7.8-py2.7.egg\mdfreader\mdf4reader.py", line 224, in _read_sd_block return array(buf, dtype='B') TypeError: long() argument must be a string or a number, not 'NoneType'

Without "_equalize_byte_length()" it seems to work.

Yours sincerely,

Rolf

rolfub commented 5 years ago

Hello Daniel,

you have a very good idea but the decision makers are no technicians. So they don't understand it or they don't want to understand it. It is a rule: "No data goes out!".

Yours sincerely,

Rolf

danielhrisca commented 5 years ago

It seems to me that both parties are at a loss, but I understand the situation.

ratal commented 5 years ago

Ok, let's do without _equalize_byte_length(), it's difficult to further troubleshoot, I have no other idea to try. I will keep code in case there is a need in future but not activate it for the moment. Thanks