Esempio n. 1
0
 def get_numpy_array(self,
                     canvas_inner_radius_nm: float,
                     px_size_nm: float,
                     extend_sides_to_diagonal: bool = False) -> np.ndarray:
     return generate_physical_pinhole(radius=self.radius,
                                      canvas_radius=get_canvas_radius_nm(
                                          canvas_inner_radius_nm,
                                          extend_sides_to_diagonal),
                                      px_size_nm=px_size_nm)
Esempio n. 2
0
 def get_numpy_array(self,
                     canvas_inner_radius_nm: float,
                     px_size_nm: float,
                     extend_sides_to_diagonal: bool = False) -> np.ndarray:
     return generate_airy(amplitude=1.0,
                          fwhm=self.emission_wavelength / (2 * self.na),
                          canvas_radius=get_canvas_radius_nm(
                              canvas_inner_radius_nm,
                              extend_sides_to_diagonal),
                          px_size_nm=px_size_nm)
Esempio n. 3
0
 def get_numpy_array(self,
                     canvas_inner_radius_nm: float,
                     px_size_nm: float,
                     extend_sides_to_diagonal: bool = False) -> np.ndarray:
     return generate_airy(amplitude=self.amplitude,
                          fwhm=self.fwhm,
                          canvas_radius=get_canvas_radius_nm(
                              canvas_inner_radius_nm,
                              extend_sides_to_diagonal),
                          px_size_nm=px_size_nm)
Esempio n. 4
0
 def get_numpy_array(self,
                     canvas_inner_radius_nm: float,
                     px_size_nm: float,
                     extend_sides_to_diagonal: bool = False) -> np.ndarray:
     return generate_doughnut(periodicity=self.periodicity,
                              zero_intensity=self.zero_intensity,
                              canvas_radius=get_canvas_radius_nm(
                                  canvas_inner_radius_nm,
                                  extend_sides_to_diagonal),
                              px_size_nm=px_size_nm)
Esempio n. 5
0
    def get_radial_profile(self, canvas_inner_radius_nm: float,
                           px_size_nm: float) -> np.ndarray:
        outer_radius_nm = get_canvas_radius_nm(canvas_inner_radius_nm,
                                               extend_sides_to_diagonal=True)
        outer_radius_px, _ = get_canvas_dimensions_px(outer_radius_nm,
                                                      px_size_nm)

        pixels_2d = self.get_numpy_array(canvas_inner_radius_nm,
                                         px_size_nm,
                                         extend_sides_to_diagonal=True)
        return pixels_2d[outer_radius_px - 1, outer_radius_px - 1:]
Esempio n. 6
0
    def get_radial_profile(self, canvas_inner_radius_nm: float,
                           px_size_nm: float) -> np.ndarray:
        """ Returns a numpy array representation of the pattern data as a radial profile. """
        outer_radius_nm = get_canvas_radius_nm(canvas_inner_radius_nm,
                                               extend_sides_to_diagonal=True)
        outer_radius_px, _ = get_canvas_dimensions_px(outer_radius_nm,
                                                      px_size_nm)

        return_value = np.zeros(outer_radius_px)
        radial_profile_result = radial_profile(
            self.get_numpy_array(canvas_inner_radius_nm, px_size_nm))
        return_value[:len(radial_profile_result)] = radial_profile_result
        return return_value
def get_frc_curve_from_kernels2d(
        kernels2d: np.ndarray,
        run_instance: "mdl.RunInstance") -> Tuple[np.ndarray, np.ndarray]:
    """
    Returns a tuple that contains arrays of X and Y values respectively of the resulting FRC curve
    from the given simulated kernels. run_instance must be a RunInstance without any multivalues.
    """

    # Pixel size in nanometres
    px_size_nm = run_instance.imaging_system_settings.scanning_step_size

    # Radius in pixels of all 2D patterns (PSF, illumination patterns, pinholes etc.)
    canvas_inner_rad_nm = run_instance.simulation_settings.canvas_inner_radius
    canvas_outer_rad_nm = get_canvas_radius_nm(canvas_inner_rad_nm,
                                               extend_sides_to_diagonal=True)
    canvas_outer_rad_px, _ = get_canvas_dimensions_px(canvas_outer_rad_nm,
                                                      px_size_nm)

    # Calculate canvas parameters
    half_canvas_side = np.int(np.floor((canvas_outer_rad_px - 1) / 2))
    freq_arr = np.fft.fftfreq(2 * half_canvas_side - 1,
                              px_size_nm)[:half_canvas_side]
    freq_arr_step = freq_arr[1] - freq_arr[0]

    # Retrieve/calculate sample/detector related parameters
    combined_sample_properties = run_instance.sample_properties.get_combined_properties(
        px_size_nm)
    input_power = combined_sample_properties.input_power
    D_0_0 = combined_sample_properties.D_origin

    pinhole = run_instance.imaging_system_settings.pinhole_function
    noise_var = run_instance.detector_properties.get_total_readout_noise_var(
        canvas_inner_rad_nm, pinhole)
    # Fourier transform kernels
    ft_kernels2d = np.abs(np.fft.fft2(kernels2d))

    # Calculate the power of signal and power of noise
    Ps = input_power * (np.abs(ft_kernels2d[0])**2
                        )  # Denominator of eq (35) in publication
    Pn = D_0_0 * ft_kernels2d[
        1, 0, 0] + noise_var  # Numerator of eq (35) in publication
    frc_spectra2d = Ps / (Ps + Pn)  # Eq (35)
    frc_spectra = radial_profile(frc_spectra2d, fftshift=True)

    # Return X and Y values
    return np.arange(0, len(frc_spectra)) * freq_arr_step, frc_spectra
Esempio n. 8
0
    def get_numpy_array(self,
                        canvas_inner_radius_nm: Optional[float] = None,
                        px_size_nm: Optional[float] = None,
                        _: bool = False) -> np.ndarray:
        """
        Returns a numpy array representation of the 2D array. If canvas_inner_radius_nm and
        px_size_nm are set, the 2D array will be resized under the assumption that it has an
        inner radius of the same size as the constant canvas_inner_radius_nm.
        """

        if canvas_inner_radius_nm is not None and px_size_nm is not None:
            _, canvas_side_length_px = get_canvas_dimensions_px(
                get_canvas_radius_nm(canvas_inner_radius_nm), px_size_nm)
            canvas_size = (canvas_side_length_px, canvas_side_length_px)

            if self.value.shape != canvas_size:
                return resize(self.value, canvas_size, order=3)

        return self.value
Esempio n. 9
0
def expand_kernels_to_2d(*kernels,
                         canvas_inner_radius_nm: float, px_size_nm: float) -> np.ndarray:
    """
    Expands radial kernels to 2D arrays. The output will be an array containing these 2D arrays.
    """

    canvas_outer_rad_px, _ = get_canvas_dimensions_px(
        get_canvas_radius_nm(canvas_inner_radius_nm, extend_sides_to_diagonal=True), px_size_nm
    )
    half_side = np.int(np.floor((canvas_outer_rad_px - 1) / 2))

    kernels2d = np.array([
        expand_dimensions(
            np.linspace(0, canvas_outer_rad_px - 1, canvas_outer_rad_px),
            kernels[i], half_side
        )
        for i in range(len(kernels))
    ])

    return kernels2d
def _simulate_single(
        run_instance: "mdl.RunInstance") -> Tuple[np.ndarray, np.ndarray]:
    """
    Main function to run the simulations. run_instance must be a RunInstance without any
    multivalues.
    """

    px_size_nm = run_instance.imaging_system_settings.scanning_step_size  # Pixel size nanometers

    # Radius in pixels of all 2D patterns (PSF, illumination patterns, pinholes etc.)
    canvas_inner_rad_nm = run_instance.simulation_settings.canvas_inner_radius
    canvas_outer_rad_nm = get_canvas_radius_nm(canvas_inner_rad_nm,
                                               extend_sides_to_diagonal=True)
    canvas_outer_rad_px, _ = get_canvas_dimensions_px(canvas_outer_rad_nm,
                                                      px_size_nm)

    # Calculate G(x,y), the convolution of the detection PSF and the pinhole function
    psf = run_instance.imaging_system_settings.optical_psf
    pinhole = run_instance.imaging_system_settings.pinhole_function

    radial_psf_and_pinhole = (
        isinstance(psf.pattern_data, mdl.RadialPatternData)
        and isinstance(pinhole.pattern_data, mdl.RadialPatternData))

    psf_arr = psf.get_numpy_array(
        canvas_inner_rad_nm,
        px_size_nm,
        extend_sides_to_diagonal=radial_psf_and_pinhole)
    #Create 2D array with 2D-sum = 1
    psf_arr = psf_arr / psf_arr.sum()
    pinhole_arr = pinhole.get_numpy_array(
        canvas_inner_rad_nm,
        px_size_nm,
        extend_sides_to_diagonal=radial_psf_and_pinhole)

    G_2D = fftconvolve(pinhole_arr, psf_arr, mode="same")
    G2_2D = fftconvolve(pinhole_arr**2, psf_arr, mode="same")
    if radial_psf_and_pinhole:
        G_rad = G_2D[canvas_outer_rad_px - 1, canvas_outer_rad_px - 1:]
        G2_rad = G2_2D[canvas_outer_rad_px - 1][canvas_outer_rad_px - 1:]
    else:
        G_rad = np.zeros(canvas_outer_rad_px)
        G2_rad = np.zeros(canvas_outer_rad_px)
        radial_profile_result = radial_profile(G_2D)
        radial_profile_result_2 = radial_profile(G2_2D)
        G_rad[:len(radial_profile_result)] = radial_profile_result
        G2_rad[:len(radial_profile_result)] = radial_profile_result_2

    # Calculate collection efficiency
    if isinstance(psf.pattern_data, mdl.AiryNAPatternData):
        collection_efficiency = na_to_collection_efficiency(
            run_instance.imaging_system_settings.optical_psf.pattern_data.na,
            run_instance.imaging_system_settings.refractive_index)
    else:
        raise ValueError(
            "Unsupported optical PSF type (only Airy from NA is currently supported)"
        )

    # Calculate ON-state probabilities after illumination
    P_on = np.zeros(canvas_outer_rad_px)
    for pulse_index, pulse in enumerate(run_instance.pulse_scheme.pulses):
        illumination_pattern_rad = pulse.illumination_pattern.get_radial_profile(
            canvas_inner_rad_nm, px_size_nm)
        response = run_instance.fluorophore_settings.get_response(
            pulse.wavelength)

        if pulse_index < len(run_instance.pulse_scheme.pulses) - 1:
            P_on = expected_P_on(
                P_pre=P_on,
                R_on=pulse.max_intensity * response.cross_section_off_to_on *
                illumination_pattern_rad,
                R_off=pulse.max_intensity * response.cross_section_on_to_off *
                illumination_pattern_rad,
                T_exp=pulse.duration)
        else:  # Last pulse (readout pulse)
            exp_kernel, var_kernel = make_kernels(
                num_fluorophore_simulations=run_instance.simulation_settings.
                num_kernel_detection_iterations,
                quantum_efficiency=run_instance.detector_properties.
                quantum_efficiency,
                collection_efficiency=collection_efficiency,
                max_intensity=pulse.max_intensity,
                relative_readout_intensity=illumination_pattern_rad,
                P_pre=P_on,
                CS_on_switch=response.cross_section_off_to_on,
                CS_off_switch=response.cross_section_on_to_off,
                CS_fluorescent=response.cross_section_emission,
                T_obs=pulse.duration,
                G=G_rad,
                G2=G2_rad)

            return exp_kernel, var_kernel

    raise ValueError("Input didn't contain any pulses!")