Exemple #1
0
def planar_imaging_start():

    colormaps = ["gray", "Greys", "brg", "prism"]
    displayname = request.forms.hidden_displayname
    username = request.get_cookie("account", secret=config.SECRET_KEY)
    if not username:
        redirect("/login")
    try:
        variables = general_functions.Read_from_dcm_database()
    except ConnectionError:
        return template(
            "error_template",
            {"error_message": "Orthanc is "
             "refusing connection."})
    variables["displayname"] = displayname
    response.set_cookie("account",
                        username,
                        secret=config.SECRET_KEY,
                        samesite="lax")
    variables["colormaps"] = colormaps

    # Get list of machines/beams/phantoms from the database
    machines_and_beams = {}
    for k in config.PLANARIMAGING_PHANTOMS:
        machines_and_beams[k] = general_functions.get_machines_and_energies(
            general_functions.get_treatmentunits_planarimaging(k))

    variables["machines_beams_phantoms"] = machines_and_beams
    return template("planar_imaging", variables)
def starshot_module():
    displayname = request.forms.hidden_displayname
    username = request.get_cookie("account", secret=config.SECRET_KEY)
    if not username:
        redirect("/login")
    try:
        variables = general_functions.Read_from_dcm_database()
        variables["displayname"] = displayname
        response.set_cookie("account", username, secret=config.SECRET_KEY, samesite="lax")
    except ConnectionError:
        return template("error_template", {"error_message": "Orthanc is refusing connection."})
    return template("starshot", variables)
Exemple #3
0
def image_review():

    colormaps = ["Greys", "gray", "brg", "prism"]
    displayname = request.forms.hidden_displayname
    username = request.get_cookie("account", secret=config.SECRET_KEY)
    if not username:
        redirect("/login")
    try:
        variables = general_functions.Read_from_dcm_database()
        variables["colormaps"] = colormaps
        variables["displayname"] = displayname
        response.set_cookie("account", username, secret=config.SECRET_KEY, samesite="lax")
    except ConnectionError:
        return template("error_template", {"error_message": "Orthanc is refusing connection."})
    return template("image_review", variables)
Exemple #4
0
def administration():
    username = request.get_cookie("account", secret=config.SECRET_KEY)
    displayname = request.forms.hidden_displayname
    if not username:
        redirect("/login")

    elif not general_functions.check_is_admin(username):
        return template("error_template",
                        {"error_message": "Insufficient rights."})
    else:
        variables = {"displayname": displayname}
        response.set_cookie("account",
                            username,
                            secret=config.SECRET_KEY,
                            samesite="lax")
        return template("administration", variables)
def starshot_calculate(imgtype, w):
    # w is the image

    clip_box = float(request.forms.hidden_clipbox)*10.0
    radius = float(request.forms.hidden_radius)
    min_peak_height = float(request.forms.hidden_mph)
    start_x = int(request.forms.hidden_px)
    start_y = int(request.forms.hidden_py)
    dpi = int(request.forms.hidden_dpi)
    sid = float(request.forms.hidden_sid)
    imgdescription = request.forms.hidden_imgdescription
    station = request.forms.hidden_station
    displayname = request.forms.hidden_displayname
    acquisition_datetime = request.forms.hidden_datetime
    
    fwhm = True if request.forms.hidden_fwhm=="true" else False
    recursive = True if request.forms.hidden_recursive=="true" else False
    invert = True if request.forms.hidden_invert=="true" else False
    # Get either dicom or non-dicom file
    if imgtype == "dicom":
        temp_folder, file_path = RestToolbox.GetSingleDcm(config.ORTHANC_URL, w)
    else:
        if request.files.get("input_nondicom_file") is not None:
            upload = request.files.get("input_nondicom_file")
            if os.path.splitext(upload.filename)[1] == ".tif":
                temp_folder = tempfile.mkdtemp(prefix=os.path.splitext(upload.filename)[0]+"_", dir=config.TEMP_NONDCM_FOLDER)
                file_path = os.path.join(temp_folder, upload.filename)
                with open(file_path, "wb") as dst:
                    upload.save(dst, overwrite=False)
                dst.close()
            else:
                return template("error_template", {"error_message": "Please load a valid image file."})
        else:
            return template("error_template", {"error_message": "Please load a valid image file."})

    args = {"imgtype": imgtype, "w": w, "clip_box": clip_box, "radius":radius, "min_peak_height":min_peak_height,
            "start_x": start_x, "start_y":start_y, "dpi":dpi, "sid":sid, "fwhm":fwhm,"recursive":recursive,  "invert":invert, 
            "temp_folder": temp_folder, "file_path":file_path, "imgdescription": imgdescription,
            "station": station, "displayname": displayname, "acquisition_datetime": acquisition_datetime,
            "config": general_functions.get_configuration()}
    p = Pool(1)
    data = p.map(starshot_helperf_catch_error, [args])
    p.close()
    p.join()
    return data
Exemple #6
0
 def login_submit():
     username = request.forms.username
     password = request.forms.password
     user_list = get_one_user(username)
     if user_list is None:
         return template("error_template.tpl",
                         error_message="User not recognized.")
     else:
         if not check_encrypted_password(password, user_list["Password"]):
             return template("error_template.tpl",
                             error_message="Wrong password.")
         else:
             response.set_cookie("account",
                                 username,
                                 secret=config.SECRET_KEY,
                                 samesite="lax")
             return template("menu_page.tpl",
                             institution=config.INSTITUTION,
                             orthanc_url=config.ORTHANC_URL,
                             qaserver_version=config.QASERVER_VERSION,
                             displayname=user_list["DisplayName"],
                             is_admin=check_is_admin(username))
Exemple #7
0
    def login_form():
        images = []
        for f in os.listdir(os.path.join(CUR_DIR, "static", "images")):
            if f.endswith('.png'):
                images.append(os.path.join("images", f))

        if images:
            image = random.choice(images)
        else:
            image = "blank"

        return template("login.tpl",
                        institution=config.INSTITUTION,
                        image=image)
Exemple #8
0
def review_trends():
    displayname = request.forms.hidden_displayname
    username = request.get_cookie("account", secret=config.SECRET_KEY)
    if not username:
        redirect("/login")

    tables = {
        "Winston Lutz": WINSTON_LUTZ_PARAMETERS,
        "Starshot": STARSHOT_PARAMETERS,
        "Picketfence": PICKETFENCE_PARAMETERS,
        "PlanarImaging": PLANARIMAGING_PARAMETERS,
        "Catphan": CATPHAN_PARAMETERS,
        "Flatness/Symmetry": FLATSYM_PARAMETERS,
        "Vmat": VMAT_PARAMETERS,
        "Fieldsize": FIELDSIZE_PARAMETERS,
        "Fieldrot": FIELDROTATION_PARAMETERS
    }
    unique_names = {
        "Winston Lutz": get_unique_names("WinstonlutzUniqueNames"),
        "Starshot": get_unique_names("StarshotUniqueNames"),
        "Picketfence": get_unique_names("PicketfenceUniqueNames"),
        "PlanarImaging": get_unique_names("PlanarImagingUniqueNames"),
        "Catphan": get_unique_names("CatphanUniqueNames"),
        "Flatness/Symmetry": get_unique_names("FlatSymUniqueNames"),
        "Vmat": get_unique_names("VmatUniqueNames"),
        "Fieldsize": get_unique_names("FieldSizeUniqueNames"),
        "Fieldrot": get_unique_names("FieldRotationUniqueNames")
    }
    variables = {
        "tables": json.dumps(tables),
        "unique_names": json.dumps(unique_names),
        "displayname": displayname,
        "is_admin": general_functions.check_is_admin(username)
    }
    response.set_cookie("account",
                        username,
                        secret=config.SECRET_KEY,
                        samesite="lax")
    return template("trends", variables)
Exemple #9
0
def catphan_calculate_helperf_catch_error(args):
    try:
        return catphan_calculate_helperf(args)
    except Exception as e:
        return template("error_template", {"error_message": str(e)})
Exemple #10
0
def edit_settings_fieldsize():
    variables = {"field_sizes": config.FIELDSIZE_FIELDS}
    return template("edit_settings_fieldsize", variables)
Exemple #11
0
def planar_imaging_helperf(args):
    # This function is used in order to prevent memory problems
    clip_box = args["clip_box"]
    phantom = args["phantom"]
    machine = args["machine"]
    beam = args["beam"]
    leedsrot1 = args["leedsrot1"]
    leedsrot2 = args["leedsrot2"]
    inv = args["inv"]
    bbox = args["bbox"]
    w1 = args["w1"]
    use_reference = args["use_reference"]
    colormap = args["colormap"]
    displayname = args["displayname"]
    acquisition_datetime = args["acquisition_datetime"]
    general_functions.set_configuration(
        args["config"])  # Transfer to this process

    # Collect data for "save results"
    tolerances = general_functions.get_tolerance_user_machine_planarimaging(
        machine, beam, phantom)  # If user_machne has specific tolerance
    if not tolerances:
        lowtresh, hightresh, generate_pdf = 0.05, 0.1, "True"
    else:
        lowtresh, hightresh, generate_pdf = tolerances

    lowtresh = float(lowtresh)
    hightresh = float(hightresh)

    # Set colormap
    cmap = matplotlib.cm.get_cmap(colormap)
    try:
        temp_folder1, file_path1 = RestToolbox.GetSingleDcm(
            config.ORTHANC_URL, w1)
    except:
        return template("error_template",
                        {"error_message": "Cannot read image."})

    ref_path1 = general_functions.get_referenceimagepath_planarimaging(
        machine, beam, phantom)

    if ref_path1 is not None:
        ref_path1 = os.path.join(config.REFERENCE_IMAGES_FOLDER, ref_path1[0])
        if os.path.exists(ref_path1):
            ref1_exists = True
        else:
            ref1_exists = False
    else:
        ref1_exists = False

    if not use_reference:
        ref1_exists = False

    # First analyze first image
    try:
        if phantom == "QC3":
            pi1 = StandardImagingQC3(file_path1)
        elif phantom == "LeedsTOR":
            pi1 = LeedsTOR(file_path1)
        elif phantom == "Las Vegas":
            pi1 = LasVegas(file_path1)
        elif phantom == "DoselabMC2MV":
            pi1 = DoselabMC2MV(file_path1)
        else:
            pi1 = DoselabMC2kV(file_path1)

        if clip_box != 0:
            try:
                #pi1.image.check_inversion_by_histogram()
                general_functions.clip_around_image(pi1.image, clip_box)
            except Exception as e:
                return template(
                    "error_template",
                    {"error_message": "Unable to apply clipbox. " + str(e)})
        pi1.analyze(low_contrast_threshold=lowtresh,
                    high_contrast_threshold=hightresh,
                    invert=inv,
                    angle_override=None if leedsrot2 == 0 else leedsrot2)
    except Exception as e:
        return template("error_template",
                        {"error_message": "Cannot analyze image 1. " + str(e)})

    # Analyze reference images if they exists

    if ref1_exists:
        try:
            if phantom == "QC3":
                ref1 = StandardImagingQC3(ref_path1)
            elif phantom == "LeedsTOR":
                ref1 = LeedsTOR(ref_path1)
            elif phantom == "Las Vegas":
                ref1 = LasVegas(ref_path1)
            elif phantom == "DoselabMC2MV":
                ref1 = DoselabMC2MV(ref_path1)
            else:
                ref1 = DoselabMC2kV(ref_path1)

            if clip_box != 0:
                try:
                    #ref1.image.check_inversion_by_histogram()
                    general_functions.clip_around_image(ref1.image, clip_box)
                except Exception as e:
                    return template("error_template", {
                        "error_message":
                        "Unable to apply clipbox. " + str(e)
                    })
            ref1.analyze(low_contrast_threshold=lowtresh,
                         high_contrast_threshold=hightresh,
                         invert=inv,
                         angle_override=None if leedsrot1 == 0 else leedsrot1)
        except:
            return template("error_template", {"error_message": "Cannot analyze reference image."\
                                               " Check that the image in the database is valid."})

    save_results = {
        "machine": machine,
        "beam": beam,
        "phantom": phantom,
        "displayname": displayname
    }

    fig = Figure(figsize=(10.5, 5), tight_layout={"w_pad": 0, "pad": 1.5})
    ax_ref = fig.add_subplot(1, 2, 1)
    ax_pi = fig.add_subplot(1, 2, 2)

    # Plot reference image and regions
    if phantom == "QC3":
        low_contrast_rois_pi1 = pi1.low_contrast_rois[
            1:]  # Exclude first point which is background
    else:
        low_contrast_rois_pi1 = pi1.low_contrast_rois

    if ref1_exists:
        if phantom == "QC3":
            low_contrast_rois_ref1 = ref1.low_contrast_rois[
                1:]  # Exclude first point which is background
        else:
            low_contrast_rois_ref1 = ref1.low_contrast_rois

    if ref1_exists:
        ax_ref.imshow(ref1.image.array,
                      cmap=cmap,
                      interpolation="none",
                      aspect="equal",
                      origin='upper')
        ax_ref.set_title(phantom + ' Reference Image')
        ax_ref.axis('off')
        # plot the background ROIS
        for roi in ref1.low_contrast_background_rois:
            roi.plot2axes(ax_ref, edgecolor='yellow')
            ax_ref.text(roi.center.x,
                        roi.center.y,
                        "B",
                        horizontalalignment='center',
                        verticalalignment='center')
        # low contrast ROIs
        for ind, roi in enumerate(low_contrast_rois_ref1):
            roi.plot2axes(ax_ref, edgecolor=roi.plot_color)
            ax_ref.text(roi.center.x,
                        roi.center.y,
                        str(ind),
                        horizontalalignment='center',
                        verticalalignment='center')
        # plot the high-contrast ROIs
        if phantom != "Las Vegas":
            mtf_temp_ref = list(ref1.mtf.norm_mtfs.values())
            for ind, roi in enumerate(ref1.high_contrast_rois):
                color = 'b' if mtf_temp_ref[
                    ind] > ref1._high_contrast_threshold else 'r'
                roi.plot2axes(ax_ref, edgecolor=color)
                ax_ref.text(roi.center.x,
                            roi.center.y,
                            str(ind),
                            horizontalalignment='center',
                            verticalalignment='center')
    else:
        ax_ref.text(0.5,
                    0.5,
                    "Reference image not available",
                    horizontalalignment='center',
                    verticalalignment='center')

    # Plot current image and regions
    ax_pi.imshow(pi1.image.array,
                 cmap=cmap,
                 interpolation="none",
                 aspect="equal",
                 origin='upper')
    ax_pi.axis('off')
    ax_pi.set_title(phantom + ' Current Image')
    # plot the background ROIS
    for roi in pi1.low_contrast_background_rois:
        roi.plot2axes(ax_pi, edgecolor='yellow')
        ax_pi.text(roi.center.x,
                   roi.center.y,
                   "B",
                   horizontalalignment='center',
                   verticalalignment='center')
    # low contrast ROIs
    for ind, roi in enumerate(low_contrast_rois_pi1):
        roi.plot2axes(ax_pi, edgecolor=roi.plot_color)
        ax_pi.text(roi.center.x,
                   roi.center.y,
                   str(ind),
                   horizontalalignment='center',
                   verticalalignment='center')
    # plot the high-contrast ROIs
    if phantom != "Las Vegas":
        mtf_temp_pi = list(pi1.mtf.norm_mtfs.values())
        for ind, roi in enumerate(pi1.high_contrast_rois):
            color = 'b' if mtf_temp_pi[
                ind] > pi1._high_contrast_threshold else 'r'
            roi.plot2axes(ax_pi, edgecolor=color)
            ax_pi.text(roi.center.x,
                       roi.center.y,
                       str(ind),
                       horizontalalignment='center',
                       verticalalignment='center')

    # Zoom on phantom if requested:
    if bbox:
        if phantom == "QC3" or phantom == "DoselabMC2MV" or phantom == "DoselabMC2kV":
            pad = 15  # Additional space between cyan bbox and plot
            if ref1_exists:
                bounding_box_ref = ref1.phantom_ski_region.bbox
                bbox_center_ref = ref1.phantom_center

                if abs(bounding_box_ref[1] -
                       bounding_box_ref[3]) >= abs(bounding_box_ref[2] -
                                                   bounding_box_ref[0]):
                    dist = abs(bounding_box_ref[1] - bounding_box_ref[3]) / 2
                    ax_ref.set_ylim(bbox_center_ref.y + dist + pad,
                                    bbox_center_ref.y - dist - pad)
                    ax_ref.set_xlim(bbox_center_ref.x - dist - pad,
                                    bbox_center_ref.x + dist + pad)
                else:
                    dist = abs(bounding_box_ref[2] - bounding_box_ref[0]) / 2
                    ax_ref.set_ylim(bbox_center_ref.y + dist + pad,
                                    bbox_center_ref.y - dist - pad)
                    ax_ref.set_xlim(bbox_center_ref.x - dist - pad,
                                    bbox_center_ref.x + dist + pad)

                ax_ref.plot([
                    bounding_box_ref[1], bounding_box_ref[1],
                    bounding_box_ref[3], bounding_box_ref[3],
                    bounding_box_ref[1]
                ], [
                    bounding_box_ref[2], bounding_box_ref[0],
                    bounding_box_ref[0], bounding_box_ref[2],
                    bounding_box_ref[2]
                ],
                            c="cyan")
                ax_ref.autoscale(False)

            bounding_box_pi = pi1.phantom_ski_region.bbox
            bbox_center_pi = pi1.phantom_center
            if abs(bounding_box_pi[1] -
                   bounding_box_pi[3]) >= abs(bounding_box_pi[2] -
                                              bounding_box_pi[0]):
                dist = abs(bounding_box_pi[1] - bounding_box_pi[3]) / 2
                ax_pi.set_ylim(bbox_center_pi.y + dist + pad,
                               bbox_center_pi.y - dist - pad)
                ax_pi.set_xlim(bbox_center_pi.x - dist - pad,
                               bbox_center_pi.x + dist + pad)
            else:
                dist = abs(bounding_box_pi[2] - bounding_box_pi[0]) / 2
                ax_pi.set_ylim(bbox_center_pi.y + dist + pad,
                               bbox_center_pi.y - dist - pad)
                ax_pi.set_xlim(bbox_center_pi.x - dist - pad,
                               bbox_center_pi.x + dist + pad)

            ax_pi.plot([
                bounding_box_pi[1], bounding_box_pi[1], bounding_box_pi[3],
                bounding_box_pi[3], bounding_box_pi[1]
            ], [
                bounding_box_pi[2], bounding_box_pi[0], bounding_box_pi[0],
                bounding_box_pi[2], bounding_box_pi[2]
            ],
                       c="cyan")
            ax_pi.autoscale(False)

        elif phantom == "Las Vegas":  # For some reason phantom_ski_regio has an underscore
            pad = 15  # Additional space between cyan bbox and plot
            if ref1_exists:
                bounding_box_ref = ref1._phantom_ski_region.bbox
                bbox_center_ref = ref1.phantom_center

                if abs(bounding_box_ref[1] -
                       bounding_box_ref[3]) >= abs(bounding_box_ref[2] -
                                                   bounding_box_ref[0]):
                    dist = abs(bounding_box_ref[1] - bounding_box_ref[3]) / 2
                    ax_ref.set_ylim(bbox_center_ref.y + dist + pad,
                                    bbox_center_ref.y - dist - pad)
                    ax_ref.set_xlim(bbox_center_ref.x - dist - pad,
                                    bbox_center_ref.x + dist + pad)
                else:
                    dist = abs(bounding_box_ref[2] - bounding_box_ref[0]) / 2
                    ax_ref.set_ylim(bbox_center_ref.y + dist + pad,
                                    bbox_center_ref.y - dist - pad)
                    ax_ref.set_xlim(bbox_center_ref.x - dist - pad,
                                    bbox_center_ref.x + dist + pad)

                ax_ref.plot([
                    bounding_box_ref[1], bounding_box_ref[1],
                    bounding_box_ref[3], bounding_box_ref[3],
                    bounding_box_ref[1]
                ], [
                    bounding_box_ref[2], bounding_box_ref[0],
                    bounding_box_ref[0], bounding_box_ref[2],
                    bounding_box_ref[2]
                ],
                            c="cyan")
                ax_ref.autoscale(False)

            bounding_box_pi = pi1._phantom_ski_region.bbox
            bbox_center_pi = pi1.phantom_center
            if abs(bounding_box_pi[1] -
                   bounding_box_pi[3]) >= abs(bounding_box_pi[2] -
                                              bounding_box_pi[0]):
                dist = abs(bounding_box_pi[1] - bounding_box_pi[3]) / 2
                ax_pi.set_ylim(bbox_center_pi.y + dist + pad,
                               bbox_center_pi.y - dist - pad)
                ax_pi.set_xlim(bbox_center_pi.x - dist - pad,
                               bbox_center_pi.x + dist + pad)
            else:
                dist = abs(bounding_box_pi[2] - bounding_box_pi[0]) / 2
                ax_pi.set_ylim(bbox_center_pi.y + dist + pad,
                               bbox_center_pi.y - dist - pad)
                ax_pi.set_xlim(bbox_center_pi.x - dist - pad,
                               bbox_center_pi.x + dist + pad)

            ax_pi.plot([
                bounding_box_pi[1], bounding_box_pi[1], bounding_box_pi[3],
                bounding_box_pi[3], bounding_box_pi[1]
            ], [
                bounding_box_pi[2], bounding_box_pi[0], bounding_box_pi[0],
                bounding_box_pi[2], bounding_box_pi[2]
            ],
                       c="cyan")
            ax_pi.autoscale(False)

        elif phantom == "LeedsTOR":
            pad = 15  # Additional space between cyan bbox and plot
            if ref1_exists:
                big_circle_idx = np.argsort([
                    ref1._regions[roi].major_axis_length for roi in ref1._blobs
                ])[-1]
                circle_roi = ref1._regions[ref1._blobs[big_circle_idx]]
                bounding_box_ref = circle_roi.bbox
                bbox_center_ref = bbox_center(circle_roi)
                max_xy = max([
                    abs(bounding_box_ref[1] - bounding_box_ref[3]) / 2,
                    abs(bounding_box_ref[0] - bounding_box_ref[2]) / 2
                ])
                ax_ref.set_ylim(bbox_center_ref.y + max_xy + pad,
                                bbox_center_ref.y - max_xy - pad)
                ax_ref.set_xlim(bbox_center_ref.x - max_xy - pad,
                                bbox_center_ref.x + max_xy + pad)
                ax_ref.plot([
                    bounding_box_ref[1], bounding_box_ref[1],
                    bounding_box_ref[3], bounding_box_ref[3],
                    bounding_box_ref[1]
                ], [
                    bounding_box_ref[2], bounding_box_ref[0],
                    bounding_box_ref[0], bounding_box_ref[2],
                    bounding_box_ref[2]
                ],
                            c="cyan")
                ax_ref.autoscale(False)

            big_circle_idx = np.argsort([
                pi1._regions[roi].major_axis_length for roi in pi1._blobs
            ])[-1]
            circle_roi = pi1._regions[pi1._blobs[big_circle_idx]]
            bounding_box_pi = circle_roi.bbox
            bbox_center_pi = bbox_center(circle_roi)

            max_xy = max([
                abs(bounding_box_pi[1] - bounding_box_pi[3]) / 2,
                abs(bounding_box_pi[0] - bounding_box_pi[2]) / 2
            ])

            ax_pi.set_ylim(bbox_center_pi.y + max_xy + pad,
                           bbox_center_pi.y - max_xy - pad)
            ax_pi.set_xlim(bbox_center_pi.x - max_xy - pad,
                           bbox_center_pi.x + max_xy + pad)
            ax_pi.plot([
                bounding_box_pi[1], bounding_box_pi[1], bounding_box_pi[3],
                bounding_box_pi[3], bounding_box_pi[1]
            ], [
                bounding_box_pi[2], bounding_box_pi[0], bounding_box_pi[0],
                bounding_box_pi[2], bounding_box_pi[2]
            ],
                       c="cyan")
            ax_pi.autoscale(False)

    # Add phantom outline:
    outline_obj_pi1, settings_pi1 = pi1._create_phantom_outline_object()
    outline_obj_pi1.plot2axes(ax_pi, edgecolor='g', **settings_pi1)
    if ref1_exists:
        outline_obj_ref1, settings_ref1 = ref1._create_phantom_outline_object()
        outline_obj_ref1.plot2axes(ax_ref, edgecolor='g', **settings_ref1)

    # Plot low frequency contrast, CNR and rMTF
    fig2 = Figure(figsize=(10.5, 10), tight_layout={"w_pad": 1})
    ax_lfc = fig2.add_subplot(2, 2, 1)
    ax_lfcnr = fig2.add_subplot(2, 2, 2)
    ax_rmtf = fig2.add_subplot(2, 2, 3)

    # lfc
    ax_lfc.plot([abs(roi.contrast) for roi in low_contrast_rois_pi1],
                marker='o',
                markersize=8,
                color='r')
    if ref1_exists:
        ax_lfc.plot([abs(roi.contrast) for roi in low_contrast_rois_ref1],
                    marker='o',
                    color='r',
                    markersize=8,
                    markerfacecolor="None",
                    linestyle="--")
    ax_lfc.plot([], [], color='r', linestyle="--", label='Reference')
    ax_lfc.plot([], [], color='r', label='Current')
    ax_lfc.plot([0, len(low_contrast_rois_pi1) - 1], [lowtresh, lowtresh],
                "-g")
    ax_lfc.grid(True)
    ax_lfc.set_title('Low-frequency Contrast')
    ax_lfc.set_xlabel('ROI #')
    ax_lfc.set_ylabel('Contrast')
    ax_lfc.set_xticks(np.arange(0, len(low_contrast_rois_pi1), 1))
    ax_lfc.legend(loc='upper right',
                  ncol=2,
                  columnspacing=0,
                  fontsize=12,
                  handletextpad=0)
    ax_lfc.margins(0.05)

    # CNR
    ax_lfcnr.plot(
        [abs(roi.contrast_to_noise) for roi in low_contrast_rois_pi1],
        marker='^',
        markersize=8,
        color='r')
    if ref1_exists:
        ax_lfcnr.plot(
            [abs(roi.contrast_to_noise) for roi in low_contrast_rois_ref1],
            marker='^',
            color='r',
            markersize=8,
            markerfacecolor="None",
            linestyle="--")
    ax_lfcnr.plot([], [], color='r', linestyle="--", label='Reference')
    ax_lfcnr.plot([], [], color='r', label='Current')
    ax_lfcnr.grid(True)
    ax_lfcnr.set_title('Contrast-Noise Ratio')
    ax_lfcnr.set_xlabel('ROI #')
    ax_lfcnr.set_ylabel('CNR')
    ax_lfcnr.set_xticks(np.arange(0, len(low_contrast_rois_pi1), 1))
    ax_lfcnr.legend(loc='upper right',
                    ncol=2,
                    columnspacing=0,
                    fontsize=12,
                    handletextpad=0)
    ax_lfcnr.margins(0.05)

    # rMTF
    if phantom != "Las Vegas":
        mtfs_pi1 = list(pi1.mtf.norm_mtfs.values())
        if ref1_exists:
            mtfs_ref1 = list(ref1.mtf.norm_mtfs.values())
        else:
            mtfs_ref1 = [np.nan] * len(mtfs_pi1)

        lppmm = pi1.mtf.spacings

        ax_rmtf.plot(lppmm, mtfs_pi1, marker='D', markersize=8, color='b')
        ax_rmtf.plot([min(lppmm), max(lppmm)], [hightresh, hightresh], "-g")

        if ref1_exists:
            ax_rmtf.plot(lppmm,
                         mtfs_ref1,
                         marker='D',
                         color='b',
                         markersize=8,
                         markerfacecolor="None",
                         linestyle="--")

        ax_rmtf.plot([], [], color='b', linestyle="--", label='Reference')
        ax_rmtf.plot([], [], color='b', label='Current')
        ax_rmtf.grid(True)
        ax_rmtf.set_title('High-frequency rMTF')
        ax_rmtf.set_xlabel('Line pairs / mm')
        ax_rmtf.set_ylabel('relative MTF')
        ax_rmtf.legend(loc='upper right',
                       ncol=2,
                       columnspacing=0,
                       fontsize=12,
                       handletextpad=0)
        ax_rmtf.margins(0.05)

        f30 = [
            ref1.mtf.relative_resolution(30) if ref1_exists else np.nan,
            pi1.mtf.relative_resolution(30)
        ]
        f40 = [
            ref1.mtf.relative_resolution(40) if ref1_exists else np.nan,
            pi1.mtf.relative_resolution(40)
        ]
        f50 = [
            ref1.mtf.relative_resolution(50) if ref1_exists else np.nan,
            pi1.mtf.relative_resolution(50)
        ]
        f80 = [
            ref1.mtf.relative_resolution(80) if ref1_exists else np.nan,
            pi1.mtf.relative_resolution(80)
        ]
    else:
        ax_rmtf.text(0.5,
                     0.5,
                     "MTF not available",
                     horizontalalignment='center',
                     verticalalignment='center')
        f30 = [np.nan, np.nan]
        f40 = [np.nan, np.nan]
        f50 = [np.nan, np.nan]
        f80 = [np.nan, np.nan]

    if ref1_exists:
        median_contrast = [
            np.median([roi.contrast for roi in low_contrast_rois_ref1]),
            np.median([roi.contrast for roi in low_contrast_rois_pi1])
        ]
        median_CNR = [
            np.median(
                [roi.contrast_to_noise for roi in low_contrast_rois_ref1]),
            np.median([roi.contrast_to_noise for roi in low_contrast_rois_pi1])
        ]
        phantom_angle = [ref1.phantom_angle, pi1.phantom_angle]
    else:
        median_contrast = [
            np.nan,
            np.median([roi.contrast for roi in low_contrast_rois_pi1])
        ]
        median_CNR = [
            np.nan,
            np.median([roi.contrast_to_noise for roi in low_contrast_rois_pi1])
        ]
        phantom_angle = [np.nan, pi1.phantom_angle]

    script = mpld3.fig_to_html(fig, d3_url=D3_URL, mpld3_url=MPLD3_URL)
    script2 = mpld3.fig_to_html(fig2, d3_url=D3_URL, mpld3_url=MPLD3_URL)

    variables = {
        "script": script,
        "script2": script2,
        "f30": f30,
        "f40": f40,
        "f50": f50,
        "f80": f80,
        "median_contrast": median_contrast,
        "median_CNR": median_CNR,
        "pdf_report_enable": generate_pdf,
        "save_results": save_results,
        "acquisition_datetime": acquisition_datetime,
        "phantom_angle": phantom_angle
    }

    if generate_pdf == "True":
        pdf_file = tempfile.NamedTemporaryFile(delete=False,
                                               prefix="PlanarImaging_",
                                               suffix=".pdf",
                                               dir=config.PDF_REPORT_FOLDER)
        metadata = RestToolbox.GetInstances(config.ORTHANC_URL, [w1])
        try:
            patient = metadata[0]["PatientName"]
        except:
            patient = ""
        try:
            stationname = metadata[0]["StationName"]
        except:
            stationname = ""
        try:
            date_time = RestToolbox.get_datetime(metadata[0])
            date_var = datetime.datetime.strptime(
                date_time[0], "%Y%m%d").strftime("%d/%m/%Y")
        except:
            date_var = ""
        pi1.publish_pdf(pdf_file,
                        notes=[
                            "Date = " + date_var, "Patient = " + patient,
                            "Station = " + stationname
                        ])

        variables["pdf_report_filename"] = os.path.basename(pdf_file.name)

    general_functions.delete_figure([fig, fig2])
    general_functions.delete_files_in_subfolders([temp_folder1
                                                  ])  # Delete image

    #gc.collect()
    return template("planar_imaging_results", variables)
Exemple #12
0
def edit_orthanc():
    return template("edit_orthanc")
Exemple #13
0
 def custom500(error):
     return template("error_template.tpl", error_message="Cause unknown.")
Exemple #14
0
def flatsym_helper(args):
    calc_definition = args["calc_definition"]
    center_definition = args["center_definition"]
    center_x = args["center_x"]
    center_y = args["center_y"]
    invert = args["invert"]
    w = args["instance"]
    station = args["station"]
    imgdescription = args["imgdescription"]
    displayname = args["displayname"]
    acquisition_datetime = args["acquisition_datetime"]

    general_functions.set_configuration(
        args["config"])  # Transfer to this process

    # Collect data for "save results"
    dicomenergy = general_functions.get_energy_from_imgdescription(
        imgdescription)
    user_machine, user_energy = general_functions.get_user_machine_and_energy(
        station, dicomenergy)
    machines_and_energies = general_functions.get_machines_and_energies(
        general_functions.get_treatmentunits_flatsym())
    tolerances = general_functions.get_tolerance_user_machine_flatsym(
        user_machine)  # If user_machne has specific tolerance
    if not tolerances:
        tolerance_flat, tolerance_sym, pdf_report_enable = general_functions.get_settings_flatsym(
        )
    else:
        tolerance_flat, tolerance_sym, pdf_report_enable = tolerances[0]

    tolerance_flat = float(tolerance_flat)
    tolerance_sym = float(tolerance_sym)

    save_results = {
        "user_machine": user_machine,
        "user_energy": user_energy,
        "machines_and_energies": machines_and_energies,
        "displayname": displayname
    }

    temp_folder, file_path = RestToolbox.GetSingleDcm(config.ORTHANC_URL, w)

    try:
        flatsym = FlatSym(file_path)
    except Exception as e:
        return template("error_template", {
            "error_message":
            "The FlatSym module cannot calculate. " + str(e)
        })

    # Define the center pixel where to get profiles:
    def find_field_centroid(img):
        '''taken from pylinac WL module'''
        min, max = np.percentile(img.image.array, [5, 99.9])
        # min, max = np.amin(img.array), np.max(img.array)

        threshold_img = img.image.as_binary((max - min) / 2 + min)
        # clean single-pixel noise from outside field
        coords = ndimage.measurements.center_of_mass(threshold_img)
        return (int(coords[-1]), int(coords[0]))

    flatsym.image.crop(pixels=2)
    flatsym.image.check_inversion()
    if invert:
        flatsym.image.invert()
    flatsym.image.array = np.flipud(flatsym.image.array)
    vmax = flatsym.image.array.max()

    if center_definition == "Automatic":
        center_int = [
            int(flatsym.image.array.shape[1] / 2),
            int(flatsym.image.array.shape[0] / 2)
        ]
        center = [0.5, 0.5]
    elif center_definition == "CAX":
        center_int = find_field_centroid(
            flatsym)  # Define as mechanical isocenter
        center = [
            int(center_int[0]) / flatsym.image.array.shape[1],
            int(center_int[1]) / flatsym.image.array.shape[0]
        ]
    else:
        center_int = [int(center_x), int(center_y)]
        center = [
            int(center_x) / flatsym.image.array.shape[1],
            int(center_y) / flatsym.image.array.shape[0]
        ]

    fig = Figure(figsize=(9, 9), tight_layout={"w_pad": 1})
    ax = fig.add_subplot(1, 1, 1)
    ax.imshow(flatsym.image.array,
              cmap=matplotlib.cm.jet,
              interpolation="none",
              vmin=0.9 * vmax,
              vmax=vmax,
              aspect="equal",
              origin='lower')
    ax.autoscale(tight=True)

    # Plot lines along which the profiles are calculated:
    ax.plot([0, flatsym.image.array.shape[1]], [center_int[1], center_int[1]],
            "b-",
            linewidth=2)
    ax.plot([center_int[0], center_int[0]], [0, flatsym.image.array.shape[0]],
            c="darkgreen",
            linestyle="-",
            linewidth=2)
    ax.set_xlim([0, flatsym.image.array.shape[1]])
    ax.set_ylim([0, flatsym.image.array.shape[0]])

    # Get profiles
    crossplane = PylinacSingleProfile(flatsym.image.array[center_int[1], :])
    inplane = PylinacSingleProfile(flatsym.image.array[:, center_int[0]])

    # Do some filtering:
    crossplane.filter(kind='median', size=0.01)
    inplane.filter(kind='median', size=0.01)

    # Normalize profiles
    norm_val_crossplane = crossplane.values[center_int[0]]
    norm_val_inplane = inplane.values[center_int[1]]
    crossplane.normalize(norm_val=norm_val_crossplane)
    inplane.normalize(norm_val=norm_val_inplane)

    # Get index of CAX of both profiles(different than center) to be used for mirroring:
    fwhm_crossplane = crossplane.fwxm_center(interpolate=True)
    fwhm_inplane = inplane.fwxm_center(interpolate=True)

    # Plot profiles
    divider = make_axes_locatable(ax)

    ax_crossplane = divider.append_axes("bottom",
                                        size="40%",
                                        pad=0.25,
                                        sharex=ax)
    ax_crossplane.set_xlim([0, flatsym.image.array.shape[1]])
    ax_crossplane.set_xticks([])
    ax_crossplane.set_title("Crossplane")

    ax_inplane = divider.append_axes("right", size="40%", pad=0.25, sharey=ax)
    ax_inplane.set_ylim([0, flatsym.image.array.shape[0]])
    ax_inplane.set_yticks([])
    ax_inplane.set_title("Inplane")

    ax_crossplane.plot(crossplane._indices, crossplane, "b-")
    ax_crossplane.plot(2 * fwhm_crossplane - crossplane._indices, crossplane,
                       "b--")
    ax_inplane.plot(inplane, inplane._indices, c="darkgreen", linestyle="-")
    ax_inplane.plot(inplane,
                    2 * fwhm_inplane - inplane._indices,
                    c="darkgreen",
                    linestyle="--")

    ax_inplane.grid(alpha=0.5)
    ax_crossplane.grid(alpha=0.5)
    mpld3.plugins.connect(fig,
                          mpld3.plugins.MousePosition(fontsize=14, fmt=".2f"))

    script = mpld3.fig_to_html(fig, d3_url=D3_URL, mpld3_url=MPLD3_URL)

    if calc_definition == "Elekta":
        method = "elekta"
    else:
        method = "varian"

    try:
        flatsym.analyze(flatness_method=method,
                        symmetry_method=method,
                        vert_position=center[0],
                        horiz_position=center[1])
    except Exception as e:
        return template("error_template",
                        {"error_message": "Analysis failed. " + str(e)})

    symmetry_hor = round(flatsym.symmetry['horizontal']['value'], 2)
    symmetry_vrt = round(flatsym.symmetry['vertical']['value'], 2)
    flatness_hor = round(flatsym.flatness['horizontal']['value'], 2)
    flatness_vrt = round(flatsym.flatness['vertical']['value'], 2)
    horizontal_width = round(
        flatsym.symmetry['horizontal']['profile'].fwxm(interpolate=True) /
        flatsym.image.dpmm, 2)
    vertical_width = round(
        flatsym.symmetry['vertical']['profile'].fwxm(interpolate=True) /
        flatsym.image.dpmm, 2)
    horizontal_penumbra_width = round(
        flatsym.symmetry['horizontal']['profile'].penumbra_width(
            interpolate=True) / flatsym.image.dpmm, 2)
    vertical_penumbra_width = round(
        flatsym.symmetry['vertical']['profile'].penumbra_width(
            interpolate=True) / flatsym.image.dpmm, 2)

    # Check if passed
    if method == "varian":
        if (flatness_hor <
                tolerance_flat) and (flatness_vrt < tolerance_flat) and (
                    symmetry_hor < tolerance_sym) and (symmetry_vrt <
                                                       tolerance_sym):
            passed = True
        else:
            passed = False
    else:
        if (abs(flatness_hor - 100) < tolerance_flat) and (
                abs(flatness_vrt - 100) < tolerance_flat) and (
                    abs(symmetry_hor - 100) < tolerance_sym) and (
                        abs(symmetry_vrt - 100) < tolerance_sym):
            passed = True
        else:
            passed = False

    variables = {
        "symmetry_hor": symmetry_hor,
        "symmetry_vrt": symmetry_vrt,
        "flatness_hor": flatness_hor,
        "flatness_vrt": flatness_vrt,
        "horizontal_width": horizontal_width,
        "vertical_width": vertical_width,
        "horizontal_penumbra_width": horizontal_penumbra_width,
        "vertical_penumbra_width": vertical_penumbra_width,
        "passed": passed,
        "pdf_report_enable": pdf_report_enable,
        "script": script,
        "save_results": save_results,
        "acquisition_datetime": acquisition_datetime,
        "calc_definition": calc_definition
    }

    # Generate pylinac report:
    if pdf_report_enable == "True":
        pdf_file = tempfile.NamedTemporaryFile(delete=False,
                                               prefix="FlatSym",
                                               suffix=".pdf",
                                               dir=config.PDF_REPORT_FOLDER)
        flatsym.publish_pdf(pdf_file)
        variables["pdf_report_filename"] = os.path.basename(pdf_file.name)

    general_functions.delete_files_in_subfolders([temp_folder])  # Delete image

    return template("flatsym_results", variables)
Exemple #15
0
def edit_settings_dynalog():
    return template("edit_settings_dynalog")
Exemple #16
0
def edit_settings_fieldrotation():
    return template("edit_settings_fieldrotation")
Exemple #17
0
def edit_settings_catphan():
    variables = {"phantoms": config.CATPHAN_PHANTOMS}
    return template("edit_settings_catphan", variables)
Exemple #18
0
def edit_settings_picketfence():
    return template("edit_settings_picketfence")
Exemple #19
0
def fieldrot_helperf_catch_error(args):
    try:
        return fieldrot_helperf(args)
    except Exception as e:
        return template("error_template", {"error_message": str(e)})
Exemple #20
0
def edit_settings_starshot():
    return template("edit_settings_starshot")
Exemple #21
0
def edit_institution():
    return template("edit_institution")
Exemple #22
0
def edit_settings_winstonlutz():
    return template("edit_settings_winstonlutz")
Exemple #23
0
def catphan_calculate_helperf(args):
    use_reference = args["use_reference"]
    phantom = args["phantom"]
    machine = args["machine"]
    beam = args["beam"]
    HU_delta = args["HU_delta"]
    colormap = args["colormap"]
    displayname = args["displayname"]
    acquisition_datetime = args["acquisition_datetime"]
    s = args["s"]
    general_functions.set_configuration(args["config"])  # Transfer to this process

    save_results = {
                    "machine": machine,
                    "beam": beam,
                    "phantom": phantom,
                    "displayname": displayname
                    }
    # Set colormap
    cmap = matplotlib.cm.get_cmap(colormap)

    # Collect data for "save results"
    tolerances = general_functions.get_tolerance_user_machine_catphan(machine, beam, phantom)  # If user_machne has specific tolerance
    if not tolerances:
        hu, lcv, scaling, thickness, lowcontrast, cnr, mtf, uniformityidx, pdf_report_enable = "100", "2", "0.5", "0.25", "1", "10", "10", "3", "False"
    else:
        hu, lcv, scaling, thickness, lowcontrast, cnr, mtf, uniformityidx, pdf_report_enable = tolerances

    hu_tolerance = float(hu)
    lcv_tolerance = float(lcv)
    scaling_tolerance = float(scaling)
    thickness_tolerance = float(thickness)
    low_contrast_tolerance = float(lowcontrast)
    cnr_threshold = float(cnr)
    mtf_tolerance = float(mtf)
    uniformityidx_tolerance = float(uniformityidx)

    ref_path = general_functions.get_referenceimagepath_catphan(machine, beam, phantom)

    if ref_path is not None:
        ref_path = os.path.join(config.REFERENCE_IMAGES_FOLDER, ref_path[0])
        if os.path.exists(ref_path):
            ref_exists = True
        else:
            ref_exists = False
    else:
        ref_exists = False
    
    folder_path = RestToolbox.GetSeries2Folder2(config.ORTHANC_URL, s)

    # Use two threads to speedup the calculation (if ref exists)
    args_current = {"hu_tolerance": hu_tolerance, "scaling_tolerance": scaling_tolerance,
                    "thickness_tolerance": thickness_tolerance, 
                    "cnr_threshold": cnr_threshold, "path": folder_path, 
                    "phantom": phantom, "low_contrast_tolerance": low_contrast_tolerance,
                    "config": general_functions.get_configuration()}
    
    args_ref = {"hu_tolerance": hu_tolerance, "scaling_tolerance": scaling_tolerance,
                "thickness_tolerance": thickness_tolerance, 
                "cnr_threshold": cnr_threshold, "path": ref_path, 
                "phantom": phantom, "low_contrast_tolerance": low_contrast_tolerance,
                "config": general_functions.get_configuration()}

    if use_reference and ref_exists:
        try:
            p = ThreadPool(2)
            [mycbct, mycbct_ref] = p.map(catphan_helperf_analyze, [args_current, args_ref])
        finally:
            p.close()
            p.join()
    else:
        mycbct = catphan_helperf_analyze(args_current)

    if use_reference and ref_exists:
        if isinstance(mycbct_ref, Exception):
            return template("error_template", {"error_message": "Unable to analyze reference image. " + str(mycbct_ref)
                                               })
    if isinstance(mycbct, Exception):
        general_functions.delete_files_in_subfolders([folder_path]) # Delete temporary images
        return template("error_template", {"error_message": "Unable to analyze image. " + str(mycbct)
                                           })
    
    try:  # add this to prevent memory problems when threads with exceptions are still alive
        
        # ######################### CTP528 - Resolution ###################################
        fig_dcm = Figure(figsize=(10.5, 5), tight_layout={"w_pad":0,  "pad": 1.5})
        ax1 = fig_dcm.add_subplot(1,2,1)
        ax2 = fig_dcm.add_subplot(1,2,2)
    
        # Reference image array
        if use_reference and ref_exists:
            ax1.imshow(mycbct_ref.ctp528.image.array, cmap=cmap, interpolation="none", aspect="equal", origin='upper')
            ax1.autoscale(enable=False)
        else:
            ax1.text(0.5, 0.5 ,"Reference image not available", horizontalalignment='center', verticalalignment='center')
    
        # Analysed current array
        ax2.imshow(mycbct.ctp528.image.array, cmap=cmap, interpolation="none", aspect="equal", origin='upper')
        ax2.set_title('CTP528 current image')
        ax1.set_title('CTP528 reference image')
        ax2.autoscale(enable=False)
    
        # Plot rMTF and gather some data
        fig_mtf = Figure(figsize=(5, 5), tight_layout={"w_pad":2, "pad": 1})
        ax_mtf = fig_mtf.add_subplot(1,1,1)
        msize = 8
        if use_reference and ref_exists:
            ax_mtf.plot(list(mycbct_ref.ctp528.mtf.norm_mtfs.keys()), list(mycbct_ref.ctp528.mtf.norm_mtfs.values()), marker='o', color="blue",
                        markersize=msize, markerfacecolor="None", linestyle="--")
    
        ax_mtf.plot(list(mycbct.ctp528.mtf.norm_mtfs.keys()), list(mycbct.ctp528.mtf.norm_mtfs.values()), marker='o', color="blue", markersize=msize)
        ax_mtf.margins(0.05)
        ax_mtf.grid('on')
        ax_mtf.set_xlabel('Line pairs / mm')
        ax_mtf.set_ylabel("Relative MTF")
        ax_mtf.set_title('Modulation transfer function')
        
        script_ctp528 = mpld3.fig_to_html(fig_dcm, d3_url=D3_URL, mpld3_url=MPLD3_URL)
        script_ctp528mtf = mpld3.fig_to_html(fig_mtf, d3_url=D3_URL, mpld3_url=MPLD3_URL)
    
        # Some data:
        mtf30_ref = mycbct_ref.ctp528.mtf.relative_resolution(30) if use_reference and ref_exists else np.nan
        mtf30 = mycbct.ctp528.mtf.relative_resolution(30)
        mtf50_ref = mycbct_ref.ctp528.mtf.relative_resolution(50) if use_reference and ref_exists else np.nan
        mtf50 = mycbct.ctp528.mtf.relative_resolution(50)
        mtf80_ref = mycbct_ref.ctp528.mtf.relative_resolution(80) if use_reference and ref_exists else np.nan
        mtf80 = mycbct.ctp528.mtf.relative_resolution(80)
    
        if use_reference and ref_exists:
            mtf_passing = True if abs(100*(mtf50-mtf50_ref)/mtf50_ref)<=mtf_tolerance else False
        else:
            mtf_passing = None
    
        # ####################### CTP404 - GEOMETRY HU LINEARITY ####################
        fig_404 = Figure(figsize=(10.5, 5), tight_layout={"w_pad":0,  "pad": 1.5})
        ax404_1 = fig_404.add_subplot(1,2,1)
        ax404_2 = fig_404.add_subplot(1,2,2)
    
        def ctp404_plotROI(mycbct, fig, axis):
            # Plot lines and circles - taken from pylinac
            # plot HU linearity ROIs
            for roi in mycbct.ctp404.hu_rois.values():
                axis.add_patch(matplotlib.patches.Circle((roi.center.x, roi.center.y), edgecolor=roi.plot_color, radius=roi.radius, fill=False))
            for roi in mycbct.ctp404.bg_hu_rois.values():
                axis.add_patch(matplotlib.patches.Circle((roi.center.x, roi.center.y), edgecolor='blue', radius=roi.radius, fill=False))
            # plot thickness ROIs
            for roi in mycbct.ctp404.thickness_rois.values():
                axis.add_patch(matplotlib.patches.Rectangle((roi.bl_corner.x, roi.bl_corner.y), width=roi.width, height=roi.height,
                                                               angle=0, edgecolor="blue", alpha=1, facecolor="g", fill=False))
            # plot geometry lines
            for line in mycbct.ctp404.lines.values():
                axis.plot((line.point1.x, line.point2.x), (line.point1.y, line.point2.y), linewidth=1, color=line.pass_fail_color)
    
            # Plot tooltips for patches
            names = []
            hu_rois_centers_x = []
            hu_rois_centers_y = []
            hu_rois_radius = []
    
            for name, roi in mycbct.ctp404.hu_rois.items():
                names.append(name)
                hu_rois_centers_x.append(roi.center.x)
                hu_rois_centers_y.append(roi.center.y)
                hu_rois_radius.append((roi.radius)**2)
    
            hu_rois_ttip = axis.scatter(hu_rois_centers_x, hu_rois_centers_y, s = hu_rois_radius, alpha=0)
            labels = [names[i] for i in range(len(names))]
            tooltip = mpld3.plugins.PointLabelTooltip(hu_rois_ttip, labels=labels)
            mpld3.plugins.connect(fig, tooltip)
            # Add tooltips for 4 lines
            inc = 1
            for line in mycbct.ctp404.lines.values():
                hu_lines_ttip = axis.plot((line.point1.x, line.point2.x), (line.point1.y, line.point2.y), alpha=0, lw=7)
                tooltip2 = mpld3.plugins.LineLabelTooltip(hu_lines_ttip[0], label="Line "+str(inc))
                mpld3.plugins.connect(fig, tooltip2)
                inc += 1
    
        # Reference image
        if use_reference and ref_exists:
            ax404_1.imshow(mycbct_ref.ctp404.image.array, cmap=cmap, interpolation="none", aspect="equal", origin='upper')
            #mycbct_ref.ctp404.plot_rois(ax404_1)
            ctp404_plotROI(mycbct_ref, fig_404, ax404_1)  # alternative
            ax404_1.autoscale(enable=False)
            ax404_1.set_xlim([0, mycbct_ref.ctp404.image.shape[1]])
            ax404_1.set_ylim([mycbct_ref.ctp404.image.shape[0], 0])
        else:
            ax404_1.text(0.5, 0.5 ,"Reference image not available", horizontalalignment='center', verticalalignment='center')
        # Current image
        ax404_2.imshow(mycbct.ctp404.image.array, cmap=cmap, interpolation="none", aspect="equal", origin='upper')
        ctp404_plotROI(mycbct, fig_404, ax404_2)  # alternative
        #mycbct.ctp404.plot_rois(ax404_2)
        ax404_2.set_xlim([0, mycbct.ctp404.image.shape[1]])
        ax404_2.set_ylim([mycbct.ctp404.image.shape[0], 0])
        ax404_1.set_title('CTP404 reference image')
        ax404_2.set_title('CTP404 current image')
        ax404_2.autoscale(enable=False)
    
        # Draw HU linearity plot
        def plot_linearity(mycbct, fig, axis, plot_delta):
            '''Taken from pylinac'''
            nominal_x_values = [roi.nominal_val for roi in mycbct.ctp404.hu_rois.values()]
            actual_values = []
            diff_values = []
            if plot_delta:
                values = []
                names = []
                for name, roi in mycbct.ctp404.hu_rois.items():
                    names.append(name)
                    values.append(roi.value_diff)
                    actual_values.append(roi.pixel_value)
                    diff_values.append(roi.value_diff)
                nominal_measurements = [0]*len(values)
                ylabel = 'HU Delta'
            else:
                values = []
                names = []
                for name, roi in mycbct.ctp404.hu_rois.items():
                    names.append(name)
                    values.append(roi.pixel_value)
                    actual_values.append(roi.pixel_value)
                    diff_values.append(roi.value_diff)
                nominal_measurements = nominal_x_values
                ylabel = 'Measured Values'
    
            points = axis.plot(nominal_x_values, values, 'g+', markersize=15, mew=2)
            axis.plot(nominal_x_values, nominal_measurements)
            axis.plot(nominal_x_values, np.array(nominal_measurements) + mycbct.ctp404.hu_tolerance, 'r--')
            axis.plot(nominal_x_values, np.array(nominal_measurements) - mycbct.ctp404.hu_tolerance, 'r--')
            axis.margins(0.07)
            axis.grid(True, alpha=0.35)
            axis.set_xlabel("Nominal Values")
            axis.set_ylabel(ylabel)
            axis.set_title("HU linearity")
            labels = [names[i]+" -- Nom.={:.1f}, Act.={:.1f}, Diff.={:.1f}".format(nominal_x_values[i], actual_values[i], diff_values[i]) for i in range(len(names))]
            tooltip = mpld3.plugins.PointLabelTooltip(points[0], labels=labels, location="top right")
            mpld3.plugins.connect(fig, tooltip)
    
        fig_404_HU = Figure(figsize=(10.5, 5), tight_layout={"w_pad":1})
        ax_HU_ref = fig_404_HU.add_subplot(1,2,1)
        ax_HU = fig_404_HU.add_subplot(1,2,2)
        # Reference HU linearity
        if use_reference and ref_exists:
            plot_linearity(mycbct_ref, fig_404_HU, ax_HU_ref, plot_delta=HU_delta)
        else:
            ax_HU_ref.text(0.5, 0.5 ,"Reference image not available", horizontalalignment='center', verticalalignment='center')
            ax_HU_ref.set_title("HU linearity")
        # Current HU linearity
        plot_linearity(mycbct, fig_404_HU, ax_HU, plot_delta=HU_delta)
        
        # Gather data from HU holes:
        if use_reference and ref_exists:
            HU_values_ref = []
            HU_std_ref = []
            HU_diff_ref = []
            cnrs404_ref = []
            for key, value in mycbct_ref.ctp404.hu_rois.items():
                HU_values_ref.append(value.pixel_value)
                HU_std_ref.append(round(value.std, 1))
                HU_diff_ref.append(value.value_diff)
                cnrs404_ref.append(round(value.cnr, 1))

            # Background HU ROIs
            for key, value in mycbct_ref.ctp404.bg_hu_rois.items():
                HU_values_ref.append(value.pixel_value)
                HU_std_ref.append(round(value.std, 1))
                HU_diff_ref.append(np.nan)
                cnrs404_ref.append(np.nan)
            
            lcv_ref = round(mycbct_ref.ctp404.lcv, 2)
            slice_thickness_ref = round(mycbct_ref.ctp404.meas_slice_thickness, 2)
            lines_ref = []  # Line length
            for l in mycbct_ref.ctp404.lines.values():
                lines_ref.append(round(l.length_mm, 2))
            lines_avg_ref = round(mycbct_ref.ctp404.avg_line_length, 2)
            phantom_roll_ref = round(mycbct_ref.ctp404.catphan_roll, 2)
            dicom_slice_thickness_ref = round(mycbct_ref.ctp404.slice_thickness, 2)
        else:
            length = len(list(mycbct.ctp404.hu_rois.values())+list(mycbct.ctp404.bg_hu_rois.values()))
            HU_values_ref = [np.nan]*length
            HU_std_ref = [np.nan]*length
            HU_diff_ref = [np.nan]*length
            cnrs404_ref = [np.nan]*length
            lcv_ref = np.nan
            slice_thickness_ref = np.nan
            lines_ref = [np.nan]*len(mycbct.ctp404.lines.values())
            lines_avg_ref = np.nan
            phantom_roll_ref = np.nan
            dicom_slice_thickness_ref = np.nan
            
    
        HU_values = []
        HU_std = []
        HU_diff = []
        HU_nominal = []
        HU_names = []
        cnrs404 = []
        HU_CNR_values_dict = {}
        for key, value in mycbct.ctp404.hu_rois.items():
            HU_values.append(value.pixel_value)
            HU_std.append(round(value.std, 1))
            HU_diff.append(value.value_diff)
            HU_nominal.append(value.nominal_val)
            HU_names.append(key)
            cnrs404.append(round(value.cnr, 1))
            HU_CNR_values_dict[key] = [value.pixel_value, round(value.cnr, 1)] 
        
        # Background HU ROIs
        for key, value in mycbct.ctp404.bg_hu_rois.items():
            HU_values.append(value.pixel_value)
            HU_std.append(round(value.std, 1))
            HU_diff.append(np.nan)
            HU_nominal.append(0)
            HU_names.append("Background "+str(key))
            cnrs404.append(np.nan)
            HU_CNR_values_dict[key] = [value.pixel_value, "nan"] 
        
        # For easier acces of values in results
        save_results["HU_CNR_values_dict"] = HU_CNR_values_dict
        lcv = mycbct.ctp404.lcv
        slice_thickness = round(mycbct.ctp404.meas_slice_thickness, 2)
        phantom_roll = round(mycbct.ctp404.catphan_roll, 2)
        dicom_slice_thickness = round(mycbct.ctp404.slice_thickness, 2)

        # Get origin slice and phantom center and slice number of other modules
        if use_reference and ref_exists:
            mm_per_pixel_ref = round(mycbct_ref.mm_per_pixel, 2)
            origin_slice_ref = mycbct_ref.origin_slice
            ctp528_slice_ref = mycbct_ref.ctp528.slice_num
            ctp486_slice_ref = mycbct_ref.ctp486.slice_num
            ctp515_slice_ref = mycbct_ref.ctp515.slice_num if phantom != "Catphan 503" else np.nan
            phantom_center_ref = [round(mycbct_ref.ctp404.phan_center.x, 2),
                                  round(mycbct_ref.ctp404.phan_center.y, 2)]
        else:
            mm_per_pixel_ref = np.nan
            origin_slice_ref = np.nan
            ctp528_slice_ref = np.nan
            ctp486_slice_ref = np.nan
            ctp515_slice_ref = np.nan
            phantom_center_ref = [np.nan, np.nan]
        mm_per_pixel = round(mycbct.mm_per_pixel, 2)
        origin_slice = mycbct.origin_slice
        ctp528_slice = mycbct.ctp528.slice_num
        ctp486_slice = mycbct.ctp486.slice_num
        ctp515_slice = mycbct.ctp515.slice_num if phantom != "Catphan 503" else np.nan
        phantom_center = [round(mycbct.ctp404.phan_center.x, 2), 
                          round(mycbct.ctp404.phan_center.y, 2)]
        
        lines = []  # Line length
        for l in mycbct.ctp404.lines.values():
            lines.append(round(l.length_mm, 2))
        lines_avg = round(mycbct.ctp404.avg_line_length, 2)
    
        passed_HU = mycbct.ctp404.passed_hu
        passed_thickness = mycbct.ctp404.passed_thickness
        passed_geometry = mycbct.ctp404.passed_geometry
    
        passed_lcv = True if lcv >= lcv_tolerance else False
        passed_404 = passed_HU and passed_thickness and passed_geometry and passed_lcv
    
        script_404 = mpld3.fig_to_html(fig_404, d3_url=D3_URL, mpld3_url=MPLD3_URL)
        script_404_HU = mpld3.fig_to_html(fig_404_HU, d3_url=D3_URL, mpld3_url=MPLD3_URL)
    
        # ############################## CTP486 - UNIFORMITY ####################
        fig_486 = Figure(figsize=(10.5, 5), tight_layout={"w_pad":0,  "pad": 1.5})
        ax486_1 = fig_486.add_subplot(1,2,1)
        ax486_2 = fig_486.add_subplot(1,2,2)
    
        if use_reference and ref_exists:
            ax486_1.imshow(mycbct_ref.ctp486.image.array, cmap=cmap, interpolation="none", aspect="equal", origin='upper')
            mycbct_ref.ctp486.plot_rois(ax486_1)
            # Add text inside ROI for reference to uniformity index:
            for ind, roi in enumerate(mycbct_ref.ctp486.rois.values()):
                ax486_1.text(roi.center.x, roi.center.y, str(ind), horizontalalignment='center', verticalalignment='center')
        else:
            ax486_1.text(0.5, 0.5 ,"Reference image not available", horizontalalignment='center', verticalalignment='center')
    
        ax486_2.imshow(mycbct.ctp486.image.array, cmap=cmap, interpolation="none", aspect="equal", origin='upper')
        mycbct.ctp486.plot_rois(ax486_2)
        # Add text inside ROI for reference to uniformity index:
        for ind, roi in enumerate(mycbct.ctp486.rois.values()):
            ax486_2.text(roi.center.x, roi.center.y, str(ind), horizontalalignment='center', verticalalignment='center')
        ax486_1.set_title('CTP486 reference image')
        ax486_1.autoscale(enable=False)
        ax486_2.set_title('CTP486 current image')
        ax486_2.autoscale(enable=False)
    
        script_486 = mpld3.fig_to_html(fig_486, d3_url=D3_URL, mpld3_url=MPLD3_URL)
    
        # Draw orthogonal profiles:
        fig_486_profile = Figure(figsize=(10.5, 5), tight_layout={"w_pad":0,  "pad": 1.5})
        ax486_profile_ref = fig_486_profile.add_subplot(1,2,1)
        ax486_profile = fig_486_profile.add_subplot(1,2,2)
        if use_reference and ref_exists:
            mycbct_ref.ctp486.plot_profiles(ax486_profile_ref)
        else:
            ax486_profile_ref.text(0.5, 0.5 ,"Reference image not available", horizontalalignment='center', verticalalignment='center')
        mycbct.ctp486.plot_profiles(ax486_profile)
        ax486_profile_ref.set_title('Reference uniformity profiles')
        ax486_profile.set_title('Current uniformity profiles')
    
        script_486_profile = mpld3.fig_to_html(fig_486_profile, d3_url=D3_URL, mpld3_url=MPLD3_URL)
    
        # Get mean pixel values and uniformity index:
        # take into account slope and intercept HU = slope * px + intercept
    
        if use_reference and ref_exists:
            hvalues_ref = [roi.pixel_value for roi in mycbct_ref.ctp486.rois.values()]
            uidx_ref = round(mycbct_ref.ctp486.uniformity_index, 2)
        else:
            hvalues_ref = [np.nan]*len(mycbct.ctp486.rois.values())
            uidx_ref = np.nan
        hvalues = [roi.pixel_value for roi in mycbct.ctp486.rois.values()]
        passed_uniformity = mycbct.ctp486.overall_passed
    
        uidx = round(mycbct.ctp486.uniformity_index, 2)
    
        passed_uniformity_index = True if abs(uidx)<=uniformityidx_tolerance else False
    
        # ############################## CTP515 - LOW CONTRAST ####################
        if phantom != "Catphan 503":
            show_ctp515 = True
            fig_515 = Figure(figsize=(10.5, 5), tight_layout={"w_pad":0,  "pad": 1.5})
            ax515_1 = fig_515.add_subplot(1,2,1)
            ax515_2 = fig_515.add_subplot(1,2,2)
            if use_reference and ref_exists:
                ax515_1.imshow(mycbct_ref.ctp515.image.array, cmap=cmap, interpolation="none", aspect="equal", origin='upper')
                mycbct_ref.ctp515.plot_rois(ax515_1)
            else:
                ax515_1.text(0.5, 0.5 ,"Reference image not available", horizontalalignment='center', verticalalignment='center')
        
            ax515_2.imshow(mycbct.ctp515.image.array, cmap=cmap, interpolation="none", aspect="equal", origin='upper')
            mycbct.ctp515.plot_rois(ax515_2)
            ax515_1.set_title('CTP515 reference image')
            ax515_1.autoscale(enable=False)
            ax515_2.set_title('CTP515 current image')
            ax515_2.autoscale(enable=False)
            
            script_515 = mpld3.fig_to_html(fig_515, d3_url=D3_URL, mpld3_url=MPLD3_URL)
        
            fig_515_contrast = Figure(figsize=(10, 5), tight_layout={"w_pad":1, "pad": 1})
            ax515_contrast = fig_515_contrast.add_subplot(1,2,1)
            ax515_cnr = fig_515_contrast.add_subplot(1,2,2)
            
            cnrs_names = []
            contrasts_515 = []
            cnrs515 = []
            for key, value in mycbct.ctp515.rois.items():
                cnrs_names.append(key)
                contrasts_515.append(value.contrast_constant)
                cnrs515.append(round(value.cnr_constant, 2))
            sizes_515 = np.array(cnrs_names, dtype=int)
            
            ax515_contrast.plot(sizes_515, contrasts_515, marker='o', color="blue",
                                markersize=8, markerfacecolor="None", linestyle="-")
            ax515_cnr.plot(sizes_515, cnrs515, marker='o', color="blue",
                                markersize=8, markerfacecolor="None", linestyle="-")
            
            if use_reference and ref_exists:
                contrasts_515_ref = []
                cnrs515_ref = []
                cnrs_names_ref = []
                for key, value in mycbct_ref.ctp515.rois.items():
                    cnrs_names_ref.append(key)
                    contrasts_515_ref.append(value.contrast_constant)
                    cnrs515_ref.append(round(value.cnr_constant, 2))
                sizes_515_ref = np.array(cnrs_names_ref, dtype=int)
                ax515_contrast.plot(sizes_515_ref, contrasts_515_ref, marker='o', color="blue",
                                    markersize=8, markerfacecolor="None", linestyle="--")
                ax515_cnr.plot(sizes_515_ref, cnrs515_ref, marker='o', color="blue",
                                    markersize=8, markerfacecolor="None", linestyle="--")
                ctp515_visible_ref = mycbct_ref.ctp515.rois_visible
            else:
                ctp515_visible_ref = np.nan
                cnrs515_ref = [np.nan]*len(mycbct.ctp515.rois.values())
            ax515_contrast.margins(0.05)
            ax515_contrast.grid(True)
            ax515_contrast.set_xlabel('ROI size (mm)')
            ax515_contrast.set_ylabel("Contrast * Diameter")
            ax515_cnr.margins(0.05)
            ax515_cnr.grid(True)
            ax515_cnr.set_xlabel('ROI size (mm)')
            ax515_cnr.set_ylabel("CNR * Diameter")
    
            script_515_contrast = mpld3.fig_to_html(fig_515_contrast, d3_url=D3_URL, mpld3_url=MPLD3_URL)
    
            ctp515_passed = mycbct.ctp515.overall_passed
            #ctp515_passed = None
            ctp515_visible = mycbct.ctp515.rois_visible
        else:
            show_ctp515 = False
            script_515_contrast = None
            script_515 = None
            ctp515_visible_ref = np.nan
            ctp515_passed = None
            ctp515_visible = np.nan
            cnrs515_ref = None
            cnrs515 = None
            cnrs_names = None
    
        general_functions.delete_files_in_subfolders([folder_path]) # Delete temporary images

        variables = {
                    "script_ctp528": script_ctp528,
                    "script_ctp528mtf": script_ctp528mtf,
                    "mtf30_ref": round(mtf30_ref, 2),
                    "mtf30": round(mtf30, 2),
                    "mtf50_ref": round(mtf50_ref, 2),
                    "mtf50": round(mtf50, 2),
                    "mtf80_ref": round(mtf80_ref, 2),
                    "mtf80": round(mtf80, 2),
                    "mtf_passing": mtf_passing,
                    "script_404": script_404,
                    "script_404_HU": script_404_HU,
                    "HU_values_ref": HU_values_ref,
                    "HU_std_ref": HU_std_ref,
                    "HU_values": HU_values,
                    "HU_std": HU_std,
                    "HU_nominal": HU_nominal,
                    "HU_names": HU_names,
                    "HU_diff_ref": HU_diff_ref,
                    "HU_diff": HU_diff,
                    "passed_HU": passed_HU,
                    "passed_thickness": passed_thickness,
                    "passed_geometry": passed_geometry,
                    "passed_lcv": passed_lcv,
                    "passed_404": passed_404,
                    "lcv_ref": lcv_ref,
                    "lcv": round(lcv, 2),
                    "slice_thickness": slice_thickness,
                    "slice_thickness_ref": slice_thickness_ref,
                    "dicom_slice_thickness": dicom_slice_thickness,
                    "dicom_slice_thickness_ref": dicom_slice_thickness_ref,
                    "lines_ref": lines_ref,
                    "lines": lines,
                    "lines_avg": lines_avg,
                    "lines_avg_ref": lines_avg_ref,
                    "phantom_roll": phantom_roll,
                    "phantom_roll_ref": phantom_roll_ref,
                    "origin_slice_ref": origin_slice_ref,
                    "origin_slice": origin_slice,
                    "ctp528_slice": ctp528_slice,
                    "ctp486_slice": ctp486_slice,
                    "ctp515_slice": ctp515_slice,
                    "ctp528_slice_ref": ctp528_slice_ref,
                    "ctp486_slice_ref": ctp486_slice_ref,
                    "ctp515_slice_ref": ctp515_slice_ref,
                    "phantom_center_ref": phantom_center_ref,
                    "phantom_center": phantom_center,
                    "mm_per_pixel": mm_per_pixel,
                    "mm_per_pixel_ref": mm_per_pixel_ref,
                    "cnrs404_ref" : cnrs404_ref,
                    "cnrs404": cnrs404,
                    "script_486": script_486,
                    "script_486_profile": script_486_profile,
                    "hvalues_ref": hvalues_ref,
                    "hvalues": hvalues,
                    "passed_uniformity": passed_uniformity,
                    "passed_uniformity_index": passed_uniformity_index,
                    "uidx": uidx,
                    "uidx_ref": uidx_ref,
                    "script_515": script_515,
                    "script_515_contrast": script_515_contrast,
                    "show_ctp515": show_ctp515,
                    "ctp515_passed": ctp515_passed,
                    "ctp515_visible": ctp515_visible,
                    "ctp515_visible_ref": ctp515_visible_ref,
                    "cnrs515_ref": cnrs515_ref,
                    "cnrs515": cnrs515,
                    "cnrs_names": cnrs_names,
                    "save_results": save_results,
                    "acquisition_datetime": acquisition_datetime,
                    "pdf_report_enable": pdf_report_enable
                    }

        # Generate pylinac report:
        if pdf_report_enable == "True":
            pdf_file = tempfile.NamedTemporaryFile(delete=False, prefix="Catphan", suffix=".pdf", dir=config.PDF_REPORT_FOLDER)
            mycbct.publish_pdf(pdf_file)
            variables["pdf_report_filename"] = os.path.basename(pdf_file.name)
    except Exception as e:
        general_functions.delete_files_in_subfolders([folder_path]) # Delete temporary images
        return template("error_template", {"error_message": "Cannot analyze image. "+str(e)
                                           })
    else:
        return template("catphan_results", variables)
Exemple #24
0
def edit_settings_flatsym():
    return template("edit_settings_flatsym")
Exemple #25
0
def flatsym_helper_catch_error(args):
    try:
        return flatsym_helper(args)
    except Exception as e:
        return template("error_template", {"error_message": str(e)})
Exemple #26
0
def edit_settings_vmat():
    return template("edit_settings_vmat")
Exemple #27
0
def edit_users():
    return template("edit_users")
Exemple #28
0
def edit_machine_mapping():
    return template("edit_machine_mapping")
Exemple #29
0
def fieldrot_helperf(args):

    test_type = args["test_type"]
    direction = args["direction"]
    direction2 = args["direction2"]
    number_samples = args["number_samples"]
    margin = args["margin"]
    clipbox = args["clipbox"]
    invert = args["invert"]
    w1 = args["w1"]
    w2 = args["w2"]
    colormap = args["colormap"]
    med_filter = args["med_filter"]
    general_functions.set_configuration(args["config"])
    imgdescription = args["imgdescription"]
    station = args["station"]
    displayname = args["displayname"]
    acquisition_datetime = args["acquisition_datetime"]
    high_contrast = args["high_contrast"]

    # Collect data for "save results"
    dicomenergy = general_functions.get_energy_from_imgdescription(
        imgdescription)
    user_machine, user_energy = general_functions.get_user_machine_and_energy(
        station, dicomenergy)
    machines_and_energies = general_functions.get_machines_and_energies(
        general_functions.get_treatmentunits_fieldrotation())
    tolerances = general_functions.get_tolerance_user_machine_fieldrotation(
        user_machine)  # If user_machne has specific tolerance

    if not tolerances:
        tt = general_functions.get_settings_fieldrotation()
    else:
        tt = tolerances[0]

    (tolerance_collabs, tolerance_collrel, tolerance_couchrel) = tt

    tolerance_collabs = float(tolerance_collabs)
    tolerance_collrel = float(tolerance_collrel)
    tolerance_couchrel = float(tolerance_couchrel)

    save_results = {
        "user_machine": user_machine,
        "user_energy": user_energy,
        "machines_and_energies": machines_and_energies,
        "displayname": displayname,
        "nominal_angle": np.linspace(360, -360, 49).tolist()
    }

    try:
        temp_folder1, file_path1 = RestToolbox.GetSingleDcm(
            config.ORTHANC_URL, w1)
        temp_folder2, file_path2 = RestToolbox.GetSingleDcm(
            config.ORTHANC_URL, w2)
    except:
        return template("error_template",
                        {"error_message": "Cannot read images."})

    # Load first image
    try:
        img1 = pylinac_image.DicomImage(file_path1)
        # Here we force pixels to background outside of box:
        if clipbox != 0:
            try:
                img1.check_inversion_by_histogram(percentiles=[
                    4, 50, 96
                ])  # Check inversion otherwise this might not work
                general_functions.clip_around_image(img1, clipbox)
            except Exception as e:
                return template(
                    "error_template",
                    {"error_message": "Unable to apply clipbox. " + str(e)})
        else:
            img1.remove_edges(pixels=2)
        if invert:
            img1.invert()
        else:
            img1.check_inversion()
        img1.flipud()
    except:
        return template("error_template",
                        {"error_message": "Cannot read image."})
    try:
        img2 = pylinac_image.DicomImage(file_path2)
        if clipbox != 0:
            try:
                img2.check_inversion_by_histogram(percentiles=[
                    4, 50, 96
                ])  # Check inversion otherwise this might not work
                general_functions.clip_around_image(img2, clipbox)
            except Exception as e:
                return template(
                    "error_template",
                    {"error_message": "Unable to apply clipbox. " + str(e)})
        else:
            img2.remove_edges(pixels=2)
        if invert:
            img2.invert()
        else:
            img2.check_inversion()
        img2.flipud()
    except:
        return template("error_template",
                        {"error_message": "Cannot read image."})

    # Apply some filtering
    if med_filter > 0:
        img1.filter(med_filter)
        img2.filter(med_filter)

    # Get radiation field box:
    try:
        center_cax1, rad_field_bounding_box1, field_corners1 = field_rotation._find_field_centroid(
            img1)
        center_cax2, rad_field_bounding_box2, field_corners2 = field_rotation._find_field_centroid(
            img2)
    except Exception as e:
        return template("error_template", {"error_message": str(e)})

    field_corners1 = field_corners1.astype(int)
    field_corners2 = field_corners2.astype(int)

    # Set colormap
    cmap = matplotlib.cm.get_cmap(colormap)

    if test_type == "Collimator absolute":
        # Get BBs
        try:
            if high_contrast:
                bbs1 = field_rotation._find_bb2(img1, rad_field_bounding_box1)
                bbs2 = field_rotation._find_bb2(img2, rad_field_bounding_box2)
            else:
                bbs1 = field_rotation._find_bb(img1, rad_field_bounding_box1)
                bbs2 = field_rotation._find_bb(img2, rad_field_bounding_box2)
        except Exception as e:
            return template("error_template", {"error_message": str(e)})

        bb_coord1_1, bw_bb_im1_1 = bbs1[0]
        bb_coord1_2, bw_bb_im1_2 = bbs1[1]
        bb_coord2_1, bw_bb_im2_1 = bbs2[0]
        bb_coord2_2, bw_bb_im2_2 = bbs2[1]

        center1_1 = (bb_coord1_1[0], bb_coord1_1[1])
        center1_2 = (bb_coord1_2[0], bb_coord1_2[1])
        center2_1 = (bb_coord2_1[0], bb_coord2_1[1])
        center2_2 = (bb_coord2_2[0], bb_coord2_2[1])

        # Line between BBs:
        bb_angle1 = np.arctan(np.inf if bb_coord1_1[0] - bb_coord1_2[0] ==
                              0 else (bb_coord1_1[1] - bb_coord1_2[1]) /
                              (bb_coord1_1[0] - bb_coord1_2[0])) * 180 / np.pi
        bb_angle2 = np.arctan(np.inf if bb_coord2_1[0] - bb_coord2_2[0] ==
                              0 else (bb_coord2_1[1] - bb_coord2_2[1]) /
                              (bb_coord2_1[0] - bb_coord2_2[0])) * 180 / np.pi

        img1_filled = np.copy(img1.array)
        img2_filled = np.copy(img2.array)

        # Fill BBs area with neighbouring values
        field_rotation.fill_BB_hole(bb_coord1_1, bw_bb_im1_1, img1_filled)
        field_rotation.fill_BB_hole(bb_coord1_2, bw_bb_im1_2, img1_filled)
        field_rotation.fill_BB_hole(bb_coord2_1, bw_bb_im2_1, img2_filled)
        field_rotation.fill_BB_hole(bb_coord2_2, bw_bb_im2_2, img2_filled)

        # Get penumbra points
        try:
            samples_left1, samples_right1, p_left1, p_right1 = field_rotation.find_penumbra_points(
                direction, number_samples, field_corners1, margin, img1_filled)
            samples_left2, samples_right2, p_left2, p_right2 = field_rotation.find_penumbra_points(
                direction2, number_samples, field_corners2, margin,
                img2_filled)
        except Exception as e:
            return template("error_template", {"error_message": str(e)})

        # Calculate field edge slopes
        pmin = 0
        pmax = np.max(
            img1.shape)  # Maksimum point for drawing regression lines

        if direction == "X":
            left_slope1, left_P1, left_err1 = field_rotation.calculate_regression(
                p_left1, samples_left1, pmin, pmax)
            right_slope1, right_P1, right_err1 = field_rotation.calculate_regression(
                p_right1, samples_right1, pmin, pmax)
        else:
            left_slope1, left_P1, left_err1 = field_rotation.calculate_regression(
                samples_left1, p_left1, pmin, pmax)
            right_slope1, right_P1, right_err1 = field_rotation.calculate_regression(
                samples_right1, p_right1, pmin, pmax)

        if direction2 == "X":
            left_slope2, left_P2, left_err2 = field_rotation.calculate_regression(
                p_left2, samples_left2, pmin, pmax)
            right_slope2, right_P2, right_err2 = field_rotation.calculate_regression(
                p_right2, samples_right2, pmin, pmax)
        else:

            left_slope2, left_P2, left_err2 = field_rotation.calculate_regression(
                samples_left2, p_left2, pmin, pmax)
            right_slope2, right_P2, right_err2 = field_rotation.calculate_regression(
                samples_right2, p_right2, pmin, pmax)

        left_edge_angle1 = np.arctan(left_slope1) * 180 / np.pi
        left_edge_angle2 = np.arctan(left_slope2) * 180 / np.pi
        right_edge_angle1 = np.arctan(right_slope1) * 180 / np.pi
        right_edge_angle2 = np.arctan(right_slope2) * 180 / np.pi

        # First plot: field and penumbra points
        fig1 = Figure(figsize=(10.5, 5.5), tight_layout={"w_pad": 3, "pad": 3})
        ax1 = fig1.add_subplot(1, 2, 1)
        ax2 = fig1.add_subplot(1, 2, 2)
        # Plot error bars and goodness of fit
        fig2 = Figure(figsize=(10, 4), tight_layout={"w_pad": 0, "pad": 1})
        ax3 = fig2.add_subplot(1, 2, 1)
        ax4 = fig2.add_subplot(1, 2, 2)
        # Plot angled lines
        fig3 = Figure(figsize=(10, 4), tight_layout={"w_pad": 0, "pad": 1})
        ax5 = fig3.add_subplot(1, 2, 1)
        ax6 = fig3.add_subplot(1, 2, 2)

        ax1.imshow(img1.array,
                   cmap=cmap,
                   interpolation="none",
                   aspect="equal",
                   origin='lower')
        ax1.set_title('Image 1')
        ax1.axis('off')
        ax2.imshow(img2.array,
                   cmap=cmap,
                   interpolation="none",
                   aspect="equal",
                   origin='lower')
        ax2.set_title('Image 2')
        ax2.axis('off')

        #Plot field corners
        ax1.plot(field_corners1[:, 1],
                 field_corners1[:, 0],
                 "mo",
                 markersize=5,
                 markeredgewidth=0)
        ax2.plot(field_corners2[:, 1],
                 field_corners2[:, 0],
                 "mo",
                 markersize=5,
                 markeredgewidth=0)

        # Plot penumbra points
        if direction == "X":
            ax1.plot(p_left1,
                     samples_left1,
                     "bx",
                     markersize=5,
                     markeredgewidth=2)
            ax1.plot(p_right1,
                     samples_right1,
                     "yx",
                     markersize=5,
                     markeredgewidth=2)
        else:
            ax1.plot(samples_left1,
                     p_left1,
                     "bx",
                     markersize=5,
                     markeredgewidth=2)
            ax1.plot(samples_right1,
                     p_right1,
                     "yx",
                     markersize=5,
                     markeredgewidth=2)

        ax1.plot(left_P1[0], left_P1[1], "b--")
        ax1.plot(right_P1[0], right_P1[1], "y--")

        if direction2 == "X":
            ax2.plot(p_left2,
                     samples_left2,
                     "bx",
                     markersize=5,
                     markeredgewidth=2)
            ax2.plot(p_right2,
                     samples_right2,
                     "yx",
                     markersize=5,
                     markeredgewidth=2)
        else:
            ax2.plot(samples_left2,
                     p_left2,
                     "bx",
                     markersize=5,
                     markeredgewidth=2)
            ax2.plot(samples_right2,
                     p_right2,
                     "yx",
                     markersize=5,
                     markeredgewidth=2)

        ax2.plot(left_P2[0], left_P2[1], "b--")
        ax2.plot(right_P2[0], right_P2[1], "y--")

        # Plot errors:
        ax3.plot(samples_left1, left_err1, "bx", markeredgewidth=2)
        ax3.plot(samples_right1, right_err1, "yx", markeredgewidth=2)
        ax4.plot(samples_left2, left_err2, "bx", markeredgewidth=2)
        ax4.plot(samples_right2, right_err2, "yx", markeredgewidth=2)

        limits_max = np.amax([
            np.amax(left_err1),
            np.amax(right_err1),
            np.amax(left_err2),
            np.amax(right_err2)
        ]) * 1.05
        limits_min = np.amin([
            np.amin(left_err1),
            np.amin(right_err1),
            np.amin(left_err2),
            np.amin(right_err2)
        ]) * 0.95
        limits = np.amax([abs(limits_max), abs(limits_min)])
        limits = limits if limits > 1 else 1

        ax3.set_ylim([-limits, limits])
        ax4.set_ylim([-limits, limits])
        ax3.set_ylabel("Deviation from fit [px]")
        ax4.set_ylabel("Deviation from fit [px]")
        ax3.set_xlabel("Field edge [px]")
        ax4.set_xlabel("Field edge [px]")
        ax3.set_title('Image 1 - Regression error')
        ax4.set_title('Image 2 - Regression error')

        # Plot angled lines:
        # If angles are negative, convert to [pi, 2pi]
        if abs(bb_angle1) > 80 and abs(bb_angle1) <= 90:
            B1 = left_edge_angle1 if left_edge_angle1 >= 0 else 180 + left_edge_angle1
            Y1 = right_edge_angle1 if right_edge_angle1 >= 0 else 180 + right_edge_angle1
            BB1 = bb_angle1 if bb_angle1 >= 0 else 180 + bb_angle1
            ref_angle_plot = PI / 2  # Reference angle for drawing (either 0 or 90)
        else:
            B1 = left_edge_angle1
            Y1 = right_edge_angle1
            BB1 = bb_angle1
            ref_angle_plot = 0

        if abs(bb_angle2) > 80 and abs(bb_angle2) <= 90:
            B2 = left_edge_angle2 if left_edge_angle2 >= 0 else 180 + left_edge_angle2
            Y2 = right_edge_angle2 if right_edge_angle2 >= 0 else 180 + right_edge_angle2
            BB2 = bb_angle2 if bb_angle2 >= 0 else 180 + bb_angle2
        else:
            B2 = left_edge_angle2
            Y2 = right_edge_angle2
            BB2 = bb_angle2

        a = 2
        x_bb1 = [-a * np.cos(BB1 * PI / 180), a * np.cos(BB1 * PI / 180)]
        y_bb1 = [-a * np.sin(BB1 * PI / 180), a * np.sin(BB1 * PI / 180)]

        x_b1 = [-a * np.cos((B1) * PI / 180), a * np.cos((B1) * PI / 180)]
        y_b1 = [-a * np.sin((B1) * PI / 180), a * np.sin((B1) * PI / 180)]

        x_b2 = [
            -a * np.cos((BB1 - (B2 - BB2)) * PI / 180), a * np.cos(
                (BB1 - (B2 - BB2)) * PI / 180)
        ]
        y_b2 = [
            -a * np.sin((BB1 - (B2 - BB2)) * PI / 180), a * np.sin(
                (BB1 - (B2 - BB2)) * PI / 180)
        ]

        x_y1 = [-a * np.cos((Y1) * PI / 180), a * np.cos((Y1) * PI / 180)]
        y_y1 = [-a * np.sin((Y1) * PI / 180), a * np.sin((Y1) * PI / 180)]

        x_y2 = [
            -a * np.cos((BB1 - (Y2 - BB2)) * PI / 180), a * np.cos(
                (BB1 - (Y2 - BB2)) * PI / 180)
        ]
        y_y2 = [
            -a * np.sin((BB1 - (Y2 - BB2)) * PI / 180), a * np.sin(
                (BB1 - (Y2 - BB2)) * PI / 180)
        ]

        ax5.plot(x_bb1, y_bb1, "g-", label="BB")
        ax5.plot(x_b1, y_b1, "b-", label="Gantry 0")
        ax5.plot(x_b2, y_b2, "b--", label="Gantry 180")

        ax6.plot(x_bb1, y_bb1, "g-", label="BB")
        ax6.plot(x_y1, y_y1, "y-", label="Gantry 0")
        ax6.plot(x_y2, y_y2, "y--", label="Gantry 180")

        if ref_angle_plot == PI / 2:
            max_xb = np.amax([np.abs(x_b1), np.abs(x_b2)])
            max_xy = np.amax([np.abs(x_y1), np.abs(x_y2)])
            ax5.set_xlim([-2 * max_xb, 2 * max_xb])
            ax5.set_ylim([-1, 1])
            ax6.set_xlim([-2 * max_xy, 2 * max_xy])
            ax6.set_ylim([-1, 1])
        else:
            max_y = np.amax([np.abs(y_b1), np.abs(y_b2)])
            max_yy = np.amax([np.abs(y_y1), np.abs(y_y2)])
            ax5.set_ylim([-2 * max_y, 2 * max_y])
            ax5.set_xlim([-1, 1])
            ax6.set_ylim([-2 * max_yy, 2 * max_yy])
            ax6.set_xlim([-1, 1])

        ax5.legend(loc='upper right', fontsize=10, edgecolor="none")
        ax5.set_title("Blue edge")
        ax5.set_xlabel("LAT [px]")
        ax5.set_ylabel("LONG [px]")
        ax6.legend(loc='upper right', fontsize=10, edgecolor="none")
        ax6.set_title("Yellow edge")
        ax6.set_xlabel("LAT [px]")
        ax6.set_ylabel("LONG [px]")

        # Plot BB line and crosses
        ax1.plot([bb_coord1_1[0], bb_coord1_2[0]],
                 [bb_coord1_1[1], bb_coord1_2[1]], "g-")
        ax2.plot([bb_coord2_1[0], bb_coord2_2[0]],
                 [bb_coord2_1[1], bb_coord2_2[1]], "g-")
        ax1.plot(center1_1[0],
                 center1_1[1],
                 'r+',
                 markersize=10,
                 markeredgewidth=2)
        ax1.plot(center1_2[0],
                 center1_2[1],
                 'r+',
                 markersize=10,
                 markeredgewidth=2)
        ax2.plot(center2_1[0],
                 center2_1[1],
                 'r+',
                 markersize=10,
                 markeredgewidth=2)
        ax2.plot(center2_2[0],
                 center2_2[1],
                 'r+',
                 markersize=10,
                 markeredgewidth=2)

        ax1.set_xlim([0, img1.shape[1]])
        ax1.set_ylim([0, img1.shape[0]])
        ax2.set_xlim([0, img2.shape[1]])
        ax2.set_ylim([0, img2.shape[0]])

        script1 = mpld3.fig_to_html(fig1, d3_url=D3_URL, mpld3_url=MPLD3_URL)
        script2 = mpld3.fig_to_html(fig2, d3_url=D3_URL, mpld3_url=MPLD3_URL)
        script3 = mpld3.fig_to_html(fig3, d3_url=D3_URL, mpld3_url=MPLD3_URL)

        variables = {
            "script1": script1,
            "script2": script2,
            "script3": script3,
            "left_edge_angle1": left_edge_angle1,
            "left_edge_angle2": left_edge_angle2,
            "right_edge_angle1": right_edge_angle1,
            "right_edge_angle2": right_edge_angle2,
            "bb_angle1": bb_angle1,
            "bb_angle2": bb_angle2,
            "test_type": test_type,
            "tolerance": tolerance_collabs
        }

    elif test_type == "Collimator relative":

        # Get penumbra points
        try:
            samples_left1, samples_right1, p_left1, p_right1 = field_rotation.find_penumbra_points(
                direction, number_samples, field_corners1, margin, img1.array)
            samples_left2, samples_right2, p_left2, p_right2 = field_rotation.find_penumbra_points(
                direction2, number_samples, field_corners2, margin, img2.array)
        except Exception as e:
            return template("error_template", {"error_message": str(e)})

        # Calculate field edge slopes
        pmin = 0
        pmax = np.max(
            img1.shape)  # Maksimum point for drawing regression lines

        if direction == "X":
            left_slope1, left_P1, left_err1 = field_rotation.calculate_regression(
                p_left1, samples_left1, pmin, pmax)
            right_slope1, right_P1, right_err1 = field_rotation.calculate_regression(
                p_right1, samples_right1, pmin, pmax)
        else:
            left_slope1, left_P1, left_err1 = field_rotation.calculate_regression(
                samples_left1, p_left1, pmin, pmax)
            right_slope1, right_P1, right_err1 = field_rotation.calculate_regression(
                samples_right1, p_right1, pmin, pmax)

        if direction2 == "X":
            left_slope2, left_P2, left_err2 = field_rotation.calculate_regression(
                p_left2, samples_left2, pmin, pmax)
            right_slope2, right_P2, right_err2 = field_rotation.calculate_regression(
                p_right2, samples_right2, pmin, pmax)
        else:
            left_slope2, left_P2, left_err2 = field_rotation.calculate_regression(
                samples_left2, p_left2, pmin, pmax)
            right_slope2, right_P2, right_err2 = field_rotation.calculate_regression(
                samples_right2, p_right2, pmin, pmax)

        left_edge_angle1 = np.arctan(left_slope1) * 180 / np.pi
        left_edge_angle2 = np.arctan(left_slope2) * 180 / np.pi
        right_edge_angle1 = np.arctan(right_slope1) * 180 / np.pi
        right_edge_angle2 = np.arctan(right_slope2) * 180 / np.pi

        # First plot: field and penumbra points
        fig1 = Figure(figsize=(10.5, 5.5), tight_layout={"w_pad": 3, "pad": 3})
        ax1 = fig1.add_subplot(1, 2, 1)
        ax2 = fig1.add_subplot(1, 2, 2)
        # Plot error bars and goodness of fit
        fig2 = Figure(figsize=(10, 4), tight_layout={"w_pad": 0, "pad": 1})
        ax3 = fig2.add_subplot(1, 2, 1)
        ax4 = fig2.add_subplot(1, 2, 2)

        ax1.imshow(img1.array,
                   cmap=cmap,
                   interpolation="none",
                   aspect="equal",
                   origin='lower')
        ax1.set_title('Image 1')
        ax1.axis('off')
        ax2.imshow(img2.array,
                   cmap=cmap,
                   interpolation="none",
                   aspect="equal",
                   origin='lower')
        ax2.set_title('Image 2')
        ax2.axis('off')

        #Plot field corners
        ax1.plot(field_corners1[:, 1],
                 field_corners1[:, 0],
                 "mo",
                 markersize=5,
                 markeredgewidth=0)
        ax2.plot(field_corners2[:, 1],
                 field_corners2[:, 0],
                 "mo",
                 markersize=5,
                 markeredgewidth=0)

        # Plot penumbra points
        if direction == "X":
            ax1.plot(p_left1,
                     samples_left1,
                     "bx",
                     markersize=5,
                     markeredgewidth=2)
            ax1.plot(p_right1,
                     samples_right1,
                     "yx",
                     markersize=5,
                     markeredgewidth=2)

        else:
            ax1.plot(samples_left1,
                     p_left1,
                     "bx",
                     markersize=5,
                     markeredgewidth=2)
            ax1.plot(samples_right1,
                     p_right1,
                     "yx",
                     markersize=5,
                     markeredgewidth=2)

        ax1.plot(left_P1[0], left_P1[1], "b--")
        ax1.plot(right_P1[0], right_P1[1], "y--")

        if direction2 == "X":
            ax2.plot(p_left2,
                     samples_left2,
                     "bx",
                     markersize=5,
                     markeredgewidth=2)
            ax2.plot(p_right2,
                     samples_right2,
                     "yx",
                     markersize=5,
                     markeredgewidth=2)

        else:
            ax2.plot(samples_left2,
                     p_left2,
                     "bx",
                     markersize=5,
                     markeredgewidth=2)
            ax2.plot(samples_right2,
                     p_right2,
                     "yx",
                     markersize=5,
                     markeredgewidth=2)

        ax2.plot(left_P2[0], left_P2[1], "b--")
        ax2.plot(right_P2[0], right_P2[1], "y--")

        ax1.set_xlim([0, img1.shape[1]])
        ax1.set_ylim([0, img1.shape[0]])
        ax2.set_xlim([0, img2.shape[1]])
        ax2.set_ylim([0, img2.shape[0]])

        # Plot errors:
        ax3.plot(samples_left1, left_err1, "bx", markeredgewidth=2)
        ax3.plot(samples_right1, right_err1, "yx", markeredgewidth=2)
        ax4.plot(samples_left2, left_err2, "bx", markeredgewidth=2)
        ax4.plot(samples_right2, right_err2, "yx", markeredgewidth=2)

        limits_max = np.amax([
            np.amax(left_err1),
            np.amax(right_err1),
            np.amax(left_err2),
            np.amax(right_err2)
        ]) * 1.05
        limits_min = np.amin([
            np.amin(left_err1),
            np.amin(right_err1),
            np.amin(left_err2),
            np.amin(right_err2)
        ]) * 0.95
        limits = np.amax([abs(limits_max), abs(limits_min)])
        limits = limits if limits > 1 else 1

        ax3.set_ylim([-limits, limits])
        ax4.set_ylim([-limits, limits])
        ax3.set_ylabel("Deviation from fit [px]")
        ax4.set_ylabel("Deviation from fit [px]")
        ax3.set_xlabel("Field edge [px]")
        ax4.set_xlabel("Field edge [px]")
        ax3.set_title('Image 1 - Regression error')
        ax4.set_title('Image 2 - Regression error')

        script1 = mpld3.fig_to_html(fig1, d3_url=D3_URL, mpld3_url=MPLD3_URL)
        script2 = mpld3.fig_to_html(fig2, d3_url=D3_URL, mpld3_url=MPLD3_URL)

        variables = {
            "script1": script1,
            "script2": script2,
            "script3": "",
            "left_edge_angle1": left_edge_angle1,
            "left_edge_angle2": left_edge_angle2,
            "right_edge_angle1": right_edge_angle1,
            "right_edge_angle2": right_edge_angle2,
            "test_type": test_type,
            "tolerance": tolerance_collrel
        }

    else:  # Couch rotation
        # Get BBs
        try:
            if high_contrast:
                bbs1 = field_rotation._find_bb2(img1, rad_field_bounding_box1)
                bbs2 = field_rotation._find_bb2(img2, rad_field_bounding_box2)
            else:
                bbs1 = field_rotation._find_bb(img1, rad_field_bounding_box1)
                bbs2 = field_rotation._find_bb(img2, rad_field_bounding_box2)
        except Exception as e:
            return template("error_template", {"error_message": str(e)})

        bb_coord1_1, bw_bb_im1_1 = bbs1[0]
        bb_coord1_2, bw_bb_im1_2 = bbs1[1]
        bb_coord2_1, bw_bb_im2_1 = bbs2[0]
        bb_coord2_2, bw_bb_im2_2 = bbs2[1]

        center1_1 = [bb_coord1_1[0], bb_coord1_1[1]]
        center1_2 = [bb_coord1_2[0], bb_coord1_2[1]]
        center2_1 = [bb_coord2_1[0], bb_coord2_1[1]]
        center2_2 = [bb_coord2_2[0], bb_coord2_2[1]]

        bb_line_center1 = [
            np.average([center1_1[0], center1_2[0]]),
            np.average([center1_1[1], center1_2[1]])
        ]
        bb_line_center2 = [
            np.average([center2_1[0], center2_2[0]]),
            np.average([center2_1[1], center2_2[1]])
        ]

        # Line between BBs:
        bb_angle1 = np.arctan(np.inf if bb_coord1_1[0] - bb_coord1_2[0] ==
                              0 else (bb_coord1_1[1] - bb_coord1_2[1]) /
                              (bb_coord1_1[0] - bb_coord1_2[0])) * 180 / np.pi
        bb_angle2 = np.arctan(np.inf if bb_coord2_1[0] - bb_coord2_2[0] ==
                              0 else (bb_coord2_1[1] - bb_coord2_2[1]) /
                              (bb_coord2_1[0] - bb_coord2_2[0])) * 180 / np.pi

        fig1 = Figure(figsize=(10.5, 5.5), tight_layout={"w_pad": 3, "pad": 3})
        ax1 = fig1.add_subplot(1, 2, 1)
        ax2 = fig1.add_subplot(1, 2, 2)

        ax1.imshow(img1.array,
                   cmap=cmap,
                   interpolation="none",
                   aspect="equal",
                   origin='lower')
        ax1.set_title('Image 1')
        ax1.axis('off')
        ax2.imshow(img2.array,
                   cmap=cmap,
                   interpolation="none",
                   aspect="equal",
                   origin='lower')
        ax2.set_title('Image 2')
        ax2.axis('off')

        # Plot BB line and crosses
        ax1.plot([bb_coord1_1[0], bb_coord1_2[0]],
                 [bb_coord1_1[1], bb_coord1_2[1]], "g-")
        ax2.plot([bb_coord2_1[0], bb_coord2_2[0]],
                 [bb_coord2_1[1], bb_coord2_2[1]], "g-")
        ax1.plot(center1_1[0],
                 center1_1[1],
                 'r+',
                 markersize=10,
                 markeredgewidth=2)
        ax1.plot(center1_2[0],
                 center1_2[1],
                 'r+',
                 markersize=10,
                 markeredgewidth=2)
        ax2.plot(center2_1[0],
                 center2_1[1],
                 'r+',
                 markersize=10,
                 markeredgewidth=2)
        ax2.plot(center2_2[0],
                 center2_2[1],
                 'r+',
                 markersize=10,
                 markeredgewidth=2)

        ax1.set_xlim([0, img1.shape[1]])
        ax1.set_ylim([0, img1.shape[0]])
        ax2.set_xlim([0, img2.shape[1]])
        ax2.set_ylim([0, img2.shape[0]])

        script1 = mpld3.fig_to_html(fig1, d3_url=D3_URL, mpld3_url=MPLD3_URL)

        variables = {
            "script1": script1,
            "script2": "",
            "script3": "",
            "bb_angle1": bb_angle1,
            "bb_angle2": bb_angle2,
            "bb_line_center1": bb_line_center1,
            "bb_line_center2": bb_line_center2,
            "test_type": test_type,
            "tolerance": tolerance_couchrel
        }
    variables["acquisition_datetime"] = acquisition_datetime
    variables["save_results"] = save_results
    general_functions.delete_files_in_subfolders([temp_folder1, temp_folder2
                                                  ])  # Delete image
    return template("fieldrot_results", variables)
Exemple #30
0
def edit_settings_planarimaging():
    variables = {"phantoms": config.PLANARIMAGING_PHANTOMS}
    return template("edit_settings_planarimaging", variables)