<commit_before>"""Create a montage image for a single mole from a rotomap."""

import cv2

import mel.lib.common
import mel.lib.image
import mel.rotomap.moles
import mel.cmd.error


def setup_parser(parser):

    parser.add_argument(
        'ROTOMAP',
        type=mel.rotomap.moles.make_argparse_rotomap_directory,
        help="Path to the rotomap to copy from.")

    parser.add_argument(
        'UUID',
        type=str,
        help="Unique id of the mole to copy.")

    parser.add_argument(
        'OUTPUT',
        type=str,
        help="Name of the image to write.")

    parser.add_argument(
        '--rot90',
        type=int,
        default=0,
        help="Rotate images 90 degrees clockwise this number of times.")


def process_args(args):
    mel.lib.common.write_image(
        args.OUTPUT,
        make_montage_image(args.ROTOMAP, args.UUID, args.rot90))


def make_montage_image(rotomap, uuid_, rot90=0):

    path_moles_list = []

    radius = 10
    montage_height = 1024

    for imagepath, moles in rotomap.yield_mole_lists():
        for m in moles:
            if m['uuid'] == uuid_:
                path_moles_list.append((imagepath, moles))

    if not path_moles_list:
        raise mel.cmd.error.UsageError(
            'UUID "{}" not found in rotomap "{}".'.format(
                uuid_, rotomap.path))

    # Pick 'best' image for this particular mole, assuming that the middle
    # image is where the mole is most prominent. This assumption is based on
    # the idea that the images represent a rotation around the subject, the
    # 'middle' image should be where the mole is most centered.
    #
    # TODO: Cater for the case where the image set represents a complete
    # rotation around the subject, and therefore the ends meet. e.g. if there
    # are 10 images, and the target mole appears in images 0, 1, 7, 8, 9 then
    # this rule will pick image 7 instead of 9.
    #
    path, mole_list = path_moles_list[len(path_moles_list) // 2]

    mole_dict = {m['uuid']: m for m in mole_list}
    mole = mole_dict[uuid_]

    context_image = cv2.imread(path)
    x = mole['x']
    y = mole['y']

    # Draw a faded mark to indicate the mole. Make it faded in case we
    # accidentally cover moles or other distinguishing marks.
    unmarked_context_image = context_image.copy()
    mel.lib.common.indicate_mole(context_image, (x, y, radius))
    context_image = cv2.addWeighted(
        unmarked_context_image, 0.75, context_image, 0.25, 0.0)

    context_image = mel.lib.common.rotated90(context_image, rot90)
    for _ in range(rot90 % 4):
        x, y = -y, x
    if x < 0:
        x = x + context_image.shape[1]
    if y < 0:
        y = y + context_image.shape[0]

    detail_image = make_detail_image(context_image, x, y, montage_height)
<commit_msg>mel.cmd.rotomapmontagesingle: use load_image<commit_after>"""Create a montage image for a single mole from a rotomap."""

import cv2

import mel.lib.common
import mel.lib.image
import mel.rotomap.moles
import mel.cmd.error


def setup_parser(parser):

    parser.add_argument(
        'ROTOMAP',
        type=mel.rotomap.moles.make_argparse_rotomap_directory,
        help="Path to the rotomap to copy from.")

    parser.add_argument(
        'UUID',
        type=str,
        help="Unique id of the mole to copy.")

    parser.add_argument(
        'OUTPUT',
        type=str,
        help="Name of the image to write.")

    parser.add_argument(
        '--rot90',
        type=int,
        default=0,
        help="Rotate images 90 degrees clockwise this number of times.")


def process_args(args):
    mel.lib.common.write_image(
        args.OUTPUT,
        make_montage_image(args.ROTOMAP, args.UUID, args.rot90))


def make_montage_image(rotomap, uuid_, rot90=0):

    path_moles_list = []

    radius = 10
    montage_height = 1024

    for imagepath, moles in rotomap.yield_mole_lists():
        for m in moles:
            if m['uuid'] == uuid_:
                path_moles_list.append((imagepath, moles))

    if not path_moles_list:
        raise mel.cmd.error.UsageError(
            'UUID "{}" not found in rotomap "{}".'.format(
                uuid_, rotomap.path))

    # Pick 'best' image for this particular mole, assuming that the middle
    # image is where the mole is most prominent. This assumption is based on
    # the idea that the images represent a rotation around the subject, the
    # 'middle' image should be where the mole is most centered.
    #
    # TODO: Cater for the case where the image set represents a complete
    # rotation around the subject, and therefore the ends meet. e.g. if there
    # are 10 images, and the target mole appears in images 0, 1, 7, 8, 9 then
    # this rule will pick image 7 instead of 9.
    #
    path, mole_list = path_moles_list[len(path_moles_list) // 2]

    mole_dict = {m['uuid']: m for m in mole_list}
    mole = mole_dict[uuid_]

    context_image = mel.rotomap.moles.load_image(path)
    x = mole['x']
    y = mole['y']

    # Draw a faded mark to indicate the mole. Make it faded in case we
    # accidentally cover moles or other distinguishing marks.
    unmarked_context_image = context_image.copy()
    mel.lib.common.indicate_mole(context_image, (x, y, radius))
    context_image = cv2.addWeighted(
        unmarked_context_image, 0.75, context_image, 0.25, 0.0)

    context_image = mel.lib.common.rotated90(context_image, rot90)
    for _ in range(rot90 % 4):
        x, y = -y, x
    if x < 0:
        x = x + context_image.shape[1]
    if y < 0:
        y = y + context_image.shape[0]

    detail_image = make_detail_image(context_image, x, y, montage_height)

{'fraction_non_alphanumeric': 0.09676278082434106, 'fraction_numerical': 0.016805236157792322, 'mean_word_length': 2.6360128617363343, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '3080048', 'n_tokens_mistral': 1904, 'n_tokens_neox': 1805, 'n_words': 570}