Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/add_watermark' into add_watermark
Browse files Browse the repository at this point in the history
  • Loading branch information
CodyCBakerPhD committed Jun 5, 2024
2 parents 39a90db + 8673d2b commit ab0df92
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ export class GuidedMetadataPage extends ManagedPage {

onUpdate: () => (this.unsavedUpdates = "conversions"),

validateOnChange,
validateOnChange: (...args) => validateOnChange.call(this, ...args),
onlyRequired: false,
onStatusChange: (state) => this.manager.updateState(`sub-${subject}/ses-${session}`, state),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export class GuidedSubjectsPage extends Page {
schema,
formProps: {
validateOnChange: (localPath, parent, path) => {
return validateOnChange(localPath, parent, ["Subject", ...path]);
return validateOnChange.call(this, localPath, parent, ["Subject", ...path]);
},
},
}));
Expand Down
2 changes: 2 additions & 0 deletions src/electron/frontend/core/validation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,12 @@ export async function validateOnChange(name, parent, path, value) {
return func.call(this, name, copy, path, value); // Can specify alternative client-side validation
} else {
const resolvedFunctionName = func.replace(`{*}`, `${name}`);

return fetch(`${baseUrl}/neuroconv/validate`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
timezone: this.workflow?.timezone?.value,
parent: copy,
function_name: resolvedFunctionName,
}),
Expand Down
25 changes: 20 additions & 5 deletions src/pyflask/manageNeuroconv/manage_neuroconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,44 +647,58 @@ def run_check_function(check_function: callable, arg: dict) -> dict:


def validate_subject_metadata(
subject_metadata: dict, check_function_name: str
subject_metadata: dict, check_function_name: str, timezone: Optional[str] = None
): # -> Union[None, InspectorMessage, List[InspectorMessage]]:
"""Function used to validate subject metadata."""
import pytz
from pynwb.file import Subject

check_function = get_check_function(check_function_name)

if isinstance(subject_metadata.get("date_of_birth"), str):
subject_metadata["date_of_birth"] = datetime.fromisoformat(subject_metadata["date_of_birth"])
if timezone is not None:
subject_metadata["date_of_birth"] = subject_metadata["date_of_birth"].replace(
tzinfo=pytz.timezone(timezone)
)

return run_check_function(check_function, Subject(**subject_metadata))


def validate_nwbfile_metadata(
nwbfile_metadata: dict, check_function_name: str
nwbfile_metadata: dict, check_function_name: str, timezone: Optional[str] = None
): # -> Union[None, InspectorMessage, List[InspectorMessage]]:
"""Function used to validate NWBFile metadata."""
import pytz
from pynwb.testing.mock.file import mock_NWBFile

check_function = get_check_function(check_function_name)

if isinstance(nwbfile_metadata.get("session_start_time"), str):
nwbfile_metadata["session_start_time"] = datetime.fromisoformat(nwbfile_metadata["session_start_time"])
if timezone is not None:
nwbfile_metadata["session_start_time"] = nwbfile_metadata["session_start_time"].replace(
tzinfo=pytz.timezone(timezone)
)

return run_check_function(check_function, mock_NWBFile(**nwbfile_metadata))


def validate_metadata(metadata: dict, check_function_name: str) -> dict:
def validate_metadata(
metadata: dict,
check_function_name: str,
timezone: Optional[str] = None,
) -> dict:
"""Function used to validate data using an arbitrary NWB Inspector function."""
from nwbinspector.nwbinspector import InspectorOutputJSONEncoder
from pynwb.file import NWBFile, Subject

check_function = get_check_function(check_function_name)

if issubclass(check_function.neurodata_type, Subject):
result = validate_subject_metadata(metadata, check_function_name)
result = validate_subject_metadata(metadata, check_function_name, timezone)
elif issubclass(check_function.neurodata_type, NWBFile):
result = validate_nwbfile_metadata(metadata, check_function_name)
result = validate_nwbfile_metadata(metadata, check_function_name, timezone)
else:
raise ValueError(
f"Function {check_function_name} with neurodata_type {check_function.neurodata_type} "
Expand Down Expand Up @@ -1002,6 +1016,7 @@ def update_conversion_progress(message):
resolved_metadata["NWBFile"]["session_start_time"] = datetime.fromisoformat(
resolved_metadata["NWBFile"]["session_start_time"]
).replace(tzinfo=zoneinfo.ZoneInfo(info["timezone"]))

if "date_of_birth" in resolved_metadata["Subject"]:
resolved_metadata["Subject"]["date_of_birth"] = datetime.fromisoformat(
resolved_metadata["Subject"]["date_of_birth"]
Expand Down
3 changes: 2 additions & 1 deletion src/pyflask/namespaces/neuroconv.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ def post(self):
validate_parser = neuroconv_namespace.parser()
validate_parser.add_argument("parent", type=dict, required=True)
validate_parser.add_argument("function_name", type=str, required=True)
validate_parser.add_argument("timezone", type=str, required=False)


@neuroconv_namespace.route("/validate")
Expand All @@ -104,7 +105,7 @@ class Validate(Resource):
@neuroconv_namespace.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
def post(self):
args = validate_parser.parse_args()
return validate_metadata(args.get("parent"), args.get("function_name"))
return validate_metadata(args.get("parent"), args.get("function_name"), args.get("timezone"))


@neuroconv_namespace.route("/upload/project")
Expand Down
6 changes: 5 additions & 1 deletion src/schemas/base-metadata.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,11 @@ export const preprocessMetadataSchema = (schema: any = baseMetadataSchema, globa
copy.order = [ "NWBFile", "Subject" ]

const minDate = "1900-01-01T00:00"
const maxDate = getISODateInTimezone().slice(0, -2) // Restrict date to current date with timezone awareness

// Set the maximum at tomorrow
const nextDay = new Date()
nextDay.setDate(nextDay.getDate() + 1)
const maxDate = getISODateInTimezone(nextDay).slice(0, -2) // Restrict date to tomorrow (with timezone awareness)


// Add unit to weight
Expand Down

0 comments on commit ab0df92

Please sign in to comment.