Ejemplo n.º 1
0
class Pipeline(Item):
    item_type = 'pipeline'
    schema = load_schema('encoded:schemas/pipeline.json')
    name_key = 'accession'
    embedded = [
        'documents', 'documents.award', 'documents.lab',
        'documents.submitted_by', 'analysis_steps', 'analysis_steps.documents',
        'analysis_steps.pipelines',
        'analysis_steps.current_version.software_versions',
        'analysis_steps.current_version.software_versions.software',
        'analysis_steps.versions', 'analysis_steps.versions.software_versions',
        'analysis_steps.versions.software_versions.software', 'lab',
        'award.pi.lab', 'standards_page', 'reference_filesets'
    ]
    embedded_with_frame = [
        Path(
            'analysis_steps.current_version.software_versions.software.references',
            exclude=['datasets', 'publication_data']),
        Path('analysis_steps.versions.software_versions.software.references',
             exclude=['datasets', 'publication_data']),
    ]
    set_status_up = [
        'analysis_steps',
        'documents',
    ]
    set_status_down = []
    audit_inherit = [
        'analysis_steps',
    ]
Ejemplo n.º 2
0
class PublicationData(FileSet):
    item_type = 'publication_data'
    schema = load_schema('encoded:schemas/publication_data.json')
    embedded = ['submitted_by', 'lab', 'award.pi.lab']
    embedded_with_frame = [
        Path('references', exclude=['datasets', 'publication_data']),
    ]
Ejemplo n.º 3
0
class HumanDonor(Donor):
    item_type = 'human_donor'
    schema = load_schema('encoded:schemas/human_donor.json')
    embedded = Donor.embedded
    embedded_with_frame = [
        Path('references', exclude=['datasets', 'publication_data']),
    ]
    rev = {
        'children': ('HumanDonor', 'parents'),
        'characterizations': ('DonorCharacterization', 'characterizes')
    }

    @calculated_property(
        schema={
            "description":
            "Human donor(s) that have this human donor in their parent property.",
            "comment":
            "Do not submit. Values in the list are reverse links of a human donors that have this biosample under their parents property.",
            "title": "Children",
            "type": "array",
            "items": {
                "type": ['string', 'object'],
                "linkFrom": "HumanDonor.parents"
            },
            "notSubmittable": True,
        })
    def children(self, request, children):
        return paths_filtered_by_status(request, children)
Ejemplo n.º 4
0
class SoftwareVersion(Item):
    item_type = 'software_version'
    schema = load_schema('encoded:schemas/software_version.json')
    embedded = ['software']
    embedded_with_frame = [
        Path('software.references', exclude=['datasets', 'publication_data']),
    ]
    set_status_up = [
        'software',
    ]
    set_status_down = []

    def __ac_local_roles__(self):
        # Use lab/award from parent software object for access control.
        properties = self.upgrade_properties()
        root = find_root(self)
        software = root.get_by_uuid(properties['software'])
        return software.__ac_local_roles__()
Ejemplo n.º 5
0
class Software(Item):
    item_type = 'software'
    schema = load_schema('encoded:schemas/software.json')
    name_key = 'name'
    embedded = [
        'versions'
    ]
    embedded_with_frame = [
        Path('references', exclude=['datasets', 'publication_data']),
    ]
    rev = {
        'versions': ('SoftwareVersion', 'software')
    }

    @calculated_property(schema={
        "title": "Versions",
        "type": "array",
        "items": {
            "type": "string",
            "linkTo": "SoftwareVersion",
        },
    })
    def versions(self, request, versions):
        return paths_filtered_by_status(request, versions)
Ejemplo n.º 6
0
class MouseDonor(Donor):
    item_type = 'mouse_donor'
    schema = load_schema('encoded:schemas/mouse_donor.json')
    embedded = Donor.embedded + [
        'genetic_modifications',
        'genetic_modifications.modified_site_by_target_id',
        'genetic_modifications.modified_site_by_target_id.genes',
        'genetic_modifications.treatments'
    ]
    embedded_with_frame = [
        Path('references', exclude=['datasets', 'publication_data']),
    ]
    set_status_up = [
        'characterizations',
        'source',
        'genetic_modifications',
        'parent_strains',
        'documents',
    ]
    set_status_down = []

    def __ac_local_roles__(self):
        # Disallow lab submitter edits
        return {Authenticated: 'role.viewing_group_member'}
Ejemplo n.º 7
0
class Series(Dataset, CalculatedSeriesAssay, CalculatedSeriesBiosample,
             CalculatedSeriesTarget, CalculatedSeriesTreatment,
             CalculatedAssaySynonyms):
    item_type = 'series'
    base_types = ['Series'] + Dataset.base_types
    schema = load_schema('encoded:schemas/series.json')
    embedded = Dataset.embedded + [
        'biosample_ontology',
        'organism',
        'target',
        'target.genes',
        'target.organism',
        'related_datasets.biosample_ontology',
        'related_datasets.files',
        'related_datasets.files.analysis_step_version',
        'related_datasets.files.analysis_step_version.analysis_step',
        'related_datasets.files.analysis_step_version.analysis_step.pipelines',
        'related_datasets.lab',
        'related_datasets.submitted_by',
        'related_datasets.award.pi.lab',
        'related_datasets.replicates.antibody',
        'related_datasets.replicates.antibody.targets',
        'related_datasets.replicates.library',
        'related_datasets.replicates.library.biosample.submitted_by',
        'related_datasets.replicates.library.biosample.source',
        'related_datasets.replicates.library.biosample.organism',
        'related_datasets.replicates.library.biosample.donor.organism',
        'related_datasets.replicates.library.biosample.treatments',
        'related_datasets.replicates.library.biosample.applied_modifications',
        'related_datasets.replicates.library.spikeins_used',
        'related_datasets.replicates.library.treatments',
        'related_datasets.replicates.libraries',
        'related_datasets.replicates.libraries.biosample.submitted_by',
        'related_datasets.replicates.libraries.biosample.source',
        'related_datasets.replicates.libraries.biosample.organism',
        'related_datasets.replicates.libraries.biosample.donor.organism',
        'related_datasets.replicates.libraries.biosample.treatments',
        'related_datasets.replicates.libraries.biosample.applied_modifications',
        'related_datasets.replicates.libraries.spikeins_used',
        'related_datasets.replicates.libraries.treatments',
        'related_datasets.possible_controls',
        'related_datasets.possible_controls.lab',
        'related_datasets.target.organism',
        'files.platform',
        'files.lab',
        'files.analysis_step_version.analysis_step',
        'files.analysis_step_version.analysis_step.pipelines',
        'files.analysis_step_version.analysis_step.versions',
        'files.analysis_step_version.analysis_step.versions.software_versions',
        'files.analysis_step_version.analysis_step.versions.software_versions.software',
        'files.analysis_step_version.software_versions',
        'files.analysis_step_version.software_versions.software',
        'files.replicate.library.biosample',
        'files.library.biosample',
        'files.quality_metrics',
        'files.quality_metrics.step_run',
        'files.quality_metrics.step_run.analysis_step_version.analysis_step',
    ]
    embedded_with_frame = [
        Path('references', exclude=['datasets', 'publication_data']),
        Path('related_datasets.references',
             exclude=['datasets', 'publication_data']),
    ]

    @calculated_property(
        schema={
            "title": "Revoked datasets",
            "type": "array",
            "items": {
                "type": "string",
                "linkTo": "File",
            },
        })
    def revoked_datasets(self, request, related_datasets):
        return [
            path for path in related_datasets
            if item_is_revoked(request, path)
        ]

    @calculated_property(define=True,
                         schema={
                             "title": "Genome assembly",
                             "type": "array",
                             "items": {
                                 "type": "string",
                             },
                         })
    def assembly(self, request, original_files, related_datasets, status):
        combined_assembly = set()
        for assembly_from_original_files in calculate_assembly(
                request, original_files, status):
            combined_assembly.add(assembly_from_original_files)
        for dataset in related_datasets:
            properties = request.embed(dataset, '@@object')
            if properties['status'] not in ('deleted', 'replaced'):
                for assembly_from_related_dataset in properties['assembly']:
                    combined_assembly.add(assembly_from_related_dataset)
        return list(combined_assembly)

    @calculated_property(define=True,
                         schema={
                             "title": "Control types",
                             "type": "array",
                             "items": {
                                 "type": "string",
                             },
                         })
    def control_type(self, request, related_datasets):
        return request.select_distinct_values('control_type',
                                              *related_datasets)
Ejemplo n.º 8
0
class Dataset(Item):
    base_types = ['Dataset'] + Item.base_types
    embedded = [
        'files',
        'files.replicate',
        'files.replicate.experiment',
        'files.replicate.experiment.lab',
        'files.replicate.experiment.target',
        'files.replicate.experiment.target.genes',
        'files.submitted_by',
        'files.lab',
        'revoked_files',
        'revoked_files.replicate',
        'revoked_files.replicate.experiment',
        'revoked_files.replicate.experiment.lab',
        'revoked_files.replicate.experiment.target',
        'revoked_files.replicate.experiment.target.genes',
        'revoked_files.submitted_by',
        'submitted_by',
        'lab',
        'award.pi.lab',
    ]
    embedded_with_frame = [
        Path('references', exclude=['datasets', 'publication_data']),
    ]
    audit_inherit = [
        'original_files',
        'revoked_files',
        'contributing_files'
        'submitted_by',
        'lab',
        'award',
        'documents.lab',
    ]
    set_status_up = [
        'original_files',
        'replicates',
        'documents',
        'target',
    ]
    set_status_down = []
    name_key = 'accession'
    rev = {
        'original_files': ('File', 'dataset'),
    }

    @calculated_property(
        schema={
            "title": "Original files",
            "type": "array",
            "items": {
                "type": ['string', 'object'],
                "linkFrom": "File.dataset",
            },
            "notSubmittable": True,
        })
    def original_files(self, request, original_files):
        return paths_filtered_by_status(request, original_files)

    @calculated_property(
        schema={
            "title": "Contributing files",
            "type": "array",
            "items": {
                "type": "string",
                "linkTo": "File",
            },
        })
    def contributing_files(self, request, original_files, status):
        derived_from = set()
        for path in original_files:
            properties = request.embed(path, '@@object?skip_calculated=true')
            derived_from.update(
                paths_filtered_by_status(request,
                                         properties.get('derived_from', [])))
        outside_files = list(derived_from.difference(original_files))
        if status in ('released', ):
            return paths_filtered_by_status(
                request,
                outside_files,
                include=('released', 'archived', 'in progress'),
            )
        else:
            return paths_filtered_by_status(
                request,
                outside_files,
                exclude=('revoked', 'deleted', 'replaced'),
            )

    @calculated_property(
        schema={
            "title": "Files",
            "type": "array",
            "items": {
                "type": "string",
                "linkTo": "File",
            },
        })
    def files(self, request, original_files, status):
        if status in ('released', 'archived'):
            return paths_filtered_by_status(
                request,
                original_files,
                include=('released', 'archived'),
            )
        else:
            return paths_filtered_by_status(
                request,
                original_files,
                exclude=('revoked', 'deleted', 'replaced'),
            )

    @calculated_property(
        schema={
            "title": "Revoked files",
            "type": "array",
            "items": {
                "type": "string",
                "linkTo": "File",
            },
        })
    def revoked_files(self, request, original_files):
        return [
            path for path in original_files if item_is_revoked(request, path)
        ]

    @calculated_property(define=True,
                         schema={
                             "title": "Genome assembly",
                             "type": "array",
                             "items": {
                                 "type": "string",
                             },
                         })
    def assembly(self, request, original_files, status):
        return calculate_assembly(request, original_files, status)

    @calculated_property(condition='assembly',
                         schema={
                             "title": "Hub",
                             "type": "string",
                         })
    def hub(self, request):
        return request.resource_path(self, '@@hub', 'hub.txt')
class BiosampleType(SharedItem):
    item_type = 'biosample_type'
    schema = load_schema('encoded:schemas/biosample_type.json')
    embedded = []
    embedded_with_frame = [
        Path('references', exclude=['datasets', 'publication_data'])
    ]

    def unique_keys(self, properties):
        keys = super(BiosampleType, self).unique_keys(properties)
        keys.setdefault('biosample_type:name', []).append(self.name(properties))
        return keys

    @calculated_property(schema={
        "title": "Name",
        "type": "string",
    })
    def name(self, properties=None):
        if properties is None:
            properties = self.upgrade_properties()
        return u'{}_{}'.format(
            properties['classification'], properties['term_id']
        ).replace(' ', '_').replace(':', '_')

    @property
    def __name__(self):
        return self.name()

    @staticmethod
    def _get_ontology_slims(registry, term_id, slim_key):
        if term_id not in registry['ontology']:
            return []
        return list(set(
            slim for slim in registry['ontology'][term_id][slim_key]
        ))

    @calculated_property(condition='term_id', schema={
        "title": "Organ",
        "type": "array",
        "items": {
            "type": "string",
        },
    })
    def organ_slims(self, registry, term_id):
        return self._get_ontology_slims(registry, term_id, 'organs')

    @calculated_property(condition='term_id', schema={
        "title": "Cell",
        "type": "array",
        "items": {
            "type": "string",
        },
    })
    def cell_slims(self, registry, term_id):
        return self._get_ontology_slims(registry, term_id, 'cells')

    @calculated_property(condition='term_id', schema={
        "title": "Developmental slims",
        "type": "array",
        "items": {
            "type": "string",
        },
    })
    def developmental_slims(self, registry, term_id):
        return self._get_ontology_slims(registry, term_id, 'developmental')

    @calculated_property(condition='term_id', schema={
        "title": "System slims",
        "type": "array",
        "items": {
            "type": "string",
        },
    })
    def system_slims(self, registry, term_id):
        return self._get_ontology_slims(registry, term_id, 'systems')

    @calculated_property(condition='term_id', schema={
        "title": "Synonyms",
        "type": "array",
        "items": {
            "type": "string",
        },
    })
    def synonyms(self, registry, term_id):
        return self._get_ontology_slims(registry, term_id, 'synonyms')
Ejemplo n.º 10
0
class Biosample(Item):
    item_type = 'biosample'
    schema = load_schema('encoded:schemas/biosample.json')
    name_key = 'accession'
    rev = {
        'characterizations': ('BiosampleCharacterization', 'characterizes'),
        'parent_of': ('Biosample', 'part_of'),
    }
    embedded = [
        'biosample_ontology',
        'donor',
        'donor.organism',
        'donor.characterizations',
        'donor.characterizations.award',
        'donor.characterizations.documents',
        'donor.characterizations.lab',
        'donor.characterizations.submitted_by',
        'donor.documents',
        'donor.documents.award',
        'donor.documents.lab',
        'donor.documents.submitted_by',
        'submitted_by',
        'lab',
        'award',
        'award.pi.lab',
        'source',
        'treatments',
        'treatments.documents.submitted_by',
        'treatments.documents.lab',
        'treatments.documents.award',
        'documents.lab',
        'documents.award',
        'documents.submitted_by',
        'originated_from',
        'originated_from.biosample_ontology',
        'part_of',
        'part_of.documents',
        'part_of.documents.award',
        'part_of.documents.lab',
        'part_of.documents.submitted_by',
        'part_of.characterizations.documents',
        'part_of.characterizations.documents.award',
        'part_of.characterizations.documents.lab',
        'part_of.characterizations.documents.submitted_by',
        'part_of.treatments.documents',
        'parent_of',
        'pooled_from',
        'pooled_from.biosample_ontology',
        'characterizations.submitted_by',
        'characterizations.award',
        'characterizations.lab',
        'characterizations.documents',
        'organism',
        'applied_modifications',
        'applied_modifications.modified_site_by_target_id',
        'applied_modifications.modified_site_by_target_id.genes',
        'applied_modifications.treatments'
    ]
    embedded_with_frame = [
        Path('donor.references', exclude=['datasets', 'publication_data']),
        Path('references', exclude=['datasets', 'publication_data']),
    ]
    audit_inherit = [
        'biosample_ontology',
        'donor',
        'donor.biosample_ontology',
        'donor.organism',
        'donor.characterizations',
        'donor.donor_documents',
        'submitted_by',
        'lab',
        'award',
        'source',
        'treatments',
        'originated_from',
        'originated_from.biosample_ontology',
        'pooled_from',
        'pooled_from.biosample_ontology',
        'organism',
        'applied_modifications',
        'applied_modifications.modified_site_by_target_id'
    ]
    set_status_up = [
        'donor',
        'part_of',
        'pooled_from',
        'originated_from',
        'genetic_modifications',
        'characterizations',
        'treatments',
        'documents',
        'host',
        'source',
    ]
    set_status_down = []

    @calculated_property(define=True,
                         schema={"title": "Sex",
                                 "type": "string"})
    def sex(self, request, donor=None, model_organism_sex=None, organism=None):
        humanFlag = False
        if organism is not None:
            organismObject = request.embed(organism, '@@object')
            if organismObject['scientific_name'] == 'H**o sapiens':
                humanFlag = True

        if humanFlag is True:
            if donor is not None:  # try to get the sex from the donor
                donorObject = request.embed(donor, '@@object')
                if 'sex' in donorObject:
                    return donorObject['sex']
                else:
                    return 'unknown'
            else:
                return 'unknown'
        else:
            if model_organism_sex is not None:
                return model_organism_sex
            else:
                return 'unknown'

    @calculated_property(define=True,
                         schema={"title": "Age",
                                 "type": "string"})
    def age(
        self,
        request,
        donor=None,
        model_organism_age=None,
        organism=None,
        sample_collection_age=None,
    ):
        # https://encodedcc.atlassian.net/browse/ENCD-5272
        if sample_collection_age is not None:
            return sample_collection_age
        humanFlag = False
        if organism is not None:
            organismObject = request.embed(organism, '@@object')
            if organismObject['scientific_name'] == 'H**o sapiens':
                humanFlag = True

        if humanFlag is True:
            if donor is not None:  # try to get the age from the donor
                donorObject = request.embed(donor, '@@object')
                if 'age' in donorObject:
                    return donorObject['age']
                else:
                    return 'unknown'
            else:
                return 'unknown'
        else:
            if model_organism_age is not None:
                return model_organism_age
            else:
                return 'unknown'

    @calculated_property(define=True,
                         schema={"title": "Age units",
                                 "type": "string"})
    def age_units(
        self,
        request,
        donor=None,
        model_organism_age_units=None,
        organism=None,
        sample_collection_age_units=None,
    ):
        # https://encodedcc.atlassian.net/browse/ENCD-5272
        if sample_collection_age_units is not None:
            return sample_collection_age_units
        humanFlag = False
        if organism is not None:
            organismObject = request.embed(organism, '@@object')
            if organismObject['scientific_name'] == 'H**o sapiens':
                humanFlag = True

        if humanFlag is True:
            if donor is not None:  # try to get the age_units from the donor
                donorObject = request.embed(donor, '@@object')
                if 'age_units' in donorObject:
                    return donorObject['age_units']
                else:
                    return None
            else:
                return None
        else:
            return model_organism_age_units

    @calculated_property(define=True,
                        schema={
                            "title": "Disease term names",
                            "description": "Ontology term(s) describing the disease affecting the biosample.",
                            "comment": "Calculated from disease_term_id",
                            "type": "array",
                            "notSubmittable": True,
                            "uniqueItems": True,
                            "minItems": 1,
                            "items": {
                                "title": "Disease term name",
                                "description": "Ontology term describing the disease affecting the biosample.",
                                "type": "string",
                            },
                        })
    def disease_term_name(self, request, registry, disease_term_id=None):
        if disease_term_id is not None:
            term_name = list()
            for term_id in disease_term_id:
                if term_id in registry['ontology']:
                    term_name.append(registry['ontology'][term_id]['name'])
                else:
                    msg = 'Disease term ID {} is not a valid ID'.format(
                        term_id
                    )
                    raise ValidationFailure('body', ['disease_term_id'], msg)
            return term_name

    @calculated_property(define=True,
                         schema={"title": "Health status",
                                 "type": "string"})
    def health_status(self, request, donor=None, model_organism_health_status=None, organism=None):
        humanFlag = False
        if organism is not None:
            organismObject = request.embed(organism, '@@object')
            if organismObject['scientific_name'] == 'H**o sapiens':
                humanFlag = True

        if humanFlag is True and donor is not None:
            donorObject = request.embed(donor, '@@object')
            if 'health_status' in donorObject:
                return donorObject['health_status']
            else:
                return None
        else:
            if humanFlag is False:
                return model_organism_health_status
            return None

    @calculated_property(define=True,
                         schema={"title": "Life stage",
                                 "type": "string"})
    def life_stage(self, request, donor=None, mouse_life_stage=None, fly_life_stage=None,
                   worm_life_stage=None, organism=None):
        humanFlag = False
        if organism is not None:
            organismObject = request.embed(organism, '@@object')
            if organismObject['scientific_name'] == 'H**o sapiens':
                humanFlag = True

        if humanFlag is True and donor is not None:
            donorObject = request.embed(donor, '@@object')
            if 'life_stage' in donorObject:
                return donorObject['life_stage']
            else:
                return 'unknown'
        else:
            if humanFlag is False:
                if mouse_life_stage is not None:
                    return mouse_life_stage
                if fly_life_stage is not None:
                    return fly_life_stage
                if worm_life_stage is not None:
                    return worm_life_stage
            return 'unknown'

    @calculated_property(define=True,
                         schema={"title": "Synchronization",
                                 "type": "string"})
    def synchronization(self, request, donor=None, mouse_synchronization_stage=None,
                        fly_synchronization_stage=None, worm_synchronization_stage=None):
        # XXX mouse_synchronization_stage does not exist
        if mouse_synchronization_stage is not None:
            return mouse_synchronization_stage
        if fly_synchronization_stage is not None:
            return fly_synchronization_stage
        if worm_synchronization_stage is not None:
            return worm_synchronization_stage
        if donor is not None:
            return request.embed(donor, '@@object').get('synchronization')

    @calculated_property(schema={
        "title": "Model organism genetic modifications",
        "description":
            "Genetic modifications made in the model organism of the biosample.",
        "type": "array",
        "items": {
            "title": "Model organism genetic modification",
            "description": "Genetic modification made in the model organism of the biosample.",
            "comment": "See genetic_modification.json for available identifiers.",
            "type": "string",
            "linkTo": "GeneticModification",
        },
    }, define=True)
    def model_organism_donor_modifications(self, request, donor=None):
        if donor is not None:
            return request.embed(donor, '@@object').get('genetic_modifications')


    @calculated_property(schema={
        "title": "Applied modifications",
        "description": "All genetic modifications made in either the model organism and/or biosample.",
        "type": "array",
        "items": {
            "title": "Applied modification",
            "description": "Genetic modification made in either the model organism and/or biosample.",
            "comment": "See genetic_modification.json for available identifiers.",
            "type": "string",
            "linkTo": "GeneticModification",
        }
    }, define=True)
    def applied_modifications(self, request, genetic_modifications=None, model_organism_donor_modifications=None):
        return get_applied_modifications(genetic_modifications, model_organism_donor_modifications)


    @calculated_property(schema={
        "title": "Characterizations",
        "type": "array",
        "items": {
            "type": ['string', 'object'],
            "linkFrom": "BiosampleCharacterization.characterizes",
        },
    })
    def characterizations(self, request, characterizations):
        return paths_filtered_by_status(request, characterizations)

    @calculated_property(schema={
        "description": "The biosample(s) that have this biosample in their part_of property.",
        "comment": "Do not submit. Values in the list are reverse links of a biosamples that are part_of this biosample.",
        "title": "Child biosamples",
        "type": "array",
        "items": {
            "type": ['string', 'object'],
            "linkFrom": "Biosample.part_of",
        },
        'notSubmittable': True,
    })
    def parent_of(self, request, parent_of):
        return paths_filtered_by_status(request, parent_of)

    @calculated_property(schema={
        "title": "Age display",
        "type": "string",
    })
    def age_display(
        self,
        request,
        donor=None,
        model_organism_age=None,
        model_organism_age_units=None,
        post_synchronization_time=None,
        post_synchronization_time_units=None,
        sample_collection_age=None,
        sample_collection_age_units=None,
    ):
        # https://encodedcc.atlassian.net/browse/ENCD-5272
        if sample_collection_age is not None:
            if sample_collection_age == 'unknown':
                return ''
            if sample_collection_age_units is not None:
                return u'{}'.format(
                    pluralize(
                        sample_collection_age, sample_collection_age_units
                    )
                )
        if post_synchronization_time is not None and post_synchronization_time_units is not None:
            return u'{}'.format(
                pluralize(post_synchronization_time, post_synchronization_time_units)
                )
        if donor is not None:
            donor = request.embed(donor, '@@object')
            if 'age' in donor and 'age_units' in donor:
                if donor['age'] == 'unknown':
                    return ''
                return u'{}'.format(pluralize(donor['age'], donor['age_units']))
        if model_organism_age is not None and model_organism_age_units is not None:
            return u'{}'.format(
                pluralize(model_organism_age, model_organism_age_units)
            )
        return None

    @calculated_property(condition='depleted_in_term_name', schema={
        "title": "Depleted in term ID",
        "type": "string",
    })
    def depleted_in_term_id(self, request, depleted_in_term_name):

        term_lookup = {
            'head': 'UBERON:0000033',
            'limb': 'UBERON:0002101',
            'salivary gland': 'UBERON:0001044',
            'male accessory sex gland': 'UBERON:0010147',
            'testis': 'UBERON:0000473',
            'female gonad': 'UBERON:0000992',
            'digestive system': 'UBERON:0001007',
            'arthropod fat body': 'UBERON:0003917',
            'antenna': 'UBERON:0000972',
            'adult maxillary segment': 'FBbt:00003016',
            'female reproductive system': 'UBERON:0000474',
            'male reproductive system': 'UBERON:0000079'
        }

        term_id = list()
        for term_name in depleted_in_term_name:
            if term_name in term_lookup:
                term_id.append(term_lookup.get(term_name))
            else:
                term_id.append('Term ID unknown')

        return term_id

    @calculated_property(condition='subcellular_fraction_term_name', schema={
        "title": "Subcellular fraction term ID",
        "type": "string",
    })
    def subcellular_fraction_term_id(self, request, subcellular_fraction_term_name):
        term_lookup = {
            'nucleus': 'GO:0005634',
            'cytosol': 'GO:0005829',
            'chromatin': 'GO:0000785',
            'membrane': 'GO:0016020',
            'mitochondria': 'GO:0005739',
            'nuclear matrix': 'GO:0016363',
            'nucleolus': 'GO:0005730',
            'nucleoplasm': 'GO:0005654',
            'polysome': 'GO:0005844',
            'insoluble cytoplasmic fraction': 'NTR:0002594'
        }

        if subcellular_fraction_term_name in term_lookup:
            return term_lookup.get(subcellular_fraction_term_name)
        else:
            return 'Term ID unknown'

    @calculated_property(schema={
        "title": "Summary",
        "type": "string",
    })
    def summary(self, request,
                organism=None,
                donor=None,
                age=None,
                age_units=None,
                life_stage=None,
                sex=None,
                biosample_ontology=None,
                starting_amount=None,
                starting_amount_units=None,
                depleted_in_term_name=None,
                disease_term_name=None,
                phase=None,
                synchronization=None,
                subcellular_fraction_term_name=None,
                post_synchronization_time=None,
                post_synchronization_time_units=None,
                post_treatment_time=None,
                post_treatment_time_units=None,
                post_nucleic_acid_delivery_time=None,
                post_nucleic_acid_delivery_time_units=None,
                treatments=None,
                part_of=None,
                originated_from=None,
                transfection_method=None,
                transfection_type=None,
                preservation_method=None,
                genetic_modifications=None,
                model_organism_donor_modifications=None):

        sentence_parts = [
            'organism_name',
            'genotype_strain',
            'sex_stage_age',
            'synchronization',
            'term_phrase',
            'modifications_list',
            'originated_from',
            'disease_term_name',
            'treatments_phrase',
            'post_nucleic_acid_delivery_time',
            'preservation_method',
            'depleted_in',
            'phase',
            'fractionated'
        ]
        organismObject = None
        donorObject = None
        if organism is not None:
            organismObject = request.embed(organism, '@@object')
        if donor is not None:
            donorObject = request.embed(donor, '@@object')

        treatment_objects_list = None
        if treatments is not None and len(treatments) > 0:
            treatment_objects_list = []
            for t in treatments:
                treatment_objects_list.append(request.embed(t, '@@object'))

        part_of_object = None
        if part_of is not None:
            part_of_object = request.embed(part_of, '@@object')

        originated_from_object = None
        if originated_from is not None:
            originated_from_object = request.embed(originated_from, '@@object')

        modifications_list = None

        applied_modifications = get_applied_modifications(
            genetic_modifications, model_organism_donor_modifications)

        if applied_modifications:
            modifications_list = []
            for gm in applied_modifications:
                gm_object = request.embed(gm, '@@object')
                modification_dict = {'category': gm_object.get('category')}
                if gm_object.get('modified_site_by_target_id'):
                    modification_dict['target'] = request.embed(
                        gm_object.get('modified_site_by_target_id'),
                                      '@@object').get('label')
                if gm_object.get('introduced_tags'):
                    modification_dict['tags'] = []
                    for tag in gm_object.get('introduced_tags'):
                        tag_dict = {'location': tag['location'], 'name': tag['name']}
                        if tag.get('promoter_used'):
                            tag_dict['promoter'] = request.embed(
                                tag.get('promoter_used'),
                                        '@@object').get('label')
                        modification_dict['tags'].append(tag_dict)

                if 'method' in gm_object:
                    modifications_list.append((gm_object['method'], modification_dict))
                elif 'nucleic_acid_delivery_method' in gm_object:
                    for item in gm_object['nucleic_acid_delivery_method']:
                        modifications_list.append((item, modification_dict))

        if biosample_ontology:
            biosample_type_object = request.embed(biosample_ontology, '@@object')
            biosample_term_name = biosample_type_object['term_name']
            biosample_type = biosample_type_object['classification']
        else:
            biosample_term_name = None
            biosample_type = None

        biosample_dictionary = generate_summary_dictionary(
            request,
            organismObject,
            donorObject,
            age,
            age_units,
            life_stage,
            sex,
            biosample_term_name,
            biosample_type,
            starting_amount,
            starting_amount_units,
            depleted_in_term_name,
            disease_term_name,
            phase,
            subcellular_fraction_term_name,
            synchronization,
            post_synchronization_time,
            post_synchronization_time_units,
            post_treatment_time,
            post_treatment_time_units,
            post_nucleic_acid_delivery_time,
            post_nucleic_acid_delivery_time_units,
            treatment_objects_list,
            preservation_method,
            part_of_object,
            originated_from_object,
            modifications_list)

        return construct_biosample_summary([biosample_dictionary],
                                           sentence_parts)

    @calculated_property(schema={
        "title": "Perturbed",
        "description": "A flag to indicate whether the biosample has been perturbed with a treatment or genetic modification.",
        "type": "boolean",
        "notSubmittable": True,
    })
    def perturbed(
        self,
        request,
        applied_modifications,
        treatments=None,
    ):
        return bool(treatments) or any(
            (
                request.embed(m, '@@object').get('perturbation', False)
                for m in applied_modifications
            )
        )