<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

###############################################################################
#  Copyright Kitware Inc.
#
#  Licensed under the Apache License, Version 2.0 ( the "License" );
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
###############################################################################

from girder.constants import AccessType
from girder.models.folder import Folder as FolderModel
from girder.models.model_base import ValidationException


class Study(FolderModel):
    class State(object):
        ACTIVE = 'active'
        COMPLETE = 'complete'

    def initialize(self):
        super(Study, self).initialize()
        # TODO: add indexes

        self._filterKeys[AccessType.READ].clear()
        self.exposeFields(level=AccessType.READ, fields=[
            '_id', 'name', 'description', 'created', 'creatorId', 'updated'
        ])
        self.summaryFields = ['_id', 'name', 'updated']
        self.prefixSearchFields = ['lowerName', 'name']

    def loadStudyCollection(self):
        # assumes collection has been created by provision_utility
        # TODO: cache this value
        return self.model('collection').findOne({'name': 'Annotation Studies'})

    def createStudy(self, name, creatorUser, featureset, annotatorUsers,
                    images):
        # this may raise a ValidationException if the name already exists
        studyFolder = self.createFolder(
            parent=self.loadStudyCollection(),
            name=name,
            description='',
            parentType='collection',
            public=None,
            creator=creatorUser,
            allowRename=False
        )
        studyFolder = self.copyAccessPolicies(
            src=self.loadStudyCollection(),
            dest=studyFolder,
            save=False
        )
        studyFolder = self.setUserAccess(
            doc=studyFolder,
            user=creatorUser,
            # TODO: make admin
            level=AccessType.READ,
            save=False
        )
        # "setMetadata" will always save
        studyFolder = self.setMetadata(
            folder=studyFolder,
            metadata={
                'featuresetId': featureset['_id']
            }
        )

        for annotatorUser in annotatorUsers:
            self.addAnnotator(studyFolder, annotatorUser, creatorUser,
                              images)

        return studyFolder

    def addAnnotator(self, study, annotatorUser, creatorUser,
                     images=None):
        Annotation = self.model('annotation', 'isic_archive')
        if not images:
            images = self.getImages(study)

        if self.childAnnotations(
                study=study,
                annotatorUser=annotatorUser).count():
            raise ValidationException(
                'Annotator user is already part of the study.')

        annotatorFolder = self.createFolder(
            parent=study,
            name='%(login)s (%(firstName)s %(lastName)s)' % annotatorUser,
            description='',
            parentType='folder',
            public=True,
            creator=creatorUser
        )
        # study creator accesses will already have been copied to this
        # sub-folder
        # TODO: all users from the study don't need access; this should be
        # changed and migrated
        self.setUserAccess(
            doc=annotatorFolder,
            user=annotatorUser,
            # TODO: make write
            level=AccessType.READ,
            save=True
        )
        self.setMetadata(
            folder=annotatorFolder,
            metadata={
                'userId': annotatorUser['_id']
            }
        )

        for image in images:
            Annotation.createAnnotation(
                study, image, creatorUser, annotatorFolder)

    def addImage(self, study, image, creatorUser):
        Folder = self.model('folder')
        Annotation = self.model('annotation', 'isic_archive')
        for annotatorFolder in Folder.find({'parentId': study['_id']}):
            Annotation.createAnnotation(
                study, image, creatorUser, annotatorFolder)

    def getFeatureset(self, study):
        return self.model('featureset', 'isic_archive').load(
            study['meta']['featuresetId'], exc=True)

    def getAnnotators(self, study):
        Folder = self.model('folder')
        User = self.model('user', 'isic_archive')
        annotatorFolders = Folder.find({'parentId': study['_id']})
        return User.find({
            '_id': {'$in': annotatorFolders.distinct('meta.userId')}
        })

    def getImages(self, study, fields=None):<commit_msg>Make new studies private by default and have a smaller set of permissions<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

###############################################################################
#  Copyright Kitware Inc.
#
#  Licensed under the Apache License, Version 2.0 ( the "License" );
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
###############################################################################

from girder.constants import AccessType
from girder.models.folder import Folder as FolderModel
from girder.models.model_base import ValidationException


class Study(FolderModel):
    class State(object):
        ACTIVE = 'active'
        COMPLETE = 'complete'

    def initialize(self):
        super(Study, self).initialize()
        # TODO: add indexes

        self._filterKeys[AccessType.READ].clear()
        self.exposeFields(level=AccessType.READ, fields=[
            '_id', 'name', 'description', 'created', 'creatorId', 'updated'
        ])
        self.summaryFields = ['_id', 'name', 'updated']
        self.prefixSearchFields = ['lowerName', 'name']

    def loadStudyCollection(self):
        # assumes collection has been created by provision_utility
        # TODO: cache this value
        return self.model('collection').findOne({'name': 'Annotation Studies'})

    def createStudy(self, name, creatorUser, featureset, annotatorUsers,
                    images):
        Group = self.model('group')
        # this may raise a ValidationException if the name already exists
        studyFolder = self.createFolder(
            parent=self.loadStudyCollection(),
            name=name,
            description='',
            parentType='collection',
            public=False,
            creator=creatorUser,
            allowRename=False
        )
        # Clear all inherited accesses
        studyFolder = self.setAccessList(
            doc=studyFolder,
            access={},
            save=False)
        # Allow study admins to read
        studyFolder = self.setGroupAccess(
            doc=studyFolder,
            group=Group.findOne({'name': 'Study Administrators'}),
            level=AccessType.READ,
            save=False)

        # "setMetadata" will always save
        studyFolder = self.setMetadata(
            folder=studyFolder,
            metadata={
                'featuresetId': featureset['_id']
            }
        )

        for annotatorUser in annotatorUsers:
            studyFolder = self.addAnnotator(
                studyFolder, annotatorUser, creatorUser, images)

        return studyFolder

    def addAnnotator(self, study, annotatorUser, creatorUser,
                     images=None):
        Annotation = self.model('annotation', 'isic_archive')
        Group = self.model('group')
        if not images:
            images = self.getImages(study)

        if self.childAnnotations(
                study=study,
                annotatorUser=annotatorUser).count():
            raise ValidationException(
                'Annotator user is already part of the study.')

        # Allow annotator to read parent study
        study = self.setUserAccess(
            doc=study,
            user=annotatorUser,
            level=AccessType.READ,
            save=True)

        annotatorFolder = self.createFolder(
            parent=study,
            name='%(login)s (%(firstName)s %(lastName)s)' % annotatorUser,
            description='',
            parentType='folder',
            # Inherit public access state from parent
            public=None,
            creator=creatorUser
        )
        # Clear all inherited accesses
        annotatorFolder = self.setAccessList(
            doc=annotatorFolder,
            access={},
            save=False)
        # Allow study admins to read
        annotatorFolder = self.setGroupAccess(
            doc=annotatorFolder,
            group=Group.findOne({'name': 'Study Administrators'}),
            level=AccessType.READ,
            save=False)
        # Allow annotator to read
        annotatorFolder = self.setUserAccess(
            doc=annotatorFolder,
            user=annotatorUser,
            # TODO: make write?
            level=AccessType.READ,
            save=False)

        # "setMetadata" will always save
        self.setMetadata(
            folder=annotatorFolder,
            metadata={
                'userId': annotatorUser['_id']
            }
        )

        for image in images:
            Annotation.createAnnotation(
                study, image, creatorUser, annotatorFolder)

        # Since parent study could theoretically have changed, return it
        return study

    def addImage(self, study, image, creatorUser):
        Folder = self.model('folder')
        Annotation = self.model('annotation', 'isic_archive')
        for annotatorFolder in Folder.find({'parentId': study['_id']}):
            Annotation.createAnnotation(
                study, image, creatorUser, annotatorFolder)

    def getFeatureset(self, study):
        return self.model('featureset', 'isic_archive').load(
            study['meta']['featuresetId'], exc=True)

    def getAnnotators(self, study):
        Folder = self.model('folder')
        User = self.model('user', 'isic_archive')
        annotatorFolders = Folder.find({'parentId': study['_id']})
        return User.find({
            '_id': {'$in': annotatorFolders.distinct('meta.userId')}
        })

    def getImages(self, study, fields=None):
{'fraction_non_alphanumeric': 0.12180764354283645, 'fraction_numerical': 0.0009056330374932077, 'mean_word_length': 2.249852854620365, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5734699', 'n_tokens_mistral': 2872, 'n_tokens_neox': 2742, 'n_words': 743}