Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include instances as attributes of the relevant class #29

Merged
merged 6 commits into from
Mar 11, 2024

Conversation

apdavison
Copy link
Member

This is a proposal for how to include predefined metadata instances (e.g. controlled terms) in the Python library (cf #24). Usage example:

In [1]: from openminds.latest.controlled_terms import AgeCategory

In [2]: AgeCategory.adult
Out[2]: <openminds.latest.controlled_terms.age_category.AgeCategory at 0x104eb3970>

In [3]: AgeCategory.adult.id
Out[3]: 'https://openminds.ebrains.eu/instances/ageCategory/adult'

In [4]: AgeCategory.adult.definition
Out[4]: "'Adult' categorizes the life cycle stage of an animal or human that reached sexual maturity."

@apdavison apdavison added this to the 0.2.0 milestone Nov 28, 2023
@apdavison apdavison added the enhancement New feature or request label Nov 28, 2023
@ehennestad
Copy link

I don't quite understand from the jinja template whether all the instances will be embedded into the python class?

I had done something similar before in the openMINDS MATLAB package, but with suggestions from Lyuba ended up doing it differently.

This is the example of a schema definition for AgeCategory.
https://github.com/openMetadataInitiative/openMINDS_MATLAB/blob/main/code/schemas/latest/%2Bopenminds/%2Bcontrolledterms/AgeCategory.m#L1

As you can see, it has a hidden CONTROLLED_INSTANCES property, and this holds the name of all known instances of this schema. In the ControlledTerm superclass there is a case in the constructor to deserialise an json ld instance if the constructor is called with an input argument which matches one of the names in the CONTROLLED_INSTANCES property

Example:

adult = openminds.controlledterms.AgeCategory('adult')

adult = 

  AgeCategory (https://openminds.ebrains.eu/controlledTerms/AgeCategory) with properties:

                     definition: "''Adult'' categorizes the life cycle stage of an animal or human that reached sexual maturity."
                    description: ""
             interlexIdentifier: "http://uri.interlex.org/base/ilx_0729043"
             knowledgeSpaceLink: ""
                           name: "adult"
    preferredOntologyIdentifier: "http://purl.obolibrary.org/obo/UBERON_0000113"
                        synonym: ["adult stage"    "post-juvenile adult"    "post-juvenile adult stage"]

  Required Properties: name

>> adult.id

ans =

    'https://openminds.ebrains.eu/instances/ageCategory/adult'

@lzehl
Copy link
Member

lzehl commented Nov 28, 2023

@ehennestad I let Andrew respond but it is not loading all instances into the class only the one of the stated type (as it is done for MATLAB as well, more or less)

build.py Outdated Show resolved Hide resolved
pipeline/utils.py Show resolved Hide resolved
@apdavison apdavison force-pushed the instances-as-class-attributes branch from 8a730da to 962ce62 Compare November 28, 2023 15:45
@Peyman-N
Copy link
Member

Python name generated for 4-(2-Hydroxyethyl)-1-piperazineEthanesulfonicAcid is four_(2_hydroxyethyl)_1_piperazine_ethanesulfonic_acid which is not a valid python variable name.
6,7-Dinitro-1,4-dihydroquinoxaline-2,3-dione is converted to six,7_dinitro_1,4_dihydroquinoxaline_2,3_dione.

@ehennestad
Copy link

ehennestad commented Feb 27, 2024

Python name generated for 4-(2-Hydroxyethyl)-1-piperazineEthanesulfonicAcid is four_(2_hydroxyethyl)_1_piperazine_ethanesulfonic_acid which is not a valid python variable name.
6,7-Dinitro-1,4-dihydroquinoxaline-2,3-dione is converted to six,7_dinitro_1,4_dihydroquinoxaline_2,3_dione.

I also had this issue with a lot of instance names, as MATLAB is very strict about property names.

I ended up changing the constructor for controlled term classes to create the object from a controlled instance if the constructor input is a string which is recognised as a known controlled instance, for example:
openminds.controlledterms.MolecularEntity('4-(2-Hydroxyethyl)-1-piperazineEthanesulfonicAcid')

and it returns the instance:

ans = 

  MolecularEntity (https://openminds.ebrains.eu/controlledTerms/MolecularEntity) with properties:

                     definition: "HEPES (4-(2-hydroxyethyl)-1-piperazineethanesulfonic acid) is a zwitterionic sulfonic acid buffering agent; one of the twenty Good's buffers. [adapted from W  ikipedia (https://en.wikipedia.org/wiki/HEPES)]"
                    description: ""
             interlexIdentifier: "http://uri.interlex.org/base/ilx_0484759"
             knowledgeSpaceLink: "https://knowledge-space.org/wiki/CHEBI:42334#2-4-2-hydroxyethyl-piperazin-1-yl-ethanesulfonic-acid"
                           name: "4-(2-hydroxyethyl)-1-piperazine ethanesulfonic acid"
    preferredOntologyIdentifier: "http://purl.obolibrary.org/obo/CHEBI_42334"
                        synonym: ["HEPES"    "2-[4-(2-hydroxyethyl)piperazin-1-yl]ethane-1-sulfonic acid"]

  Required Properties: name

I think this is a better solution because you can keep using all the original names and don't have to worry about remapping them

* pipeline:
  fix typo in comment
  update support link
  Use plural attribute names where the property is an array
  Add "Development" section to README
  Ensure `pipeline` branch has the same README as `main`
  sort the preamble, to eliminate random changes from run to run
  Fix for #23
  regression test for #23

# Conflicts:
#	build.py
#	pipeline/translator.py
@apdavison
Copy link
Member Author

@ehennestad and @Peyman-N I've fixed the Python name generation, but I've also added a by_name() class method to controlled-terms classes, similar to the solution suggested by @ehennestad. This method also uses synonyms for lookups, e.g.:

In [1]: from openminds.latest.controlled_terms import MolecularEntity

In [2]: MolecularEntity.by_name("HEPES") == MolecularEntity.by_name("4-(2-hydroxyethyl)-1-piperazine ethanesulfonic acid")
Out[2]: True

@lzehl lzehl merged commit 5579fb3 into pipeline Mar 11, 2024
1 check passed
@lzehl lzehl deleted the instances-as-class-attributes branch March 11, 2024 06:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants