facebookresearch / labgraph

LabGraph is a Python framework for rapidly prototyping experimental systems for real-time streaming applications. It is particularly well-suited to real-time neuroscience, physiology and psychology experiments.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How does logging work in LabGraph?

yahiaali opened this issue · comments

❓ Questions and Help

Question

LabGraph includes an HDF5Logger node, but the documentation does not explain how to use this node. How should the HDF5Logger be added to a Graph?

What I have tried

Using the simple_viz.py example, I have attempted to add a logger to the Demo graph:

class Demo(lg.Graph):
    AVERAGED_NOISE: AveragedNoise
    PLOT: Plot
    LOGGER: lg.HDF5Logger

    def setup(self) -> None:
        logger_config = lg.LoggerConfig(
            output_directory=os.getcwd(),
            streams_by_logging_id=self.AVERAGED_NOISE._get_streams())
        self.LOGGER.configure(logger_config)

        self.AVERAGED_NOISE.configure(
            AveragedNoiseConfig(sample_rate=SAMPLE_RATE,
                                num_features=NUM_FEATURES,
                                window=WINDOW))
        self.PLOT.configure(
            PlotConfig(refresh_rate=REFRESH_RATE, num_bars=NUM_FEATURES))

    def connections(self) -> lg.Connections:
        return ((self.AVERAGED_NOISE.OUTPUT, self.PLOT.INPUT),)

    def process_modules(self) -> Tuple[lg.Module, ...]:
        return (self.AVERAGED_NOISE, self.PLOT)

This graphs runs normally (no errors), but it does not create an HDF5 file for logging. What is missing?

I figured out the issue. Logging is enabled by overriding Graph.logging like so:

class Demo(lg.Graph):
    AVERAGED_NOISE: AveragedNoise
    PLOT: Plot

    def setup(self) -> None:
        self.AVERAGED_NOISE.configure(
            AveragedNoiseConfig(sample_rate=SAMPLE_RATE,
                                num_features=NUM_FEATURES,
                                window=WINDOW))
        self.PLOT.configure(
            PlotConfig(refresh_rate=REFRESH_RATE, num_bars=NUM_FEATURES))

    def connections(self) -> lg.Connections:
        return ((self.AVERAGED_NOISE.OUTPUT, self.PLOT.INPUT), )

    def process_modules(self) -> Tuple[lg.Module, ...]:
        return (self.AVERAGED_NOISE, self.PLOT)

    def logging(self) -> Dict[str, Topic]:
        return {'noise_input': self.AVERAGED_NOISE.GENERATOR.OUTPUT,
                'noise_avg': self.AVERAGED_NOISE.OUTPUT}

Note, to avoid an AttributeError when running this, you will need to move RandomMessage from here to a separate file and then import it. This is due to a quirk in the way Python pickles variables.