Skip to content

Commit dd4275e

Browse files
committed
Allow for missing data in input metadata table.
Warn that the column is missing. Add include_experiment_description to write nwb.
1 parent 5dcc24a commit dd4275e

File tree

7 files changed

+137
-36
lines changed

7 files changed

+137
-36
lines changed

allensdk/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
#
3636
import logging
3737

38-
__version__ = '2.16.1'
38+
__version__ = '2.16.2'
3939

4040

4141
try:

allensdk/brain_observatory/behavior/behavior_project_cache/tables/metadata_table_schemas.py

+30-11
Original file line numberDiff line numberDiff line change
@@ -11,49 +11,68 @@
1111
class BehaviorSessionMetadataSchema(RaisingSchema):
1212
age_in_days = Int(required=True, description="Subject age")
1313
behavior_session_id = Int(
14-
required=True,
14+
required=False,
15+
allow_none=True,
1516
description=(
1617
"Unique identifier for the "
1718
"behavior session to write into "
1819
"NWB format"
1920
),
2021
)
2122
cre_line = String(
22-
required=True, description="Genetic cre line of the subject."
23+
required=False,
24+
allow_none=True,
25+
description="Genetic cre line of the subject."
2326
)
2427
date_of_acquisition = String(
25-
required=True,
28+
required=False,
29+
allow_none=True,
2630
description=(
2731
"Date of acquisition of " "behavior session, in string " "format"
2832
),
2933
)
3034
driver_line = List(
3135
String,
32-
required=True,
36+
required=False,
37+
allow_none=True,
3338
cli_as_single_argument=True,
3439
description="Genetic driver line(s) of subject",
3540
)
3641
equipment_name = String(
37-
required=True, description=("Name of the equipment used.")
42+
required=False,
43+
allow_none=True,
44+
description=("Name of the equipment used.")
3845
)
3946
full_genotype = String(
40-
required=True, description="Full genotype of subject"
47+
required=False,
48+
allow_none=True,
49+
description="Full genotype of subject"
4150
)
4251
mouse_id = String(
43-
required=True,
52+
required=False,
53+
allow_none=True,
4454
description="LabTracks ID of the subject. aka external_specimen_name.",
4555
)
4656
project_code = String(
47-
rquired=True,
57+
rquired=False,
58+
allow_none=True,
4859
description="LabTracks ID of the subject. aka external_specimen_name.",
4960
)
5061
reporter_line = String(
51-
required=True, description="Genetic reporter line(s) of subject"
62+
required=False,
63+
allow_none=True,
64+
description="Genetic reporter line(s) of subject"
5265
)
5366
session_type = String(
54-
required=True, description="Full name of session type."
67+
required=False,
68+
allow_none=True,
69+
description="Full name of session type."
70+
)
71+
sex = String(
72+
required=False,
73+
allow_none=True,
74+
description="Subject sex"
5575
)
56-
sex = String(required=True, description="Subject sex")
5776

5877
@mm.post_load
5978
def convert_date_time(self, data, **kwargs):

allensdk/brain_observatory/behavior/data_objects/stimuli/presentations.py

+18-9
Original file line numberDiff line numberDiff line change
@@ -596,19 +596,28 @@ def _check_for_errant_omitted_stimulus(
596596
Dataframe with omitted stimulus removed from first row or if not
597597
found, return input_df unmodified.
598598
"""
599+
600+
def safe_omitted_check(input_df: pd.Series,
601+
stimulus_block: Optional[int]):
602+
if stimulus_block is not None:
603+
first_row = input_df[
604+
input_df['stimulus_block'] == stim_block].iloc[0]
605+
else:
606+
first_row = input_df.iloc[0]
607+
608+
if not pd.isna(first_row["omitted"]):
609+
if first_row["omitted"]:
610+
input_df = input_df.drop(first_row.name, axis=0)
611+
return input_df
612+
599613
if "omitted" in input_df.columns and len(input_df) > 0:
600614
if "stimulus_block" in input_df.columns:
601615
for stim_block in input_df['stimulus_block'].unique():
602-
first_row = input_df[
603-
input_df['stimulus_block'] == stim_block].iloc[0]
604-
if not pd.isna(first_row["omitted"]):
605-
if first_row["omitted"]:
606-
input_df = input_df.drop(first_row.name, axis=0)
616+
input_df = safe_omitted_check(input_df=input_df,
617+
stimulus_block=stim_block)
607618
else:
608-
first_row = input_df.iloc[0]
609-
if not pd.isna(first_row["omitted"]):
610-
if first_row["omitted"]:
611-
input_df = input_df.drop(first_row.name, axis=0)
619+
input_df = safe_omitted_check(input_df=input_df,
620+
stimulus_block=None)
612621
return input_df
613622

614623
@staticmethod

allensdk/brain_observatory/behavior/write_nwb/behavior/__main__.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ def run(self):
2727
nwb_filepath=bs_id_dir / f"behavior_session_{bs_id}.nwb",
2828
skip_metadata=self.args["skip_metadata_key"],
2929
skip_stim=self.args["skip_stimulus_file_key"],
30+
include_experiment_description=self.args[
31+
'include_experiment_description'
32+
]
3033
)
3134
logging.info("File successfully created")
3235

@@ -43,6 +46,7 @@ def write_behavior_nwb(
4346
nwb_filepath: Path,
4447
skip_metadata: List[str],
4548
skip_stim: List[str],
49+
include_experiment_description=True
4650
) -> str:
4751
"""Load and write a BehaviorSession as NWB.
4852
@@ -61,6 +65,8 @@ def write_behavior_nwb(
6165
List of metadata keys to skip when comparing data.
6266
skip_stim : list of str
6367
List of stimulus file keys to skip when comparing data.
68+
include_experiment_description : bool
69+
If True, include experiment description in NWB file.
6470
6571
Returns
6672
-------
@@ -79,7 +85,11 @@ def write_behavior_nwb(
7985
session_data=behavior_session_metadata,
8086
serializer=BehaviorSession,
8187
)
82-
nwb_writer.write_nwb(skip_metadata=skip_metadata, skip_stim=skip_stim)
88+
nwb_writer.write_nwb(
89+
skip_metadata=skip_metadata,
90+
skip_stim=skip_stim,
91+
include_experiment_description=include_experiment_description
92+
)
8393

8494
return str(nwb_filepath)
8595

allensdk/brain_observatory/behavior/write_nwb/behavior/schemas.py

+69-14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import marshmallow as mm
2+
from warnings import warn
3+
import pandas as pd
24
from allensdk.brain_observatory.argschema_utilities import (
35
InputFile,
46
RaisingSchema,
@@ -18,6 +20,7 @@
1820
OutputDir,
1921
OutputFile,
2022
String,
23+
Bool
2124
)
2225

2326

@@ -54,29 +57,81 @@ class Meta:
5457
required=True,
5558
description="Path of output.json to be written",
5659
)
60+
include_experiment_description = Bool(
61+
required=False,
62+
description="If True, include experiment description in NWB file.",
63+
default=True
64+
)
5765

5866
def _get_behavior_metadata(self, bs_row):
5967
""" """
6068
behavior_session_metadata = {}
6169

62-
behavior_session_metadata["age_in_days"] = bs_row["age_in_days"]
63-
behavior_session_metadata["cre_line"] = bs_row["cre_line"]
64-
behavior_session_metadata["date_of_acquisition"] = bs_row[
65-
"date_of_acquisition"
66-
]
67-
behavior_session_metadata["driver_line"] = sorted(
68-
bs_row["driver_line"]
70+
behavior_session_metadata["age_in_days"] = self._retrieve_value(
71+
bs_row=bs_row, column_name="age_in_days"
72+
)
73+
behavior_session_metadata["cre_line"] = self._retrieve_value(
74+
bs_row=bs_row, column_name="cre_line"
75+
)
76+
behavior_session_metadata["date_of_acquisition"] = self._retrieve_value( # noqa: E501
77+
bs_row=bs_row, column_name="date_of_acquisition"
78+
)
79+
behavior_session_metadata["driver_line"] = self._retrieve_value(
80+
bs_row=bs_row, column_name="driver_line"
81+
)
82+
behavior_session_metadata["equipment_name"] = self._retrieve_value(
83+
bs_row=bs_row, column_name="equipment_name"
84+
)
85+
behavior_session_metadata["full_genotype"] = self._retrieve_value(
86+
bs_row=bs_row, column_name="full_genotype"
87+
)
88+
behavior_session_metadata["mouse_id"] = self._retrieve_value(
89+
bs_row=bs_row, column_name="mouse_id"
90+
)
91+
behavior_session_metadata["project_code"] = self._retrieve_value(
92+
bs_row=bs_row, column_name="project_code"
93+
)
94+
behavior_session_metadata["reporter_line"] = self._retrieve_value(
95+
bs_row=bs_row, column_name="reporter_line"
96+
)
97+
behavior_session_metadata["session_type"] = self._retrieve_value(
98+
bs_row=bs_row, column_name="session_type"
99+
)
100+
behavior_session_metadata["sex"] = self._retrieve_value(
101+
bs_row=bs_row,
102+
column_name="sex"
69103
)
70-
behavior_session_metadata["equipment_name"] = bs_row["equipment_name"]
71-
behavior_session_metadata["full_genotype"] = bs_row["full_genotype"]
72-
behavior_session_metadata["mouse_id"] = bs_row["mouse_id"]
73-
behavior_session_metadata["project_code"] = bs_row["project_code"]
74-
behavior_session_metadata["reporter_line"] = bs_row["reporter_line"]
75-
behavior_session_metadata["session_type"] = bs_row["session_type"]
76-
behavior_session_metadata["sex"] = bs_row["sex"]
77104

78105
return behavior_session_metadata
79106

107+
def _retrieve_value(self, bs_row: pd.Series, column_name: str):
108+
"""Pull a column safely, return None otherwise.
109+
110+
Parameters
111+
----------
112+
bs_row : pd.Series
113+
Row of a BehaviorSessionTable
114+
column_name : str
115+
Name of column to retrieve
116+
117+
Returns
118+
-------
119+
value : object
120+
Value of column_name in bs_row, or None if column_name is not in
121+
bs_row
122+
"""
123+
if column_name not in bs_row.index:
124+
warn(f"Warning, {column_name} not in metadata table. Unless this "
125+
"has been added to the inputs skip_metadata_key or "
126+
"skip_stimulus_file_key, creating the NWB file "
127+
"may fail.")
128+
return None
129+
else:
130+
value = bs_row[column_name]
131+
if isinstance(value, list):
132+
value = sorted(value)
133+
return value
134+
80135

81136
class BehaviorInputSchema(BaseInputSchema):
82137
behavior_session_id = Int(

allensdk/brain_observatory/behavior/write_nwb/nwb_writer_utils.py

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ def _update_session(
1313
self,
1414
lims_session: BehaviorSession,
1515
ophys_experiment_ids: Optional[List[int]] = None,
16+
**kwargs
1617
) -> BehaviorSession:
1718
"""Call session methods to update certain values within the session.
1819

allensdk/brain_observatory/behavior/write_nwb/ophys/__main__.py

+7
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ def run(self):
2929
nwb_filepath=oe_id_dir / f"behavior_ophys_experiment_{oe_id}.nwb",
3030
skip_metadata=self.args["skip_metadata_key"],
3131
skip_stim=self.args["skip_stimulus_file_key"],
32+
include_experiment_description=self.args[
33+
'include_experiment_description'
34+
]
3235
)
3336
logging.info("File successfully created")
3437

@@ -43,6 +46,7 @@ def write_experiment_nwb(
4346
nwb_filepath: Path,
4447
skip_metadata: List[str],
4548
skip_stim: List[str],
49+
include_experiment_description=True
4650
) -> str:
4751
"""Load and write a BehaviorOphysExperiment as NWB.
4852
@@ -61,6 +65,8 @@ def write_experiment_nwb(
6165
List of metadata keys to skip when comparing data.
6266
skip_stim : list of str
6367
List of stimulus file keys to skip when comparing data.
68+
include_experiment_description : bool
69+
If True, include experiment description in NWB file.
6470
6571
Returns
6672
-------
@@ -83,6 +89,7 @@ def write_experiment_nwb(
8389
ophys_experiment_ids=self.args["ophys_container_experiment_ids"],
8490
skip_metadata=skip_metadata,
8591
skip_stim=skip_stim,
92+
include_experiment_description=include_experiment_description
8693
)
8794

8895
return str(nwb_filepath)

0 commit comments

Comments
 (0)