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

Add wrapper classes that allow for easier immutable "evolution" of investigation file entities #125

Open
9 tasks
holtgrewe opened this issue Jan 15, 2024 · 0 comments
Assignees
Labels
enhancement New feature or request

Comments

@holtgrewe
Copy link
Member

holtgrewe commented Jan 15, 2024

Is your feature request related to a problem? Please describe.
For working with immutable datatypes, one needs to make copies with certain attributes updated only. This works well for simple types such as OntologyTermRef or Comment. However, modifying deeply nested types such as Study is hard because of interdependent fields.

Also, accessing the "listed" Tuple[Something, ...] members are hard to access.

Describe the solution you'd like
The section sketches the needed wrappers and API with checkboxes to tick. Each can go into its own ticket to break this into smaller units.

Provide a altamisa.wrappers module that provides wrappers for InvestigationInfo, Study, Assay, and possibly others. These wrappers should:

  • be immutable themselves
  • provide inner: <Inner> attribute for accessing the wrapped class
  • provide different functionality as follows
    • the functions that return modified shallow copies should return the wrapper types
    • note that it is very cheap to construct the wrapper types so they can be created on the fly if necessary, e.g.
      investigation = (
          InvestigationWrapperRemoval(investigation)
              .with_publication_removed(pubmed_id="123")
              .with_publication_appended(PublicationInfo(pubmed_id="...", ...))
      ).inner

Lookup

  • provide functions such as query_publications(*, pubmed_id: Optional[str]=None, doi: Optional[str]=None, ...) that allows easy querying for a listed members
    • special for Dict[str, OntologySourceRef etc., along the lines of: query_ontology_source_refs(*, key: Optional[str]=None, name: Optional[str]=None, ...)

Removal

  • provide functions such as `with_publications_removed(*, pubmed_id: Optional[str]=None, ...)
    • for OntologySourceRef, also provide key in the arguments

Adding

  • provide function such as with_publication_appended(value: PublicationInfo) and with_publications_appended(values: Iterable[PublicationInfo])
    • for inserting after a certain index: with_publication_inserted(index: int, value: PublicationInfo) and with_publications_inserted(index: int, values: Iterable[PublicationInfo])
  • for Dict fields provide functions such as with_set_ontology_source_ref(key: str, value: OntologySourceRef, *, allow_replace: bool = True)

Tests, Documentation and Cookbook

  • Ensure that we have unit tests
  • API documentation should exist
  • Add a cookbook that explains how to use this for some common use cases:
    • add a new StudyInfo
    • listing all protocols of a study, adding a new one, and adding a new one unless it exists
    • listing ontologies, adding a new one, and adding a new one unless it exists
    • listing factors, adding a new one, and adding a new one unless it exists
  • Also, show how to create a IsaBundle (cf. Add IsaBundle as a container for investigation, study, assay #122) from scratch both "big bang" with the constructor API, but also with the wrappers allowing for more incremental creation.

API Sketch

  • altamisa.wrappers.ProtocolInfoLookup
    • def query_parameters(*, key: Optional[str]=None, ...)
    • def query_components(*, key: Optional[str]=None, ...)
  • altamisa.wrappers.ProtocolInfoAdd
    • def with_parameter_set(key: str, value: FreeTextOrTermRef)
    • def with_component_set(key: str, value: ProtocolComponentInfo)
    • def with_comment_appended(value: Comment)
    • def with_comment_inserted(index: int, value: Comment)
    • def with_comments_appended(values: Iterable[Comment])
    • def with_comments_inserted(index: int, values: Iterable[Comment])
  • altamisa.wrappers.ProtocolInfoRemove (last parameter always _all: boolean = False to remove all)
    • def with_parameter_removed(*, key: Optional[str]=None, name: Optional[str]=None)
  • altamisa.wrappers.InvestigationInfoLookup
    • def query_ontology_source_refs(*, key: Optional[str]=None, name: Optional[str] = None, ...)
    • def query_publications(*, pubmed_id: Optional[str]=None, ...)
    • def query_factors(*, ...)
    • def query_assays(*, ...)
    • def query_protocols(*, key: Optional[str]=None, ...)
    • def query_contacts(*, ...)
  • altamisa.wrappers.InvestigationInfoAdd
    • def with_ontology_source_ref_set(key: str, value: OntologyRef)
    • def with_publication_appended(value: PublicationInfo)
    • def with_publications_appended(values: Iterable[PublicationInfo])
    • def with_publication_inserted(index: int, value: PublicationInfo)
    • def with_publications_inserted(index: int, values: Iterable[PublicationInfo])
    • def with_contact_appended(value: ContactInfo)
    • def with_contacts_appended(values: Iterable[ContactInfo])
    • def with_contact_inserted(index: int, value: ContactInfo)
    • def with_contacts_inserted(index: int, values: Iterable[ContactInfo])
    • def with_study_appended(value: StudyInfo)
    • def with_studies_appended(values: Iterable[StudyInfo])
    • def with_study_inserted(index: int, value: StudyInfo)
    • def with_studies_inserted(index: int, values: Iterable[StudyInfo])
  • altamisa.wrappers.InvestigationInfoRemove (last parameter always _all: boolean = False to remove all)
    • def with_ontology_source_ref_removed(*, key: Optional[str]=None, name: Optional[str]=None)
    • def with_publication_removed(*, pubmed_id: Optional[str]=None, ...)
    • def with_contact_removed(*, ...)
    • def with_study_removed(*, ...)
  • altamisa.wrappers.StudyInfoLookup
    • def query_designs(*, ...)
    • def query_publications(*, ...)
    • def query_factors(*, key: Optional[str]=None, ...)
    • def query_assays(*, ...)
    • def query_protocols(*, key: Optional[str]=None, ...)
    • def query_contacts(*, key: Optional[str]=None, ...)
  • altamisa.wrappers.StudyInfoAdd
    • def with_design_appended(value: DesignDescriptorsInfo)
    • def with_designs_appended(values: Iterable[DesignDescriptorsInfo])
    • def with_design_inserted(index: int, value: DesignDescriptorsInfo)
    • def with_designs_inserted(index: int, values: Iterable[DesignDescriptorsInfo])
    • def with_publication_appended(value: PublicationInfo)
    • def with_publications_appended(values: Iterable[PublicationInfo])
    • def with_publication_inserted(index: int, value: PublicationInfo)
    • def with_publications_inserted(index: int, values: Iterable[PublicationInfo])
    • def with_factor_set(key: string, value: FactorInfo)
    • def with_assay_appended(value: AssayInfo)
    • def with_assays_appended(values: Iterable[AssayInfo])
    • def with_assay_inserted(index: int, value: AssayInfo)
    • def with_assays_inserted(index: int, values: Iterable[AssayInfo])
    • def with_protocol_set(key: string, value: ProtocolInfo)
    • def with_contact_appended(value: ContactInfo)
    • def with_contacts_appended(values: Iterable[ContactInfo])
    • def with_contact_inserted(index: int, value: ContactInfo)
    • def with_contacts_inserted(index: Int, values: Iterable[ContactInfo])
  • altamisa.wrappers.StudyInfoRemove (last parameter always _all: boolean = False to remove all)
    • def with_design_removed(*, ...)
    • def with_publication_removed(*, ...)
    • def with_factor_removed(*, key: Optional[str]=None, ...)
    • def with_assay_removed(*, ...)
    • def with_protocol_removed(*, key: Optional[str]=None, ...)
    • def with_contact_removed(*, ...)

Describe alternatives you've considered
N/A

Additional context

@holtgrewe holtgrewe added the enhancement New feature or request label Jan 15, 2024
@holtgrewe holtgrewe changed the title Add wrapper classes that allow for easier immutable "evolution" Add wrapper classes that allow for easier immutable "evolution" of investigation file entities Jan 15, 2024
@sellth sellth self-assigned this Jan 19, 2024
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

No branches or pull requests

2 participants