Search code examples
pythondictionarytupleshdf58-bit

Continue counting after 8-bit counter is full in dict


Lets start off that this is my first python program, so I will have some misconceptions on how parts of the code work.

Data is extracted from a 8-bit memory, this data is saved in a HDF5 file and I need to work with this HDF5 data. The dictionary I want to work with of this file has 3 keys with each key having multiple values. One of the keys is a counter and when it reached 256, it will reset to 0. This is expected due to the 8-bit memory.

So my challenge is to read the data of this key and when it overflows, then instead of resetting, counting up from the previous value. this is needed to make continues plots with the counter on the x-axis.

My issues starts with how to read out the values of a specific key one-by-one and, when needed, changing it. For the semi-working code(that resets the counter to 0, but does plot it) I used zip() to unpack the dict to a tuple(?). But after this i'm stuck again.

Here is the whole code so far.

import h5py
import matplotlib.pyplot as plt
import numpy as np
from pathlib import Path

measdatapath =  Path(r'C:\Users\...')
title = 'Best_test_data_ever.hdf5'
plotpath = measdatapath / title

data = h5py.File(plotpath, 'r')
list(data.keys())

relevant_data = data['HDF5Data'][:]

# variable z is the counter

x, y, z = zip(*relevent_data)

fig, axs = plt.subplots(2,1, sharex=True)

axs[0].plot(z,x)
axs[0].set_ylabel("Awesome line")
axs[0].xaxis.set_label_position('top')
axs[0].set_title(title)


axs[1].plot(z,y)
axs[1].set_ylabel("Almost as awesome line")

axs[1].set_xlabel("Broken counter")


plt.show()

to summarize my challenges:

  • How to read the data from a dict or tuple one-by-one and change it if necessary
  • How to continue counting when the counter reaches 256 instead of resetting

Note: above is scrambled code from different sources, I have a limited idea of what I am doing, but eager to learn.

so far I have tried to look up online how to solve this with a tuple or dict, but it didn't help.

Edit: The counting goes from 0 to 255 and then resets to 0. Below the current counting I have from the data:

(3, 7, 10, 14, 17, 21, 24, 28, 31, 34, 39, 42, 45, 48, 51, 54, 57, 61, 64, 67, 70, 73, 77, 80, 84, 88, 91, 94, 98, 100, 104, 107, 111, 114, 117, 121, 124, 127, 131, 133, 137, 140, 143, 146, 150, 153, 157, 160, 164, 167, 170, 173, 176, 179, 183, 186, 189, 191, 195, 198, 201, 203, 207, 210, 213, 217, 220, 223, 227, 230, 233, 236, 240, 243, 246, 249, 253, 1, 4, 8, 11, 15, 18, 22, 25, 28, 32, 35, 39, 42, 46, 49, 52, 55, 58, 61, 65, 68, 72, 75)


Solution

  • There are probably many ways of fixing up that counter. Here is one:

    We start by ensuring that we run on numpy arrays. See my last side-note at the bottom about this.

    z = np.asarray(z)
    

    We then detect that a wrap-around happened:

    wraparound = z[1:] < z[:-1]
    

    This gives us an array like [false, false, ..., true, false, ..., true, false, ...]. We convert this to an integer array [0, 0, ..., 1, 0, ..., 1, 0, ...].

    wraparound = wraparound.astype(int)
    

    We can then use np.cumsum to accumulate how often a wrap-around happened up to the given index. This gives us an array [0, 0, ..., 1, 1, ... 2, 2, ...].

    wraparound = wraparound.cumsum()
    

    Now we just need to multiply with 256 and add it to the counter. Note that the wraparound array has one fewer entries than the base counter.

    counter = z.astype(int)
    counter[1:] += wraparound
    

    To write it in as few lines as possible:

    z = np.asarray(z)
    counter = z.astype(int)
    counter[1:] += (z[1:] < z[:-1]).astype(int).cumsum() * 256
    

    Side note: x, y, z = zip(*relevent_data) is very inefficient since it replaces all numpy arrays with basic Python types. Write this instead to get transposed array views: x, y, z = relevent_data.T