def insert_admin_account() -> None: """Insert default admin account.""" user_email = 'admin@medtagger' password = '******' password_hash = hash_password(password) with db_transaction_session() as session: user_exists = session.query( exists().where(User.email == user_email)).scalar() if user_exists: logger.warning('Admin user already exists with email "%s"', user_email) return role = Role.query.filter_by(name='admin').first() if not role: logger.error( 'Role not found! You have probably forgot to apply fixtures.') return user = User(user_email, password_hash, 'Admin', 'MedTagger') user.roles.append(role) session.add(user) logger.info('User added with email "%s" and password "%s"', user_email, password)
def update( task_key: str, name: str = None, image_path: str = None, # pylint: disable-msg=too-many-arguments datasets_keys: List[str] = None, description: str = None, label_examples: List[str] = None) -> Task: """Update Datasets where this Task will be available. :param task_key: key that will identify such Task :param name: (optional) new name for such Task :param image_path: (optional) new path to the image which shows on the UI :param description: (optional) Description of a given Task :param label_examples: (optional) List of paths to examples of labels for given Task :param datasets_keys: (optional) keys of Datasets which should have this Task """ with db_transaction_session() as session: task = Task.query.filter(Task.key == task_key).one() update_parameter_if_needed(task, 'name', name) update_parameter_if_needed(task, 'image_path', image_path) update_parameter_if_needed(task, 'description', description) update_parameter_if_needed(task, 'label_examples', label_examples) if datasets_keys: datasets = Dataset.query.filter( Dataset.key.in_(datasets_keys)).all() # type: ignore task.datasets = datasets session.add(task) return task
def add_task( key: str, name: str, image_path: str, datasets_keys: List[str], # pylint: disable-msg=too-many-arguments description: str, label_examples: List[str], tags: List[LabelTag]) -> Task: """Add new Task to the database. :param key: key that will identify such Task :param name: name that will be used in the Use Interface for such Task :param image_path: path to the image that represents such Task (used in User Interface) :param datasets_keys: Keys of Datasets that Task takes Scans from :param description: Description of a given Task :param label_examples: List of paths to examples of labels for given Task :param tags: Label Tags that will be created and assigned to Task :return: Task object """ with db_transaction_session() as session: task = Task(key, name, image_path) datasets = Dataset.query.filter( Dataset.key.in_(datasets_keys)).all() # type: ignore task.datasets = datasets task.label_examples = label_examples task.available_tags = tags task.description = description session.add(task) return task
def disable(task_key: str) -> None: """Disable existing Task.""" with db_transaction_session(): disabling_query = Task.query.filter(Task.key == task_key) updated = disabling_query.update({'disabled': True}, synchronize_session='fetch') if not updated: raise InternalErrorException(f'Task "{task_key}" was not disabled due to unknown database error.')
def add_new_user(new_user: User) -> int: """Add new user. :return: id of the new user """ with db_transaction_session() as session: session.add(new_user) return new_user.id
def unassign_label_tag(tag: LabelTag, task_key: str) -> None: """Unassign Label Tag from Task. :param tag: tag that should be unassigned from Task :param task_key: key that will identify such Task """ with db_transaction_session() as session: task = Task.query.filter(Task.key == task_key).one() task.available_tags.remove(tag) session.add(task)
def assign_label_tag(tag: LabelTag, task_key: str) -> None: """Assign existing Label Tag to Task. :param tag: tag that should be assigned to Task :param task_key: key that will identify such Task """ with db_transaction_session() as session: task = Task.query.filter(Task.key == task_key).one() task.available_tags.append(tag) session.add(task)
def add_new_dataset(key: str, name: str) -> Dataset: """Add new Dataset to the database. :param key: key that will identify such Dataset :param name: name that will be used in the Use Interface for such Dataset :return: Dataset object """ dataset = Dataset(key, name) with db_transaction_session() as session: session.add(dataset) return dataset
def increase_skip_count_of_a_scan(scan_id: ScanID) -> bool: """Increase skip_count of a Scan with given scan_id. :param scan_id: ID of a Scan which skip_count should be increased :return: boolean information whether the Scan was skipped or not """ with db_transaction_session() as session: query = session.query(Scan) query = query.filter(Scan.id == scan_id) updated = query.update({'skip_count': Scan.skip_count + 1}) return bool(updated)
def add_slice( self, orientation: SliceOrientation = SliceOrientation.Z) -> 'Slice': """Add new slice into this Scan. :return: ID of a Slice """ new_slice = Slice(orientation) new_slice.scan = self with db_transaction_session() as session: session.add(new_slice) return new_slice
def delete_slice(_slice: db_models.Slice) -> None: """Remove Slice from SQL database and Storage.""" slice_id = _slice.id scan_id = _slice.scan_id with db_transaction_session() as session: query = session.query(db_models.Scan).filter(db_models.Scan.id == scan_id) query.update({'declared_number_of_slices': db_models.Scan.declared_number_of_slices - 1}) session.query(db_models.Slice).filter(db_models.Slice.id == slice_id).delete() OriginalSlice.filter(id=slice_id).delete() ProcessedSlice.filter(id=slice_id).delete()
def set_user_role(user_id: int, role_name: str) -> None: """Set user's role. Old role will be replaced.""" try: user = UsersRepository.get_user_by_id(user_id) except NoResultFound: raise InvalidArgumentsException('User with this id does not exist.') try: role = get_role_with_name(role_name) except NoResultFound: raise InvalidArgumentsException('Role with this name does not exist.') with db_transaction_session() as session: user.roles = [role] session.add(user)
def add_new_scan(dataset: Dataset, number_of_slices: int, user: User = None) -> Scan: """Add new Scan to the database. :param dataset: Dataset object :param number_of_slices: number of Slices that will be uploaded :param user: (optional) User that uploaded scan :return: Scan object """ scan = Scan(dataset, number_of_slices, user) with db_transaction_session() as session: session.add(scan) return scan
def add_new_tag(key: str, name: str, tools: List[LabelTool], task_id: TaskID) -> LabelTag: """Add new Label Tag to the database. :param key: key that will identify such Label Tag :param name: name that will be used in the User Interface for such Label Tag :param tools: list of tools for given LabelTag that will be available on labeling page :param task_id: id of Task that owns this Label Tag :return: Label Tag object """ label_tag = LabelTag(key, name, tools) label_tag.task_id = task_id with db_transaction_session() as session: session.add(label_tag) return label_tag
def add_new_point_label_element(label_id: LabelID, position: LabelPosition, label_tag: LabelTag) -> LabelElementID: """Add new Point Element for given Label. :param label_id: Label's ID :param position: position (x, y, slice_index) of the Label :param label_tag: Label Tag object :return: ID of a Element """ point_label_element = PointLabelElement(position, label_tag) point_label_element.label_id = label_id with db_transaction_session() as session: session.add(point_label_element) return point_label_element.id
def add_action_response(action_id: ActionID, response: Dict) -> ActionResponse: """Add response for given Action.""" action = Action.query.filter(Action.id == action_id).one() if action.action_type == 'Survey': valid = action.validate_response(response) if not valid: raise InvalidResponseException( 'Your answers does not match keys in Survey.') with db_transaction_session() as session: survey_id = cast(SurveyID, action_id) action_response = SurveyResponse(survey_id, response) session.add(action_response) else: raise UnsupportedActionException( 'Action does not support returning Respose.') return action_response
def _clear_databases() -> None: logger.info('Removing all data from PostgreSQL.') with db_transaction_session() as sess: for table in reversed(Base.metadata.sorted_tables): sess.execute( 'TRUNCATE TABLE "{}" RESTART IDENTITY CASCADE;'.format( table.name)) Session.close_all() logger.info('Removing all data from Cassandra.') storage_session = storage.create_session() storage_session.set_keyspace(storage.MEDTAGGER_KEYSPACE) for model_name in dir(models): model = getattr(models, model_name) if issubclass(model.__class__, ModelMetaClass) and model.__table_name__: storage_session.execute('TRUNCATE {}'.format(model.__table_name__))
def add_task(key: str, name: str, image_path: str, datasets_keys: List[str], tags: List[LabelTag]) -> Task: """Add new Task to the database. :param key: key that will identify such Task :param name: name that will be used in the Use Interface for such Task :param image_path: path to the image that represents such Task (used in User Interface) :param datasets_keys: Keys of Datasets that Task takes Scans from :param tags: Label Tags that will be created and assigned to Task :return: Task object """ with db_transaction_session() as session: task = Task(key, name, image_path) datasets = Dataset.query.filter(Dataset.key.in_(datasets_keys)).all() # type: ignore task.datasets = datasets task.available_tags = tags session.add(task) return task
def add_new_rectangular_label_element(label_id: LabelID, position: LabelPosition, shape: LabelShape, label_tag: LabelTag) -> LabelElementID: """Add new Rectangular Element for given Label. :param label_id: Label's ID :param position: position (x, y, slice_index) of the Label :param shape: shape (width, height) of the Label :param label_tag: Label Tag object :return: ID of a Element """ rectangular_label_element = RectangularLabelElement( position, shape, label_tag) rectangular_label_element.label_id = label_id with db_transaction_session() as session: session.add(rectangular_label_element) return rectangular_label_element.id
def update(task_key: str, name: str = None, image_path: str = None, datasets_keys: List[str] = None) -> Task: """Update Datasets where this Task will be available. :param task_key: key that will identify such Task :param name: (optional) new name for such Task :param image_path: (optional) new path to the image which shows on the UI :param datasets_keys: (optional) keys of Datasets which should have this Task """ with db_transaction_session() as session: task = Task.query.filter(Task.key == task_key).one() if name: task.name = name if image_path: task.image_path = image_path if datasets_keys: datasets = Dataset.query.filter(Dataset.key.in_(datasets_keys)).all() # type: ignore task.datasets = datasets session.add(task) return task
def add_new_brush_label_element(label_id: LabelID, slice_index: int, width: int, height: int, image: bytes, label_tag: LabelTag) -> LabelElementID: """Add new Brush Element for given Label. :param label_id: Label's ID :param slice_index: index of Slice :param width: width of the Label's image :param height: height of the Label's image :param image: bytes with image representation of a binary mask :param label_tag: Label Tag object :return: ID of a Element """ # pylint: disable=too-many-arguments brush_label_element = BrushLabelElement(slice_index, width, height, label_tag) brush_label_element.label_id = label_id with db_transaction_session() as session: session.add(brush_label_element) BrushLabelElementStorage.create(id=brush_label_element.id, image=image) return brush_label_element.id
def update(key: str, name: str = None, tools: List[LabelTool] = None, task_id: TaskID = None) -> LabelTag: """Update Tools that are available in Label Tag. :param key: key that will identify such Label Tag :param name: (optional) new name for such Label Tag :param tools: (optional) list of tools for given LabelTag that will be available on labeling page :param task_id: (optional) Task ID for another Task which should be linked to this Label Tag :return: Label Tag object """ label_tag = get_label_tag_by_key(key) if name: label_tag.name = name if tools: label_tag.tools = tools if task_id: label_tag.task_id = task_id with db_transaction_session() as session: session.add(label_tag) return label_tag
def add_new_label(scan_id: ScanID, task_key: str, user: User, labeling_time: LabelingTime, comment: str = None, is_predefined: bool = False) -> Label: """Add new Label for given Scan. :param scan_id: Scan ID for which Label has been created :param task_key: Task Key for which Label has been created :param user: User object that created this Label :param labeling_time: time needed to create this Label on Labeling Page :param comment: (optional) comment for this Label :param is_predefined: (optional) mark this Label as predefined :return: Label object """ label = Label(user, labeling_time, comment, is_predefined) label.scan_id = scan_id label.task = Task.query.filter(Task.key == task_key).one() with db_transaction_session() as session: session.add(label) return label
def add_new_chain_label_element(label_id: LabelID, slice_index: int, label_tag: LabelTag, points: List[Point], loop: bool) -> LabelElementID: """Add new Chain Element for given Label. :param label_id: Label's ID :param slice_index: Slice's index :param label_tag: Label Tag object :param points: array of points where points with consecutive indices are connected :param loop: true if first and last points are connected :return: ID of a Element """ chain_label_element = ChainLabelElement(slice_index, label_tag, loop) chain_label_element.label_id = label_id with db_transaction_session() as session: session.add(chain_label_element) for order, point in enumerate(points): chain_label_element_point = ChainLabelElementPoint( point.x, point.y, chain_label_element.id, order) session.add(chain_label_element_point) return chain_label_element.id
def try_to_mark_scan_as_stored(scan_id: ScanID) -> bool: """Mark Scan as STORED only if all Slices were STORED. :param scan_id: ID of a Scan which should be tried to mark as STORED :return: boolean information if Scan was marked or not """ with db_transaction_session() as session: stored_slices_subquery = session.query( func.count(Slice.id).label('count')) stored_slices_subquery = stored_slices_subquery.filter( Slice.scan_id == scan_id) stored_slices_subquery = stored_slices_subquery.filter( Slice.status == SliceStatus.STORED) stored_slices_subquery = stored_slices_subquery.subquery() query = session.query(Scan) query = query.filter(Scan.id == scan_id) query = query.filter(Scan.status != ScanStatus.STORED) query = query.filter( Scan.declared_number_of_slices == stored_slices_subquery.c.count) updated = query.update({'status': ScanStatus.STORED}, synchronize_session=False) return bool(updated)
def add_role(role_name: str) -> Role: """Add new Role to the database.""" role = Role(name=role_name) with db_transaction_session() as session: session.add(role) return role
def delete_tag_by_key(key: str) -> None: """Remove Label Tag from database.""" with db_transaction_session() as session: session.query(LabelTag).filter(LabelTag.key == key).delete()
def set_user_settings(user: User, name: str, value: object) -> None: """Set user's settings parameter of specified name to provided value.""" with db_transaction_session() as session: setattr(user.settings, name, value) session.add(user.settings)
def set_user_info(user: User, first_name: str, last_name: str) -> None: """Set user's info.""" with db_transaction_session() as session: user.first_name = first_name user.last_name = last_name session.add(user)
def delete_scan_by_id(scan_id: ScanID) -> None: """Remove Scan from SQL database.""" with db_connection_session() as session: scan = session.query(Scan).filter(Scan.id == scan_id).one() with db_transaction_session() as session: session.delete(scan)