catalystneuro / ndx-patterned-ogen

patterned (holographic) optogenetic extension to NWB standard
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

Using extension for projector ogen #10

Open matham opened 5 months ago

matham commented 5 months ago

This is a follow up to https://github.com/NeurodataWithoutBorders/helpdesk/discussions/78.

We have a system, documented here, that uses a normal projector with a custom microscope to optogenetically stimulate a slice, while recording from a multi-electrode array. I would like to use this extension for saving the data, but I can't quite make it fit.

How we do it is a user draws a bunch of shapes (ROIs - polygons, circles etc) and then associates a temporal function with each shape. Then, the software stimulates the tissue by adjusting the intensity of the pixels in each ROI according to the temporal function. Therefore, for each point in time and for every ROI, I have an RGB value indicating the intensity for that ROI.

I can see how to add the masks in the extension with OptogeneticStimulusTarget. But then, I could use the PatternedOptogeneticStimulusTable, and for every frame projected, for every ROI, and for every color (e.g if stimulating red/green simultaneously), I can add an interval indicating the start and end time of the frame (it's a 120Hz - 1.44kHz projector) along with the intensity (watt used by LED). But that loses some of the context.

It would be nicer to instead use e.g. a TimeSeries or similar where for every projected frame we have a frame start/end time and the RGB intensity for each ROI. Would this be possible to support?

alessandratrapani commented 5 months ago

Hi @matham ! Sorry for taking so long to answer!

It would be nicer to instead use e.g. a TimeSeries or similar where for every projected frame we have a frame start/end time and the RGB intensity for each ROI. Would this be possible to support?

Good news! There is already a way to reference a TimeSeries when adding an interval to the PatternedOptogeneticStimulusTable. PatternedOptogeneticStimulusTable inherits from TimeInterval, and as you can see from this tutorial here, you can define a TimeSeries, add it to the acquisition module, and then reference it to a specific time interval. Within the particular case of this extension, it would be something like this:

stimulus_table = PatternedOptogeneticStimulusTable(
    name="PatternedOptogeneticStimulusTable", description="Patterned stimulus"
)
# create your temporal functions for optogen stimulus
temporal_fun_1 = TimeSeries(
    name="series1",
    data=np.arange(1000),
    unit="m",
    timestamps=np.linspace(0.5, 601, 1000),
)
temporal_fun_2 = TimeSeries(
    name="series2", 
    data=np.arange(600), 
    unit="V", 
    starting_time=0.0, 
    rate=1.0
)
nwbfile.add_acquisition(temporal_fun_1)
nwbfile.add_acquisition(temporal_fun_2)

stimulus_table.add_interval(
    start_time=0.0,
    stop_time=1.0,
    power=70e-3,
    frequency=20.0,
    pulse_width=0.01,
    stimulus_pattern=polygon_shape, # You could define the stimulus shape here as well
    targets=nwbfile.lab_meta_data["Hologram1"],
    stimulus_site=site,
    timeseries=temporal_fun_1 # reference the stimulation function used in this interval
)
stimulus_table.add_interval(
    start_time=0.5,
    stop_time=1.0,
    power=50e-3,
    frequency=20.0,
    pulse_width=0.01,
    stimulus_pattern=circular_shape,
    targets=hologram_2,
    stimulus_site=site,
    timeseries=temporal_fun_2 
)

nwbfile.add_time_intervals(stimulus_table)

I saw from the other issue that you were wondering what the OptogeneticStimulusPattern could be used for: as far as I understood from your setup, you could use this neuro data type to store the dimension of a single shape, and if the shape applies to more then one stimulated ROIs you could define the pattern once and reuse it.

Let me know if this approach works for your case. Don’t hesitate to tag me on your PRs or for reviews.