diff --git a/sample-management-custom/caosdb-server/scripting/bin/crawl_sample_data_async.py b/sample-management-custom/caosdb-server/scripting/bin/crawl_sample_data_async.py index ace23eef4c481fdc20057fce83ef44d4c45dbca5..f3fff6dd3469613378aa7c702d8d90f750694362 100755 --- a/sample-management-custom/caosdb-server/scripting/bin/crawl_sample_data_async.py +++ b/sample-management-custom/caosdb-server/scripting/bin/crawl_sample_data_async.py @@ -176,6 +176,7 @@ def update_sample_records(data, htmluserlog_public): # Samples might need additional post processing samples = post_process_samples(samples, data) + logger.info(samples) synchroize(samples, additional_property_ents, htmluserlog_public) diff --git a/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/default_constants.yml b/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/default_constants.yml index 12edef83b5b463839429faabad5a22e6a543c621..119abc9c165507e9b33a7f69e3224017ba55e2f2 100644 --- a/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/default_constants.yml +++ b/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/default_constants.yml @@ -18,8 +18,8 @@ csv_column_names: entity_id: "LinkAhead ID" custom_label_prop: "Custom Label" - start_date_prop: "Date start" - end_date_prop: "Date stop" + start_date_prop: "Start date" + end_date_prop: "End date" igsn_doi_prop: "IGSN DOI" csv_column_descriptions: diff --git a/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_add_special_properties.py b/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_add_special_properties.py index cb7ce01ba2e526bd68068daab685818d85959424..5c559d42f9e926303f2c2d94d0bb26e2c42d5d38 100644 --- a/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_add_special_properties.py +++ b/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_add_special_properties.py @@ -21,6 +21,7 @@ import pandas as pd from caosadvancedtools.datainconsistency import DataInconsistencyError from .sample_upload_get_container import get_container +from .sample_upload_get_device import get_device from .sample_upload_get_person import get_person from .utils import get_column_header_name, get_entity_name, update_property, return_value_if_not_none @@ -32,25 +33,32 @@ def add_special_properties(sample: db.Record, data: pd.Series) -> db.Record: """ main_user_prop = db.get_entity_by_name(get_entity_name("Main User")) - container_rt = db.get_entity_name(get_entity_name("container_rt")) - parent_sample_prop = db.get_entity_name(get_entity_name("parent_sample_prop")) + container_rt = db.get_entity_by_name(get_entity_name("container_rt")) + device_rt = db.get_entity_by_name(get_entity_name("Device")) + parent_sample_prop = db.get_entity_by_name(get_entity_name("parent_sample_prop")) if (get_column_header_name("Main User") in data and return_value_if_not_none(data[get_column_header_name("Main User")]) is not None): main_user = get_person(return_value_if_not_none(data[get_column_header_name("Main User")])) - sample = update_property(sample, main_user_prop.id, main_user) + sample = update_property(sample, main_user_prop.id, main_user, property_name=main_user_prop.name) if (get_column_header_name("Storage ID") in data and return_value_if_not_none(data[get_column_header_name("Storage ID")]) is not None): container = get_container(return_value_if_not_none( data[get_column_header_name("Storage ID")])) - sample = update_property(sample, container_rt.id, container) + sample = update_property(sample, container_rt.id, container, property_name=container_rt.name) + + if (get_column_header_name("Device") in data and + return_value_if_not_none(data[get_column_header_name("Device")]) is not None): + device = get_device(return_value_if_not_none( + data[get_column_header_name("Device")])) + sample = update_property(sample, device_rt.id, device, property_name=device_rt.name) if (get_column_header_name("Parent LinkAhead ID") in data and return_value_if_not_none(data[get_column_header_name("Parent LinkAhead ID")]) is not None): parent = return_value_if_not_none( data[get_column_header_name("Parent LinkAhead ID")]) - sample = update_property(sample, parent_sample_prop.id, parent) + sample = update_property(sample, parent_sample_prop.id, parent, property_name=parent_sample_prop.name) for name in ["Curator", "Collector"]: prop = db.get_entity_by_name(get_entity_name(name)) @@ -59,6 +67,6 @@ def add_special_properties(sample: db.Record, data: pd.Series) -> db.Record: persons = [get_person(id_str) for id_str in return_value_if_not_none( data[get_column_header_name(name)])] sample = update_property(sample, prop.id, persons, - datatype=db.LIST(get_entity_name("Person"))) + datatype=db.LIST(get_entity_name("Person")), property_name=prop.name) return sample diff --git a/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_column_definitions.py b/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_column_definitions.py index 8384ed934c1449d7b27ca5d6681de95e6d723d6f..235d6949eb3153c6d1e4891cb5938242bda5f987 100644 --- a/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_column_definitions.py +++ b/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_column_definitions.py @@ -97,6 +97,7 @@ SPECIAL_TREATMENT_SAMPLE = _use_custom_names([ "Campaign", "Collector", "Curator", + "Device", "Elevation start", "Elevation stop", "Embargo", diff --git a/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_get_device.py b/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_get_device.py new file mode 100644 index 0000000000000000000000000000000000000000..08cf3f0ac5b3148361fc8517cdbcbabf6f48e63e --- /dev/null +++ b/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_get_device.py @@ -0,0 +1,42 @@ +# +# Copyright (C) 2025 Indiscale GmbH <info@indiscale.com> +# Copyright (C) 2025 Florian Spreckelsen <f.spreckelsen@indiscale.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +import linkahead as db + +from caosadvancedtools.datainconsistency import DataInconsistencyError + +from .utils import get_entity_name + +def get_device(identifier: str) -> db.Record: + """Return the container record for a given identifier string. By + default, that's simply the id but may be overwritten for + customization. + + """ + try: + return db.cached.cached_get_entity_by( + query=f"FIND '{get_entity_name('Device')}' WITH ID='{identifier}'" + ) + except db.EmptyUniqueQueryError: + try: + return db.cached.cached_get_entity_by( + query=f"FIND '{get_entity_name('Device')}' WITH name='{identifier}'" + ) + except db.EmptyUniqueQueryError: + raise DataInconsistencyError( + f"Couldn't find a {get_entity_name('Device')} with name or id {identifier}." + ) diff --git a/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_get_event.py b/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_get_event.py index 39ca20439768eb1d0d371b4df89eca89acb8c135..7c762df32b703c26ef937bf76e0a3bafe4519e2a 100644 --- a/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_get_event.py +++ b/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/sample_upload_get_event.py @@ -37,13 +37,13 @@ def add_event_to_sample(sample: db.Record, data: pd.Series) -> db.Record: # We performed the sanity checks so we can assume that if the # Start/Stop Latitude exists, all start/stop data exist. positions = [] - position_prop = db.get_entity_name(get_entity_name("Position")) + position_prop = db.get_entity_by_name(get_entity_name("Position")) # Take care of positions for mode in ["start", "stop"]: if (get_column_header_name(f"Latitude {mode}") in data and return_value_if_not_none(data[get_column_header_name(f"Latitude {mode}")]) is not None): - position.append( + positions.append( _create_position( mode=mode, lat=return_value_if_not_none(data[get_column_header_name(f"Latitude {mode}")]), @@ -53,18 +53,18 @@ def add_event_to_sample(sample: db.Record, data: pd.Series) -> db.Record: ) if positions: event = update_property(event, position_prop.id, positions, - datatype=db.LIST(get_entity_name("Position"))) + datatype=db.LIST(get_entity_name("Position")), property_name=position_prop.name) for time_p in ["start_date_prop", "end_date_prop"]: prop = db.get_entity_by_name(get_entity_name(time_p)) if (get_column_header_name(time_p) in data and return_value_if_not_none(data[get_column_header_name(time_p)]) is not None): event = update_property(event, prop.id, return_value_if_not_none( - data[get_column_header_name(time_p)])) + data[get_column_header_name(time_p)]), property_name=prop.name) # only add if there was any event data at all: if len(event.properties) > 0: - sample = update_property(sample, event_rt.id, event) + sample = update_property(sample, event_rt.id, event, property_name=event_rt.name) return sample @@ -101,10 +101,10 @@ def _perform_sanity_checks(sample, data): bool_list = [get_column_header_name(f"{val}_{name}") in data for val in [ "latitude", "longitude", "elevation"]] raise_error = False - if bool_list.any(): - if not bool_list.all(): + if any(bool_list): + if not all(bool_list): raise_error = True - elif [return_value_if_not_none(data[get_column_header_name(f"{val}_{name}")]) is None for val in ["latitude", "longitude", "elevation"]].any(): + elif any([return_value_if_not_none(data[get_column_header_name(f"{val}_{name}")]) is None for val in ["latitude", "longitude", "elevation"]]): raise_error = True if raise_error: diff --git a/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/utils.py b/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/utils.py index c482eeee68360683d92332817fc8aaf5c75ccc38..d047e6bbfd6a39cae610526d17238d3675533447 100644 --- a/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/utils.py +++ b/sample-management-custom/caosdb-server/scripting/bin/sample_helpers/utils.py @@ -55,15 +55,11 @@ def update_property(entity: db.Record, property_id: int, value, property_name="" entity.add_property(id=property_id, value=value, name=property_name, datatype=datatype) else: entity.add_property(id=property_id, value=value, name=property_name) - logger.debug("{}: Adding {} = {}".format(entity.id, property_id, value.id if - isinstance(value, db.Entity) else value)) else: if isinstance(value, list) and not entity.get_property(property_id).datatype.startswith("LIST"): entity.get_property(property_id).datatype = db.LIST( entity.get_property(property_id).datatype) entity.get_property(property_id).value = value - logger.debug("{}: Setting {} = {}".format(entity.id, property_id, value.id if - isinstance(value, db.Entity) else value)) return entity diff --git a/sample-management-custom/caosdb-server/scripting/home/identifiables.yml b/sample-management-custom/caosdb-server/scripting/home/identifiables.yml index 01181ef3afa4701b08593090cd76bc2b4fbbf4a9..25a6e4a6a1f05dc4537c58dd97afb447b3ab4e60 100644 --- a/sample-management-custom/caosdb-server/scripting/home/identifiables.yml +++ b/sample-management-custom/caosdb-server/scripting/home/identifiables.yml @@ -1,7 +1,6 @@ ControlledRecordType: - name Event: - - Device - start_date - Position SampleType: