feat: create nwb acquisition module#9
Conversation
|
for right/left_reward_delivery_time, value will be earned, manual, or automatic. Earned will be if the trial_outcome.data.trial.is_auto_response_right is null. automatic will be if auto_response is true or false. Manual is a bit trickier bc its not aligned with a go cue. There will be a GiveManualWaterRight software event that has the software timestamps of when manual water was given. These software event timestamps will need to be correlated with the harp timestamps |
| except (KeyError, FileNotFoundError): | ||
| return pd.DataFrame({"data": []}) | ||
|
|
||
| def get_lick_times(self, is_right: bool) -> np.ndarray: |
There was a problem hiding this comment.
Do we want to make this compatible for the LicketySplit boards too? The software can switch between either. Might make it easier in the future if boxes ever want to switch but would also not be that hard to add when we need it
There was a problem hiding this comment.
yeah I was honestly being lazy about this. I think it should be straightforward to add and can do it as part of this PR.
There was a problem hiding this comment.
tried to address here: 38fecfc. Takes in a stream name to allow for allowing compatibility for both boards
| each timestamp as a detected lick (``True``). | ||
| """ | ||
| lick_times = self.get_lick_times(is_right) | ||
| port_column = "DIPort1" if is_right else "DIPort0" |
There was a problem hiding this comment.
would it be easier to pass the port string as an arg rather than the is_right flag? Then the port would be hardcoded only one place and if anything changed in configuration, it would be easier to change
There was a problem hiding this comment.
yeah good call. I went back and forth with it but seems like having the port passed in will make it more flexible to changes
There was a problem hiding this comment.
kind of related to above, tried to address here: 38fecfc.
| for i, trial_index in enumerate(trial_indices_in_reward_times): | ||
| if i in manual_indices_in_reward_times: | ||
| annotated_rewards.append("manual") | ||
| continue |
There was a problem hiding this comment.
this is kinda confusing me but i could be misunderstanding it. Why do you need to loop through the trial_indices_in_reward_times to annotate the manual times? It seems like you should be able to annotate manual_indices_in_reward_times directly with "manual" since manual water is completely independent from trials and multiple could happen within a trial.
There was a problem hiding this comment.
ah good catch! yeah this is not needed, and also uncovered that I was not adding the manual times to the nwb. Will remove this logic, that should make it easier to follow I think
There was a problem hiding this comment.
the times were already there. tried to simplify the logic here 38fecfc
micahwoodard
left a comment
There was a problem hiding this comment.
Okay this looks good to me. Not sure about the licketysplit stuff but minor thing since no df rig is using licketysplits yet
| .at(stream_name) | ||
| .load() | ||
| .data | ||
| ) |
There was a problem hiding this comment.
I think reading either janelia lickometer or LicketySplit would look more like
if "HarpLickometerRight" in data:
licks = self.data["HarpLickometerRight"]['LickState']["Channel0"] == True
else:
di_state = data['HarpBehavior']['DigitalInputState'][port]
lick = di_state.loc[di_state == True]
but would also need something to check for HarpLickometerRight and HarpLickometerLeft
This PR attempts to address #7. Uses information from this issue which has which raw streams to use: #5. The acquisition module currently in the NWB has these 4 streams associated with behavior:
It sets up an acquisition builder module that can then be mapped directly to NWB without the need to take on dependencies from
pynwb.An initial example notebook can be found here on how to access the object:
https://github.com/AllenNeuralDynamics/dynamic-foraging-processing/blob/7-create-nwb-acquisition-processing-module/examples/acquisition_builder_example.ipynb
UPDATE: Removed example notebook because it's redundant to the raw data loader. Renamed to go under an nwb module since this is will be primarily used for nwb packaging
Added the reward annotation and licks. For now, licks are only using ports from the Janelia board. Can update it later I think if the lickety split ones are also used.
The hardware times are used for the timestamps. For the reward annotation, need trial information which comes from the software events. Thus, the closest software time is found for a given hardware time, and then that is used to annotate the reward