diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 236d6137..263796b8 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -29,7 +29,7 @@ services: container_name: epbiotransformer3 celery_worker: - image: git.envipath.com/envipath/envipy-bayer:1.0 + image: git.envipath.com/envipath/envipy-bayer:1.2 container_name: epcelery env_file: - .env diff --git a/epdb/models.py b/epdb/models.py index 81bc456e..6b15a7a4 100644 --- a/epdb/models.py +++ b/epdb/models.py @@ -860,7 +860,7 @@ class Compound( @staticmethod @transaction.atomic def create( - package: "Package", smiles: str, name: str = None, description: str = None, *args, **kwargs + package: "Package", smiles: str, name: str = None, description: str = None, molfile: str = None, *args, **kwargs ) -> "Compound": if smiles is None or smiles.strip() == "": raise InvalidSMILESException("SMILES is required") @@ -885,9 +885,11 @@ class Compound( # Check if we find a direct match for a given SMILES if qs.exists(): - found_compound = qs.first().compound + found_structure = qs.first() + found_compound = found_structure.compound if name: + found_structure.add_alias(name) found_compound.add_alias(name) return found_compound @@ -900,9 +902,11 @@ class Compound( # Check if we can find the standardized one if qs.exists(): # TODO should we add a structure? - found_compound = qs.first().compound + found_structure = qs.first() + found_compound = found_structure.compound if name: + found_structure.add_alias(name) found_compound.add_alias(name) return found_compound @@ -1161,7 +1165,7 @@ class CompoundStructure( @staticmethod @transaction.atomic def create( - compound: Compound, smiles: str, name: str = None, description: str = None, *args, **kwargs + compound: Compound, smiles: str, name: str = None, description: str = None, molfile: str = None, *args, **kwargs ): # Clean for potential XSS if name is not None: @@ -1189,6 +1193,10 @@ class CompoundStructure( cs.smiles = smiles cs.compound = compound + # Check if molfile is present and valid + if molfile is not None and FormatConverter.from_molfile(molfile) is not None: + cs.molfile = molfile + if "normalized_structure" in kwargs: cs.normalized_structure = kwargs["normalized_structure"] @@ -1206,6 +1214,8 @@ class CompoundStructure( @property def as_svg(self, width: int = 800, height: int = 400): + if self.molfile is not None and self.molfile.strip() != "": + return IndigoUtils.mol_to_svg(self.molfile, width=width, height=height) return IndigoUtils.mol_to_svg(self.smiles, width=width, height=height) @property @@ -2341,7 +2351,8 @@ class Node(EnviPathModel, AliasMixin, ScenarioMixin, AdditionalInformationMixin) "node_label_id": self.default_node_label.url, "image": f"{self.url}?image=svg", "image_svg": IndigoUtils.mol_to_svg( - self.default_node_label.smiles, width=40, height=40 + self.default_node_label.molfile if self.default_node_label.molfile is not None and self.default_node_label.molfile.strip() else self.default_node_label.smiles, + width=40, height=40 ), "image_type": "svg", "name": self.get_name(), @@ -2395,6 +2406,8 @@ class Node(EnviPathModel, AliasMixin, ScenarioMixin, AdditionalInformationMixin) @property def as_svg(self): + if self.default_node_label.molfile is not None and self.default_node_label.molfile.strip() != "": + return IndigoUtils.mol_to_svg(self.default_node_label.molfile) return IndigoUtils.mol_to_svg(self.default_node_label.smiles) def get_timeseries_data(self): diff --git a/epdb/views.py b/epdb/views.py index 67e6f3e4..20bdf7d2 100644 --- a/epdb/views.py +++ b/epdb/views.py @@ -1124,6 +1124,9 @@ def package_model(request, package_uuid, model_uuid): } ) + # Sort data by prob desc + res["pred"] = sorted(res["pred"], key=lambda x: x["probability"], reverse=True) + return JsonResponse(res, safe=False) elif half_life: diff --git a/static/css/input.css b/static/css/input.css index 98ad1678..10ed39fa 100644 --- a/static/css/input.css +++ b/static/css/input.css @@ -34,3 +34,8 @@ } @import "./daisyui-theme.css"; + +select.select[multiple] { + display: block; + white-space: normal; +}