Skip to content

Commit 956d0e7

Browse files
committed
Added units
1 parent aebe985 commit 956d0e7

File tree

2 files changed

+54
-21
lines changed

2 files changed

+54
-21
lines changed

script/oca_to_linkml.py

+28-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# typically, in some DH web/templates/[schema folder]/, which reads by default
1111
# a file called oca_bundle.json
1212
#
13-
# > python3 ../../../script/oca_to_linkml.py [-i oca_bundle_file_name]
13+
# > python3 ../../../script/oca_to_linkml.py [-i [oca_bundle_file_name.json]]
1414
#
1515
# Output:
1616
#
@@ -254,6 +254,7 @@
254254
"title",
255255
"range",
256256
"range_2",
257+
"unit",
257258
"identifier",
258259
"multivalued",
259260
"minimum_cardinality",
@@ -397,6 +398,8 @@ def writeSchemaCore():
397398

398399
return SCHEMA;
399400

401+
402+
################################ SLOT OUTPUT ################################
400403
def writeSlots():
401404
# Ensure SCHEMA_SLOTS has language variation
402405
addLocaleHeaders(SCHEMA_SLOTS, ["slot_group","title","description","comments","examples"]);
@@ -410,9 +413,11 @@ def writeSlots():
410413
slot['class_name'] = SCHEMA["name"];
411414
slot['name'] = slot_name;
412415
slot['title'] = oca_labels[slot_name];
413-
slot['range'] = oca_attributes[slot_name]; # Yeilds Type
414-
slot['pattern'] = oca_formats[slot_name];
415-
slot['description'] = oca_informations[slot_name];
416+
slot['range'] = oca_attributes[slot_name]; # Type is a required field?
417+
if slot_name in oca_formats:
418+
slot['pattern'] = oca_formats[slot_name];
419+
if slot_name in oca_informations:
420+
slot['description'] = oca_informations[slot_name];
416421

417422
# Minnum and maximum number of values in array of a multivalued field.
418423
# See https://oca.colossi.network/specification/#cardinality-overlay
@@ -490,6 +495,16 @@ def writeSlots():
490495
case "Boolean":
491496
pass
492497

498+
# OCA mentions a oca_overlays["unit"]["metric_system"] (usually = "SI"),
499+
# So here is a place to do unit conversion to UCUM if possible.
500+
# https://ucum.nlm.nih.gov/ucum-lhc/demo.html
501+
if slot_name in oca_units:
502+
# slot unit: / ucum_code: cm
503+
if "metric_system" in oca_overlays["unit"]:
504+
slot['unit'] = oca_overlays["unit"]["metric_system"] + ":" + oca_units[slot_name];
505+
else:
506+
slot['unit'] = oca_units[slot_name];
507+
493508
# Now convert any slot datatypes where pattern matches OCA-specific data type
494509
for type_name in SCHEMA["types"]:
495510
if "pattern" in SCHEMA["types"][type_name]:
@@ -509,11 +524,10 @@ def writeSlots():
509524
#slot['comments_'+locale] # No OCA equivalent
510525
#slot['examples_'+locale] # No OCA equivalent
511526

512-
513-
514527
save_tsv("schema_slots.tsv", SCHEMA_SLOTS, slots);
515528

516529

530+
################################ ENUM OUTPUT ################################
517531
def writeEnums():
518532
addLocaleHeaders(SCHEMA_ENUMS, ["title", "menu_1"]);
519533
enums = [];
@@ -545,8 +559,8 @@ def writeEnums():
545559

546560
# Load OCA schema bundle specification
547561
if options.input_oca_file and os.path.isfile(options.input_oca_file):
548-
with open(options.input_oca_file, "r") as f:
549-
oca_obj = json.load(f);
562+
with open(options.input_oca_file, "r") as file_handle:
563+
oca_obj = json.load(file_handle);
550564
else:
551565
os.exit("- [Input OCA bundle file is required]")
552566

@@ -599,6 +613,12 @@ def writeEnums():
599613
# attribute_entries is dictionary of [enumeration name]: {code, label}
600614
oca_entry_labels = oca_overlays["entry"][0]["attribute_entries"];
601615

616+
# Also has "metric_system": "SI",
617+
if "unit" in oca_overlays:
618+
oca_units = oca_overlays["unit"]["attribute_units"];
619+
else:
620+
oca_units = {}
621+
602622
SCHEMA = writeSchemaCore();
603623
writeSlots();
604624
writeEnums();

script/tabular_to_schema.py

+26-13
Original file line numberDiff line numberDiff line change
@@ -114,18 +114,27 @@ def set_examples (slot, example_string):
114114
slot['examples'] = examples;
115115

116116
# Parse annotation_string into slot.examples. Works for multilingual slot locale
117-
def set_annotations (slot, annotation_string):
118-
119-
if annotation_string > '':
117+
def set_attribute (slot, attribute, content):
118+
print (content)
119+
if content > '':
120120
annotations = {};
121-
for v in annotation_string.split(';'):
122-
(key, value) = v.split(':');
123-
value = value.strip();
124-
if value.lower() == 'true':
125-
value = bool(value);
126-
annotations[key.strip()] = value;
127-
128-
slot['annotations'] = annotations;
121+
for v in content.split(';'):
122+
if ':' in v:
123+
(key, value) = v.split(':');
124+
key = key.strip();
125+
value = value.strip();
126+
if value.lower() == 'true':
127+
value = bool(value);
128+
129+
if attribute == 'unit' and key != 'ucum_code':
130+
# FUTURE: do unit conversion here
131+
annotations['ucum_code'] = value;
132+
else:
133+
annotations[key] = value;
134+
else:
135+
if attribute == 'unit':
136+
annotations['ucum_code'] = value;
137+
slot[attribute] = annotations;
129138

130139

131140
# A slot's or enum's exact_mappings array gets populated with all the
@@ -273,6 +282,7 @@ def set_classes(schema_slot_path, schema, locale_schemas, export_format, warning
273282

274283
slot_range = row.get('range','');
275284
slot_range_2 = row.get('range_2','');
285+
slot_unit = row.get('unit','');
276286
slot_pattern = row.get('pattern','');
277287
slot_structured_pattern = row.get('structured_pattern','');
278288
slot_minimum_value = row.get('minimum_value','');
@@ -296,8 +306,10 @@ def set_classes(schema_slot_path, schema, locale_schemas, export_format, warning
296306

297307
if slot_minimum_cardinality > '': slot['minimum_cardinality'] = int(slot_minimum_cardinality);
298308
if slot_maximum_cardinality > '': slot['maximum_cardinality'] = int(slot_maximum_cardinality);
299-
309+
300310
set_range(slot, slot_range, slot_range_2);
311+
if slot_unit > '': slot['unit'] = slot_unit;
312+
301313
set_min_max(slot, slot_minimum_value, slot_maximum_value);
302314
if slot_pattern > '': slot['pattern'] = slot_pattern;
303315
if slot_structured_pattern > '':
@@ -307,8 +319,9 @@ def set_classes(schema_slot_path, schema, locale_schemas, export_format, warning
307319
'interpolated': True
308320
}
309321

322+
set_attribute(slot, "unit", slot_unit);
310323
set_examples(slot, slot_examples);
311-
set_annotations(slot, slot_annotations);
324+
set_attribute(slot, "annotations", slot_annotations);
312325
set_mappings(slot, row, export_format);
313326

314327
# If slot has already been set up in schema['slots'] then compare

0 commit comments

Comments
 (0)