diff --git a/pyflask/manageNeuroconv/manage_neuroconv.py b/pyflask/manageNeuroconv/manage_neuroconv.py index e6d2fabc9..27727640b 100644 --- a/pyflask/manageNeuroconv/manage_neuroconv.py +++ b/pyflask/manageNeuroconv/manage_neuroconv.py @@ -258,7 +258,11 @@ def get_metadata_schema(source_data: Dict[str, dict], interfaces: dict) -> Dict[ """Function used to fetch the metadata schema from a CustomNWBConverter instantiated from the source_data.""" from neuroconv.utils import NWBMetaDataEncoder - converter = instantiate_custom_converter(source_data, interfaces) + resolved_source_data = replace_none_with_nan( + source_data, resolve_references(get_custom_converter(interfaces).get_source_schema()) + ) + + converter = instantiate_custom_converter(resolved_source_data, interfaces) schema = converter.get_metadata_schema() metadata = converter.get_metadata() @@ -423,7 +427,11 @@ def convert_to_nwb(info: dict) -> str: resolved_output_path.parent.mkdir(exist_ok=True, parents=True) # Ensure all parent directories exist - converter = instantiate_custom_converter(info["source_data"], info["interfaces"]) + resolved_source_data = replace_none_with_nan( + info["source_data"], resolve_references(get_custom_converter(info["interfaces"]).get_source_schema()) + ) + + converter = instantiate_custom_converter(resolved_source_data, info["interfaces"]) def update_conversion_progress(**kwargs): announcer.announce(dict(**kwargs, nwbfile_path=nwbfile_path), "conversion_progress") diff --git a/src/renderer/src/stories/JSONSchemaForm.js b/src/renderer/src/stories/JSONSchemaForm.js index 36060fd91..c7e4d865f 100644 --- a/src/renderer/src/stories/JSONSchemaForm.js +++ b/src/renderer/src/stories/JSONSchemaForm.js @@ -23,7 +23,7 @@ const encode = (str) => { const additionalPropPattern = "additional"; -const provideNaNMessage = `
Type NaN to represent an unknown value.`; +const templateNaNMessage = `
Type NaN to represent an unknown value.`; import { Validator } from "jsonschema"; import { successHue, warningHue, errorHue } from "./globals"; @@ -378,8 +378,8 @@ export class JSONSchemaForm extends LitElement { throw new Error(message); }; - validateSchema = async (resolved, schema, name) => { - return await validator + validateSchema = (resolved, schema, name) => { + return validator .validate(resolved, schema) .errors.map((e) => { const propName = e.path.slice(-1)[0] ?? name ?? e.property; @@ -399,8 +399,8 @@ export class JSONSchemaForm extends LitElement { // Allow referring to floats as null (i.e. JSON NaN representation) if (e.message === "is not of a type(s) number") { - if (resolvedValue === "NaN") return; - else e.message = `${e.message}. ${provideNaNMessage}`; + if ((resolvedValue === "NaN") | (resolvedValue === null)) return; + else if (isRow) e.message = `${e.message}. ${templateNaNMessage}`; } const prevHeader = name ? header(name) : "Row"; @@ -422,7 +422,7 @@ export class JSONSchemaForm extends LitElement { const copy = structuredClone(resolved); delete copy.__disabled; - const result = await this.validateSchema(copy, this.schema); + const result = this.validateSchema(copy, this.schema); const resolvedErrors = this.#resolveErrors(result, this.base, resolved); @@ -815,7 +815,7 @@ export class JSONSchemaForm extends LitElement { const skipValidation = !this.validateEmptyValues && value === undefined; const validateArgs = input.pattern || skipValidation ? [] : [value, schema]; - const jsonSchemaErrors = validateArgs.length === 2 ? await this.validateSchema(...validateArgs, name) : []; + const jsonSchemaErrors = validateArgs.length === 2 ? this.validateSchema(...validateArgs, name) : []; const valid = skipValidation ? true : await this.validateOnChange(name, parent, pathToValidate, value); @@ -860,9 +860,16 @@ export class JSONSchemaForm extends LitElement { // Throw at least a basic warning if a non-linked property is required and missing if (!hasLinks && isRequired) { if (this.validateEmptyValues) { + const rowName = pathToValidate.slice(-1)[0]; + const isRow = typeof rowName === "number"; + errors.push({ message: `${schema.title ?? header(name)} ${this.#isARequiredPropertyString}. ${ - schema.type === "number" ? provideNaNMessage : "" + schema.type === "number" + ? isRow + ? templateNaNMessage + : "
Use the 'I Don't Know' checkbox if unsure." + : "" }`, type: "error", missing: true, diff --git a/src/renderer/src/stories/JSONSchemaInput.js b/src/renderer/src/stories/JSONSchemaInput.js index 3c61f412b..aae940a4b 100644 --- a/src/renderer/src/stories/JSONSchemaInput.js +++ b/src/renderer/src/stories/JSONSchemaInput.js @@ -435,7 +435,7 @@ export class JSONSchemaInput extends LitElement { white-space: nowrap; } - .nan-handler label { + .nan-handler span { margin-left: 5px; font-size: 12px; } @@ -1074,12 +1074,14 @@ export class JSONSchemaInput extends LitElement { // const isBlank = value === ''; - if (isInteger) newValue = parseInt(value); - else if (isNumber) newValue = parseFloat(value); + if (isInteger) value = newValue = parseInt(value); + else if (isNumber) value = newValue = parseFloat(value); if (isNumber) { if ("min" in schema && newValue < schema.min) newValue = schema.min; else if ("max" in schema && newValue > schema.max) newValue = schema.max; + + if (isNaN(newValue)) newValue = undefined; } if (schema.transform) newValue = schema.transform(newValue, this.value, schema); @@ -1090,7 +1092,7 @@ export class JSONSchemaInput extends LitElement { // if (!regex.test(isNaN(newValue) ? value : newValue)) newValue = this.value // revert to last value // } - if (!isNaN(newValue) && newValue !== value) { + if (isNumber && newValue !== value) { ev.target.value = newValue; value = newValue; } @@ -1108,19 +1110,20 @@ export class JSONSchemaInput extends LitElement { ${isRequiredNumber ? html`
{ const siblingInput = ev.target.parentNode.previousElementSibling; if (ev.target.checked) { - this.#updateData(fullPath, NaN); + this.#updateData(fullPath, null); siblingInput.setAttribute("disabled", true); } else { siblingInput.removeAttribute("disabled"); const ev = new Event("input"); siblingInput.dispatchEvent(ev); } + this.#triggerValidation(name, path); }} - >
` + >I Don't Know` : ""} `; }