Skip to content

Define a module for windowing streaming data #113

Closed

Description

What's needed?

We need to access a window of data that is received from the LogicalMeter and can be used by downstream users, usually trained machine learning models.

This should use a ring buffer as an underlying data structure

The anticipated feature are

  • updates the data regularly
  • can access data by time windows
  • can create an ordered copy of a slice of the ring buffer as numpy array
  • OPTIONAL: can return a resampled ordered copy of a slice of the ring buffer

The last feature is marked as optional because it's possible to create two windows with the same data with different sampling rates without that feature.

Additional Features are

  • aggregations/operations on windows like mean and standard deviation shared with the TimeseriesAvg (for further ideas see also

Proposed solution

Essentially this is the user facing interface to the ring buffer taking care of dealing with all kinds time related and providing bounded and ordered data batches to the user when requested.

Furthermore it's supposed the update the ring buffer on new incoming samples from the LogicalMeter.

Use cases

This will be used in the forecasting pipeline as the central data storage for

  • storing time series data that can be piped into ml predictions,
  • calculating features as
    • daily averages
    • energy consumption/production in a certain time window
    • mean and standard deviation
    • polynomial coefficients (for power curves)

Alternatives and workarounds

This could, instead of being a wrapper around, as well directly end up in the ring buffer.

In the past pandas dataframes have been used. It turned out as too inefficient due to

  • memory allocation when operating (e.g. (joining, resampling,...),
  • creation of new dataframes on new incoming data.

Activity

  1. added
    part:❓We need to figure out which part is affected
    priority:❓We need to figure out how soon this should be addressed
    type:enhancementNew feature or enhancement visitble to users
    on Dec 13, 2022
  2. added
    priority:highAddress this as soon as possible
    and removed
    part:❓We need to figure out which part is affected
    priority:❓We need to figure out how soon this should be addressed
    on Dec 13, 2022
  3. matthias-wende-frequenz commented on Dec 19, 2022

    @matthias-wende-frequenz
    ContributorAuthor

    This data structure could furthermore take care of loading historic data, as an alternative approach to the seamless transition between disk data and streaming data. This could be simplified if we would cache transformed logical meter data on disk.

    ...
    # get a receiver that sends us data and create a new data batcher storing data of the last n_days and load the initial data from disk
    data_batcher = DataBatcher(size = n_days * 3600 * 24, current_ph1_rx, data_dir = "~/my_data")
    
  4. changed the title [-]Define a data structure for storing data batches[/-] [+]Define an actor for storing data batches[/+] on Dec 20, 2022
  5. changed the title [-]Define an actor for storing data batches[/-] [+]Define a module for storing data batches[/+] on Dec 20, 2022
  6. ela-kotulska-frequenz commented on Dec 20, 2022

    @ela-kotulska-frequenz
    Contributor

    How frequently would the mean be updated and send?

  7. matthias-wende-frequenz commented on Dec 21, 2022

    @matthias-wende-frequenz
    ContributorAuthor

    How frequently would the mean be updated and send?

    Does this question belong to this issue? This module is just about batching data from a stream.

  8. matthias-wende-frequenz commented on Dec 21, 2022

    @matthias-wende-frequenz
    ContributorAuthor

    For resampling we might consider using the python wrapper around libsamplerate

  9. changed the title [-]Define a module for storing data batches[/-] [+]Define a module for buffering streaming data[/+] on Dec 27, 2022
  10. 25 remaining items

  11. ela-kotulska-frequenz commented on Jan 9, 2023

    @ela-kotulska-frequenz
    Contributor

    I am wondering how the data would be returned to the user.
    If I understand correctly it will copy the ringbuffer (to not override it by mistake).

    If yes, then for example:
    Consider actor that every 5 seconds needs last 1 hour data resampled every 1 sec.
    Would it copy whole 1 hour array every 5 seconds?
    Or would it return only the latest 5 seconds data to be appended to the previously received data?

  12. matthias-wende-frequenz commented on Jan 10, 2023

    @matthias-wende-frequenz
    ContributorAuthor

    I think we need to address how we define the term distance

    step as pandas is using it?

    That's not needed as mentioned here.

  13. matthias-wende-frequenz commented on Jan 10, 2023

    @matthias-wende-frequenz
    ContributorAuthor

    I am wondering how the data would be returned to the user.
    If I understand correctly it will copy the ringbuffer (to not override it by mistake).

    If yes, then for example:
    Consider actor that every 5 seconds needs last 1 hour data resampled every 1 sec.
    Would it copy whole 1 hour array every 5 seconds?
    Or would it return only the latest 5 seconds data to be appended to the previously received data?

    That's indeed a very good question.

    The ringbuffer is designed to copy only if

    • The requested time period is crossing the start/end of the buffer.
    • The requested time period contains missing entries.
    • The force_copy parameter was set to True (default False)

    As we try to avoid coping as much as possible I think we should inherit from the default ring buffer behavior.

  14. idlir-shkurti-frequenz commented on Jan 10, 2023

    @idlir-shkurti-frequenz
    Contributor

    What distinguishes our approach is that our window is not an once created immutable series of windows, as in your second example, but instead is one window that gets constantly updated.

    Just to make sure I understand this properly. It seems to me that the second example is a bit more general if we need the classic sliding window functionality. I understand that if we want these windows to represent things like days or weeks then the windows will not overlap but isn't it better to generalise this by applying the second example?

  15. idlir-shkurti-frequenz commented on Jan 10, 2023

    @idlir-shkurti-frequenz
    Contributor

    The ringbuffer is designed to copy only if

    By copy do you mean load the entire window again instead of appending the ringbuffer? If so then I agree with the bullet points.

  16. mathias-baumann-frequenz commented on Jan 23, 2023

    @mathias-baumann-frequenz
    Contributor

    By copy do you mean load the entire window again instead of appending the ringbuffer?

    There is no "appending", only overwriting already allocated memory and possibly old out-of-date data.

    You can request any datetime range from the ringbuffer buffer.window(start, end) and the returned array/list will be a view to the actual raw buffer except for the cases @matthias-wende-frequenz outlined above.
    In those cases it will be a newly allocated buffer.

  17. thomas-nicolai-frequenz commented on Jan 24, 2023

    @thomas-nicolai-frequenz

    There is no "appending"

    @idlir-shkurti-frequenz this is the main reason for the ring buffer. its has a fixed sizes and thus there is no such things as appending. appending always means new memory allocation and that in turn may invoke the garbage collector.

    In those cases it will be a newly allocated buffer.

    Please try to use that feature carefully. There has to be a really good reason using that.

  18. matthias-wende-frequenz commented on Jan 25, 2023

    @matthias-wende-frequenz
    ContributorAuthor

    Just to make sure I understand this properly. It seems to me that the second example is a bit more general if we need the classic sliding window functionality. I understand that if we want these windows to represent things like days or weeks then the windows will not overlap but isn't it better to generalise this by applying the second example?

    There is no overlap as it's just one window that constantly moves with the data flow. So it'll always have the latest data and with each new incoming data point the oldest data point is removed.

    There has been a confusion between the TimeseriesAvg and the MovingWindow, that is sketched here so please forget the two examples Tiyash gave.

  19. matthias-wende-frequenz commented on Jan 25, 2023

    @matthias-wende-frequenz
    ContributorAuthor

    In those cases it will be a newly allocated buffer.

    Please try to use that feature carefully. There has to be a really good reason using that.

    The underlying ringbuffer already minimizes coping to the cases described above.
    Additionally I'll add examples howto arrange the buffer when initializing the MovingWindow to further minimize the likelihood of copying.

  20. linked a pull request that will close this issueAdd a Moving Window Class #190on Jan 31, 2023
  21. moved this from To do to Review in progress in Python SDK Roadmapon Feb 7, 2023
  22. moved this from Review in progress to Done in Python SDK Roadmapon Feb 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

part:data-pipelineAffects the data pipelinepriority:highAddress this as soon as possibletype:enhancementNew feature or enhancement visitble to users

Type

No type

Fields

Priority

None yet

Projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions