From 25f854f9c4f6e45341ed8648fae9f70ef148a69f Mon Sep 17 00:00:00 2001 From: Vinayakjeet Singh Karki <139736674+vinayakjeet@users.noreply.github.com> Date: Tue, 2 Apr 2024 01:16:23 +0530 Subject: [PATCH 1/4] update4 Signed-off-by: Vinayakjeet Singh Karki <139736674+vinayakjeet@users.noreply.github.com> --- sbol_utilities/helper_functions.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/sbol_utilities/helper_functions.py b/sbol_utilities/helper_functions.py index 168debfc..ce3a861c 100644 --- a/sbol_utilities/helper_functions.py +++ b/sbol_utilities/helper_functions.py @@ -363,4 +363,21 @@ def is_circular(obj: Union[sbol3.Component, sbol3.LocalSubComponent, sbol3.Exter :param obj: design to be checked :return: true if circular """ - return any(n==sbol3.SO_CIRCULAR for n in obj.types) \ No newline at end of file + return any(n==sbol3.SO_CIRCULAR for n in obj.types) + +def is_composite(obj): + def has_dna_type(o): + return any(tyto.SO.DNA == tyto.SO.get_uri_by_term(t) for t in o.types) + + def has_assembly_plan(o): + if not hasattr(o, "generated_by"): + return False + for activity_ref in o.generated_by: + activity = activity_ref.lookup() + if activity and 'http://sbols.org/v3#assemblyPlan' in activity.types and 'sbol:design' in activity.types: + return True + return False + + if isinstance(obj, sbol3.Component): + return has_dna_type(obj) and has_assembly_plan(obj) + return False From 7255ef0d012beaac3d6ad650a71871813bac8eb4 Mon Sep 17 00:00:00 2001 From: Vinayakjeet Singh Karki <139736674+vinayakjeet@users.noreply.github.com> Date: Mon, 10 Feb 2025 14:52:32 +0530 Subject: [PATCH 2/4] Update helper_functions.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hi @jakebeal, I have implemented all requested changes: - **Removed** the unnecessary `hasattr(o, "generated_by")` check. - **Replaced** `'sbol:design'` with `sbol3.SBOL_DESIGN`. - **Added** a docstring to `is_composite()` for better documentation. Please review and let me know if any further modifications are needed. Thanks! 🚀 --- sbol_utilities/helper_functions.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/sbol_utilities/helper_functions.py b/sbol_utilities/helper_functions.py index ce3a861c..15663962 100644 --- a/sbol_utilities/helper_functions.py +++ b/sbol_utilities/helper_functions.py @@ -366,15 +366,25 @@ def is_circular(obj: Union[sbol3.Component, sbol3.LocalSubComponent, sbol3.Exter return any(n==sbol3.SO_CIRCULAR for n in obj.types) def is_composite(obj): + """Check if an SBOL Component is a composite. + + A composite component is defined as: + 1. Having a DNA type. + 2. Being generated by an assembly plan activity. + + :param obj: SBOL Component to be checked. + :return: True if the component is composite, otherwise False. + """ + def has_dna_type(o): + """Check if the component has a DNA type.""" return any(tyto.SO.DNA == tyto.SO.get_uri_by_term(t) for t in o.types) def has_assembly_plan(o): - if not hasattr(o, "generated_by"): - return False + """Check if the component was generated by an assembly plan.""" for activity_ref in o.generated_by: activity = activity_ref.lookup() - if activity and 'http://sbols.org/v3#assemblyPlan' in activity.types and 'sbol:design' in activity.types: + if activity and 'http://sbols.org/v3#assemblyPlan' in activity.types and sbol3.SBOL_DESIGN in activity.types: return True return False From 9720930e54d57ee95d0c7d82d600cf4f646dc2e5 Mon Sep 17 00:00:00 2001 From: Vinayakjeet Singh Karki <139736674+vinayakjeet@users.noreply.github.com> Date: Mon, 10 Feb 2025 19:25:39 +0530 Subject: [PATCH 3/4] Update helper_functions.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hi @jakebeal, I have implemented all requested changes: - **Removed** the unnecessary `hasattr(o, "generated_by")` check. - **Replaced** `'sbol:design'` with `sbol3.SBOL_DESIGN`. - **Added** a docstring to `is_composite()` for better documentation. Please review and let me know if any further modifications are needed. Thanks! 🚀 From 50272d3cbd7f55b947988ec4a6a95bb042572f89 Mon Sep 17 00:00:00 2001 From: Vinayakjeet Singh Karki <139736674+vinayakjeet@users.noreply.github.com> Date: Tue, 11 Feb 2025 15:33:56 +0530 Subject: [PATCH 4/4] Update test_helpers.py #69 test cases --- test/test_helpers.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/test_helpers.py b/test/test_helpers.py index 3bc5605f..f05ea068 100644 --- a/test/test_helpers.py +++ b/test/test_helpers.py @@ -1,6 +1,8 @@ import unittest import os from pathlib import Path +import sbol3 +import tyto from sbol_utilities import component @@ -31,6 +33,36 @@ def test_url_sanitization(self): self.assertEqual(strip_filetype_suffix('http://foo/bar/baz.gb'), 'http://foo/bar/baz') self.assertEqual(strip_filetype_suffix('http://foo/bar/baz.qux'), 'http://foo/bar/baz.qux') + def test_is_composite(self): + """Test the is_composite function.""" + # Set up a test SBOL document and namespace + doc = sbol3.Document() + sbol3.set_namespace('http://sbolstandard.org/test') + # Case 1: Valid composite component (Has DNA type + Assembly Plan) + comp1 = sbol3.Component('comp1', types=[tyto.SO.DNA]) + assembly_activity = sbol3.Activity('activity1') + assembly_activity.types.append("http://sbols.org/v3#assemblyPlan") + assembly_activity.types.append(sbol3.SBOL_DESIGN) + # Add activity to the document + doc.add(assembly_activity) + comp1.generated_by.append(sbol3.ReferencedObject(assembly_activity.identity)) + doc.add(comp1) + self.assertTrue(is_composite(comp1), "Expected comp1 to be composite") + # Case 2: Not composite (No DNA type, but has Assembly Plan) + comp2 = sbol3.Component('comp2', types=[tyto.SO.RNA]) # RNA type instead of DNA + comp2.generated_by.append(sbol3.ReferencedObject(assembly_activity.identity)) + doc.add(comp2) + self.assertFalse(is_composite(comp2), "Expected comp2 to NOT be composite") + # Case 3: Not composite (Has DNA type, but no Assembly Plan) + comp3 = sbol3.Component('comp3', types=[tyto.SO.DNA]) + doc.add(comp3) + self.assertFalse(is_composite(comp3), "Expected comp3 to NOT be composite") + # Case 4: Not composite (No DNA type, No Assembly Plan) + comp4 = sbol3.Component('comp4', types=[tyto.SO.RNA]) + doc.add(comp4) + self.assertFalse(is_composite(comp4), "Expected comp4 to NOT be composite") + + def test_filtering_top_level_objects(self): """Check filtering Top Level Objects by a condition""" test_dir = os.path.dirname(os.path.realpath(__file__))