예제 #1
0
class Spike(BlockBasedPermissionsMixin, BaseInfo, DataObject):
    """
    NEO Spike @ G-Node.
    """
    # NEO attributes
    name = models.CharField(max_length=DEFAULTS['name_max_length'],
                            blank=True,
                            null=True)
    time = models.FloatField()
    time__unit = TimeUnitField('time__unit',
                               default=DEFAULTS['default_time_unit'])
    sampling_rate = models.FloatField('sampling_rate', blank=True, null=True)
    sampling_rate__unit = SamplingUnitField('sampling_rate__unit',
                                            blank=True,
                                            null=True)
    left_sweep = models.FloatField('left_sweep', blank=True, null=True)
    left_sweep__unit = TimeUnitField('left_sweep__unit', blank=True, null=True)

    # NEO data arrays
    waveform = models.FileField(storage=fs,
                                upload_to=make_upload_path,
                                blank=True,
                                null=True)
    waveform__unit = SignalUnitField('waveform__unit',
                                     default=DEFAULTS['default_data_unit'])

    # NEO relationships
    segment = VersionedForeignKey(Segment)
    unit = VersionedForeignKey(Unit, blank=True, null=True)

    def save(self, *args, **kwargs):
        self.block = self.segment.block
        super(Spike, self).save(*args, **kwargs)
예제 #2
0
class AnalogSignal(BlockBasedPermissionsMixin, BaseInfo, DataObject):
    """
    NEO AnalogSignal @ G-Node.
    """
    # NEO attributes
    name = models.CharField(max_length=DEFAULTS['name_max_length'],
                            blank=True,
                            null=True)
    sampling_rate = models.FloatField('sampling_rate')
    sampling_rate__unit = SamplingUnitField(
        'sampling_rate__unit', default=DEFAULTS['default_samp_unit'])
    t_start = models.FloatField('t_start')
    t_start__unit = TimeUnitField('t_start__unit',
                                  default=DEFAULTS['default_time_unit'])

    # NEO relationships
    segment = VersionedForeignKey(Segment)
    recordingchannel = VersionedForeignKey(RecordingChannel,
                                           blank=True,
                                           null=True)

    # NEO data arrays
    signal = models.FileField(storage=fs,
                              upload_to=make_upload_path,
                              blank=True,
                              null=True)
    signal__unit = SignalUnitField('signal__unit',
                                   default=DEFAULTS['default_data_unit'])

    def save(self, *args, **kwargs):
        self.block = self.segment.block
        super(AnalogSignal, self).save(*args, **kwargs)
예제 #3
0
class EpochArray(BlockBasedPermissionsMixin, BaseInfo, DataObject):
    """
    NEO EpochArray @ G-Node.
    """
    name = models.CharField(max_length=DEFAULTS['name_max_length'],
                            blank=True,
                            null=True)

    # NEO data arrays
    labels = models.FileField(storage=fs,
                              upload_to=make_upload_path,
                              blank=True,
                              null=True)
    times = models.FileField(storage=fs,
                             upload_to=make_upload_path,
                             blank=True,
                             null=True)
    times__unit = TimeUnitField('times__unit',
                                default=DEFAULTS['default_time_unit'])
    durations = models.FileField(storage=fs,
                                 upload_to=make_upload_path,
                                 blank=True,
                                 null=True)
    durations__unit = TimeUnitField('durations__unit',
                                    default=DEFAULTS['default_time_unit'])

    # NEO relationships
    segment = VersionedForeignKey(Segment)

    def save(self, *args, **kwargs):
        self.block = self.segment.block
        super(EpochArray, self).save(*args, **kwargs)
예제 #4
0
class ACLFakeModel(BaseGnodeObject):
    """ simple versioned model """
    test_attr = models.IntegerField()
    test_str_attr = models.CharField(max_length=50, blank=True)
    test_ref = VersionedForeignKey(
        ACLFakeOwnedModel, blank=True, null=True, on_delete=models.SET_NULL
    )
예제 #5
0
class BaseInfo(BaseGnodeObject):
    """ Base abstract class for any NEO object (except Block) """

    # block reference is used to determine access to an object
    block = VersionedForeignKey(Block)
    metadata = VersionedForeignKey(Section, null=True, blank=True)
    description = models.CharField(max_length=1024, blank=True, null=True)

    class Meta:
        abstract = True

    @property
    def has_data(self):
        return False  # no data by default

    @property
    def size(self):
        raise NotImplementedError()
예제 #6
0
class Value(DocumentBasedPermissionsMixin, BaseGnodeObject):
    """
    Class implemented metadata Value.
    """
    data = models.TextField('data')
    uncertainty = models.CharField(max_length=100, blank=True, null=True)
    unit = models.CharField(max_length=100, blank=True, null=True)
    reference = models.CharField(max_length=100, blank=True, null=True)
    definition = models.CharField(max_length=100, blank=True, null=True)
    filename = models.CharField(max_length=100, blank=True, null=True)
    encoder = models.CharField(max_length=100, blank=True, null=True)
    checksum = models.CharField(max_length=100, blank=True, null=True)
    property = VersionedForeignKey(Property, on_delete=models.CASCADE)
    document = VersionedForeignKey(Document)

    def save(self, *args, **kwargs):
        self.document = self.property.document
        super(Value, self).save(*args, **kwargs)
예제 #7
0
class Property(DocumentBasedPermissionsMixin, BaseGnodeObject):
    """
    Class represents a metadata "Property". Defines any kind of metadata
    property and may be linked to the Section.
    """

    # odML fields
    name = models.CharField('name', max_length=100)
    definition = models.CharField(max_length=100, blank=True, null=True)
    mapping = models.CharField(max_length=100, blank=True, null=True)
    dependency = models.CharField(max_length=100, blank=True, null=True)
    dependencyvalue = models.CharField(max_length=100, blank=True, null=True)
    section = VersionedForeignKey(Section, on_delete=models.CASCADE)
    document = VersionedForeignKey(Document)

    def save(self, *args, **kwargs):
        self.document = self.section.document
        super(Property, self).save(*args, **kwargs)
예제 #8
0
class IrregularlySampledSignal(BlockBasedPermissionsMixin, BaseInfo,
                               DataObject):
    """
    NEO IrregularlySampledSignal @ G-Node.
    """
    # NEO attributes
    name = models.CharField(max_length=DEFAULTS['name_max_length'],
                            blank=True,
                            null=True)
    t_start = models.FloatField('t_start')
    t_start__unit = TimeUnitField('t_start__unit',
                                  default=DEFAULTS['default_time_unit'])

    # NEO relationships
    segment = VersionedForeignKey(Segment)
    recordingchannel = VersionedForeignKey(RecordingChannel,
                                           blank=True,
                                           null=True)

    # NEO data arrays
    signal = models.FileField(storage=fs,
                              upload_to=make_upload_path,
                              blank=True,
                              null=True)
    signal__unit = SignalUnitField('signal__unit',
                                   default=DEFAULTS['default_data_unit'])
    times = models.FileField(storage=fs,
                             upload_to=make_upload_path,
                             blank=True,
                             null=True)
    times__unit = TimeUnitField('times__unit',
                                default=DEFAULTS['default_time_unit'])

    def full_clean(self, *args, **kwargs):
        """ Add some validation to keep 'signal' and 'times' dimensions
        consistent. Currently switched off. """
        super(IrregularlySampledSignal, self).full_clean(*args, **kwargs)

    def save(self, *args, **kwargs):
        self.block = self.segment.block
        super(IrregularlySampledSignal, self).save(*args, **kwargs)
예제 #9
0
class Unit(BlockBasedPermissionsMixin, BaseInfo):
    """
    NEO Unit @ G-Node.
    """
    name = models.CharField(max_length=DEFAULTS['name_max_length'])

    # NEO relationships
    recordingchannelgroup = VersionedForeignKey(RecordingChannelGroup)

    def save(self, *args, **kwargs):
        self.block = self.recordingchannelgroup.block
        super(Unit, self).save(*args, **kwargs)
예제 #10
0
class SpikeTrain(BlockBasedPermissionsMixin, BaseInfo, DataObject):
    """
    NEO SpikeTrain @ G-Node.
    """
    # NEO attributes
    name = models.CharField(max_length=DEFAULTS['name_max_length'],
                            blank=True,
                            null=True)
    t_start = models.FloatField('t_start')
    t_start__unit = TimeUnitField('t_start__unit',
                                  default=DEFAULTS['default_time_unit'])
    t_stop = models.FloatField('t_stop')
    t_stop__unit = TimeUnitField('t_stop__unit',
                                 default=DEFAULTS['default_time_unit'])

    # NEO relationships
    segment = VersionedForeignKey(Segment)
    unit = VersionedForeignKey(Unit, blank=True, null=True)

    # NEO data arrays
    times = models.FileField(storage=fs,
                             upload_to=make_upload_path,
                             blank=True,
                             null=True)
    times__unit = TimeUnitField('times__unit',
                                default=DEFAULTS['default_time_unit'])
    waveforms = models.FileField(storage=fs,
                                 upload_to=make_upload_path,
                                 blank=True,
                                 null=True)
    waveforms__unit = SignalUnitField('waveforms__unit', blank=True, null=True)

    # rewrite the size property when waveforms are supported
    def compute_size(self):
        return self.times.size

    def save(self, *args, **kwargs):
        self.block = self.segment.block
        super(SpikeTrain, self).save(*args, **kwargs)
예제 #11
0
class Block(BasePermissionsMixin, BaseGnodeObject):
    """
    NEO Block @ G-Node.
    """
    # NEO attributes
    name = models.CharField(max_length=DEFAULTS['name_max_length'])
    description = models.CharField(max_length=1024, blank=True, null=True)
    filedatetime = models.DateTimeField(null=True, blank=True)
    index = models.IntegerField(null=True, blank=True)
    metadata = VersionedForeignKey(Section, null=True, blank=True)

    @property
    def size(self):
        return sum([s.size for s in self.segment_set.all()])
예제 #12
0
class Event(BlockBasedPermissionsMixin, BaseInfo):
    """
    NEO Event @ G-Node.
    """
    # NEO attributes
    name = models.CharField(max_length=DEFAULTS['name_max_length'],
                            blank=True,
                            null=True)
    label = models.CharField('label', max_length=DEFAULTS['name_max_length'])
    time = models.FloatField('time')
    time__unit = TimeUnitField('time__unit',
                               default=DEFAULTS['default_time_unit'])

    # NEO relationships
    segment = VersionedForeignKey(Segment)

    def save(self, *args, **kwargs):
        self.block = self.segment.block
        super(Event, self).save(*args, **kwargs)
예제 #13
0
class parent_fake(VersionedM2M):
    """ M2M relationship class """
    parent = VersionedForeignKey(FakeParentModel)
    fake = VersionedForeignKey(FakeModel)
예제 #14
0
class FakeChildModel(BaseGnodeObject):
    """ simple versioned model with parent """
    test_attr = models.IntegerField()
    test_ref = VersionedForeignKey(
        FakeParentModel, blank=True, null=True, on_delete=models.SET_NULL
    )
예제 #15
0
class recordingchannel_rcg(VersionedM2M):
    recordingchannelgroup = VersionedForeignKey(RecordingChannelGroup)
    recordingchannel = VersionedForeignKey(RecordingChannel)
예제 #16
0
class Section(DocumentBasedPermissionsMixin, BaseGnodeObject):
    """
    Class represents a metadata "Section". Used to organize metadata
    (properties - values), Datafiles and NEO Blocks in a tree-like structure.
    May be recursively linked to itself.

    May be made public or shared with specific users via sharing of the related
    Document.

    Document field is always set, even for low-level Sections in the odML
    hierarchy. This is done to avoid recursive SQL-calls to fetch appropriate
    Section permissions.
    """

    # odML fields
    name = models.CharField(max_length=100)
    type = models.CharField(max_length=50, blank=True, null=True)
    reference = models.CharField(max_length=100, blank=True, null=True)
    definition = models.CharField(max_length=100, blank=True, null=True)
    link = models.CharField(max_length=100, blank=True, null=True)
    include = models.CharField(max_length=100, blank=True, null=True)
    repository = models.CharField(max_length=100, blank=True, null=True)
    mapping = models.CharField(max_length=100, blank=True, null=True)
    section = VersionedForeignKey(
        'self', blank=True, null=True, related_name='section_set',
        on_delete=models.CASCADE
    )
    document = VersionedForeignKey(
        Document, blank=True, null=True, on_delete=models.CASCADE
    )

    # position in the list on the same level in the tree
    tree_position = models.IntegerField(default=0)
    # field indicates whether it is a "template" section
    is_template = models.BooleanField(default=False)

    # manager that proxies correct QuerySet
    objects = SectionManager()

    @property
    def sections(self):
        return self.section_set.order_by("-tree_position")

    def fetch_deep_ids(self, ids):
        """ return all section ids located inside sections with given ids. This
        function as many sql calls as there are levels of the section tree """
        qs = self.__class__.objects.filter(parent_section_id__in=ids)
        down_one_level = list(qs.values_list('pk', flat=True))
        if down_one_level:
            return ids + self.fetch_deep_ids(down_one_level)
        return ids

    def stats(self, cascade=False):
        """ Section statistics """
        sec_ids = [self.pk]
        if cascade:  # recursively traverse a tree of child sections
            sec_ids = self.fetch_deep_ids(sec_ids)

        stats = {}  # calculate section statistics
        for rm in self._meta.get_all_related_objects():
            if not rm.model == self.__class__:
                kwargs = {rm.field.name + '_id__in': sec_ids}
                v = rm.model.objects.filter(**kwargs).count()
            else:
                v = len(sec_ids) - 1  # exclude self

            stats[rm.name] = v

        return stats

    def _get_next_tree_pos(self):
        """ Returns the next tree index "inside" self. """
        if self.sections:
            return int(self.sections[0].tree_position) + 1
        return 1

    def save(self, *args, **kwargs):
        def obj_has_changed(old, new):
            return (old is None and new is not None) or \
                   (new is None and old is not None) or \
                   (old is not None and new is not None and not old.pk == new.pk)

        if self.pk is not None and self.pk != "":  # update case
            old = self.__class__.objects.get(pk=self.pk)

            if obj_has_changed(old.section, self.section):
                if not self.section is None:
                    self.document = self.section.document

            elif obj_has_changed(old.document, self.document):
                if not old.section is None:
                    raise ValueError("Clean parent section to change Document")

        else:  # create case
            # section has a priority. if section is set, the document of the new
            # section will be taken from the parent section, not from the
            # current 'document' attribute
            if self.section is None and self.document is None:
                raise ValidationError("Either document or section must present")

            if self.section is not None:
                self.document = self.section.document

        self.full_clean()
        super(Section, self).save(*args, **kwargs)