+
# Multiomix
@@ -15,7 +15,6 @@ This document is focused on the **development** of the system. If you are lookin
- Node JS >= `20.x` (tested version: `20.x`)
- [Modulector][modulector] `2.2.0`
- [BioAPI][bioapi] `1.2.1`
-- R `4.4.2` (required for `differential-expression`)
## Installation
@@ -67,7 +66,6 @@ Every time you want to work with Multiomix, you need to follow the below steps:
1. `python3 -m celery -A multiomics_intermediate worker -l info -Q stats`
1. `python3 -m celery -A multiomics_intermediate worker -l info -Q inference`
1. `python3 -m celery -A multiomics_intermediate worker -l info -Q sync_datasets`
- 1. `python3 -m celery -A multiomics_intermediate worker -l info -Q differential_expression`
1. If you want to check Task in the GUI you can run [Flower](https://flower.readthedocs.io/en/latest/index.html) `python3 -m celery -A multiomics_intermediate flower`
**NOTE:** maybe in Windows is needed to add `--pool=solo` to the previous commands. Example: `python3 -m celery -A multiomics_intermediate worker -l info -Q correlation_analysis --concurrency 1 --pool=solo`
diff --git a/config/requirements.txt b/config/requirements.txt
index 1279b8de..253e7564 100644
--- a/config/requirements.txt
+++ b/config/requirements.txt
@@ -28,5 +28,3 @@ scipy==1.13.0
statsmodels==0.14.2
xlrd==2.0.1
openpyxl==3.1.5
-rpy2==3.6.1
-urllib3==2.5.0
\ No newline at end of file
diff --git a/config/requirements_celery.txt b/config/requirements_celery.txt
index 5c6b30bc..859c0823 100644
--- a/config/requirements_celery.txt
+++ b/config/requirements_celery.txt
@@ -25,5 +25,3 @@ scipy==1.13.0
statsmodels==0.14.2
xlrd==2.0.1
openpyxl==3.1.5
-rpy2==3.6.1
-urllib3==2.5.0
\ No newline at end of file
diff --git a/docker-compose_dist.yml b/docker-compose_dist.yml
index b8aa0abe..ca1ac3db 100644
--- a/docker-compose_dist.yml
+++ b/docker-compose_dist.yml
@@ -233,21 +233,6 @@ services:
# REDIS_HOST: 'redis'
# REDIS_PORT: 6379
- # Celery worker for differential expression
- differential-expression-worker:
- image: omicsdatascience/multiomix:5.6.0-celery
- restart: 'always'
- depends_on:
- - db
- - mongo
- volumes:
- - media_data:/src/media
- environment:
- <<: *common-variables
- QUEUE_NAME: 'differential_expression' # This MUST NOT be changed
- CONCURRENCY: 2
- # PostgreSQL, Mongo y Redis usan los valores por defecto del resto de servicios
-
# Django backend service
multiomix:
image: omicsdatascience/multiomix:5.6.0
@@ -305,7 +290,6 @@ services:
- stats-worker
- inference-worker
- sync-datasets-worker
- - differential-expression-worker
volumes:
mongo_data:
diff --git a/src/api_service/migrations/0062_alter_experiment_clinical_source_and_more.py b/src/api_service/migrations/0062_alter_experiment_clinical_source_and_more.py
deleted file mode 100644
index c86db344..00000000
--- a/src/api_service/migrations/0062_alter_experiment_clinical_source_and_more.py
+++ /dev/null
@@ -1,142 +0,0 @@
-# Generated by Django 4.2.19 on 2026-01-14 21:38
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- (
- "datasets_synchronization",
- "0036_alter_cgdsstudy_clinical_patient_dataset_and_more",
- ),
- ("genes", "0002_auto_20210114_2331"),
- ("user_files", "0015_alter_userfile_options"),
- ("api_service", "0061_alter_experiment_shared_users"),
- ]
-
- operations = [
- migrations.AlterField(
- model_name="experiment",
- name="clinical_source",
- field=models.ForeignKey(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.SET_NULL,
- related_name="experiments_as_clinical_source",
- to="api_service.experimentclinicalsource",
- ),
- ),
- migrations.AlterField(
- model_name="experiment",
- name="gem_source",
- field=models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- related_name="experiments_as_gem_source",
- to="api_service.experimentsource",
- ),
- ),
- migrations.AlterField(
- model_name="experiment",
- name="mRNA_source",
- field=models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- related_name="experiments_as_mrna_source",
- to="api_service.experimentsource",
- ),
- ),
- migrations.AlterField(
- model_name="experimentclinicalsource",
- name="extra_cgds_dataset",
- field=models.ForeignKey(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.CASCADE,
- related_name="experiment_clinical_sources_as_extra_cgds_dataset",
- to="datasets_synchronization.cgdsdataset",
- ),
- ),
- migrations.AlterField(
- model_name="experimentsource",
- name="cgds_dataset",
- field=models.ForeignKey(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.CASCADE,
- related_name="experiment_sources_as_cgds_dataset",
- to="datasets_synchronization.cgdsdataset",
- ),
- ),
- migrations.AlterField(
- model_name="experimentsource",
- name="user_file",
- field=models.ForeignKey(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.CASCADE,
- related_name="experiment_sources_as_user_file",
- to="user_files.userfile",
- ),
- ),
- migrations.AlterField(
- model_name="genecnacombination",
- name="experiment",
- field=models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- related_name="%(class)ss",
- to="api_service.experiment",
- ),
- ),
- migrations.AlterField(
- model_name="genecnacombination",
- name="gene",
- field=models.ForeignKey(
- db_column="gene",
- db_constraint=False,
- on_delete=django.db.models.deletion.DO_NOTHING,
- related_name="%(class)ss_as_gene",
- to="genes.gene",
- ),
- ),
- migrations.AlterField(
- model_name="genemethylationcombination",
- name="experiment",
- field=models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- related_name="%(class)ss",
- to="api_service.experiment",
- ),
- ),
- migrations.AlterField(
- model_name="genemethylationcombination",
- name="gene",
- field=models.ForeignKey(
- db_column="gene",
- db_constraint=False,
- on_delete=django.db.models.deletion.DO_NOTHING,
- related_name="%(class)ss_as_gene",
- to="genes.gene",
- ),
- ),
- migrations.AlterField(
- model_name="genemirnacombination",
- name="experiment",
- field=models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- related_name="%(class)ss",
- to="api_service.experiment",
- ),
- ),
- migrations.AlterField(
- model_name="genemirnacombination",
- name="gene",
- field=models.ForeignKey(
- db_column="gene",
- db_constraint=False,
- on_delete=django.db.models.deletion.DO_NOTHING,
- related_name="%(class)ss_as_gene",
- to="genes.gene",
- ),
- ),
- ]
diff --git a/src/api_service/models.py b/src/api_service/models.py
index a0177314..e18ec18e 100644
--- a/src/api_service/models.py
+++ b/src/api_service/models.py
@@ -45,7 +45,6 @@ class ExperimentSource(models.Model):
inference_experiments_as_mrna: QuerySet[InferenceExperiment]
gem_source: QuerySet['Experiment']
mrna_source: QuerySet['Experiment']
-
user_file = models.ForeignKey(
UserFile,
on_delete=models.CASCADE,
@@ -336,9 +335,7 @@ def number_of_rows(self) -> int:
"""
if self.user_file:
return self.user_file.number_of_rows
- if self.cgds_dataset:
- return self.__get_cgds_datasets_joined_df().shape[0]
- return 0
+ return self.__get_cgds_datasets_joined_df().shape[0]
@property
def number_of_samples(self) -> int:
@@ -348,9 +345,7 @@ def number_of_samples(self) -> int:
"""
if self.user_file:
return self.user_file.number_of_samples
- if self.cgds_dataset:
- return self.__get_cgds_datasets_joined_df().shape[1]
- return 0
+ return self.__get_cgds_datasets_joined_df().shape[1]
class Experiment(models.Model):
@@ -401,8 +396,10 @@ class Experiment(models.Model):
# TODO: this can be stored in the Methylation type entity. Set the corresponding nullity in the new schema
correlate_with_all_genes: bool = models.BooleanField(blank=False, null=False, default=True)
- shared_institutions = models.ManyToManyField(Institution, blank=True, related_name='shared_correlation_analysis')
- shared_users = models.ManyToManyField(User, blank=True, related_name='shared_users_correlation_analysis')
+ shared_institutions = models.ManyToManyField(Institution, blank=True,
+ related_name='shared_correlation_analysis')
+ shared_users = models.ManyToManyField(User, blank=True,
+ related_name='shared_users_correlation_analysis')
is_public = models.BooleanField(blank=False, null=False, default=False)
@property
@@ -420,7 +417,7 @@ def get_combination_class(self):
"""
return get_combination_class(self.type)
- def get_clinical_columns(self) -> list[str]:
+ def get_clinical_columns(self):
"""
Gets a list of columns from the clinical data
@return: List of fields in clinical data
diff --git a/src/api_service/utils.py b/src/api_service/utils.py
index ff242e33..511cc9fa 100644
--- a/src/api_service/utils.py
+++ b/src/api_service/utils.py
@@ -131,7 +131,5 @@ def get_cgds_dataset(cgds_study: CGDSStudy, file_type: FileType) -> Optional[CGD
return cgds_study.cna_dataset
elif file_type == FileType.METHYLATION:
return cgds_study.methylation_dataset
- elif file_type == FileType.CLINICAL:
- return cgds_study.clinical_patient_dataset
else:
return None
diff --git a/src/api_service/views.py b/src/api_service/views.py
index 901da96b..c0566d7f 100644
--- a/src/api_service/views.py
+++ b/src/api_service/views.py
@@ -210,10 +210,10 @@ def get_queryset(self):
experiment: Experiment = Experiment.objects.filter(
Q(pk=experiment_id) &
(
- Q(user=user) |
- Q(is_public=True) |
- Q(shared_institutions__institutionadministration__user=user) |
- Q(shared_users=user)
+ Q(user=user) |
+ Q(is_public=True) |
+ Q(shared_institutions__institutionadministration__user=user) |
+ Q(shared_users=user)
)
).distinct().get()
combinations_queryset = experiment.combinations
@@ -293,7 +293,6 @@ def get_queryset(self):
serializer_class = ExperimentSerializerDetail
permission_classes = [permissions.IsAuthenticated, ExperimentIsNotRunning]
-
class RemoveInstitutionFromExperimentView(APIView):
"""
API endpoint to remove an institution from an experiment.
@@ -301,8 +300,7 @@ class RemoveInstitutionFromExperimentView(APIView):
"""
permission_classes = [permissions.IsAuthenticated]
- @staticmethod
- def post(request):
+ def post(self, request):
"""
Remove an institution from the experiment.
"""
@@ -330,16 +328,14 @@ def post(request):
{"message": f"Institution {institution.id} removed from experiment {experiment.id}."}
)
-
class RemoveUserFromExperimentView(APIView):
"""
- API endpoint to remove a user from an experiment.
+ API endpoint to remove an user from an experiment.
Only the owner of the experiment can perform this action.
"""
permission_classes = [permissions.IsAuthenticated]
- @staticmethod
- def post(request):
+ def post(self, request):
"""
Remove an institution from the experiment.
"""
@@ -367,7 +363,6 @@ def post(request):
{"message": f"User {user.id} removed from experiment {experiment.id}."}
)
-
class ToggleExperimentPublicView(APIView):
"""
API endpoint to toggle the 'is_public' field of an experiment.
@@ -375,8 +370,7 @@ class ToggleExperimentPublicView(APIView):
"""
permission_classes = [permissions.IsAuthenticated]
- @staticmethod
- def post(request):
+ def post(self, request):
"""
Toggle the 'is_public' field of the experiment.
"""
@@ -396,7 +390,6 @@ def post(request):
{"id": experiment.id, "is_public": experiment.is_public}
)
-
class InstitutionNonExperimentsSharedListView(generics.ListAPIView):
"""
REST endpoint: Get all institution NOT associated with a specific experiment.
@@ -416,7 +409,6 @@ def get_queryset(self):
id__in=experiment.shared_institutions.values_list('id', flat=True)
)
-
class UsersNonExperimentsSharedListView(generics.ListAPIView):
"""
REST endpoint: Get all users NOT associated with a specific experiment.
@@ -434,7 +426,6 @@ def get_queryset(self):
associated_user_ids = experiment.shared_users.values_list('id', flat=True)
return get_user_model().objects.exclude(id__in=associated_user_ids)
-
class UsersExperimentsSharedListView(generics.ListAPIView):
"""
REST endpoint: Get all institution associated with a specific experiment.
@@ -450,7 +441,6 @@ def get_queryset(self):
experiment = get_object_or_404(Experiment, id=experiment_id)
return experiment.shared_users
-
class InstitutionExperimentsSharedListView(generics.ListAPIView):
"""
REST endpoint: Get all institution associated with a specific experiment.
@@ -466,15 +456,13 @@ def get_queryset(self):
experiment = get_object_or_404(Experiment, id=experiment_id)
return experiment.shared_institutions
-
class AddInstitutionToExperimentView(APIView):
"""
API endpoint to add an institution to an experiment.
"""
permission_classes = [permissions.IsAuthenticated]
- @staticmethod
- def post(request):
+ def post(self, request):
data = request.data
institution_id = data.get('institutionId')
experiment_id = data.get('experimentId')
@@ -484,7 +472,7 @@ def post(request):
{"error": "Both 'institutionId' and 'experimentId' are required."},
status=status.HTTP_400_BAD_REQUEST
)
-
+
experiment = get_object_or_404(Experiment, id=experiment_id)
institution = get_object_or_404(Institution, id=institution_id)
@@ -493,15 +481,13 @@ def post(request):
serializer = InstitutionSerializer(institution)
return Response(serializer.data)
-
class AddUserToExperimentView(APIView):
"""
API endpoint to add an institution to an experiment.
"""
permission_classes = [permissions.IsAuthenticated]
- @staticmethod
- def post(request):
+ def post(self, request):
data = request.data
user_id = data.get('userId')
experiment_id = data.get('experimentId')
@@ -511,7 +497,7 @@ def post(request):
{"error": "Both 'institutionId' and 'experimentId' are required."},
status=status.HTTP_400_BAD_REQUEST
)
-
+
experiment = get_object_or_404(Experiment, id=experiment_id)
user = get_object_or_404(User, id=user_id)
@@ -1215,14 +1201,14 @@ def post(request: Request):
# Gets Gene and GEM expression with time values
gene_values, gem_values, clinical_time_values, _gene_samples, _gem_samples, \
clinical_samples = pipelines.get_valid_data_from_sources(
- experiment,
- gene,
- gem,
- round_values=False,
- return_samples_identifiers=True,
- clinical_attribute=time_attribute,
- fill_clinical_missing_samples=False
- )
+ experiment,
+ gene,
+ gem,
+ round_values=False,
+ return_samples_identifiers=True,
+ clinical_attribute=time_attribute,
+ fill_clinical_missing_samples=False
+ )
# Gets event values
clinical_event_values: np.ndarray = experiment.clinical_source.get_specific_samples_and_attributes(
diff --git a/src/api_service/websocket_functions.py b/src/api_service/websocket_functions.py
index 9fc51255..237e34b9 100644
--- a/src/api_service/websocket_functions.py
+++ b/src/api_service/websocket_functions.py
@@ -40,7 +40,7 @@ def send_update_cgds_studies_command():
def send_update_biomarkers_command(user_id: int):
"""
- Sends a message indicating that a Biomarker's state update has occurred
+ Sends a message indicating that an Biomarker's state update has occurred
"""
user_group_name = f'notifications_{user_id}'
message = {
@@ -51,7 +51,7 @@ def send_update_biomarkers_command(user_id: int):
def send_update_user_file_command(user_id: int):
"""
- Sends a message indicating that a user file's state update has occurred
+ Sends a message indicating that an user file's state update has occurred
"""
user_group_name = f'notifications_{user_id}'
message = {
@@ -84,18 +84,6 @@ def send_update_trained_models_command(user_id: int):
send_message(user_group_name, message)
-def send_update_differential_expression_experiments_command(user_id: int):
- """
- Sends a message indicating that a DifferentialExpressionExperiment state update has occurred
- @param user_id: DifferentialExpressionExperiment's user's id to send the WS message
- """
- user_group_name = f'notifications_{user_id}'
- message = {
- 'command': 'update_differential_expression_experiments'
- }
- send_message(user_group_name, message)
-
-
def send_update_prediction_experiment_command(user_id: int):
"""
Sends a message indicating that a InferenceExperiment state update has occurred
@@ -119,10 +107,9 @@ def send_update_cluster_label_set_command(user_id: int):
}
send_message(user_group_name, message)
-
def send_update_institutions_command(user_id: int):
"""
- Sends a message indicating that an Institution state update has occurred
+ Sends a message indicating that a Institution state update has occurred
@param user_id: Institution's user's id to send the WS message
"""
user_group_name = f'notifications_{user_id}'
@@ -131,14 +118,13 @@ def send_update_institutions_command(user_id: int):
}
send_message(user_group_name, message)
-
def send_update_user_for_institution_command(user_id: int):
"""
- Sends a message indicating that an Institution_user state update has occurred
+ Sends a message indicating that a Institution_user state update has occurred
@param user_id: Institution's user's id to send the WS message
"""
user_group_name = f'notifications_{user_id}'
message = {
'command': 'update_user_for_institution'
}
- send_message(user_group_name, message)
+ send_message(user_group_name, message)
\ No newline at end of file
diff --git a/src/datasets_synchronization/admin.py b/src/datasets_synchronization/admin.py
index 6463ff93..670b8c4c 100644
--- a/src/datasets_synchronization/admin.py
+++ b/src/datasets_synchronization/admin.py
@@ -5,9 +5,8 @@
class CGDSStudyAdmin(admin.ModelAdmin):
list_display = ('name', 'description', 'version', 'date_last_synchronization', 'state')
- list_filter = ('state', 'tissues')
+ list_filter = ('state',)
search_fields = ('name', 'description')
- filter_horizontal = ('tissues',)
def delete_queryset(self, request, queryset):
"""
@@ -43,9 +42,9 @@ def delete_queryset(self, request, queryset):
'mirna_dataset__name', 'mrna_dataset__name')
+
class SurvivalColumnsTupleAdmin(admin.ModelAdmin):
"""Useful for SurvivalColumnsTupleCGDSDataset and SurvivalColumnsTupleUserFile models."""
-
@staticmethod
@admin.display(description='CGDS Dataset')
def dataset(obj: Union[SurvivalColumnsTupleCGDSDataset, SurvivalColumnsTupleUserFile]) -> str:
@@ -54,7 +53,6 @@ def dataset(obj: Union[SurvivalColumnsTupleCGDSDataset, SurvivalColumnsTupleUser
list_display = ('pk', 'dataset', 'time_column', 'event_column')
search_fields = ('time_column', 'event_column')
-
# IMPORTANT: these models should be managed in the CGDS Panel in the frontend!
admin.site.register(CGDSStudy, CGDSStudyAdmin)
admin.site.register(CGDSDataset, CGDSDatasetAdmin)
diff --git a/src/datasets_synchronization/migrations/0036_alter_cgdsstudy_clinical_patient_dataset_and_more.py b/src/datasets_synchronization/migrations/0036_alter_cgdsstudy_clinical_patient_dataset_and_more.py
deleted file mode 100644
index 189242c2..00000000
--- a/src/datasets_synchronization/migrations/0036_alter_cgdsstudy_clinical_patient_dataset_and_more.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# Generated by Django 4.2.19 on 2026-01-14 21:38
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("datasets_synchronization", "0035_auto_20230922_2356"),
- ]
-
- operations = [
- migrations.AlterField(
- model_name="cgdsstudy",
- name="clinical_patient_dataset",
- field=models.OneToOneField(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.SET_NULL,
- related_name="cgds_studies_as_clinical_patient_dataset",
- to="datasets_synchronization.cgdsdataset",
- ),
- ),
- migrations.AlterField(
- model_name="cgdsstudy",
- name="clinical_sample_dataset",
- field=models.OneToOneField(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.SET_NULL,
- related_name="cgds_studies_as_clinical_sample_dataset",
- to="datasets_synchronization.cgdsdataset",
- ),
- ),
- migrations.AlterField(
- model_name="cgdsstudy",
- name="cna_dataset",
- field=models.OneToOneField(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.SET_NULL,
- related_name="cgds_studies_as_cna_dataset",
- to="datasets_synchronization.cgdsdataset",
- ),
- ),
- migrations.AlterField(
- model_name="cgdsstudy",
- name="methylation_dataset",
- field=models.OneToOneField(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.SET_NULL,
- related_name="cgds_studies_as_methylation_dataset",
- to="datasets_synchronization.cgdsdataset",
- ),
- ),
- migrations.AlterField(
- model_name="cgdsstudy",
- name="mirna_dataset",
- field=models.OneToOneField(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.SET_NULL,
- related_name="cgds_studies_as_mirna_dataset",
- to="datasets_synchronization.cgdsdataset",
- ),
- ),
- migrations.AlterField(
- model_name="cgdsstudy",
- name="mrna_dataset",
- field=models.OneToOneField(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.SET_NULL,
- related_name="cgds_studies_as_mrna_dataset",
- to="datasets_synchronization.cgdsdataset",
- ),
- ),
- ]
diff --git a/src/datasets_synchronization/migrations/0037_cgdsstudy_tissue.py b/src/datasets_synchronization/migrations/0037_cgdsstudy_tissue.py
deleted file mode 100644
index 2d916279..00000000
--- a/src/datasets_synchronization/migrations/0037_cgdsstudy_tissue.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Generated by Django 4.2.19 on 2026-02-23 00:20
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("tissues", "0001_initial"),
- (
- "datasets_synchronization",
- "0036_alter_cgdsstudy_clinical_patient_dataset_and_more",
- ),
- ]
-
- operations = [
- migrations.AddField(
- model_name="cgdsstudy",
- name="tissue",
- field=models.ForeignKey(
- blank=True,
- null=True,
- on_delete=django.db.models.deletion.SET_NULL,
- to="tissues.tissue",
- ),
- ),
- ]
diff --git a/src/datasets_synchronization/migrations/0038_remove_cgdsstudy_tissue_cgdsstudy_tissues.py b/src/datasets_synchronization/migrations/0038_remove_cgdsstudy_tissue_cgdsstudy_tissues.py
deleted file mode 100644
index b004849a..00000000
--- a/src/datasets_synchronization/migrations/0038_remove_cgdsstudy_tissue_cgdsstudy_tissues.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Generated by Django 4.2.19 on 2026-03-05 22:27
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("tissues", "0002_tissue_code_and_initial_data"),
- ("datasets_synchronization", "0037_cgdsstudy_tissue"),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name="cgdsstudy",
- name="tissue",
- ),
- migrations.AddField(
- model_name="cgdsstudy",
- name="tissues",
- field=models.ManyToManyField(blank=True, to="tissues.tissue"),
- ),
- ]
diff --git a/src/datasets_synchronization/models.py b/src/datasets_synchronization/models.py
index 43a7b472..41482be8 100644
--- a/src/datasets_synchronization/models.py
+++ b/src/datasets_synchronization/models.py
@@ -10,7 +10,6 @@
from common.methylation import MethylationPlatform
from feature_selection.models import TrainedModel
from statistical_properties.models import StatisticalValidation
-from tissues.models import Tissue
from user_files.models import UserFile
from user_files.models_choices import FileType
from pandas import DataFrame
@@ -105,7 +104,6 @@ def __get_reverse_study(self) -> Optional['CGDSDataset']:
return cast(Optional['CGDSDataset'], self.clinical_patient_dataset)
elif hasattr(self, 'clinical_sample_dataset'):
return cast(Optional['CGDSDataset'], self.clinical_sample_dataset)
- return None
@property
def study(self) -> Optional['CGDSDataset']:
@@ -113,7 +111,7 @@ def study(self) -> Optional['CGDSDataset']:
def __str__(self) -> str:
study_name = self.study.name if self.study else '-'
- return f'PK: {self.pk} | File: {self.file_path} | Col: {self.mongo_collection_name} | Assigned to study: {study_name}'
+ return f'File: {self.file_path} | Col: {self.mongo_collection_name} | Assigned to study: {study_name}'
def __compute_number_of_row_and_samples_and_save(self) -> None:
"""
@@ -289,7 +287,6 @@ class CGDSStudy(models.Model):
null=True,
related_name='cgds_studies_as_clinical_sample_dataset'
)
- tissues = models.ManyToManyField(Tissue, blank=True)
task_id: Optional[str] = models.CharField(max_length=100, blank=True, null=True) # Celery Task ID
def __str__(self) -> str:
@@ -329,4 +326,4 @@ def delete(self, *args, **kwargs) -> None:
dataset.delete()
# Sends a websocket message to update the state in the frontend
- send_update_cgds_studies_command()
\ No newline at end of file
+ send_update_cgds_studies_command()
diff --git a/src/datasets_synchronization/serializers.py b/src/datasets_synchronization/serializers.py
index 3f78d88f..26bd47fe 100644
--- a/src/datasets_synchronization/serializers.py
+++ b/src/datasets_synchronization/serializers.py
@@ -28,7 +28,7 @@ class Meta:
fields = ['id', 'time_column', 'event_column']
def get_fields(self, *args, **kwargs):
- fields = super(SurvivalColumnsTupleCGDSSimpleSerializer, self).get_fields()
+ fields = super(SurvivalColumnsTupleCGDSSimpleSerializer, self).get_fields(*args, **kwargs)
request = self.context.get('request', None)
if request and getattr(request, 'method', None) == "POST":
fields['id'].required = False
@@ -123,9 +123,9 @@ def __check_collection_name(mongo_collection_name: str, editing_cgds_dataset_id:
})
def __update_cgds_dataset(
- self,
- cgds_dataset_instance: CGDSDataset,
- validated_data_pop
+ self,
+ cgds_dataset_instance: CGDSDataset,
+ validated_data_pop
) -> Optional[CGDSDataset]:
"""
Updates a CGDSDataset instance from a request data
@@ -186,9 +186,10 @@ def __update_survival_columns(cgds_dataset_instance: CGDSDataset, validated_data
# If there's an existing id, updates the element
if 'id' in survival_column:
try:
- survival_column_obj: SurvivalColumnsTupleCGDSDataset = SurvivalColumnsTupleCGDSDataset.objects.get(
- pk=survival_column['id']
- )
+ survival_column_obj: SurvivalColumnsTupleCGDSDataset = SurvivalColumnsTupleCGDSDataset. \
+ objects.get(
+ pk=survival_column['id']
+ )
survival_column_obj.time_column = survival_column['time_column']
survival_column_obj.event_column = survival_column['event_column']
survival_column_obj.save()
@@ -224,10 +225,9 @@ def create(self, validated_data) -> Optional[CGDSStudy]:
methylation_dataset = self.__create_cgds_dataset(validated_data.pop('methylation_dataset'))
clinical_patient_dataset = self.__create_cgds_dataset(validated_data.pop('clinical_patient_dataset'))
clinical_sample_dataset = self.__create_cgds_dataset(validated_data.pop('clinical_sample_dataset'))
- tissues = validated_data.pop('tissues', [])
# Creates the CGDSStudy
- cgds_study = CGDSStudy.objects.create(
+ return CGDSStudy.objects.create(
mrna_dataset=mrna_dataset,
mirna_dataset=mirna_dataset,
cna_dataset=cna_dataset,
@@ -236,8 +236,6 @@ def create(self, validated_data) -> Optional[CGDSStudy]:
clinical_sample_dataset=clinical_sample_dataset,
**validated_data
)
- cgds_study.tissues.set(tissues)
- return cgds_study
@staticmethod
def __set_clinical_datasets_to_existing_experiments(cgds_study: CGDSStudy):
@@ -305,27 +303,27 @@ def update(self, instance: CGDSStudy, validated_data):
instance.clinical_patient_dataset = clinical_patient_dataset
instance.clinical_sample_dataset = clinical_sample_dataset
- # Updates M2M tissues if provided
- if 'tissues' in validated_data:
- instance.tissues.set(validated_data['tissues'])
-
# Saves new changes and returns instance
instance.save()
return instance
class SimpleCGDSDatasetSerializer(serializers.ModelSerializer):
- """CGDSDataset serializer with few fields for list views."""
- name = serializers.CharField(source='study.name', read_only=True)
- description = serializers.CharField(source='study.description', read_only=True)
- version = serializers.CharField(source='study.version', read_only=True)
- file_obj = serializers.SerializerMethodField(method_name='get_file_obj')
-
class Meta:
model = CGDSDataset
- fields = ['id', 'name', 'description', 'version', 'date_last_synchronization', 'file_type', 'file_obj']
-
- @staticmethod
- def get_file_obj(_instance: CGDSDataset):
- """Returns None to avoid sending the file in list views."""
- return None
+ fields = []
+
+ def to_representation(self, instance):
+ # Gets the file content for user_file
+ data = super(SimpleCGDSDatasetSerializer, self).to_representation(instance)
+
+ # Serialize the study
+ study = instance.study
+ data['name'] = study.name
+ data['description'] = study.description
+ data['version'] = study.version
+ data['date_last_synchronization'] = instance.date_last_synchronization
+ data['file_type'] = instance.file_type
+ data['file_obj'] = None
+
+ return data
diff --git a/src/datasets_synchronization/urls.py b/src/datasets_synchronization/urls.py
index e5f71a5d..595a6b54 100644
--- a/src/datasets_synchronization/urls.py
+++ b/src/datasets_synchronization/urls.py
@@ -7,9 +7,6 @@
# CGDS Studies
path('studies', views.CGDSStudyList.as_view(), name='cgds_studies'),
path('studies/For questions or suggestions please contact us:
+{intl.formatMessage({ id: 'about.contact.questions' })}
{EMAILS.map((email) => (@@ -98,7 +101,7 @@ export const AboutUs = () => {
))} -You can also contact us for creating your research institution. It will let researchers share datasets inside Multiomix.
+{intl.formatMessage({ id: 'about.contact.institutions' })}