def test_propagation_round_trip():
    screen = phasescreen.ft_phase_screen(0.16, 512, 4.2 / 512, 100, 0.01)

    # Input E Field
    E = numpy.exp(1j * screen)

    prop1 = opticalpropagation.angularSpectrum(E, 500e-9, 4.2 / 512, 4.2 / 512, 10000.)
    prop2 = opticalpropagation.angularSpectrum(prop1, 500e-9, 4.2 / 512, 4.2 / 512, -10000.)

    assert numpy.allclose(E, prop2)
Beispiel #2
0
def test_propagation_round_trip():
    screen = phasescreen.ft_phase_screen(0.16, 512, 4.2 / 512, 100, 0.01)

    # Input E Field
    E = numpy.exp(1j * screen)

    prop1 = opticalpropagation.angularSpectrum(E, 500e-9, 4.2 / 512, 4.2 / 512,
                                               10000.)
    prop2 = opticalpropagation.angularSpectrum(prop1, 500e-9, 4.2 / 512,
                                               4.2 / 512, -10000.)

    assert numpy.allclose(E, prop2)
def test_propagation_conserves_intensity():
    screen = phasescreen.ft_phase_screen(0.16, 512, 4.2 / 512, 100, 0.01)

    # Input E Field
    E = numpy.exp(1j * screen)

    Em = E * circle(150, 512)
    sum1 = (abs(Em) ** 2).sum()
    prop1 = opticalpropagation.angularSpectrum(Em, 500e-9, 4.2 / 512, 4.2 / 512, 10000.)
    sum2 = (abs(prop1) ** 2).sum()

    assert numpy.allclose(sum1, sum2)
Beispiel #4
0
def test_propagation_conserves_intensity():
    screen = phasescreen.ft_phase_screen(0.16, 512, 4.2 / 512, 100, 0.01)

    # Input E Field
    E = numpy.exp(1j * screen)

    Em = E * circle(150, 512)
    sum1 = (abs(Em)**2).sum()
    prop1 = opticalpropagation.angularSpectrum(Em, 500e-9, 4.2 / 512,
                                               4.2 / 512, 10000.)
    sum2 = (abs(prop1)**2).sum()

    assert numpy.allclose(sum1, sum2)
Beispiel #5
0
def physical_atmosphere_propagation(
            phase_screens, output_mask, layer_altitudes, source_altitude,
            wavelength, output_pixel_scale,
            propagation_direction="up"):
    '''
    Finds total line of sight complex amplitude by propagating light through phase screens

    Parameters:
        radii (dict, optional): Radii of each meta pupil of each screen height in pixels. If not given uses pupil radius.
        apos (ndarray, optional):  The angular position of the GS in radians. If not set, will use the config position
    '''

    scrnNo = len(phase_screens)
    z_total = 0
    scrnRange = range(0, scrnNo)

    nx_output_pixels = phase_screens[0].shape[0]

    phs2Rad = 2 * numpy.pi / (wavelength * 10 ** 9)

    # Get initial up/down dependent params
    if propagation_direction == "up":
        ht = 0
        ht_final = source_altitude
        if ht_final==0:
            raise ValueError("Can't propagate up to infinity")
        scrnAlts = layer_altitudes

        EFieldBuf = output_mask.copy().astype(CDTYPE)
        logger.debug("Create EField Buf of mask")

    else:
        ht = layer_altitudes[scrnNo-1]
        ht_final = 0
        scrnAlts = layer_altitudes[::-1]
        phase_screens = phase_screens[::-1]
        EFieldBuf = numpy.exp(
                1j*numpy.zeros((nx_output_pixels,) * 2)).astype(CDTYPE)
        logger.debug("Create EField Buf of zero phase")

    # Propagate to first phase screen (if not already there)
    if ht!=scrnAlts[0]:
        logger.debug("propagate to first phase screen")
        z = abs(scrnAlts[0] - ht)
        z_total += z
        EFieldBuf[:] = opticalpropagation.angularSpectrum(
                    EFieldBuf, wavelength,
                    output_pixel_scale, output_pixel_scale, z)

    # Go through and propagate between phase screens
    for i in scrnRange:

        phase = phase_screens[i]
        # print("Got phase")

        # Convert phase to radians
        phase *= phs2Rad

        # Change sign if propagating up
        if propagation_direction == 'up':
            phase *= -1
        # print("Get distance")
        # Get propagation distance for this layer
        if i==(scrnNo-1):
            z = abs(ht_final - ht) - z_total
        else:
            z = abs(scrnAlts[i+1] - scrnAlts[i])

        # Update total distance counter
        z_total += z

        # print("Make EField")
        # Apply phase to EField
        EFieldBuf *= numpy.exp(1j*phase)

        # Do ASP for last layer to next
        EFieldBuf[:] = opticalpropagation.angularSpectrum(
                    EFieldBuf, wavelength,
                    output_pixel_scale, output_pixel_scale, z)

        # logger.debug("Propagation: {}, {} m. Total: {}".format(i, z, z_total))

    return EFieldBuf
Beispiel #6
0
def physical_atmosphere_propagation(
            phase_screens, output_mask, layer_altitudes, source_altitude,
            wavelength, output_pixel_scale,
            propagation_direction="up"):
    '''
    Finds total line of sight complex amplitude by propagating light through phase screens

    Parameters:
        radii (dict, optional): Radii of each meta pupil of each screen height in pixels. If not given uses pupil radius.
        apos (ndarray, optional):  The angular position of the GS in radians. If not set, will use the config position
    '''

    scrnNo = len(phase_screens)
    z_total = 0
    scrnRange = range(0, scrnNo)
    prop_scrns = phase_screens.copy()

    nx_output_pixels = phase_screens[0].shape[0]

    phs2Rad = 2 * numpy.pi / (wavelength * 10 ** 9)

    # Get initial up/down dependent params
    if propagation_direction == "up":
        ht = 0
        ht_final = source_altitude
        if ht_final==0:
            raise ValueError("Can't propagate up to infinity")
        scrnAlts = layer_altitudes

        EFieldBuf = output_mask.copy().astype(CDTYPE)
        logger.debug("Create EField Buf of mask")

    else:
        ht = layer_altitudes[scrnNo-1]
        ht_final = 0
        scrnAlts = layer_altitudes[::-1]
        prop_scrns = prop_scrns[::-1]
        EFieldBuf = numpy.exp(
                1j*numpy.zeros((nx_output_pixels,) * 2)).astype(CDTYPE)
        logger.debug("Create EField Buf of zero phase")

    # Propagate to first phase screen (if not already there)
    if ht!=scrnAlts[0]:
        logger.debug("propagate to first phase screen")
        z = abs(scrnAlts[0] - ht)
        z_total += z
        EFieldBuf[:] = opticalpropagation.angularSpectrum(
                    EFieldBuf, wavelength,
                    output_pixel_scale, output_pixel_scale, z)

    # Go through and propagate between phase screens
    for i in scrnRange:

        phase = prop_scrns[i]
        # print("Got phase")

        # Convert phase to radians
        phase *= phs2Rad

        # Change sign if propagating up
        if propagation_direction == 'up':
            phase *= -1
        # print("Get distance")
        # Get propagation distance for this layer
        if i==(scrnNo-1):
            z = abs(ht_final - ht) - z_total
        else:
            z = abs(scrnAlts[i+1] - scrnAlts[i])

        # Update total distance counter
        z_total += z

        # print("Make EField")
        # Apply phase to EField
        EFieldBuf *= numpy.exp(1j*phase)

        # Do ASP for last layer to next
        EFieldBuf[:] = opticalpropagation.angularSpectrum(
                    EFieldBuf, wavelength,
                    output_pixel_scale, output_pixel_scale, z)

        # logger.debug("Propagation: {}, {} m. Total: {}".format(i, z, z_total))

    return EFieldBuf
Beispiel #7
0
def physical_atmosphere_propagation(phase_screens,
                                    output_mask,
                                    layer_altitudes,
                                    source_altitude,
                                    wavelength,
                                    output_pixel_scale,
                                    propagation_direction="up",
                                    input_efield=None):
    '''
    Finds total line of sight complex amplitude by propagating light through phase screens

    If the source altitude is infinity (denoted as 0), then the result of the propagation is
    the

    Parameters:
        
    '''

    scrnNo = len(phase_screens)
    z_total = 0
    scrnRange = range(0, scrnNo)

    nx_output_pixels = phase_screens[0].shape[0]

    phs2Rad = 2 * numpy.pi / (wavelength * 10**9)

    if input_efield is None:
        EFieldBuf = numpy.exp(1j * numpy.zeros(
            (nx_output_pixels, ) * 2)).astype(CDTYPE)

    # Get initial up/down dependent params
    if propagation_direction == "up":
        ht = 0
        ht_final = source_altitude
        # if ht_final==0:
        #     raise ValueError("Can't propagate up to infinity")
        scrnAlts = layer_altitudes
        # If propagating up from telescope, apply mask to the EField
        EFieldBuf *= output_mask
        logger.debug("Create EField Buf of mask")

    else:
        ht = layer_altitudes[scrnNo - 1]
        ht_final = 0
        scrnAlts = layer_altitudes[::-1]
        phase_screens = phase_screens[::-1]
        logger.debug("Create EField Buf of zero phase")

    # Propagate to first phase screen (if not already there)
    if ht != scrnAlts[0]:
        logger.debug("propagate to first phase screen")
        z = abs(scrnAlts[0] - ht)
        z_total += z
        EFieldBuf[:] = opticalpropagation.angularSpectrum(
            EFieldBuf, wavelength, output_pixel_scale, output_pixel_scale, z)

    # Go through and propagate between phase screens
    for i in scrnRange:

        phase = phase_screens[i]
        # print("Got phase")

        # Convert phase to radians
        phase *= phs2Rad

        # Apply phase to EField
        EFieldBuf *= numpy.exp(1j * phase)

        # Change sign if propagating up
        # if propagation_direction == 'up':
        #     phase *= -1
        # print("Get distance")
        # Get propagation distance for this layer
        if i == (scrnNo - 1):
            if ht_final == 0:
                # if the final height is infinity, don't propagate any more!
                continue
            else:
                z = abs(ht_final - ht) - z_total
        else:
            z = abs(scrnAlts[i + 1] - scrnAlts[i])

        # Update total distance counter
        z_total += z

        # print("Make EField")

        # Do ASP for last layer to next
        EFieldBuf[:] = opticalpropagation.angularSpectrum(
            EFieldBuf, wavelength, output_pixel_scale, output_pixel_scale, z)

        # logger.debug("Propagation: {}, {} m. Total: {}".format(i, z, z_total))

    return EFieldBuf
Beispiel #8
0
    def makePhasePhys(self, radii=None, apos=None):
        '''
        Finds total line of sight complex amplitude by propagating light through phase screens

        Parameters:
            radii (dict, optional): Radii of each meta pupil of each screen height in pixels. If not given uses pupil radius.
            apos (ndarray, optional):  The angular position of the GS in radians. If not set, will use the config position
        '''

        scrnNo = len(self.scrns)
        z_total = 0
        scrnRange = range(0, scrnNo)

        # Get initial up/down dependent params
        if self.propagationDirection == "up":
            ht = 0
            ht_final = self.config.height
            if ht_final==0:
                raise ValueError("Can't propagate up to infinity")
            scrnAlts = self.atmosConfig.scrnHeights

            self.EFieldBuf = self.outMask.copy().astype(CDTYPE)
            logger.debug("Create EField Buf of mask")

        else:
            ht = self.atmosConfig.scrnHeights[scrnNo-1]
            ht_final = 0
            scrnRange = scrnRange[::-1]
            scrnAlts = self.atmosConfig.scrnHeights[::-1]
            self.EFieldBuf = numpy.exp(
                    1j*numpy.zeros((self.nx_out_pixels,) * 2)).astype(CDTYPE)
            logger.debug("Create EField Buf of zero phase")

        # Propagate to first phase screen (if not already there)
        if ht!=scrnAlts[0]:
            logger.debug("propagate to first phase screen")
            z = abs(scrnAlts[0] - ht)
            self.EFieldBuf[:] = opticalpropagation.angularSpectrum(
                        self.EFieldBuf, self.wavelength,
                        self.out_pixel_scale, self.out_pixel_scale, z)

        # Go through and propagate between phase screens
        for i in scrnRange:
            # Check optional radii and position
            if radii is None:
                radius = None
            else:
                radius = radii[i]

            if self.metaPupilPos is None:
                pos = None
            else:
                pos = self.metaPupilPos[i]

            # Get phase for this layer
            phase = self.getMetaPupilPhase(
                    self.scrns[i],
                    self.atmosConfig.scrnHeights[i], radius=radius, pos=pos)

            # Convert phase to radians
            phase *= self.phs2Rad

            # Change sign if propagating up
            if self.propagationDirection == 'up':
                self.phase *= -1

            # Get propagation distance for this layer
            if i==(scrnNo-1):
                z = abs(ht_final - ht) - z_total
            else:
                z = abs(scrnAlts[i+1] - scrnAlts[i])

            # Update total distance counter
            z_total += z

            # Apply phase to EField
            self.EFieldBuf *= numpy.exp(1j*phase)

            # Do ASP for last layer to next
            self.EFieldBuf[:] = opticalpropagation.angularSpectrum(
                        self.EFieldBuf, self.wavelength,
                        self.out_pixel_scale, self.out_pixel_scale, z)

            logger.debug("Propagation: {}, {} m. Total: {}".format(i, z, z_total))

            self.EField[:] = self.EFieldBuf

        return self.EField