diff --git a/primed/primed_anvil/helpers.py b/primed/primed_anvil/helpers.py index 88460087..39193ade 100644 --- a/primed/primed_anvil/helpers.py +++ b/primed/primed_anvil/helpers.py @@ -2,6 +2,7 @@ from anvil_consortium_manager.models import WorkspaceGroupSharing from django.db.models import Exists, F, OuterRef, Value +from primed.cdsa.models import CDSAWorkspace from primed.dbgap.models import dbGaPWorkspace from primed.miscellaneous_workspaces.models import OpenAccessWorkspace @@ -34,7 +35,7 @@ def get_summary_table_data(): "access_mechanism", # Rename columns to have the same names. workspace_name=F("workspace__name"), - study=F("dbgap_study_accession__studies__short_name"), + study_name=F("dbgap_study_accession__studies__short_name"), data=F("available_data__name"), ) df_dbgap = pd.DataFrame.from_dict(dbgap) @@ -48,11 +49,25 @@ def get_summary_table_data(): "access_mechanism", # Rename columns to have the same names. workspace_name=F("workspace__name"), - study=F("studies__short_name"), + study_name=F("studies__short_name"), data=F("available_data__name"), ) df_open = pd.DataFrame.from_dict(open) + # Query for CDSAWorkspaces. + cdsa = CDSAWorkspace.objects.annotate( + access_mechanism=Value("CDSA"), + is_shared=Exists(shared), + ).values( + "is_shared", + "access_mechanism", + # Rename columns to have the same names. + workspace_name=F("workspace__name"), + study_name=F("study__short_name"), + data=F("available_data__name"), + ) + df_cdsa = pd.DataFrame.from_dict(cdsa) + # This union may not work with MySQL < 10.3: # https://code.djangoproject.com/ticket/31445 # qs = dbgap.union(open) @@ -65,20 +80,20 @@ def get_summary_table_data(): # df = pd.DataFrame.from_dict(qs) # Instead combine in pandas. - df = pd.concat([df_dbgap, df_open]) + df = pd.concat([df_cdsa, df_dbgap, df_open]) # If there are no workspaces, return an empty list. if df.empty: return [] # Sort by specific columns - df = df.sort_values(by=["study", "access_mechanism"]) + df = df.sort_values(by=["study_name", "access_mechanism"]) # Concatenate multiple studies into a single comma-delimited string. df = ( df.groupby( ["workspace_name", "data", "is_shared", "access_mechanism"], dropna=False, - )["study"] + )["study_name"] .apply(lambda x: ", ".join(x)) .reset_index() .drop("workspace_name", axis=1) @@ -90,7 +105,7 @@ def get_summary_table_data(): data = ( pd.pivot_table( df, - index=["study", "is_shared", "access_mechanism"], + index=["study_name", "is_shared", "access_mechanism"], columns=["data"], # set this to len to count the number of workspaces instead of returning a boolean value. aggfunc=lambda x: len(x) > 0, @@ -100,6 +115,7 @@ def get_summary_table_data(): ) .rename_axis(columns=None) .reset_index() + .rename(columns={"study_name": "study", "B": "c"}) ) # Remove the dummy "no_data" column if it exists. if "no_data" in data: diff --git a/primed/primed_anvil/tests/test_helpers.py b/primed/primed_anvil/tests/test_helpers.py index a79aa586..78a20b57 100644 --- a/primed/primed_anvil/tests/test_helpers.py +++ b/primed/primed_anvil/tests/test_helpers.py @@ -3,6 +3,7 @@ from anvil_consortium_manager.tests.factories import WorkspaceGroupSharingFactory from django.test import TestCase +from primed.cdsa.tests.factories import CDSAWorkspaceFactory from primed.dbgap.tests.factories import dbGaPWorkspaceFactory from primed.miscellaneous_workspaces.tests.factories import OpenAccessWorkspaceFactory from primed.primed_anvil.tests.factories import AvailableDataFactory, StudyFactory @@ -44,8 +45,8 @@ def test_one_dbgap_workspace_one_study_not_shared_no_available_data(self): def test_one_open_access_workspace_one_study_not_shared_no_available_data(self): AvailableDataFactory.create(name="Foo") study = StudyFactory.create(short_name="TEST") - open_access_workspace = OpenAccessWorkspaceFactory.create() - open_access_workspace.studies.add(study) + workspace = OpenAccessWorkspaceFactory.create() + workspace.studies.add(study) res = helpers.get_summary_table_data() self.assertEqual(len(res), 1) self.assertEqual(len(res[0]), 4) @@ -62,10 +63,8 @@ def test_one_open_access_workspace_one_study_not_shared_no_available_data(self): def test_one_dbgap_workspace_one_study_not_shared_with_one_available_data(self): available_data = AvailableDataFactory.create(name="Foo") study = StudyFactory.create(short_name="TEST") - dbgap_workspace = dbGaPWorkspaceFactory.create( - dbgap_study_accession__studies=[study] - ) - dbgap_workspace.available_data.add(available_data) + workspace = dbGaPWorkspaceFactory.create(dbgap_study_accession__studies=[study]) + workspace.available_data.add(available_data) res = helpers.get_summary_table_data() self.assertEqual(len(res), 1) self.assertEqual(len(res[0]), 4) @@ -83,11 +82,9 @@ def test_one_dbgap_workspace_one_study_not_shared_with_two_available_data(self): available_data_1 = AvailableDataFactory.create(name="Foo") available_data_2 = AvailableDataFactory.create(name="Bar") study = StudyFactory.create(short_name="TEST") - dbgap_workspace = dbGaPWorkspaceFactory.create( - dbgap_study_accession__studies=[study] - ) - dbgap_workspace.available_data.add(available_data_1) - dbgap_workspace.available_data.add(available_data_2) + workspace = dbGaPWorkspaceFactory.create(dbgap_study_accession__studies=[study]) + workspace.available_data.add(available_data_1) + workspace.available_data.add(available_data_2) res = helpers.get_summary_table_data() self.assertEqual(len(res), 1) self.assertEqual(len(res[0]), 5) @@ -122,11 +119,9 @@ def test_one_dbgap_workspace_two_studies_not_shared_no_available_data(self): def test_one_dbgap_workspace_one_study_shared_no_available_data(self): AvailableDataFactory.create(name="Foo") study = StudyFactory.create(short_name="TEST") - dbgap_workspace = dbGaPWorkspaceFactory.create( - dbgap_study_accession__studies=[study] - ) + workspace = dbGaPWorkspaceFactory.create(dbgap_study_accession__studies=[study]) WorkspaceGroupSharingFactory.create( - workspace=dbgap_workspace.workspace, group__name="PRIMED_ALL" + workspace=workspace.workspace, group__name="PRIMED_ALL" ) res = helpers.get_summary_table_data() self.assertEqual(len(res), 1) @@ -163,17 +158,17 @@ def test_two_dbgap_workspaces_one_study_one_shared(self): available_data_1 = AvailableDataFactory.create(name="Foo") available_data_2 = AvailableDataFactory.create(name="Bar") study = StudyFactory.create(short_name="TEST") - dbgap_workspace_1 = dbGaPWorkspaceFactory.create( + workspace_1 = dbGaPWorkspaceFactory.create( dbgap_study_accession__studies=[study] ) - dbgap_workspace_1.available_data.add(available_data_1) + workspace_1.available_data.add(available_data_1) WorkspaceGroupSharingFactory.create( - workspace=dbgap_workspace_1.workspace, group__name="PRIMED_ALL" + workspace=workspace_1.workspace, group__name="PRIMED_ALL" ) - dbgap_workspace_2 = dbGaPWorkspaceFactory.create( + workspace_2 = dbGaPWorkspaceFactory.create( dbgap_study_accession__studies=[study] ) - dbgap_workspace_2.available_data.add(available_data_2) + workspace_2.available_data.add(available_data_2) res = helpers.get_summary_table_data() self.assertEqual(len(res), 2) self.assertIn( @@ -229,8 +224,8 @@ def test_one_dbgap_workspace_one_open_access_workspace_different_studies(self): study_1 = StudyFactory.create(short_name="TEST") dbGaPWorkspaceFactory.create(dbgap_study_accession__studies=[study_1]) study_2 = StudyFactory.create(short_name="Other") - open_access_workspace = OpenAccessWorkspaceFactory.create() - open_access_workspace.studies.add(study_2) + workspace = OpenAccessWorkspaceFactory.create() + workspace.studies.add(study_2) res = helpers.get_summary_table_data() self.assertEqual(len(res), 2) self.assertIn( @@ -256,8 +251,8 @@ def test_one_dbgap_workspace_one_open_access_workspace_same_study(self): AvailableDataFactory.create(name="Foo") study = StudyFactory.create(short_name="TEST") dbGaPWorkspaceFactory.create(dbgap_study_accession__studies=[study]) - open_access_workspace = OpenAccessWorkspaceFactory.create() - open_access_workspace.studies.add(study) + workspace = OpenAccessWorkspaceFactory.create() + workspace.studies.add(study) res = helpers.get_summary_table_data() self.assertEqual(len(res), 2) self.assertIn( @@ -284,12 +279,10 @@ def test_one_dbgap_workspace_one_open_access_workspace_different_available_data( ): available_data_1 = AvailableDataFactory.create(name="Foo") study = StudyFactory.create(short_name="TEST") - dbgap_workspace = dbGaPWorkspaceFactory.create( - dbgap_study_accession__studies=[study] - ) - dbgap_workspace.available_data.add(available_data_1) - open_access_workspace = OpenAccessWorkspaceFactory.create() - open_access_workspace.studies.add(study) + workspace = dbGaPWorkspaceFactory.create(dbgap_study_accession__studies=[study]) + workspace.available_data.add(available_data_1) + workspace = OpenAccessWorkspaceFactory.create() + workspace.studies.add(study) res = helpers.get_summary_table_data() self.assertEqual(len(res), 2) self.assertIn( @@ -310,3 +303,244 @@ def test_one_dbgap_workspace_one_open_access_workspace_different_available_data( }, res, ) + + def test_one_cdsa_workspace_not_shared_no_available_data(self): + AvailableDataFactory.create(name="Foo") + study = StudyFactory.create(short_name="TEST") + CDSAWorkspaceFactory.create(study=study) + res = helpers.get_summary_table_data() + self.assertEqual(len(res), 1) + self.assertEqual(len(res[0]), 4) + self.assertIn("study", res[0]) + self.assertEqual(res[0]["study"], "TEST") + self.assertIn("access_mechanism", res[0]) + self.assertEqual(res[0]["access_mechanism"], "CDSA") + self.assertIn("is_shared", res[0]) + self.assertEqual(res[0]["is_shared"], False) + # Available data columns. + self.assertIn("Foo", res[0]) + self.assertEqual(res[0]["Foo"], False) + + def test_one_cdsa_workspace_not_shared_with_one_available_data(self): + available_data = AvailableDataFactory.create(name="Foo") + study = StudyFactory.create(short_name="TEST") + workspace = CDSAWorkspaceFactory.create(study=study) + workspace.available_data.add(available_data) + res = helpers.get_summary_table_data() + self.assertEqual(len(res), 1) + self.assertEqual(len(res[0]), 4) + self.assertIn("study", res[0]) + self.assertEqual(res[0]["study"], "TEST") + self.assertIn("access_mechanism", res[0]) + self.assertEqual(res[0]["access_mechanism"], "CDSA") + self.assertIn("is_shared", res[0]) + self.assertEqual(res[0]["is_shared"], False) + # Available data columns. + self.assertIn("Foo", res[0]) + self.assertEqual(res[0]["Foo"], True) + + def test_one_cdsa_workspace_not_shared_with_two_available_data(self): + available_data_1 = AvailableDataFactory.create(name="Foo") + available_data_2 = AvailableDataFactory.create(name="Bar") + study = StudyFactory.create(short_name="TEST") + workspace = CDSAWorkspaceFactory.create( + study=study, + ) + workspace.available_data.add(available_data_1) + workspace.available_data.add(available_data_2) + res = helpers.get_summary_table_data() + self.assertEqual(len(res), 1) + self.assertEqual(len(res[0]), 5) + self.assertIn("study", res[0]) + self.assertEqual(res[0]["study"], "TEST") + self.assertIn("access_mechanism", res[0]) + self.assertEqual(res[0]["access_mechanism"], "CDSA") + self.assertIn("is_shared", res[0]) + self.assertEqual(res[0]["is_shared"], False) + # Available data columns. + self.assertIn("Foo", res[0]) + self.assertEqual(res[0]["Foo"], True) + + def test_one_cdsa_workspace_one_study_shared_no_available_data(self): + AvailableDataFactory.create(name="Foo") + study = StudyFactory.create(short_name="TEST") + workspace = CDSAWorkspaceFactory.create(study=study) + WorkspaceGroupSharingFactory.create( + workspace=workspace.workspace, group__name="PRIMED_ALL" + ) + res = helpers.get_summary_table_data() + self.assertEqual(len(res), 1) + self.assertEqual(len(res[0]), 4) + self.assertIn("study", res[0]) + self.assertEqual(res[0]["study"], "TEST") + self.assertIn("access_mechanism", res[0]) + self.assertEqual(res[0]["access_mechanism"], "CDSA") + self.assertIn("is_shared", res[0]) + self.assertEqual(res[0]["is_shared"], True) + # Available data columns. + self.assertIn("Foo", res[0]) + self.assertEqual(res[0]["Foo"], False) + + def test_two_cdsa_workspaces_one_study(self): + AvailableDataFactory.create(name="Foo") + study = StudyFactory.create(short_name="TEST") + CDSAWorkspaceFactory.create(study=study) + CDSAWorkspaceFactory.create(study=study) + res = helpers.get_summary_table_data() + self.assertEqual(len(res), 1) + self.assertEqual(len(res[0]), 4) + self.assertIn("study", res[0]) + self.assertEqual(res[0]["study"], "TEST") + self.assertIn("access_mechanism", res[0]) + self.assertEqual(res[0]["access_mechanism"], "CDSA") + self.assertIn("is_shared", res[0]) + self.assertEqual(res[0]["is_shared"], False) + # Available data columns. + self.assertIn("Foo", res[0]) + self.assertEqual(res[0]["Foo"], False) + + def test_two_cdsa_workspaces_one_study_one_shared(self): + available_data_1 = AvailableDataFactory.create(name="Foo") + available_data_2 = AvailableDataFactory.create(name="Bar") + study = StudyFactory.create(short_name="TEST") + workspace_1 = CDSAWorkspaceFactory.create(study=study) + workspace_1.available_data.add(available_data_1) + WorkspaceGroupSharingFactory.create( + workspace=workspace_1.workspace, group__name="PRIMED_ALL" + ) + workspace_2 = CDSAWorkspaceFactory.create(study=study) + workspace_2.available_data.add(available_data_2) + res = helpers.get_summary_table_data() + self.assertEqual(len(res), 2) + self.assertIn( + { + "study": "TEST", + "is_shared": True, + "access_mechanism": "CDSA", + "Foo": True, + "Bar": False, + }, + res, + ) + self.assertIn( + { + "study": "TEST", + "is_shared": False, + "access_mechanism": "CDSA", + "Foo": False, + "Bar": True, + }, + res, + ) + + def test_two_cdsa_workspaces(self): + AvailableDataFactory.create(name="Foo") + study_1 = StudyFactory.create(short_name="TEST") + study_2 = StudyFactory.create(short_name="Other") + CDSAWorkspaceFactory.create(study=study_1) + CDSAWorkspaceFactory.create(study=study_2) + res = helpers.get_summary_table_data() + self.assertEqual(len(res), 2) + self.assertIn( + { + "study": "Other", + "is_shared": False, + "access_mechanism": "CDSA", + "Foo": False, + }, + res, + ) + self.assertIn( + { + "study": "TEST", + "is_shared": False, + "access_mechanism": "CDSA", + "Foo": False, + }, + res, + ) + + def test_one_cdsa_workspace_one_open_access_workspace_different_studies(self): + AvailableDataFactory.create(name="Foo") + study_1 = StudyFactory.create(short_name="TEST") + CDSAWorkspaceFactory.create(study=study_1) + study_2 = StudyFactory.create(short_name="Other") + workspace = OpenAccessWorkspaceFactory.create() + workspace.studies.add(study_2) + res = helpers.get_summary_table_data() + self.assertEqual(len(res), 2) + self.assertIn( + { + "study": "TEST", + "is_shared": False, + "access_mechanism": "CDSA", + "Foo": False, + }, + res, + ) + self.assertIn( + { + "study": "Other", + "is_shared": False, + "access_mechanism": "Open access", + "Foo": False, + }, + res, + ) + + def test_one_cdsa_workspace_one_open_access_workspace_same_study(self): + AvailableDataFactory.create(name="Foo") + study = StudyFactory.create(short_name="TEST") + CDSAWorkspaceFactory.create(study=study) + workspace = OpenAccessWorkspaceFactory.create() + workspace.studies.add(study) + res = helpers.get_summary_table_data() + self.assertEqual(len(res), 2) + self.assertIn( + { + "study": "TEST", + "is_shared": False, + "access_mechanism": "CDSA", + "Foo": False, + }, + res, + ) + self.assertIn( + { + "study": "TEST", + "is_shared": False, + "access_mechanism": "Open access", + "Foo": False, + }, + res, + ) + + def test_one_cdsa_workspace_one_open_access_workspace_different_available_data( + self, + ): + available_data_1 = AvailableDataFactory.create(name="Foo") + study = StudyFactory.create(short_name="TEST") + workspace = CDSAWorkspaceFactory.create(study=study) + workspace.available_data.add(available_data_1) + workspace = OpenAccessWorkspaceFactory.create() + workspace.studies.add(study) + res = helpers.get_summary_table_data() + self.assertEqual(len(res), 2) + self.assertIn( + { + "study": "TEST", + "is_shared": False, + "access_mechanism": "CDSA", + "Foo": True, + }, + res, + ) + self.assertIn( + { + "study": "TEST", + "is_shared": False, + "access_mechanism": "Open access", + "Foo": False, + }, + res, + ) diff --git a/primed/primed_anvil/tests/test_views.py b/primed/primed_anvil/tests/test_views.py index e2a53555..9a95ea11 100644 --- a/primed/primed_anvil/tests/test_views.py +++ b/primed/primed_anvil/tests/test_views.py @@ -1245,7 +1245,6 @@ def test_includes_open_access_workspaces(self): study = StudyFactory.create() open_workspace = OpenAccessWorkspaceFactory.create() open_workspace.studies.add(study) - open_workspace.available_data.add(self.available_data) self.client.force_login(self.user) response = self.client.get(self.get_url()) self.assertIn("summary_table", response.context_data) @@ -1255,8 +1254,15 @@ def test_includes_dbgap_workspaces(self): """dbGaP workspaces are included in the table.""" # One open access workspace with one study, with one available data type. # One dbGaP workspae with two studies. - study = StudyFactory.create() - dbGaPWorkspaceFactory.create(dbgap_study_accession__studies=[study]) + dbGaPWorkspaceFactory.create() + self.client.force_login(self.user) + response = self.client.get(self.get_url()) + self.assertIn("summary_table", response.context_data) + self.assertEqual(len(response.context_data["summary_table"].rows), 1) + + def test_includes_cdsa_workspaces(self): + """CDSA workspaces are included in the table.""" + CDSAWorkspaceFactory.create() self.client.force_login(self.user) response = self.client.get(self.get_url()) self.assertIn("summary_table", response.context_data)