nmdc-runtime 2.6.0__py3-none-any.whl → 2.12.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. nmdc_runtime/Dockerfile +177 -0
  2. nmdc_runtime/api/analytics.py +90 -0
  3. nmdc_runtime/api/boot/capabilities.py +9 -0
  4. nmdc_runtime/api/boot/object_types.py +126 -0
  5. nmdc_runtime/api/boot/triggers.py +84 -0
  6. nmdc_runtime/api/boot/workflows.py +116 -0
  7. nmdc_runtime/api/core/auth.py +212 -0
  8. nmdc_runtime/api/core/idgen.py +200 -0
  9. nmdc_runtime/api/core/metadata.py +777 -0
  10. nmdc_runtime/api/core/util.py +114 -0
  11. nmdc_runtime/api/db/mongo.py +436 -0
  12. nmdc_runtime/api/db/s3.py +37 -0
  13. nmdc_runtime/api/endpoints/capabilities.py +25 -0
  14. nmdc_runtime/api/endpoints/find.py +634 -0
  15. nmdc_runtime/api/endpoints/jobs.py +206 -0
  16. nmdc_runtime/api/endpoints/lib/helpers.py +274 -0
  17. nmdc_runtime/api/endpoints/lib/linked_instances.py +193 -0
  18. nmdc_runtime/api/endpoints/lib/path_segments.py +165 -0
  19. nmdc_runtime/api/endpoints/metadata.py +260 -0
  20. nmdc_runtime/api/endpoints/nmdcschema.py +515 -0
  21. nmdc_runtime/api/endpoints/object_types.py +38 -0
  22. nmdc_runtime/api/endpoints/objects.py +277 -0
  23. nmdc_runtime/api/endpoints/operations.py +78 -0
  24. nmdc_runtime/api/endpoints/queries.py +701 -0
  25. nmdc_runtime/api/endpoints/runs.py +98 -0
  26. nmdc_runtime/api/endpoints/search.py +38 -0
  27. nmdc_runtime/api/endpoints/sites.py +205 -0
  28. nmdc_runtime/api/endpoints/triggers.py +25 -0
  29. nmdc_runtime/api/endpoints/users.py +214 -0
  30. nmdc_runtime/api/endpoints/util.py +817 -0
  31. nmdc_runtime/api/endpoints/wf_file_staging.py +307 -0
  32. nmdc_runtime/api/endpoints/workflows.py +353 -0
  33. nmdc_runtime/api/entrypoint.sh +7 -0
  34. nmdc_runtime/api/main.py +495 -0
  35. nmdc_runtime/api/middleware.py +43 -0
  36. nmdc_runtime/api/models/capability.py +14 -0
  37. nmdc_runtime/api/models/id.py +92 -0
  38. nmdc_runtime/api/models/job.py +57 -0
  39. nmdc_runtime/api/models/lib/helpers.py +78 -0
  40. nmdc_runtime/api/models/metadata.py +11 -0
  41. nmdc_runtime/api/models/nmdc_schema.py +146 -0
  42. nmdc_runtime/api/models/object.py +180 -0
  43. nmdc_runtime/api/models/object_type.py +20 -0
  44. nmdc_runtime/api/models/operation.py +66 -0
  45. nmdc_runtime/api/models/query.py +246 -0
  46. nmdc_runtime/api/models/query_continuation.py +111 -0
  47. nmdc_runtime/api/models/run.py +161 -0
  48. nmdc_runtime/api/models/site.py +87 -0
  49. nmdc_runtime/api/models/trigger.py +13 -0
  50. nmdc_runtime/api/models/user.py +207 -0
  51. nmdc_runtime/api/models/util.py +260 -0
  52. nmdc_runtime/api/models/wfe_file_stages.py +122 -0
  53. nmdc_runtime/api/models/workflow.py +15 -0
  54. nmdc_runtime/api/openapi.py +178 -0
  55. nmdc_runtime/api/swagger_ui/assets/EllipsesButton.js +146 -0
  56. nmdc_runtime/api/swagger_ui/assets/EndpointSearchWidget.js +369 -0
  57. nmdc_runtime/api/swagger_ui/assets/script.js +252 -0
  58. nmdc_runtime/api/swagger_ui/assets/style.css +155 -0
  59. nmdc_runtime/api/swagger_ui/swagger_ui.py +34 -0
  60. nmdc_runtime/config.py +56 -1
  61. nmdc_runtime/minter/adapters/repository.py +22 -2
  62. nmdc_runtime/minter/config.py +2 -0
  63. nmdc_runtime/minter/domain/model.py +55 -1
  64. nmdc_runtime/minter/entrypoints/fastapi_app.py +1 -1
  65. nmdc_runtime/mongo_util.py +89 -0
  66. nmdc_runtime/site/backup/nmdcdb_mongodump.py +1 -1
  67. nmdc_runtime/site/backup/nmdcdb_mongoexport.py +1 -3
  68. nmdc_runtime/site/changesheets/data/OmicsProcessing-to-catted-Biosamples.tsv +1561 -0
  69. nmdc_runtime/site/changesheets/scripts/missing_neon_soils_ecosystem_data.py +311 -0
  70. nmdc_runtime/site/changesheets/scripts/neon_soils_add_ncbi_ids.py +210 -0
  71. nmdc_runtime/site/dagster.yaml +53 -0
  72. nmdc_runtime/site/entrypoint-daemon.sh +29 -0
  73. nmdc_runtime/site/entrypoint-dagit-readonly.sh +26 -0
  74. nmdc_runtime/site/entrypoint-dagit.sh +29 -0
  75. nmdc_runtime/site/export/ncbi_xml.py +731 -40
  76. nmdc_runtime/site/export/ncbi_xml_utils.py +142 -26
  77. nmdc_runtime/site/graphs.py +80 -29
  78. nmdc_runtime/site/ops.py +522 -183
  79. nmdc_runtime/site/repair/database_updater.py +210 -1
  80. nmdc_runtime/site/repository.py +108 -117
  81. nmdc_runtime/site/resources.py +72 -36
  82. nmdc_runtime/site/translation/gold_translator.py +22 -21
  83. nmdc_runtime/site/translation/neon_benthic_translator.py +1 -1
  84. nmdc_runtime/site/translation/neon_soil_translator.py +5 -5
  85. nmdc_runtime/site/translation/neon_surface_water_translator.py +1 -2
  86. nmdc_runtime/site/translation/submission_portal_translator.py +216 -69
  87. nmdc_runtime/site/translation/translator.py +64 -1
  88. nmdc_runtime/site/util.py +8 -3
  89. nmdc_runtime/site/validation/util.py +16 -12
  90. nmdc_runtime/site/workspace.yaml +13 -0
  91. nmdc_runtime/static/NMDC_logo.svg +1073 -0
  92. nmdc_runtime/static/ORCID-iD_icon_vector.svg +4 -0
  93. nmdc_runtime/static/README.md +5 -0
  94. nmdc_runtime/static/favicon.ico +0 -0
  95. nmdc_runtime/util.py +175 -348
  96. nmdc_runtime-2.12.0.dist-info/METADATA +45 -0
  97. nmdc_runtime-2.12.0.dist-info/RECORD +131 -0
  98. {nmdc_runtime-2.6.0.dist-info → nmdc_runtime-2.12.0.dist-info}/WHEEL +1 -2
  99. nmdc_runtime/containers.py +0 -14
  100. nmdc_runtime/core/db/Database.py +0 -15
  101. nmdc_runtime/core/exceptions/__init__.py +0 -23
  102. nmdc_runtime/core/exceptions/base.py +0 -47
  103. nmdc_runtime/core/exceptions/token.py +0 -13
  104. nmdc_runtime/domain/users/queriesInterface.py +0 -18
  105. nmdc_runtime/domain/users/userSchema.py +0 -37
  106. nmdc_runtime/domain/users/userService.py +0 -14
  107. nmdc_runtime/infrastructure/database/db.py +0 -3
  108. nmdc_runtime/infrastructure/database/models/user.py +0 -10
  109. nmdc_runtime/lib/__init__.py +0 -1
  110. nmdc_runtime/lib/extract_nmdc_data.py +0 -41
  111. nmdc_runtime/lib/load_nmdc_data.py +0 -121
  112. nmdc_runtime/lib/nmdc_dataframes.py +0 -829
  113. nmdc_runtime/lib/nmdc_etl_class.py +0 -402
  114. nmdc_runtime/lib/transform_nmdc_data.py +0 -1117
  115. nmdc_runtime/site/drsobjects/ingest.py +0 -93
  116. nmdc_runtime/site/drsobjects/registration.py +0 -131
  117. nmdc_runtime/site/translation/emsl.py +0 -43
  118. nmdc_runtime/site/translation/gold.py +0 -53
  119. nmdc_runtime/site/translation/jgi.py +0 -32
  120. nmdc_runtime/site/translation/util.py +0 -132
  121. nmdc_runtime/site/validation/jgi.py +0 -43
  122. nmdc_runtime-2.6.0.dist-info/METADATA +0 -199
  123. nmdc_runtime-2.6.0.dist-info/RECORD +0 -83
  124. nmdc_runtime-2.6.0.dist-info/top_level.txt +0 -1
  125. /nmdc_runtime/{client → api}/__init__.py +0 -0
  126. /nmdc_runtime/{core → api/boot}/__init__.py +0 -0
  127. /nmdc_runtime/{core/db → api/core}/__init__.py +0 -0
  128. /nmdc_runtime/{domain → api/db}/__init__.py +0 -0
  129. /nmdc_runtime/{domain/users → api/endpoints}/__init__.py +0 -0
  130. /nmdc_runtime/{infrastructure → api/endpoints/lib}/__init__.py +0 -0
  131. /nmdc_runtime/{infrastructure/database → api/models}/__init__.py +0 -0
  132. /nmdc_runtime/{infrastructure/database/models → api/models/lib}/__init__.py +0 -0
  133. /nmdc_runtime/{site/drsobjects/__init__.py → api/models/minter.py} +0 -0
  134. {nmdc_runtime-2.6.0.dist-info → nmdc_runtime-2.12.0.dist-info}/entry_points.txt +0 -0
  135. {nmdc_runtime-2.6.0.dist-info → nmdc_runtime-2.12.0.dist-info}/licenses/LICENSE +0 -0
@@ -14,7 +14,6 @@ from dagster import (
14
14
  StringSource,
15
15
  InitResourceContext,
16
16
  )
17
- from fastjsonschema import JsonSchemaValueException
18
17
  from frozendict import frozendict
19
18
  from linkml_runtime.dumpers import json_dumper
20
19
  from pydantic import BaseModel, AnyUrl
@@ -27,7 +26,7 @@ from nmdc_runtime.api.models.object import DrsObject, AccessURL, DrsObjectIn
27
26
  from nmdc_runtime.api.models.operation import ListOperationsResponse
28
27
  from nmdc_runtime.api.models.util import ListRequest
29
28
  from nmdc_runtime.site.normalization.gold import normalize_gold_id
30
- from nmdc_runtime.util import unfreeze, nmdc_jsonschema_validator_noidpatterns
29
+ from nmdc_runtime.util import unfreeze, get_nmdc_schema_validator
31
30
  from nmdc_schema import nmdc
32
31
 
33
32
 
@@ -109,7 +108,7 @@ class RuntimeApiUserClient(RuntimeApiClient):
109
108
  },
110
109
  )
111
110
  response.raise_for_status()
112
- return response.json()["cursor"]["firstBatch"]
111
+ return response.json()["cursor"]["batch"]
113
112
 
114
113
  def get_omics_processing_records_by_gold_project_id(self, gold_project_id: str):
115
114
  gold_project_id = normalize_gold_id(gold_project_id)
@@ -126,7 +125,7 @@ class RuntimeApiUserClient(RuntimeApiClient):
126
125
  },
127
126
  )
128
127
  response.raise_for_status()
129
- return response.json()["cursor"]["firstBatch"]
128
+ return response.json()["cursor"]["batch"]
130
129
 
131
130
  def get_biosamples_for_study(self, study_id: str):
132
131
  # TODO: 10000 is an arbitrarily large number that has been chosen for the max_page_size param.
@@ -147,6 +146,19 @@ class RuntimeApiUserClient(RuntimeApiClient):
147
146
  response.raise_for_status()
148
147
  return response.json()["resources"]
149
148
 
149
+ def get_data_generation_records_for_study(self, study_id: str):
150
+ # TODO: same as above, we are using a large max_page_size to avoid pagination.
151
+ response = self.request(
152
+ "GET",
153
+ f"/nmdcschema/data_generation_set",
154
+ {
155
+ "filter": json.dumps({"associated_studies": study_id}),
156
+ "max_page_size": 10000,
157
+ },
158
+ )
159
+ response.raise_for_status()
160
+ return response.json()["resources"]
161
+
150
162
  def get_omics_processing_by_name(self, name: str):
151
163
  response = self.request(
152
164
  "POST",
@@ -157,7 +169,7 @@ class RuntimeApiUserClient(RuntimeApiClient):
157
169
  },
158
170
  )
159
171
  response.raise_for_status()
160
- return response.json()["cursor"]["firstBatch"]
172
+ return response.json()["cursor"]["batch"]
161
173
 
162
174
  def get_study(self, study_id: str):
163
175
  response = self.request(
@@ -169,7 +181,7 @@ class RuntimeApiUserClient(RuntimeApiClient):
169
181
  },
170
182
  )
171
183
  response.raise_for_status()
172
- return response.json()["cursor"]["firstBatch"]
184
+ return response.json()["cursor"]["batch"]
173
185
 
174
186
 
175
187
  class RuntimeApiSiteClient(RuntimeApiClient):
@@ -453,6 +465,17 @@ class NmdcPortalApiClient:
453
465
  response.raise_for_status()
454
466
  return response.json()
455
467
 
468
+ def make_submission_images_public(
469
+ self, submission_id: str, *, study_id: str
470
+ ) -> Dict[str, Any]:
471
+ response = self._request(
472
+ "POST",
473
+ f"/api/metadata_submission/{submission_id}/image/make_public",
474
+ json={"study_id": study_id},
475
+ )
476
+ response.raise_for_status()
477
+ return response.json()
478
+
456
479
 
457
480
  @resource(
458
481
  config_schema={
@@ -507,36 +530,49 @@ class MongoDB:
507
530
  self.db = self.client[dbname]
508
531
 
509
532
  def add_docs(self, docs, validate=True, replace=True):
510
- try:
511
- if validate:
512
- nmdc_jsonschema_validator_noidpatterns(docs)
513
- rv = {}
514
- for collection_name, docs in docs.items():
515
- rv[collection_name] = self.db[collection_name].bulk_write(
516
- [
517
- (
518
- ReplaceOne({"id": d["id"]}, d, upsert=True)
519
- if replace
520
- else InsertOne(d)
521
- )
522
- for d in docs
523
- ]
524
- )
525
- now = datetime.now(timezone.utc)
526
- self.db.txn_log.insert_many(
527
- [
528
- {
529
- "tgt": {"id": d.get("id"), "c": collection_name},
530
- "type": "upsert",
531
- "ts": now,
532
- # "dtl": {},
533
- }
534
- for d in docs
535
- ]
536
- )
537
- return rv
538
- except JsonSchemaValueException as e:
539
- raise ValueError(e.message)
533
+ """
534
+ TODO: Document this function.
535
+ """
536
+ if validate:
537
+ validator = get_nmdc_schema_validator()
538
+ # Fail fast on first validation error.
539
+ for result in validator.iter_results(docs, target_class="Database"):
540
+ raise ValueError(result.message)
541
+ rv = {}
542
+ for collection_name, collection_docs in docs.items():
543
+ # If `collection_docs` is empty, abort this iteration.
544
+ #
545
+ # Note: We do this because the `bulk_write` method called below will raise
546
+ # an `InvalidOperation` exception if it is passed 0 operations.
547
+ #
548
+ # Reference: https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html#pymongo.collection.Collection.bulk_write
549
+ #
550
+ if len(collection_docs) == 0:
551
+ continue
552
+
553
+ rv[collection_name] = self.db[collection_name].bulk_write(
554
+ [
555
+ (
556
+ ReplaceOne({"id": d["id"]}, d, upsert=True)
557
+ if replace
558
+ else InsertOne(d)
559
+ )
560
+ for d in collection_docs
561
+ ]
562
+ )
563
+ now = datetime.now(timezone.utc)
564
+ self.db.txn_log.insert_many(
565
+ [
566
+ {
567
+ "tgt": {"id": d.get("id"), "c": collection_name},
568
+ "type": "upsert",
569
+ "ts": now,
570
+ # "dtl": {},
571
+ }
572
+ for d in collection_docs
573
+ ]
574
+ )
575
+ return rv
540
576
 
541
577
 
542
578
  @resource(
@@ -1,5 +1,4 @@
1
1
  import collections
2
- import csv
3
2
  import re
4
3
  from typing import List, Tuple, Union
5
4
  from nmdc_schema import nmdc
@@ -45,6 +44,7 @@ class GoldStudyTranslator(Translator):
45
44
  analysis_projects: List[JSON_OBJECT] = [],
46
45
  gold_nmdc_instrument_map_df: pd.DataFrame = pd.DataFrame(),
47
46
  include_field_site_info: bool = False,
47
+ enable_biosample_filtering: bool = True,
48
48
  *args,
49
49
  **kwargs,
50
50
  ) -> None:
@@ -53,15 +53,20 @@ class GoldStudyTranslator(Translator):
53
53
  self.study = study
54
54
  self.study_type = nmdc.StudyCategoryEnum(study_type)
55
55
  self.include_field_site_info = include_field_site_info
56
+ self.enable_biosample_filtering = enable_biosample_filtering
56
57
  # Filter biosamples to only those with `sequencingStrategy` of
57
- # "Metagenome" or "Metatranscriptome"
58
- self.biosamples = [
59
- biosample
60
- for biosample in biosamples
61
- if any(
62
- _is_valid_project(project) for project in biosample.get("projects", [])
63
- )
64
- ]
58
+ # "Metagenome" or "Metatranscriptome" if filtering is enabled
59
+ if enable_biosample_filtering:
60
+ self.biosamples = [
61
+ biosample
62
+ for biosample in biosamples
63
+ if any(
64
+ _is_valid_project(project)
65
+ for project in biosample.get("projects", [])
66
+ )
67
+ ]
68
+ else:
69
+ self.biosamples = biosamples
65
70
  # Fetch the valid projectGoldIds that are associated with filtered
66
71
  # biosamples on their `projects` field
67
72
  valid_project_ids = {
@@ -116,6 +121,9 @@ class GoldStudyTranslator(Translator):
116
121
  :param gold_entity: GOLD entity object
117
122
  :return: PersonValue corresponding to the first PI in the `contacts` field
118
123
  """
124
+ if "contacts" not in gold_entity:
125
+ return None
126
+
119
127
  pi_dict = next(
120
128
  (
121
129
  contact
@@ -169,7 +177,7 @@ class GoldStudyTranslator(Translator):
169
177
  project["ncbiBioSampleAccession"], default_prefix="biosample"
170
178
  )
171
179
  for project in biosample_projects
172
- if project["ncbiBioSampleAccession"]
180
+ if project.get("ncbiBioSampleAccession")
173
181
  ]
174
182
 
175
183
  def _get_samp_taxon_id(
@@ -333,12 +341,7 @@ class GoldStudyTranslator(Translator):
333
341
  if field_value is None:
334
342
  return None
335
343
 
336
- return nmdc.QuantityValue(
337
- has_raw_value=field_value,
338
- has_numeric_value=nmdc.Double(field_value),
339
- has_unit=unit,
340
- type="nmdc:QuantityValue",
341
- )
344
+ return self._parse_quantity_value(str(field_value), unit)
342
345
 
343
346
  def _get_text_value(
344
347
  self, gold_entity: JSON_OBJECT, gold_field: str
@@ -564,13 +567,11 @@ class GoldStudyTranslator(Translator):
564
567
  gold_biosample_id = gold_biosample["biosampleGoldId"]
565
568
  return nmdc.Biosample(
566
569
  add_date=gold_biosample.get("addDate"),
567
- alt=self._get_quantity_value(
568
- gold_biosample, "altitudeInMeters", unit="meters"
569
- ),
570
+ alt=self._get_quantity_value(gold_biosample, "altitudeInMeters", unit="m"),
570
571
  collected_from=nmdc_field_site_id,
571
572
  collection_date=self._get_collection_date(gold_biosample),
572
573
  depth=self._get_quantity_value(
573
- gold_biosample, ("depthInMeters", "depthInMeters2"), unit="meters"
574
+ gold_biosample, ("depthInMeters", "depthInMeters2"), unit="m"
574
575
  ),
575
576
  description=gold_biosample.get("description"),
576
577
  diss_oxygen=self._get_quantity_value(gold_biosample, "oxygenConcentration"),
@@ -609,7 +610,7 @@ class GoldStudyTranslator(Translator):
609
610
  ),
610
611
  specific_ecosystem=gold_biosample.get("specificEcosystem"),
611
612
  subsurface_depth=self._get_quantity_value(
612
- gold_biosample, "subsurfaceDepthInMeters", unit="meters"
613
+ gold_biosample, "subsurfaceDepthInMeters", unit="m"
613
614
  ),
614
615
  temp=self._get_quantity_value(
615
616
  gold_biosample, "sampleCollectionTemperature"
@@ -11,7 +11,6 @@ from nmdc_runtime.site.util import get_basename
11
11
  from nmdc_runtime.site.translation.neon_utils import (
12
12
  _get_value_or_none,
13
13
  _create_controlled_identified_term_value,
14
- _create_controlled_term_value,
15
14
  _create_geolocation_value,
16
15
  _create_quantity_value,
17
16
  _create_timestamp_value,
@@ -349,6 +348,7 @@ class NeonBenthicDataTranslator(Translator):
349
348
  description=f"sequencing results for {basename}",
350
349
  type="nmdc:DataObject",
351
350
  data_object_type=do_type,
351
+ data_category=nmdc.DataCategoryEnum.instrument_data.text,
352
352
  in_manifest=manifest_id,
353
353
  )
354
354
 
@@ -10,7 +10,6 @@ from nmdc_runtime.site.util import get_basename
10
10
  from nmdc_runtime.site.translation.neon_utils import (
11
11
  _get_value_or_none,
12
12
  _create_controlled_identified_term_value,
13
- _create_controlled_term_value,
14
13
  _create_geolocation_value,
15
14
  _create_quantity_value,
16
15
  _create_timestamp_value,
@@ -153,7 +152,7 @@ class NeonSoilDataTranslator(Translator):
153
152
  collection_date=_create_timestamp_value(
154
153
  biosample_row["collectDate"].values[0]
155
154
  ),
156
- temp=_create_quantity_value(biosample_row["soilTemp"].values[0], "Celsius"),
155
+ temp=_create_quantity_value(biosample_row["soilTemp"].values[0], "Cel"),
157
156
  depth=nmdc.QuantityValue(
158
157
  has_minimum_numeric_value=_get_value_or_none(
159
158
  biosample_row, "sampleTopDepth"
@@ -169,13 +168,13 @@ class NeonSoilDataTranslator(Translator):
169
168
  analysis_type=_get_value_or_none(biosample_row, "sequenceAnalysisType"),
170
169
  env_package=_create_text_value(biosample_row["sampleType"].values[0]),
171
170
  nitro=_create_quantity_value(
172
- biosample_row["nitrogenPercent"].values[0], "percent"
171
+ biosample_row["nitrogenPercent"].values[0], "%"
173
172
  ),
174
173
  org_carb=_create_quantity_value(
175
- biosample_row["organicCPercent"].values[0], "percent"
174
+ biosample_row["organicCPercent"].values[0], "%"
176
175
  ),
177
176
  carb_nitro_ratio=_create_quantity_value(
178
- biosample_row["CNratio"].values[0], None
177
+ biosample_row["CNratio"].values[0], "ratio"
179
178
  ),
180
179
  ph=_create_double_value(biosample_row["soilInWaterpH"].values[0]),
181
180
  water_content=(
@@ -264,6 +263,7 @@ class NeonSoilDataTranslator(Translator):
264
263
  description=f"sequencing results for {basename}",
265
264
  type="nmdc:DataObject",
266
265
  md5_checksum=checksum,
266
+ data_category=nmdc.DataCategoryEnum.instrument_data.text,
267
267
  data_object_type=do_type,
268
268
  )
269
269
 
@@ -3,7 +3,6 @@ import sqlite3
3
3
  from typing import Dict, Optional, Union
4
4
 
5
5
  import pandas as pd
6
- import requests
7
6
  import requests_cache
8
7
 
9
8
  from nmdc_schema import nmdc
@@ -12,7 +11,6 @@ from nmdc_runtime.site.util import get_basename
12
11
  from nmdc_runtime.site.translation.neon_utils import (
13
12
  _get_value_or_none,
14
13
  _create_controlled_identified_term_value,
15
- _create_controlled_term_value,
16
14
  _create_geolocation_value,
17
15
  _create_quantity_value,
18
16
  _create_timestamp_value,
@@ -397,6 +395,7 @@ class NeonSurfaceWaterDataTranslator(Translator):
397
395
  description=f"sequencing results for {basename}",
398
396
  type="nmdc:DataObject",
399
397
  data_object_type=do_type,
398
+ data_category=nmdc.DataCategoryEnum.instrument_data.text,
400
399
  in_manifest=manifest_id,
401
400
  )
402
401