diff --git a/Manifest.toml b/Manifest.toml
index 41892f5aeb9a9a23c6b2761170d5bf15296e0d3d..0710f6a14600fcdbc1b9154532d89a55ed0daa95 100644
--- a/Manifest.toml
+++ b/Manifest.toml
@@ -1,6 +1,6 @@
 # This file is machine-generated - editing it directly is not advised
 
-julia_version = "1.9.3"
+julia_version = "1.10.0"
 manifest_format = "2.0"
 project_hash = "2c20afabe03d014276e9478d0fdccbc2cdd634c1"
 
@@ -64,7 +64,7 @@ weakdeps = ["Dates", "LinearAlgebra"]
 [[deps.CompilerSupportLibraries_jll]]
 deps = ["Artifacts", "Libdl"]
 uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
-version = "1.0.5+0"
+version = "1.0.5+1"
 
 [[deps.Conda]]
 deps = ["Downloads", "JSON", "VersionParsing"]
@@ -179,21 +179,26 @@ uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
 [[deps.LibCURL]]
 deps = ["LibCURL_jll", "MozillaCACerts_jll"]
 uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
-version = "0.6.3"
+version = "0.6.4"
 
 [[deps.LibCURL_jll]]
 deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
 uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
-version = "7.84.0+0"
+version = "8.4.0+0"
 
 [[deps.LibGit2]]
-deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
+deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"]
 uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
 
+[[deps.LibGit2_jll]]
+deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"]
+uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5"
+version = "1.6.4+0"
+
 [[deps.LibSSH2_jll]]
 deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
 uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
-version = "1.10.2+0"
+version = "1.11.0+1"
 
 [[deps.Libdl]]
 uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
@@ -240,7 +245,7 @@ uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
 [[deps.MbedTLS_jll]]
 deps = ["Artifacts", "Libdl"]
 uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
-version = "2.28.2+0"
+version = "2.28.2+1"
 
 [[deps.Memoization]]
 deps = ["MacroTools"]
@@ -265,7 +270,7 @@ uuid = "a63ad114-7e13-5084-954f-fe012c677804"
 
 [[deps.MozillaCACerts_jll]]
 uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
-version = "2022.10.11"
+version = "2023.1.10"
 
 [[deps.NearestNeighbors]]
 deps = ["Distances", "StaticArrays"]
@@ -286,7 +291,7 @@ version = "1.12.9"
 [[deps.OpenBLAS_jll]]
 deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
 uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"
-version = "0.3.21+4"
+version = "0.3.23+2"
 
 [[deps.OpenSSL_jll]]
 deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
@@ -308,15 +313,15 @@ version = "2.5.10"
 [[deps.Pkg]]
 deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
 uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
-version = "1.9.2"
+version = "1.10.0"
 
 [[deps.PlanarLarvae]]
 deps = ["DelimitedFiles", "HDF5", "JSON3", "LinearAlgebra", "MAT", "Meshes", "OrderedCollections", "Random", "SHA", "StaticArrays", "Statistics", "StatsBase", "StructTypes"]
-git-tree-sha1 = "6b2dc28d56bcef101672cbf2bb784bbd5d88d579"
+git-tree-sha1 = "d964d040e319fe3bd9140e5bf91d648de6acc96f"
 repo-rev = "main"
 repo-url = "https://gitlab.pasteur.fr/nyx/PlanarLarvae.jl"
 uuid = "c2615984-ef14-4d40-b148-916c85b43307"
-version = "0.15.0"
+version = "0.16.0"
 
 [[deps.PrecompileTools]]
 deps = ["Preferences"]
@@ -345,7 +350,7 @@ deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
 uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
 
 [[deps.Random]]
-deps = ["SHA", "Serialization"]
+deps = ["SHA"]
 uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
 
 [[deps.ReferenceFrameRotations]]
@@ -385,6 +390,7 @@ version = "1.1.0"
 [[deps.SparseArrays]]
 deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"]
 uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
+version = "1.10.0"
 
 [[deps.StaticArrays]]
 deps = ["LinearAlgebra", "Random", "StaticArraysCore", "Statistics"]
@@ -400,7 +406,7 @@ version = "1.4.0"
 [[deps.Statistics]]
 deps = ["LinearAlgebra", "SparseArrays"]
 uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
-version = "1.9.0"
+version = "1.10.0"
 
 [[deps.StatsAPI]]
 deps = ["LinearAlgebra"]
@@ -421,9 +427,9 @@ uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
 version = "1.10.0"
 
 [[deps.SuiteSparse_jll]]
-deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"]
+deps = ["Artifacts", "Libdl", "libblastrampoline_jll"]
 uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
-version = "5.10.1+6"
+version = "7.2.1+1"
 
 [[deps.TOML]]
 deps = ["Dates"]
@@ -478,19 +484,19 @@ version = "1.3.0"
 [[deps.Zlib_jll]]
 deps = ["Libdl"]
 uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
-version = "1.2.13+0"
+version = "1.2.13+1"
 
 [[deps.libblastrampoline_jll]]
 deps = ["Artifacts", "Libdl"]
 uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"
-version = "5.8.0+0"
+version = "5.8.0+1"
 
 [[deps.nghttp2_jll]]
 deps = ["Artifacts", "Libdl"]
 uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
-version = "1.48.0+0"
+version = "1.52.0+1"
 
 [[deps.p7zip_jll]]
 deps = ["Artifacts", "Libdl"]
 uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
-version = "17.4.0+0"
+version = "17.4.0+2"
diff --git a/Project.toml b/Project.toml
index 269205b0387619bc07687a13b0a88f5d088a6edc..d89941a5749fe838aabda8b400e0188114dd1e44 100644
--- a/Project.toml
+++ b/Project.toml
@@ -1,7 +1,7 @@
 name = "TaggingBackends"
 uuid = "e551f703-3b82-4335-b341-d497b48d519b"
 authors = ["François Laurent", "Institut Pasteur"]
-version = "0.17"
+version = "0.18"
 
 [deps]
 Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
diff --git a/pyproject.toml b/pyproject.toml
index 9107283dbe586a75370f259d43ba83ae7eb57fbb..f6b1f51148e9541f672fbd1e6722cb4d5fb992c0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "TaggingBackends"
-version = "0.17"
+version = "0.18"
 description = "Backbone for LarvaTagger.jl tagging backends"
 authors = ["François Laurent"]
 
diff --git a/src/taggingbackends/explorer.py b/src/taggingbackends/explorer.py
index 5ee4a0b3260528359c7a52ab9a98ac9cd47863b0..ff726b88eaafd022ab9225649c93fa1ac31bc5fd 100644
--- a/src/taggingbackends/explorer.py
+++ b/src/taggingbackends/explorer.py
@@ -24,6 +24,7 @@ else:
         logging.warning("Failed to set PyCall with compiled_modules=False")
     try:
         from julia import TaggingBackends
+        from julia import PlanarLarvae
     except ImportError:
         logging.warning(f"TaggingBackends not found in JULIA_PROJECT={JULIA_PROJECT}; \
 please see https://gitlab.pasteur.fr/nyx/TaggingBackends#recommended-installation")
@@ -443,11 +444,16 @@ run `poetry add {pkg}` from directory: \n
             files = dict(files_)
         return files
 
-    def prepare_labels(self, input_files):
+    def prepare_labels(self, input_files, allowed_file_extensions=None,
+        single_input=False):
         if isinstance(input_files, dict):
             input_files_and_labels = dict()
             for parent in input_files.keys():
-                input_files_and_labels[parent] = self.prepare_labels(input_files[parent])
+                input_files_and_labels[parent] = self.prepare_labels(
+                    input_files[parent],
+                    single_input=single_input,
+                    allowed_file_extensions=allowed_file_extensions,
+                )
             return input_files_and_labels
         #
         from .data.labels import Labels, labels_file_extension
@@ -456,30 +462,61 @@ run `poetry add {pkg}` from directory: \n
         # note: these *metadata* files are pushed by LarvaTagger.jl and form an
         #       undocumented mechanism to preserve metadata that are generated
         #       on the Julia side.
-        found = 0
+        metadata_found = 0
         for file in list(input_files):
             if file.name == "metadata":
                 input_files.remove(file)
                 with open(file, "r") as f:
                     labels.metadata = json.load(f)
-                if found == 1:
+                if metadata_found == 1:
                     logging.warning("multiple metadata files found")
-                found += 1
-        assert 0 < len(input_files)
-        # if any labels file is found, assume the other files are its data
-        # dependencies, and exclude the labels file from the list of input files
-        found = 0
-        for file in list(input_files):
-            if any([file.name.endswith(ext) for ext in labels_file_extension]):
-                labels.input_labels = file
-                input_files.remove(file)
-                if found == 1:
-                    logging.warning("multiple label files found")
-                found += 1
+                metadata_found += 1
+        # check whether an input data file has been designated
+        primary_input = None
+        if metadata_found and 'filename' in labels.metadata.keys():
+            primary_input = labels.metadata['filename']
+            for file in input_files:
+                if file.name == primary_input:
+                    primary_input = file
+                    break
+            if isinstance(primary_input, str):
+                logging.warning(f'file not found: {primary_input}')
+                primary_input = None
+        # identify existing labels (label files only)
+        labels_found = 0
+        if primary_input is None:
+            for file in input_files:
+                if any(file.name.endswith(ext) for ext in labels_file_extension):
+                    labels.input_labels = file
+                    if labels_found == 1:
+                        logging.warning("multiple label files found")
+                    labels_found += 1
+        elif any(primary_input.name.endswith(ext) for ext in labels_file_extension):
+            labels.input_labels = primary_input
+            labels_found = 1
+        # filter out likely unsupported files
+        if allowed_file_extensions:
+            input_files = [f for f in input_files
+                if any(f.name.endswith(ext) for ext in allowed_file_extensions)]
+        # force-identify the input data files
         assert 0 < len(input_files)
+        if single_input and primary_input is None:
+            primary_input = input_files[0]
+            logging.info(f'selecting file: {primary_input}')
+            input_files = [pathlib.Path(f.source)
+                for f in PlanarLarvae.Formats.find_associated_files(str(primary_input))]
+        # ensure the primary input file comes first in the list of input files
+        if not (primary_input is None or input_files[0] == primary_input):
+            input_files = [f for f in input_files if f != primary_input]
+            input_files.insert(0, primary_input)
+        #
         labels.tracking = input_files
         #
-        if not labels.metadata:
+        if labels.metadata:
+            if labels.metadata.get('date_time', None) == 'NA':
+                logging.debug('discarding metadata entry "date_time"')
+                del labels.metadata['date_time']
+        else:
             file = input_files[0]
             labels.metadata = {'filename': file.name}
         #