Exemplo n.º 1
0
    def on_any_event(self, event):

        path = event.dest_path if event.event_type == "moved" else event.src_path

        if (event.is_directory
                # check if its a hidden file
                or bool(re.search(r'\/\..*?\/', path)) or
                not path.lower().endswith(self.pattern)):
            return

        self._log(f'File {path} for {event.event_type}')

        image = ImageModel.objects(path=event.src_path).first()

        if image is None and event.event_type != 'deleted':
            self._log(f'Adding new file to database: {path}')
            ImageModel.create_from_path(path).save()

        elif event.event_type == 'moved':
            self._log(f'Moving image from {event.src_path} to {path}')
            image.update(path=path)

        elif event.event_type == 'deleted':
            self._log(f'Deleting image from database {path}')
            ImageModel.objects(path=path).delete()
Exemplo n.º 2
0
    def get(self, image_id):
        """ Called when loading from the annotator client """
        image = ImageModel.objects(id=image_id)\
            .exclude('events').first()

        if image is None:
            return {'success': False, 'message': 'Could not load image'}, 400

        dataset = current_user.datasets.filter(id=image.dataset_id).first()
        if dataset is None:
            return {
                'success': False,
                'message': 'Could not find associated dataset'
            }, 400

        categories = CategoryModel.objects(deleted=False)\
            .in_bulk(dataset.categories).items()

        # Get next and previous image
        images = ImageModel.objects(dataset_id=dataset.id, deleted=False)
        pre = images.filter(
            file_name__lt=image.file_name).order_by('-file_name').first()
        nex = images.filter(
            file_name__gt=image.file_name).order_by('file_name').first()

        preferences = {}
        if not Config.LOGIN_DISABLED:
            preferences = current_user.preferences

        # Generate data about the image to return to client
        data = {
            'image': query_util.fix_ids(image),
            'categories': [],
            'dataset': query_util.fix_ids(dataset),
            'preferences': preferences,
            'permissions': {
                'dataset': dataset.permissions(current_user),
                'image': image.permissions(current_user)
            }
        }

        data['image']['previous'] = pre.id if pre else None
        data['image']['next'] = nex.id if nex else None

        for category in categories:
            category = query_util.fix_ids(category[1])

            category_id = category.get('id')
            annotations = AnnotationModel.objects(image_id=image_id, category_id=category_id, deleted=False)\
                .exclude('events').all()

            category['show'] = True
            category['visualize'] = False
            category[
                'annotations'] = [] if annotations is None else query_util.fix_ids(
                    annotations)
            data.get('categories').append(category)

        return data
Exemplo n.º 3
0
    def get(self, dataset_id):
        args = dataset_generate.parse_args()
        dataset = current_user.datasets.filter(id=dataset_id,
                                               deleted=False).first()
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        AnnotationModel.objects(dataset_id=dataset.id).delete()
        ImageModel.objects(dataset_id=dataset.id).update(
            set__annotated=False, set__num_annotations=0)
        return {'success': True}
Exemplo n.º 4
0
    def get(self, dataset_id):
        """ All users in the dataset """
        args = dataset_generate.parse_args()

        dataset = current_user.find_exist_dataset_by_id(dataset_id)
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        AnnotationModel.objects(dataset_id=dataset.id)\
            .update(metadata=dataset.default_annotation_metadata)
        ImageModel.objects(dataset_id=dataset.id)\
            .update(metadata={})

        return {'success': True}
Exemplo n.º 5
0
    def get(self, dataset_id):
        """ All users in the dataset """
        args = dataset_generate.parse_args()

        dataset = current_user.datasets.filter(id=dataset_id,
                                               deleted=False).first()
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        AnnotationModel.objects(dataset_id=dataset.id).update(
            metadata=dataset.default_annotation_metadata)
        ImageModel.objects(dataset_id=dataset.id).update(metadata={})

        return {'success': True}
Exemplo n.º 6
0
def scan_dataset(task_id, dataset_id):

    task = TaskModel.objects.get(id=task_id)
    dataset = DatasetModel.objects.get(id=dataset_id)

    task.update(status="PROGRESS")
    socket = create_socket()

    directory = dataset.directory
    toplevel = list(os.listdir(directory))
    task.info(f"Scanning {directory}")

    count = 0
    for root, dirs, files in os.walk(directory):

        try:
            youarehere = toplevel.index(root.split('/')[-1])
            progress = int(((youarehere) / len(toplevel)) * 100)
            task.set_progress(progress, socket=socket)
        except:
            pass

        if root.split('/')[-1].startswith('.'):
            continue

        for file in files:
            path = os.path.join(root, file)

            if path.endswith(ImageModel.PATTERN):
                db_image = ImageModel.objects(path=path).first()

                if db_image is not None:
                    continue

                try:
                    ImageModel.create_from_path(path, dataset.id).save()
                    count += 1
                    task.info(f"New file found: {path}")
                except:
                    task.warning(f"Could not read {path}")

    [
        thumbnail_generate_single_image.delay(image.id)
        for image in ImageModel.objects(regenerate_thumbnail=True).all()
    ]

    task.info(f"Created {count} new image(s)")
    task.set_progress(100, socket=socket)
Exemplo n.º 7
0
    def get(self):
        """ Endpoint called by dataset viewer client """

        args = page_data.parse_args()
        limit = args['limit']
        page = args['page']
        folder = args['folder']

        datasets = current_user.datasets.filter(deleted=False)
        pagination = Pagination(datasets.count(), limit, page)
        datasets = datasets[pagination.start:pagination.end]

        datasets_json = []
        for dataset in datasets:
            dataset_json = query_util.fix_ids(dataset)
            images = ImageModel.objects(dataset_id=dataset.id, deleted=False)

            dataset_json['numberImages'] = images.count()
            dataset_json['numberAnnotated'] = images.filter(annotated=True).count()
            dataset_json['permissions'] = dataset.permissions(current_user)
            
            first = images.first()
            if first is not None:
                dataset_json['first_image_id'] = images.first().id
            datasets_json.append(dataset_json)

        return {
            "pagination": pagination.export(),
            "folder": folder,
            "datasets": datasets_json,
            "categories": query_util.fix_ids(current_user.categories.filter(deleted=False).all())
        }
Exemplo n.º 8
0
    def get(self, category_id):
        """"Endpoint called by category image list """
        args = page_data.parse_args()
        limit = args['limit']
        page = args['page']

        category = current_user.categories.filter(id=category_id).first()

        # check if the id exits
        if category is None:
            return {"message": "Invalid category id"}, 400

        image_ids = AnnotationModel.objects(category_id=category_id).distinct('image_id')
        image_ids.sort()

        pagination = Pagination(len(image_ids), limit, page)
        image_ids = image_ids[pagination.start:pagination.end]

        images = []
        for image_id in image_ids:
          img = ImageModel.objects(id=image_id, annotated=True).first()
          if img:
            images.append(query_util.fix_ids(img))

        return {
          "category": query_util.fix_ids(category),
          "pagination": pagination.export(),
          "page": page,
          "images": images,
        }
Exemplo n.º 9
0
    def get(self, dataset_id):
        """ All users in the dataset """
        args = dataset_generate.parse_args()

        dataset = current_user.datasets.filter(id=dataset_id,
                                               deleted=False).first()
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        images = ImageModel.objects(dataset_id=dataset.id, deleted=False)
        annotated_images = images.filter(annotated=True)
        annotations = AnnotationModel.objects(dataset_id=dataset_id,
                                              deleted=False)

        # Calculate annotation counts by category in this dataset
        category_count = dict()
        image_category_count = dict()
        for category in dataset.categories:

            # Calculate the annotation count in the current category in this dataset
            cat_name = CategoryModel.objects(id=category).first()['name']
            cat_count = AnnotationModel.objects(dataset_id=dataset_id,
                                                category_id=category,
                                                deleted=False).count()
            category_count.update({str(cat_name): cat_count})

            # Calculate the annotated images count in the current category in this dataset
            image_count = len(
                AnnotationModel.objects(dataset_id=dataset_id,
                                        category_id=category,
                                        deleted=False).distinct('image_id'))
            image_category_count.update({str(cat_name): image_count})

        stats = {
            'total': {
                'Users': dataset.get_users().count(),
                'Images': images.count(),
                'Annotated Images': annotated_images.count(),
                'Annotations': annotations.count(),
                'Categories': len(dataset.categories),
                'Time Annotating (s)': (images.sum('milliseconds') or 0) / 1000
            },
            'average': {
                'Image Size (px)':
                images.average('width'),
                'Image Height (px)':
                images.average('height'),
                'Annotation Area (px)':
                annotations.average('area'),
                'Time (ms) per Image':
                images.average('milliseconds') or 0,
                'Time (ms) per Annotation':
                annotations.average('milliseconds') or 0
            },
            'categories': category_count,
            'images_per_category': image_category_count
        }
        return stats
Exemplo n.º 10
0
    def post(self, image_id):
        """ COCO data test """

        image_model = ImageModel.objects(id=image_id).first()
        image_model.update(superpixel_generated=False)

        reload(image_model.path_original, image_model.path)

        return {"success": True}
Exemplo n.º 11
0
def generate_thumbnails():
    PREFIX = "[Thumbnails]"
    print(
        f'{PREFIX} Sending request for regenerating images with non actual thumbnails',
        flush=True)
    [
        generate_thumbnail(image)
        for image in ImageModel.objects(regenerate_thumbnail=True).all()
    ]
Exemplo n.º 12
0
 def create_image_by_path(self, path):
     if path.endswith(ImageModel.PATTERN):
         db_image = ImageModel.objects(path=path).first()
         if db_image is not None:
             raise ValueError('Image Should Not Exist In This Path: ' + path)
         
         try:
             ImageModel.create_from_path(path, self.dataset.id).save()
         except:
             raise ValueError('Create Image Failed Given Path: ' + path + ', Dataset Id: ' + int(self.dataset.id))
Exemplo n.º 13
0
    def get(self, dataset_id):
        """ All users in the dataset """

        dataset = current_user.datasets.filter(id=dataset_id,
                                               deleted=False).first()
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        images = ImageModel.objects(dataset_id=dataset.id, deleted=False)
        num_images_cs_not_annotated = len(
            ImageModel.objects(dataset_id=dataset.id,
                               cs_annotated=[],
                               deleted=False))

        cs_stats = {
            'total': {
                'Images': images.count(),
                'CS Annotated Images': num_images_cs_not_annotated,
            }
        }
        return cs_stats
Exemplo n.º 14
0
    def post(self, image_id):
        """ COCO data test """
        print("in real metric lol prposal")

        image_model = ImageModel.objects(id=image_id).first()
        if not image_model:
            return {"message": "Invalid image ID"}, 400

        metric(image_model.path_mask, image_model.path,
               image_model.path_original, image_id)

        return {"success": True}
Exemplo n.º 15
0
def create_image_by_path(path):
    created_image_size = 0
    if path.endswith(ImageModel.PATTERN):
        db_image = ImageModel.objects(path=path).first()
        if db_image is not None:
            return 0
        try:
            ImageModel.create_from_path(path, dataset.id).save()
            created_image_size += 1
            task.info(f"New file found: {path}")
        except:
            task.warning(f"Could not read {path}")
    return created_image_size
 def to_datasets_json(self, datasets, current_user):
     datasets_json = []
     for dataset in datasets:
         dataset_json = self.fix_ids(dataset)
         images = ImageModel.objects(dataset_id=dataset.id, deleted=False)
         dataset_json['numberImages'] = images.count()
         dataset_json['numberAnnotated'] = images.filter(
             annotated=True).count()
         dataset_json['permissions'] = dataset.permissions(current_user)
         first = images.first()
         if first is not None:
             dataset_json['first_image_id'] = images.first().id
         datasets_json.append(dataset_json)
     return datasets_json
Exemplo n.º 17
0
    def on_any_event(self, event):
        print("hello")
        path = event.dest_path if event.event_type == "moved" else event.src_path

        if event.is_directory:
            # Listen to directory events as some file systems don't generate
            # per-file `deleted` events when moving/deleting directories
            if event.event_type == 'deleted':
                self._log(f'Deleting images from database {path}')
                ImageModel.objects(path=re.compile('^' +
                                                   re.escape(path))).delete()
            return

        if (
                # check if its a hidden file
                bool(re.search(r'\/\..*?\/', path))
                or not path.lower().endswith(self.pattern)):
            return

        self._log(f'File {path} for {event.event_type}')

        image = ImageModel.objects(path=event.src_path).first()

        if image is None and event.event_type != 'deleted':
            self._log(f'Adding new file to database: {path}')
            image = ImageModel.create_from_path(path).save()

            #generate_thumbnail(image)

        elif event.event_type == 'moved':
            self._log(f'Moving image from {event.src_path} to {path}')
            image.update(path=path)
            #generate_thumbnail(image)

        elif event.event_type == 'deleted':
            self._log(f'Deleting image from database {path}')
            ImageModel.objects(path=path).delete()
Exemplo n.º 18
0
    def post(self, image_id):
        """ COCO data test """
        print("WTF")
        if not SUPER_LOADED:
            print("SSN not loaded")
            return {"disabled": True, "message": "DEXTR is disabled"}, 400

        image_model = ImageModel.objects(id=image_id).first()
        if not image_model:
            return {"message": "Invalid image ID"}, 400

        save(image_model.path_mask, image_model.path,
             image_model.path_original, image_id)

        return {"success": True}
Exemplo n.º 19
0
    def post(self, image_id):
        """ COCO data test """
        print("WTF")

        image_model = ImageModel.objects(id=image_id).first()
        if not image_model:
            return {"message": "Invalid image ID"}, 400

        path, path_mask, path_original, path_super_original = main(
            image_model.path, image_model.path_original)
        image_model.update(path_original=path_original)
        image_model.update(path_mask=path_mask)
        image_model.update(path=path)
        image_model.update(path_super_original=path_super_original)
        image_model.update(superpixel_generated=True)

        return {"success": True}
Exemplo n.º 20
0
    def post(self, image_id):
        """ COCO data test """
        print("WTF")
        if not SUPER_LOADED:
            print("SSN not loaded")
            return {"disabled": True, "message": "DEXTR is disabled"}, 400

        print("hannah du geiles super stücki")

        image_model = ImageModel.objects(id=image_id).first()
        if not image_model:
            return {"message": "Invalid image ID"}, 400

        image = Image.open(image_model.path)
        result = superpixel.predict_mask(image)

        main()

        return {"segmentaiton": Mask(result).polygons().segmentation}
Exemplo n.º 21
0
    def post(self, image_id):
        """ COCO data test """
        args = dextr_args.parse_args()
        points = args.get('points')
        classcolor = args.get('classcolor')
        print(classcolor)

        print("in super_model")
        image_model = ImageModel.objects(id=image_id).first()
        if not image_model:
            return {"message": "Invalid image ID"}, 400

        #image = Image.open(image_model.path)

        colorize(classcolor, points, image_model.path_original,
                 image_model.path)
        #image_model.update(path_mask=path_mask)

        return {"success": True}
Exemplo n.º 22
0
    def post(self, image_id):
        """ COCO data test """
        print("Origin Model")

        image_model = ImageModel.objects(id=image_id).first()
        if not image_model:
            return {"message": "Invalid image ID"}, 400

        #image = Image.open(image_model.path)
        annotations = AnnotationModel.objects(image_id=image_id)

        for annotation in annotations:

            for segmentation in annotation.segmentation:
                print(segmentation)
                origin(image_model.path, segmentation)

        AnnotationModel.objects(image_id=image_id).delete()

        return {"success": True}
Exemplo n.º 23
0
    def get(self, dataset_id):

        # args = dataset_refresh.parse_args()
        # dataset_id = args['dataset_id']

        images = ImageModel.objects(dataset_id=dataset_id)
        image_refresh_count = 0
        image_annotated_count = 0
        image_count = images.count()
        image_json = query_util.fix_ids(images)
        for image in images:
            if image.cs_annotated != []:
                image_annotated_count += 1
            else:
                image.update(set__cs_annotating=False, set__cs_annotated=[])
                image_refresh_count += 1
        return {
            'image_refresh_count': image_refresh_count,
            'total_image_count': image_count,
            'images': image_json
        }
Exemplo n.º 24
0
    def post(self, image_id):
        """ COCO data test """
        print("Converter Model")

        image_model = ImageModel.objects(id=image_id).first()
        if not image_model:
            return {"message": "Invalid image ID"}, 400

        #image = Image.open(image_model.path)
        annotations = AnnotationModel.objects(image_id=image_id)

        for annotation in annotations:
            category_id = annotation.category_id
            category = CategoryModel.objects(id=category_id).first()

            for segmentation in annotation.segmentation:
                print(segmentation)
                convert(image_model.path, segmentation, category.color)

        AnnotationModel.objects(image_id=image_id).delete()

        return {"success": True}
Exemplo n.º 25
0
    def post(self, image_id):
        """ COCO data test """

        if not DEXTR_LOADED:
            return {"disabled": True, "message": "DEXTR is disabled"}, 400

        args = dextr_args.parse_args()
        points = args.get('points')
        # padding = args.get('padding')
        # threshold = args.get('threshold')

        if len(points) != 4:
            return {"message": "Invalid points entered"}, 400

        image_model = ImageModel.objects(id=image_id).first()
        if not image_model:
            return {"message": "Invalid image ID"}, 400

        image = Image.open(image_model.path)
        result = dextr.predict_mask(image, points)

        return {"segmentaiton": Mask(result).polygons().segmentation}
Exemplo n.º 26
0
    def post(self):
        """ Creates an annotation """
        args = create_annotation.parse_args()
        image_id = args.get('image_id')
        category_id = args.get('category_id')
        isbbox = args.get('isbbox')
        metadata = args.get('metadata', {})
        segmentation = args.get('segmentation', [])
        bbox = args.get('bbox', [])
        keypoints = args.get('keypoints', [])

        # change appro after setting login_user
        # image = current_user.images.filter(id=image_id, deleted=False).first()
        # image = ImageModel.objects.get(id=image_id, deleted=False).first()
        image = ImageModel.objects(id=image_id).first()
        if image is None:
            return {"message": "Invalid image id"}, 400

        logger.info(
            f'{current_user.username} has created an annotation for image {image_id} with {isbbox}'
        )
        logger.info(
            f'{current_user.username} has created an annotation for image {image_id}'
        )

        # add condition if user is not authenticed or dataset is public
        try:
            annotation = AnnotationModel(image_id=image_id,
                                         category_id=category_id,
                                         metadata=metadata,
                                         segmentation=segmentation,
                                         bbox=bbox,
                                         keypoints=keypoints,
                                         isbbox=isbbox)
            annotation.save()
        except (ValueError, TypeError) as e:
            return {'message': str(e)}, 400

        return query_util.fix_ids(annotation)
Exemplo n.º 27
0
def disconnect():
    if current_user.is_authenticated:
        logger.info(
            f'Socket connection has been disconnected with {current_user.username}'
        )
        image_id = session.get('annotating')

        # Remove user from room
        if image_id is not None:
            image = ImageModel.objects(id=image_id).first()
            if image is not None:
                start = session.get('annotating_time', time.time())
                event = SessionEvent.create(start, current_user)

                image.add_event(event)
                image.update(pull__annotating=current_user.username)
                emit('annotating', {
                    'image_id': image_id,
                    'active': False,
                    'username': current_user.username
                },
                     broadcast=True,
                     include_self=False)
Exemplo n.º 28
0
    def get(self, image_id):
        """ Called when loading from the annotator client """
        image = ImageModel.objects(id=image_id)\
            .exclude('events').first()

        if image is None:
            return {'success': False, 'message': 'Could not load image'}, 400

        dataset = current_user.datasets.filter(id=image.dataset_id).first()
        if dataset is None:
            return {
                'success': False,
                'message': 'Could not find associated dataset'
            }, 400

        categories = CategoryModel.objects(deleted=False)\
            .in_bulk(dataset.categories).items()

        # Generate data about the image to return to client
        data = {'categories': []}

        for category in categories:
            category = query_util.fix_ids(category[1])

            category_id = category.get('id')
            annotations = AnnotationModel.objects(image_id=image_id, category_id=category_id, deleted=False)\
                .exclude('events').all()

            category['show'] = True
            category['visualize'] = False
            category[
                'annotations'] = [] if annotations is None else query_util.fix_ids(
                    annotations)
            data.get('categories').append(category)

        return data
Exemplo n.º 29
0
    def get(self, dataset_id):
        """ All users in the dataset """
        args = dataset_generate.parse_args()

        dataset = current_user.datasets.filter(id=dataset_id,
                                               deleted=False).first()
        if dataset is None:
            return {"message": "Invalid dataset id"}, 400

        images = ImageModel.objects(dataset_id=dataset.id, deleted=False)
        annotated_images = images.filter(annotated=True)
        annotations = AnnotationModel.objects(dataset_id=dataset_id,
                                              deleted=False)
        stats = {
            'total': {
                'Users': dataset.get_users().count(),
                'Images': images.count(),
                'Annotated Images': annotated_images.count(),
                'Annotations': annotations.count(),
                'Categories': len(dataset.categories),
                'Time Annotating (s)': (images.sum('milliseconds') or 0) / 1000
            },
            'average': {
                'Image Size (px)':
                images.average('width'),
                'Image Height (px)':
                images.average('height'),
                'Annotation Area (px)':
                annotations.average('area'),
                'Time (ms) per Image':
                images.average('milliseconds') or 0,
                'Time (ms) per Annotation':
                annotations.average('milliseconds') or 0
            }
        }
        return stats
Exemplo n.º 30
0
    def post(self):
        """
        Called when saving data from the annotator client
        """
        data = request.get_json(force=True)
        image = data.get('image')
        dataset = data.get('dataset')
        image_id = image.get('id')

        image_model = ImageModel.objects(id=image_id).first()

        if image_model is None:
            return {'success': False, 'message': 'Image does not exist'}, 400

        # Check if current user can access dataset
        db_dataset = current_user.datasets.filter(
            id=image_model.dataset_id).first()
        if dataset is None:
            return {
                'success': False,
                'message': 'Could not find associated dataset'
            }

        db_dataset.update(annotate_url=dataset.get('annotate_url', ''))

        categories = CategoryModel.objects.all()
        annotations = AnnotationModel.objects(image_id=image_id)

        current_user.update(preferences=data.get('user', {}))

        annotated = False
        # Iterate every category passed in the data
        for category in data.get('categories', []):
            category_id = category.get('id')

            # Find corresponding category object in the database
            db_category = categories.filter(id=category_id).first()
            if db_category is None:
                continue

            category_update = {'color': category.get('color')}
            if current_user.can_edit(db_category):
                category_update['keypoint_edges'] = category.get(
                    'keypoint_edges', [])
                category_update['keypoint_labels'] = category.get(
                    'keypoint_labels', [])

            db_category.update(**category_update)

            # Iterate every annotation from the data annotations
            for annotation in category.get('annotations', []):

                # Find corresponding annotation object in database
                annotation_id = annotation.get('id')
                db_annotation = annotations.filter(id=annotation_id).first()

                if db_annotation is None:
                    continue

                # Paperjs objects are complex, so they will not always be passed. Therefor we update
                # the annotation twice, checking if the paperjs exists.

                # Update annotation in database
                sessions = []
                total_time = 0
                for session in annotation.get('sessions', []):
                    date = datetime.datetime.fromtimestamp(
                        int(session.get('start')) / 1e3)
                    model = SessionEvent(
                        user=current_user.username,
                        created_at=date,
                        milliseconds=session.get('milliseconds'),
                        tools_used=session.get('tools'))
                    total_time += session.get('milliseconds')
                    sessions.append(model)

                db_annotation.update(add_to_set__events=sessions,
                                     inc__milliseconds=total_time,
                                     set__keypoints=annotation.get(
                                         'keypoints', []),
                                     set__metadata=annotation.get('metadata'),
                                     set__color=annotation.get('color'))

                paperjs_object = annotation.get('compoundPath', [])

                # Update paperjs if it exists
                if len(paperjs_object) == 2:

                    width = db_annotation.width
                    height = db_annotation.height

                    # Generate coco formatted segmentation data
                    segmentation, area, bbox = coco_util.\
                        paperjs_to_coco(width, height, paperjs_object)

                    db_annotation.update(
                        set__segmentation=segmentation,
                        set__area=area,
                        set__bbox=bbox,
                        set__paper_object=paperjs_object,
                    )

                    if area > 0:
                        annotated = True

        image_model.update(set__metadata=image.get('metadata', {}),
                           set__annotated=annotated,
                           set__category_ids=image.get('category_ids', []),
                           set__regenerate_thumbnail=annotated)

        return {"success": True}