Ejemplo n.º 1
0
def calibrate(ims_import_res,
              n_best_fields=6,
              divs=5,
              metadata=None,
              progress=None):
    if metadata is None:
        metadata = {}
    calib = Calibration({f"metadata.instrument": metadata})

    qdf = ims_import_res.qualities()
    quality = qdf.sort_values(["field_i", "channel_i",
                               "cycle_i"])["quality"].values.reshape(
                                   (ims_import_res.n_fields,
                                    ims_import_res.n_channels,
                                    ims_import_res.n_cycles))
    best_field_iz = np.argsort(np.sum(
        quality, axis=(1, 2)))[::-1][0:n_best_fields].tolist()

    n_cycles = ims_import_res.n_cycles
    zstack_depths = [
        0
    ] * n_cycles  # TASK: This will need to come from ims_import_res metadata
    calib.add({f"zstack_depths.instrument": zstack_depths})

    _calibrate(ims_import_res.ims[best_field_iz, :, :],
               calib,
               divs=divs,
               progress=progress)

    return calib
Ejemplo n.º 2
0
 def it_adds():
     c = Calibration(
         {"p_failure_to_bind_amino_acid.label[C].batch_2020_03_01": 1.0})
     c.add({"p_failure_to_attach_to_dye.label[C].batch_2020_03_01": 2.0})
     assert len(c) == 2
Ejemplo n.º 3
0
def _calibrate(flchcy_ims, divs=5, progress=None, overload_psf=None):
    """
    Accumulate calibration data using a set of fields.

    Arguments:
        flchcy_ims: frame, channel, cycles ims to be analyzed
            These are typically only a small subset of high quality fields.
            NOTE: "Cycles" here are considered to be z-stack slices, NOT chem-cycles.
        divs: The regional sub-divisions.
    """

    n_fields, n_channels, n_cycles = flchcy_ims.shape[0:3]
    n_z_slices = n_cycles  # This is just an alias to remind me that cycle=z-slice here.

    peak_mea = 11
    peak_dim = (peak_mea, peak_mea)

    if overload_psf is not None:
        # This is used for testing
        peak_dim = overload_psf.shape

    calib = Calibration()

    for ch_i in range(n_channels):
        z_and_region_to_psf = np.zeros((n_z_slices, divs, divs, *peak_dim))

        # BACKGROUND
        # Masks out the foreground and uses remaining pixels to estimate
        # regional background mean and std.
        # --------------------------------------------------------------

        flcy_calibs = [
            _calibrate_bg_and_psf_im(flchcy_ims[fl_i, ch_i, cy_i])
            for fl_i in range(n_fields) for cy_i in range(n_cycles)
        ]

        calib.add({
            f"regional_bg_mean.instrument_channel[{ch_i}]":
            np.mean([
                np.array(
                    flcy_calibs[f"regional_bg_mean.instrument_channel[{ch_i}]"]
                ) for c in flcy_calibs
            ])
        })

        # reg_psfs = np.sum([
        #     np.array(c[f"regional_psf_zstack.instrument_channel[{ch_i}]"])
        #     for c in flcy_calibs
        # ], axis=(2, 3))
        #
        # denominator = np.sum(z_and_region_to_psf, axis=(2, 3))[:, :, None, None]
        # calib.add({
        #     f"regional_psf_zstack.instrument_channel[{ch_i}]": reg_psfs /
        # })
        #
        # z_and_region_to_psf = utils.np_safe_divide(z_and_region_to_psf, denominator)
        #
        # calib.add({
        #     f"regional_bg_std.instrument_channel[{ch_i}]": np.mean([
        #         np.array(c[f"regional_bg_std.instrument_channel[{ch_i}]"])
        #         for c in flcy_calibs
        #     ])
        # })

        # if overload_psf is not None:
        #     # This is used for testing
        #     z_and_region_to_psf = np.broadcast_to(
        #         overload_psf, (n_z_slices, divs, divs, *peak_dim)
        #     ).tolist()
        #
        # else:
        #     # PSF
        #     # Accumulate the PSF regionally over every field
        #     # Then divide each PSF though by it's own mass so that the
        #     # AUC under each PSF is 1.
        #     # --------------------------------------------------------------
        #     [
        #         _calibrate_bg_im(flchcy_ims[fl_i, ch_i, cy_i], regional_bg_mean, regional_bg_std)
        #         for fl_i in range(n_fields)
        #         for cy_i in range(n_cycles)
        #     ]
        #
        #     for fl_i in range(n_fields):
        #
        #         for cy_i in range(n_cycles):
        #             # Remember: cy_i is a pseudo-cycle: it is really a z-slice
        #             # with z_depths[cy_i] holding the actual depth
        #
        #             regional_bg_mean = np.array(
        #                 calib[f"regional_bg_mean.instrument_channel[{ch_i}]"]
        #             )
        #             _calibrate_psf_im(flchcy_ims[fl_i, ch_i, cy_i], regional_bg_mean)
        #
        #             # ACCUMULATE each field, will normalize at the end
        #             z_and_region_to_psf[cy_i] += reg_psfs

        # # NORMALIZE all psfs
        # denominator = np.sum(z_and_region_to_psf, axis=(3, 4))[:, :, :, None, None]
        # z_and_region_to_psf = utils.np_safe_divide(z_and_region_to_psf, denominator)
        #
        # calib.add(
        #     {
        #         f"regional_psf_zstack.instrument_channel[{ch_i}]": z_and_region_to_psf.tolist()
        #     }
        # )

        # FOREGROUND
        # Runs the standard sigproc_field analysis (without balancing)
        # to get the regional radmats for regional histogram balancing.
        # This requires that the PSF already be estimated so that the
        # radiometry can run.
        # --------------------------------------------------------------

        # Spoof the sigproc_v2 worker into bypassing illumination balance by giving it all zeros
        calib.add({
            f"regional_illumination_balance.instrument_channel[{ch_i}]":
            np.ones((divs, divs)).tolist()
        })

        sigproc_params = SigprocV2Params(
            calibration=calib,
            instrument_subject_id=None,
            radiometry_channels=dict(ch=ch_i),
        )
        fl_radmats = []
        fl_locs = []
        for fl_i in range(n_fields):
            if progress is not None:
                progress(fl_i, n_fields)
            chcy_ims = flchcy_ims[fl_i, ch_i:(ch_i + 1), :]
            (
                chcy_ims,
                locs,
                radmat,
                aln_offsets,
                aln_scores,
            ) = sigproc_field(chcy_ims, sigproc_params)
            fl_radmats += [radmat]
            fl_locs += [locs]
        fl_radmat = np.concatenate(fl_radmats)
        fl_loc = np.concatenate(fl_locs)

        # BALANCE
        sig = np.nan_to_num(fl_radmat[:, ch_i, :, 0].flatten())
        noi = fl_radmat[:, ch_i, :, 1].flatten()
        snr = np.nan_to_num(sig / noi)

        locs = np.tile(fl_loc, (1, n_cycles)).reshape((-1, 2))

        snr_mask = snr > 10
        sig = sig[snr_mask]
        locs = locs[snr_mask]

        top = np.max((locs[:, 0], locs[:, 1]))
        y = utils.ispace(0, top, divs + 1)
        x = utils.ispace(0, top, divs + 1)

        def regional_locs_mask(yi, xi):
            """Create a mask for locs inside of a region"""
            mask = (y[yi] <= locs[:, 0]) & (locs[:, 0] < y[yi + 1])
            mask &= (x[xi] <= locs[:, 1]) & (locs[:, 1] < x[xi + 1])
            return mask

        medians = np.zeros((divs, divs))
        for yi in range(len(y) - 1):
            for xi in range(len(x) - 1):
                loc_mask = regional_locs_mask(yi, xi)
                bright_mask = sig > 2.0
                _sig = sig[loc_mask & bright_mask]
                medians[yi, xi] = np.median(_sig)

        center = np.max(medians)
        balance = np.zeros((divs, divs))
        for yi in range(len(y) - 1):
            for xi in range(len(x) - 1):
                loc_mask = regional_locs_mask(yi, xi)
                bright_mask = sig > 2.0
                _sig = sig[loc_mask & bright_mask]

        for yi in range(len(y) - 1):
            for xi in range(len(x) - 1):
                loc_mask = regional_locs_mask(yi, xi)
                bright_mask = sig > 2.0
                _sig = sig[loc_mask & bright_mask]
                median = np.median(_sig)
                balance[yi, xi] = center / median
                _sig *= balance[yi, xi]

        calib.add({
            f"regional_illumination_balance.instrument_channel[{ch_i}]":
            balance.tolist()
        })

    return calib