Source code for slideatlas.models.image

# coding=utf-8

from mongoengine import EmbeddedDocument, BinaryField, BooleanField, DateTimeField, \
    EmbeddedDocumentField, FloatField, GenericEmbeddedDocumentField, IntField, \
    ListField, StringField
from mongoengine.errors import NotRegistered

from .common import MultipleDatabaseModelDocument

################################################################################
__all__ = ('Image',)


################################################################################
class StartupView(EmbeddedDocument):
    center = ListField(FloatField(), required=False)
    rotation = FloatField(required=False)
    zoom = IntField(required=False)


################################################################################
class Annotation(EmbeddedDocument):
    meta = {
        'abstract': True,
        'allow_inheritance': True,
        }

    display_name = StringField(required=False, db_field='displayname')
    color = StringField(required=False)
    points = ListField(ListField(IntField(), required=True), required=False)


class CircleAnnotation(Annotation):
    type = StringField(required=True, default='circle', choices=('circle',))

    radius = IntField(required=False)


class FreehandAnnotation(Annotation):
    type = StringField(required=True, default='freehand', choices=('freehand',))

    measure_type = IntField(required=False, db_field='measuretype')
    closed = IntField(required=False)
    special_type = StringField(required=False, choices=('rectangle',), db_field='specialtype')


class PointerAnnotation(Annotation):
    type = StringField(required=True, default='pointer', choices=('pointer',))


class LinearmeasureAnnotation(Annotation):
    type = StringField(required=True, default='linearmeasure', choices=('linearmeasure',))


class EmbeddedAnnotationField(GenericEmbeddedDocumentField):
    type_map = {
        'circle': CircleAnnotation,
        'freehand': FreehandAnnotation,
        'pointer': PointerAnnotation,
        'linearmeasure': LinearmeasureAnnotation,
    }

    def __init__(self, *args, **kwargs):
        super(EmbeddedAnnotationField, self).__init__(
            choices=tuple(self.type_map.itervalues()),
            *args, **kwargs)

    def to_python(self, value):
        try:
            value = super(EmbeddedAnnotationField, self).to_python(value)
        except KeyError:
            try:
                doc_cls = self.type_map[value['type']]
                value = doc_cls._from_son(value)
            except KeyError:
                raise NotRegistered()
        return value


class Bookmark(EmbeddedDocument):
    annotation = EmbeddedAnnotationField(required=False)
    center = ListField(IntField(), required=False)
    details = StringField(required=False)
    lens = FloatField(required=False)
    title = StringField(required=False)
    zoom = IntField(required=False)


################################################################################
[docs]class Image(MultipleDatabaseModelDocument): """ The model Image record, any methods will go into a mixin """ meta = { 'collection': 'images', # 'allow_inheritance' : True 'indexes': [ { 'fields': ('filename',), # TODO: only need to index this for Ptiff images 'cls': False, 'unique': False, # TODO: this should be true for Ptiff images 'sparse': False, }, { 'fields': ('sha512',), # TODO: only need to index this for Ptiff images 'cls': False, 'unique': True, 'sparse': True, # TODO: this should not be true for Ptiff images }, ] } filename = StringField(required=False, verbose_name='Filename', help_text='The original filename of the uploaded image') sha512 = StringField(required=False, verbose_name='SHA512 Hash', help_text='The SHA512 hash of the PTIFF image file\'s content.') label = StringField(required=False, #TODO: make unique verbose_name='Label', help_text='The human-readable label for the image') uploaded_at = DateTimeField(required=False, verbose_name='Upload Time', help_text='The time that the image was first uploaded.') origin = ListField(FloatField(), required=False, default=lambda: [0.,0.,0.], verbose_name='Origin', help_text='x / y / z world coords (necessary to import NDPA annotations)') spacing = ListField(FloatField(), required=False, default=lambda: [1.,1.,1.], verbose_name='Spacing', help_text='x / y / z nanometers/pixel or "1.0" if unknown') dimensions = ListField(IntField(), required=True, verbose_name='Dimensions', help_text='x / y / z dimensions of non-padded region of base layer in pixels. z-dimension is 1 for non-stack images.') levels = IntField(required=False, default=0, verbose_name='Levels', help_text='Levels in multiresolution pyramid (specific to pyramid2 and pyrmid3 types)') components = IntField(required=False, default=3, verbose_name='Components', help_text='') # New fields coordinate_system = StringField(required=False, choices=('Pixel', 'Photo'), default='Pixel', db_field='CoordinateSystem', verbose_name='', help_text='') tile_size = IntField(required=False, default=256, db_field='TileSize', verbose_name='TileSize', help_text='dimensions of each square tile') bounds = ListField(IntField(), required=False, default=lambda: [0,0,0,0,0,0], verbose_name='', help_text='xMin / xMax / yMin / yMax nanometers or "Units" if unknown') metadataready = BooleanField(required=False, verbose_name='', help_text='') name = StringField(required=False, verbose_name='', help_text='') thumb = BinaryField(required=False, verbose_name='', help_text='') type = StringField(required=False, choices=('stack',), verbose_name='', help_text='If this is not set, then assume pyramid2. "stack" is a simple array of images named 1.png, 2.png ...') copyright = StringField(required=False, verbose_name='', help_text='') # TODO: this should be an embedded document startup_view = EmbeddedDocumentField(StartupView, required=False, verbose_name='', help_text='') # TODO: this should be an embedded document bookmarks = ListField(EmbeddedDocumentField(Bookmark), required=False, verbose_name='', help_text='') # TODO: set '_cls' field on all documents in database