Пример #1
0
def elaz2radec_lst(el, az, lst, lat = 38.43312) :
    """DO NOT USE THIS ROUTINE FOR ANTHING THAT NEEDS TO BE RIGHT.  IT DOES NOT
    CORRECT FOR PRECESSION.

    Calculates the Ra and Dec from elavation, aximuth, LST and Latitude.

    This function is vectorized with numpy so should be fast.  Standart numpy
    broadcasting should also work.

    All angles in degrees, lst in seconds. Latitude defaults to GBT.
    """

    # Convert everything to radians.
    el = sp.radians(el)
    az = sp.radians(az)
    lst = sp.array(lst, dtype = float)*2*sp.pi/86400
    lat = sp.radians(lat)
    # Calculate dec.
    dec = sp.arcsin(sp.sin(el)*sp.sin(lat) +
                    sp.cos(el)*sp.cos(lat)*sp.cos(az))
    # Calculate the hour angle
    ha = sp.arccos((sp.sin(el) - sp.sin(lat)*sp.sin(dec)) /
                   (sp.cos(lat)*sp.cos(dec)))
    ra = sp.degrees(lst - ha) % 360

    return ra, sp.degrees(dec)
Пример #2
0
def elaz2radec_lst(el, az, lst, lat=38.43312):
    """DO NOT USE THIS ROUTINE FOR ANTHING THAT NEEDS TO BE RIGHT.  IT DOES NOT
    CORRECT FOR PRECESSION.

    Calculates the Ra and Dec from elavation, aximuth, LST and Latitude.

    This function is vectorized with numpy so should be fast.  Standart numpy
    broadcasting should also work.

    All angles in degrees, lst in seconds. Latitude defaults to GBT.
    """

    # Convert everything to radians.
    el = sp.radians(el)
    az = sp.radians(az)
    lst = sp.array(lst, dtype=float) * 2 * sp.pi / 86400
    lat = sp.radians(lat)
    # Calculate dec.
    dec = sp.arcsin(
        sp.sin(el) * sp.sin(lat) + sp.cos(el) * sp.cos(lat) * sp.cos(az))
    # Calculate the hour angle
    ha = sp.arccos(
        (sp.sin(el) - sp.sin(lat) * sp.sin(dec)) / (sp.cos(lat) * sp.cos(dec)))
    ra = sp.degrees(lst - ha) % 360

    return ra, sp.degrees(dec)
Пример #3
0
    def transformPicture(self, accelData):
        x, y, z = accelData[0], accelData[1], accelData[2]
        offset = 512
        # rotate
        if self.wm.buttons["A"]:
            self.c += 1
            print(self.c)
            if self.c % 2 == 0:
                centeredZ = z - offset
                centeredX = x - offset
                rot_angle = int(
                    -(scipy.degrees(scipy.arctan2(centeredZ, centeredX)) - 90))
                if rot_angle < 0:
                    rot_angle = 360 + rot_angle
                self.image.setPixmap(
                    self.pixmap.transformed(
                        QtGui.QTransform().rotate(rot_angle),
                        1).scaledToHeight(400))

        # zoom
        if self.wm.buttons["Down"]:
            centeredZ = z - offset
            centeredY = y - offset

            tilt_angle = scipy.degrees(scipy.arctan2(centeredZ,
                                                     centeredY)) - 90
            scale_val = abs(tilt_angle / 100)
            self.image.setPixmap(
                self.pixmap.transformed(QtGui.QTransform().scale(
                    scale_val, scale_val)))
Пример #4
0
def main():
    satstress_test_dir = os.path.dirname(os.path.abspath(__file__))
    test_outfile = os.path.join(satstress_test_dir, "test_nsr_diurnal.pkl")
    test_satellite = os.path.join("input", "Europa.satellite")

    # Create a new satellite object, as defined by the input file:
    the_sat = satstress.Satellite(open(test_satellite, 'r'))

    # Create a StressCalc object, that calculates both the NSR and Diurnal
    # stresses on the Satellite just instantiated:
    the_stresses = satstress.StressCalc(
        [satstress.Diurnal(the_sat),
         satstress.NSR(the_sat)])

    # do a series of calculations, varying all the inputs at each iteration
    theta = 0.0
    phi = 0.0
    t = 0.0

    # a list to store the calculation results in for later checking
    Taulist = []

    while the_stresses.stresses[1].Delta(
    ) > 0.01 and t < 2.0 * scipy.pi / the_sat.mean_motion():
        print("""Tau(theta = %g, phi = %g, time = %g, Delta = %g) = """ %
              (scipy.degrees(theta), scipy.degrees(phi), t,
               the_stresses.stresses[1].Delta()))
        Taulist.append(the_stresses.tensor(theta=theta, phi=phi, t=0))
        print Taulist[-1], "\n"
        theta = theta + scipy.pi / 23.0
        phi = phi + scipy.pi / 11.0
        t = t + (scipy.pi / 11.0) / the_sat.mean_motion()

        # Re-construct the NSR stress (and the_stresses StressCalc object)
        # changing the forcing period, so that we can have the NSR stresses
        # vary with each iteration too.
        the_sat.nsr_period = the_sat.nsr_period / 1.5
        the_stresses = satstress.StressCalc(
            [satstress.Diurnal(the_sat),
             satstress.NSR(the_sat)])

    # Now we want to compare this against reference output, just to make sure
    # that we're getting the right numbers...

    pickledTau = pickle.load(open(test_outfile, 'r'))
    for (tau1, tau2) in zip(Taulist, pickledTau):
        if tau1.all() != tau2.all():
            print("\nTest failed.  :(\n")
            sys.exit(1)

    print("\nTest passed! :)\n")
    sys.exit()
Пример #5
0
def matrixToEuler(m,order='Aerospace',inDegrees=True):
    if order == 'Aerospace' or order == 'ZYX':
        sp = -m[2,0]
        if sp < (1-EPS):
            if sp > (-1+EPS):
                p = arcsin(sp)
                r = arctan2(m[2,1],m[2,2])
                y = arctan2(m[1,0],m[0,0])
            else:
                p = -pi/2.
                r = 0
                y = pi-arctan2(-m[0,1],m[0,2])
        else:
            p = pi/2.
            y = arctan2(-m[0,1],m[0,2])
            r = 0
        
        if inDegrees:
            return degrees((y,p,r))
        else:
            return (y,p,r)
    elif order == 'BVH' or order == 'ZXY':
        sx = m[2,1]
        if sx < (1-EPS):
            if sx > (-1+EPS):
                x = arcsin(sx)
                z = arctan2(-m[0,1],m[1,1])
                y = arctan2(-m[2,0],m[2,2])
            else:
                x = -pi/2
                y = 0
                z = -arctan2(m[0,2],m[0,0])
        else:
            x = pi/2
            y = 0
            z = arctan2(m[0,2],m[0,0])
        if inDegrees:
            return degrees((z,x,y))
        else:
            return (z,x,y)

    elif order == "ZXZ":
        x = arccos(m[2,2])
        z2 = arctan2(m[2,0],m[2,1])
        z1 = arctan2(m[0,2],-m[1,2])
        if inDegrees:
            return degrees((z1,x,z2))
        else:
            return (z1,x,z2)
Пример #6
0
 def _update_strain(self):
     self.e = (self.exy - self.eyx) / 2
     self.k = (self.exx + self.eyy) * 1000000. / 2
     self.strain = scipy.sqrt((self.exx - self.eyy) * (self.exx - self.eyy) + (self.exy + self.eyx) * (self.exy + self.eyx)) * 1000000.
     self.k_max = self.k + self.strain / 2
     self.k_min = self.k - self.strain / 2
     self.az = scipy.degrees(2 * scipy.arctan2(self.exy + self.eyx, self.eyy - self.exx))
Пример #7
0
def apparent_elevation(theta_true, height):
    """
    Calculate the apparent elevation of the target.
    :param theta_true: The true elevation angle (degrees).
    :param height: The height of the radar (km).
    :return: The apparent elevation angle of the target (degrees).
    """
    def integrand(z):
        """
        Determine the integrand for calculating the apparent elevation angle.
        :param z: The altitude (km).
        :return: The integrand.
        """

        # Effective radius of the Earth (km)
        re = 6378.137

        # Standard values
        a = 0.000315
        b = 0.1361

        # Refractive index and derivative as a function of altitude
        n_z = 1. + a * exp(-b * z)
        np_z = -(a * b * exp(-b * z))

        # Refractive index at the given height
        n_h = 1. + a * exp(-b * height)

        tan_phi = tan(
            arccos(((re + height) * n_h) / ((re + z) * n_z) *
                   cos(radians(theta_true))))

        return np_z / (n_z * tan_phi)

    return theta_true - degrees(integrate.romberg(integrand, height, 1000))
Пример #8
0
 def edgeStrength(self, phgeo, mask, kernelw):
     edges = canny(phgeo, sigma=kernelw)
     bounds = find_boundaries(edges, mode='thick')
     slopedeg = degrees(self.slope(phgeo))
     histv, _ = np.histogram(abs(slopedeg[(bounds & mask)]),
                             bins=self._slopeBins)
     return histv
    def _update_canvas(self):
        """
        Update the figure when the user changes an input value.
        :return:
        """
        frequency = float(self.frequency.text())
        cone_half_angle = radians(float(self.cone_half_angle.text()))
        base_radius = float(self.base_radius.text())

        # Set the incident angles
        incident_angle = linspace(0, pi, 1801)

        # Calculate the radar cross section
        rcs = array([
            radar_cross_section(frequency, cone_half_angle, base_radius, ia)
            for ia in incident_angle
        ])

        # Clear the axes for the updated plot
        self.axes1.clear()

        # Display the results
        self.axes1.plot(degrees(incident_angle),
                        10 * log10(rcs[:, 0]),
                        '',
                        label='VV')
        self.axes1.plot(degrees(incident_angle),
                        10 * log10(rcs[:, 1]),
                        '--',
                        label='HH')

        # Set the plot title and labels
        self.axes1.set_title('RCS vs Incident Angle', size=14)
        self.axes1.set_ylabel('RCS (dBsm)', size=12)
        self.axes1.set_xlabel('Incident Angle (deg)', size=12)

        # Set the tick label size
        self.axes1.tick_params(labelsize=12)

        # Set the legend
        self.axes1.legend(loc='upper right', prop={'size': 10})

        # Turn on the grid
        self.axes1.grid(linestyle=':', linewidth=0.5)

        # Update the canvas
        self.my_canvas.draw()
Пример #10
0
    def _update_canvas(self):
        """
        Update the figure when the user changes an input value
        :return:
        """
        # Get the parameters from the form
        frequency = float(self.frequency.text())
        number_of_elements = int(self.number_of_elements.text())
        scan_angle = float(self.scan_angle.text())
        element_spacing = float(self.element_spacing.text())
        side_lobe_level = float(self.side_lobe_level.text())

        # Get the selected antenna from the form
        antenna_type = self.antenna_type.currentText()

        # Set the angular span
        theta = linspace(0.0, pi, 1000)

        # Set up the args
        kwargs = {
            'number_of_elements': number_of_elements,
            'scan_angle': radians(scan_angle),
            'element_spacing': element_spacing,
            'frequency': frequency,
            'theta': theta,
            'window_type': antenna_type,
            'side_lobe_level': side_lobe_level
        }

        # Get the array factor
        af = linear_array.array_factor(**kwargs)

        # Clear the axes for the updated plot
        self.axes1.clear()

        # Create the line plot
        self.axes1.plot(degrees(theta),
                        20.0 * log10(abs(af) + finfo(float).eps), '')

        # Set the y axis limit
        self.axes1.set_ylim(-80, 5)

        # Set the x and y axis labels
        self.axes1.set_xlabel("Theta (degrees)", size=12)
        self.axes1.set_ylabel("Array Factor (dB)", size=12)

        # Turn on the grid
        self.axes1.grid(linestyle=':', linewidth=0.5)

        # Set the plot title and labels
        self.axes1.set_title('Linear Array Antenna Pattern', size=14)

        # Set the tick label size
        self.axes1.tick_params(labelsize=12)

        # Update the canvas
        self.my_canvas.draw()
Пример #11
0
 def errorAngle(actual,estimate):        
     error = actual*estimate.conjugate()
     error.normalise()
     # Cast error to float so that we can deal with fixed point numbers
     # throws an error otherwise
     eAngle = degrees(2*arccos(float(error.w)))
     
     eAngle = abs(eAngle - 360) if eAngle > 180 else eAngle
     return eAngle
Пример #12
0
 def collectData(self, accelData):
     if self.count < 32:
         self.count += 1
         x, z = accelData[0], accelData[2]
         rot_angle = int(-(scipy.degrees(scipy.arctan2(z - 512, x - 512)) -
                           90))
         self.list.append(rot_angle)
     else:
         self.transformPicture(accelData)
         self.count = 0
         self.list = []
Пример #13
0
 def _update_strain(self):
     self.e = (self.exy - self.eyx) / 2
     self.k = (self.exx + self.eyy) * 1000000. / 2
     self.strain = scipy.sqrt((self.exx - self.eyy) *
                              (self.exx - self.eyy) +
                              (self.exy + self.eyx) *
                              (self.exy + self.eyx)) * 1000000.
     self.k_max = self.k + self.strain / 2
     self.k_min = self.k - self.strain / 2
     self.az = scipy.degrees(
         2 * scipy.arctan2(self.exy + self.eyx, self.eyy - self.exx))
Пример #14
0
def nichols_plot(sys_list, omega=None, grid=None):
    """Nichols plot for a system

    Plots a Nichols plot for the system over a (optional) frequency range.

    Parameters
    ----------
    sys_list : list of LTI, or LTI
        List of linear input/output systems (single system is OK)
    omega : array_like
        Range of frequencies (list or bounds) in rad/sec
    grid : boolean, optional
        True if the plot should include a Nichols-chart grid. Default is True.

    Returns
    -------
    None
    """
    # Get parameter values
    grid = config._get_param('nichols', 'grid', grid, True)

    # If argument was a singleton, turn it into a list
    if not getattr(sys_list, '__iter__', False):
        sys_list = (sys_list, )

    # Select a default range if none is provided
    if omega is None:
        omega = default_frequency_range(sys_list)

    for sys in sys_list:
        # Get the magnitude and phase of the system
        mag_tmp, phase_tmp, omega = sys.freqresp(omega)
        mag = np.squeeze(mag_tmp)
        phase = np.squeeze(phase_tmp)

        # Convert to Nichols-plot format (phase in degrees,
        # and magnitude in dB)
        x = unwrap(sp.degrees(phase), 360)
        y = 20 * sp.log10(mag)

        # Generate the plot
        plt.plot(x, y)

    plt.xlabel('Phase (deg)')
    plt.ylabel('Magnitude (dB)')
    plt.title('Nichols Plot')

    # Mark the -180 point
    plt.plot([-180], [0], 'r+')

    # Add grid
    if grid:
        nichols_grid()
Пример #15
0
def calSquareDegree_conver(sqdeg,dec0):
    """
    input sqdeg: unit in deg.
    dec0: dec center in decimal deg.
    assume decw = sqrt(sqdeg)
    return: raw

    ref:http://en.wikipedia.org/wiki/Solid_angle
    """
    sa = sqdeg/((180./S.pi)**2)
    decw = S.sqrt(sqdeg)
    raw = S.degrees(sa /(S.sin(S.radians(dec0+decw/2.) ) - S.sin(S.radians(dec0-decw/2.))))
    return raw
Пример #16
0
 def stopRecordingRot(self):
     self.wm.accelerometer.unregister_callback(self.recordAccel)
     for value in self.currentGestureData:
         x, y, z = value[0], value[1], value[2]
         rot_angle = int(-(sp.degrees(sp.arctan2(z-512, x-512)) - 90))
         self.rotList.append(rot_angle)
     print(self.rotList)
     self.currentGestureData = []
     direction = self.getDirection()
     if direction == 1:
         self.callback(2)
     else:
         self.callback(-2)
Пример #17
0
def calSquareDegree_conver(sqdeg,dec0):
    """
    input sqdeg: unit in deg.
    dec0: dec center in decimal deg.
    assume decw = sqrt(sqdeg)
    return: raw

    ref:http://en.wikipedia.org/wiki/Solid_angle
    """
    sa = sqdeg/((180./S.pi)**2)
    decw = S.sqrt(sqdeg)
    raw = S.degrees(sa /(S.sin(S.radians(dec0+decw/2.) ) - S.sin(S.radians(dec0-decw/2.))))
    return raw
Пример #18
0
def nichols_plot(syslist, omega=None, grid=True):
    """Nichols plot for a system

    Plots a Nichols plot for the system over a (optional) frequency range.

    Parameters
    ----------
    syslist : list of LTI, or LTI
        List of linear input/output systems (single system is OK)
    omega : array_like
        Range of frequencies (list or bounds) in rad/sec
    grid : boolean, optional
        True if the plot should include a Nichols-chart grid. Default is True.

    Returns
    -------
    None
    """

    # If argument was a singleton, turn it into a list
    if (not getattr(syslist, '__iter__', False)):
        syslist = (syslist,)

    # Select a default range if none is provided
    if omega is None:
        omega = default_frequency_range(syslist)

    for sys in syslist:
        # Get the magnitude and phase of the system
        mag_tmp, phase_tmp, omega = sys.freqresp(omega)
        mag = np.squeeze(mag_tmp)
        phase = np.squeeze(phase_tmp)

        # Convert to Nichols-plot format (phase in degrees,
        # and magnitude in dB)
        x = unwrap(sp.degrees(phase), 360)
        y = 20*sp.log10(mag)

        # Generate the plot
        plt.plot(x, y)

    plt.xlabel('Phase (deg)')
    plt.ylabel('Magnitude (dB)')
    plt.title('Nichols Plot')

    # Mark the -180 point
    plt.plot([-180], [0], 'r+')

    # Add grid
    if grid:
        nichols_grid()
    def transformPicture(self, accelData):
        x, y, z = accelData[0], accelData[1], accelData[2]
        offset = 512
        # rotate
        if self.wm.buttons["A"]:
            self.c += 1
            print(self.c)
            if self.c % 2 == 0:
                centeredZ = z - offset
                centeredX = x - offset
                rot_angle = int(-(scipy.degrees(scipy.arctan2(centeredZ, centeredX)) - 90))
                if rot_angle < 0:
                    rot_angle = 360 + rot_angle
                self.image.setPixmap(self.pixmap.transformed(
                    QtGui.QTransform().rotate(rot_angle), 1).scaledToHeight(400))

        # zoom
        if self.wm.buttons["Down"]:
            centeredZ = z - offset
            centeredY = y - offset

            tilt_angle = scipy.degrees(scipy.arctan2(centeredZ, centeredY)) - 90
            scale_val = abs(tilt_angle / 100)
            self.image.setPixmap(self.pixmap.transformed(QtGui.QTransform().scale(scale_val, scale_val)))
Пример #20
0
	def __init__(self, foilid, material, top_radius_cm, bottom_radius_cm, angle_rad):
		self.foilid   = foilid
		self.material = material

		self.top_radius_cm    = top_radius_cm
		self.bottom_radius_cm = bottom_radius_cm
		self.angle_rad = angle_rad
		self.angle_deg = scipy.degrees(self.angle_rad)
		self.geo_area_cm2 = self.getGeometricalArea()

		self.use_flag_mark = ' '			

		self.roughness_A = 0.0 
		self.n_spoke1    = 0
		self.n_spoke2    = 0
		self.spoke1_wid  = 0.0
		self.spoke2_wid  = 0.0		
Пример #21
0
 def zoomPicture(self, accelData):
     y, z = accelData[1], accelData[2]
     offset = 512
     centeredZ = z - offset
     centeredY = y - offset
     tilt_angle = scipy.degrees(scipy.arctan2(centeredZ, centeredY)) - 90
     if tilt_angle <= -90:
         tilt_angle = 360 + tilt_angle
     scale_val = (tilt_angle / 100) + 1
     if scale_val < 0:
         scale_val = -scale_val
     self.image.setPixmap(
         self.pixmap.transformed(
             QtGui.QTransform().scale(scale_val, scale_val),
             QtCore.Qt.SmoothTransformation))
     self.drawingPixmap = self.image.pixmap()
     self.resetUndoRedoStack()
Пример #22
0
def main():
    satstress_test_dir = os.path.dirname(os.path.abspath(__file__))
    test_outfile       = os.path.join(satstress_test_dir, "test_nsr_diurnal.pkl")
    test_satellite     = os.path.join("input", "Europa.satellite")

    # Create a new satellite object, as defined by the input file:
    the_sat = satstress.Satellite(open(test_satellite,'r'))

    # Create a StressCalc object, that calculates both the NSR and Diurnal
    # stresses on the Satellite just instantiated:
    the_stresses = satstress.StressCalc([satstress.Diurnal(the_sat), satstress.NSR(the_sat)])

    # do a series of calculations, varying all the inputs at each iteration
    theta = 0.0
    phi   = 0.0
    t     = 0.0

    # a list to store the calculation results in for later checking
    Taulist = []

    while the_stresses.stresses[1].Delta() > 0.01 and t < 2.0*scipy.pi/the_sat.mean_motion():
        print("""Tau(theta = %g, phi = %g, time = %g, Delta = %g) = """ % (scipy.degrees(theta), scipy.degrees(phi), t, the_stresses.stresses[1].Delta()))
        Taulist.append(the_stresses.tensor(theta=theta, phi=phi, t=0))
        print Taulist[-1], "\n"
        theta = theta + scipy.pi/23.0
        phi   = phi   + scipy.pi/11.0
        t     = t     + (scipy.pi/11.0)/the_sat.mean_motion()

        # Re-construct the NSR stress (and the_stresses StressCalc object)
        # changing the forcing period, so that we can have the NSR stresses
        # vary with each iteration too.
        the_sat.nsr_period = the_sat.nsr_period / 1.5
        the_stresses = satstress.StressCalc([satstress.Diurnal(the_sat), satstress.NSR(the_sat)])

    # Now we want to compare this against reference output, just to make sure
    # that we're getting the right numbers...

    pickledTau = pickle.load(open(test_outfile, 'r'))
    for (tau1, tau2) in zip(Taulist, pickledTau):
        if tau1.all() != tau2.all():
            print("\nTest failed.  :(\n")
            sys.exit(1)

    print("\nTest passed! :)\n")
    sys.exit()
Пример #23
0
def angsep(x1,y1,x2,y2):
    #    """
    #    spherical angle separation, aka haversine formula  
    #    input and output are in degrees               
    #    """
    dlat = sp.radians(y2 - y1)
    dlon = sp.radians(x2 - x1)
    y1 = sp.radians(y1)
    y2 = sp.radians(y2)
    a = sp.sin(dlat/2.)*sp.sin(dlat/2.) + sp.cos(y1)*sp.cos(y2)*sp.sin(dlon/2.)*sp.sin(dlon/2.)
    #if a<0 or a>1.: print 'a:',a,x1,y1,x2,y2,dlat,dlon,'!!!!!'
    try:
        c  = 2*sp.arctan2(sp.sqrt(a), sp.sqrt(1.-a))
    except:
        print '!!!:',a,x1,y1,x2,y2,dlat,dlon,'!!!!!'
        c=0
        pass
    return sp.degrees(c)
Пример #24
0
def obsolete_calc_azimuth(lat1, lon1, lat2, lon2):
    """NOT USED
       Calculate a trace azimuth given start and end positions.

    lat1          latitude of start point
    lon1          longitude of start point
    lat2          latitude of end point
    lon2          longitude of end point

    Returns azimuth at start point in degrees, in range [0, 360).
    """
    lat1 = radians(lat1)
    lon1 = radians(lon1)
    lat2 = radians(lat2)
    lon2 = radians(lon2)
    numerator = sin(lon1 - lon2) * cos(lat2)
    denominator = sin(arccos((sin(lat2) * sin(lat1)) + (cos(lat1) * cos(lat2) *
                                                        cos(lon2 - lon1))))
    azimuth = degrees(arcsin(numerator / denominator))
    return azimuth
Пример #25
0
def obsolete_calc_azimuth(lat1, lon1, lat2, lon2):
    """NOT USED
       Calculate a trace azimuth given start and end positions.

    lat1          latitude of start point
    lon1          longitude of start point
    lat2          latitude of end point
    lon2          longitude of end point

    Returns azimuth at start point in degrees, in range [0, 360).
    """
    lat1 = radians(lat1)
    lon1 = radians(lon1)
    lat2 = radians(lat2)
    lon2 = radians(lon2)
    numerator = sin(lon1 - lon2) * cos(lat2)
    denominator = sin(
        arccos((sin(lat2) * sin(lat1)) +
               (cos(lat1) * cos(lat2) * cos(lon2 - lon1))))
    azimuth = degrees(arcsin(numerator / denominator))
    return azimuth
Пример #26
0
def obsolete_calc_azimuth3(lat1, lon1, lat2, lon2):
    """NOT USED
       Calculate a trace azimuth given start and end positions.

    lat1          latitude of start point
    lon1          longitude of start point
    lat2          latitude of end point
    lon2          longitude of end point

    Returns azimuth at start point in degrees, in range [0, 360).
    """

    x = (lon1 - lon2) * (cos(lat1))
    y = lat1 - lat2
    if y == 0:
        azimuth = 90
    elif x == 0:
        azimuth = 0
    else:
        azimuth = degrees(arctan2(x, y))
    return azimuth
Пример #27
0
def obsolete_calc_azimuth3(lat1, lon1, lat2, lon2):
    """NOT USED
       Calculate a trace azimuth given start and end positions.

    lat1          latitude of start point
    lon1          longitude of start point
    lat2          latitude of end point
    lon2          longitude of end point

    Returns azimuth at start point in degrees, in range [0, 360).
    """

    x = (lon1 - lon2) * (cos(lat1))
    y = lat1 - lat2
    if y == 0:
        azimuth = 90
    elif x == 0:
        azimuth = 0
    else:
        azimuth = degrees(arctan2(x, y))
    return azimuth
Пример #28
0
def plot_ellipse(ax, x, y, a, b, ang, **kwargs):
    """Plot ellipse(s) on the specified axis.

    Parameters
    ----------
    ax : axis
        Axis to plot on.
    x : float
        X coordinate of center. All ellipses have same center.
    y : float
        Y coordinate of center. All ellipses have same center.
    a : float or 1d array
        Major axis of ellipse(s).
    b : float or 1d array
        Minor axis of ellipse(s).
    ang : float
        Angle of ellipse(s), in radian. All ellipses have same angle.
    """
    for av, bv in zip(a, b):
        ell = Ellipse([x, y], av, bv, angle=scipy.degrees(ang), **kwargs)
        ax.add_artist(ell)
Пример #29
0
    def _update_canvas(self):
        """
        Update the figure when the user changes an input value.
        :return:
        """
        frequency = float(self.frequency.text())
        nose_radius = float(self.nose_radius.text())
        base_radius = float(self.base_radius.text())
        length = float(self.length.text())

        # Set the incident angles
        incident_angle = linspace(0, pi, 1801)

        # Calculate the radar cross section
        rcs = array([
            radar_cross_section(frequency, nose_radius, base_radius, length,
                                ia) for ia in incident_angle
        ])

        # Clear the axes for the updated plot
        self.axes1.clear()

        # Display the results
        self.axes1.plot(degrees(incident_angle), 10 * log10(rcs), '')

        # Set the plot title and labels
        self.axes1.set_title('RCS vs Incident Angle', size=14)
        self.axes1.set_ylabel('RCS (dBsm)', size=12)
        self.axes1.set_xlabel('Incident Angle (deg)', size=12)

        # Set the tick label size
        self.axes1.tick_params(labelsize=12)

        # Turn on the grid
        self.axes1.grid(linestyle=':', linewidth=0.5)

        # Update the canvas
        self.my_canvas.draw()
Пример #30
0
def populate_geo_coord_polygon(polygon, number_of_points, seed=None,
                               exclude=None, randoms=None):
    """Populate a polygon with uniformly distributed points.
       Takes into account the curvature of the earth.

    Input:
       polygon - list of vertices of polygon, vertices in (lat, long)
       number_of_points - (optional) number of points
       seed - seed for random number generator (default=None)
       exclude - list of polygons (inside main polygon) from where points
       should be excluded

       randoms - array of numbers between 0 and 1 to be used as the
                 random numbers for calculating the latitude of the
                 points.  Obviously is this case the numbers are not
                 random.  This should just be used for writing tests.

    Output:
       points - list of points inside polygon

    Examples:
       populate_polygon( [[0,0], [-40,0], [-40,1], [0,1]], 6,
                         randoms = (0.0, 0.2, 0.4, 0.6, 0.8, 1.0))
       will return six not so randomly selected points inside the unit square
    """

    if seed is not None:
        random.seed(seed)

    if randoms is None:
        randoms = random.random(number_of_points)
    else:
        # Ensure randoms is a numpy array
        randoms = array(randoms)

    # print polygon
    points = []

    # Find outer extent of polygon
    max_x = min_x = polygon[0][1]
    max_y = min_y = polygon[0][0]
    for point in polygon[1:]:
        x = point[1]
        if x > max_x:
            max_x = x
        if x < min_x:
            min_x = x
        y = point[0]
        if y > max_y:
            max_y = y
        if y < min_y:
            min_y = y

    max_y_rad = radians(max_y)
    min_y_rad = radians(min_y)

    # Do this until we have a points array of points inside the polygon that
    # greater or equal the number of points requested (we'll slice at return)
    while len(points) < number_of_points:
        y_p_rad = arcsin(randoms * abs((sin(max_y_rad) - sin(min_y_rad))) +
                         sin(min_y_rad))
        y_p = degrees(y_p_rad)
        x_p = random.uniform(min_x, max_x, number_of_points)
        points_p = array([y_p, x_p]).T

        points_p = points_p[inside_polygon(points_p.tolist(), polygon)]
        if exclude is not None and len(points_p) > 0:
            for ex_poly in exclude:
                points_p = points_p[
                    outside_polygon(points_p.tolist(), ex_poly)]

        if len(points_p) > 0:
            points.extend(points_p.tolist())

        randoms = random.random(number_of_points)

    return points[:number_of_points]
Пример #31
0
    def setFoilDimension(self):
        print('--- method: %s ---' % sys._getframe().f_code.co_name)
        if not os.path.exists(self.yamlfile):
            sys.stderr.write('input parameter_file does not exist.: %s\n' %
                             self.param['foil_dimension_file'])
            quit()

        self.foils = []
        self.use_foilid_list = []
        print(
            "------------------------------------------------------------------------"
        )
        print("Foil Input Dimension")
        print(
            "Foil-ID   : Material, Top radi, Bottom radi, Angle, Angle, GeoArea Use?"
        )
        print(
            "                        (cm)        (cm)     (rad)  (deg)   (cm2)      "
        )
        print(
            "------------------------------------------------------------------------"
        )
        total_geometric_area = 0.0
        total_geometric_area_obs1 = 0.0
        total_geometric_area_obs2 = 0.0
        for line in open(self.param['foil_dimension_file']):
            cols = line.split()
            if cols[0] == '#':
                continue

            foil_id = len(self.foils) + 1

            foil_parab_top_radius = float(cols[0])  # mm
            foil_parab_bot_radius = float(cols[1])  # mm
            foil_parab_angle_rad = float(cols[2])
            foil_parab_angle_deg = scipy.degrees(foil_parab_angle_rad)

            foil_parab_bot_radius_cm = 0.1 * foil_parab_bot_radius
            foil_parab_top_radius_cm = 0.1 * foil_parab_top_radius

            if foil_parab_angle_deg <= self.param[
                    'maximum_incident_angle_deg'] and (
                        2.0 * foil_parab_top_radius_cm <=
                        self.param['maximum_diameter_cm']):
                self.use_foilid_list.append(foil_id)

            foil_cone_angle_rad = foil_parab_angle_rad  # assumed for CubeSat

            self.foils.append(
                niresp.xrc.Foil(foil_id, self.material,
                                foil_parab_top_radius_cm,
                                foil_parab_bot_radius_cm, foil_cone_angle_rad))

            self.foils[-1].roughness_A = self.param['roughness_A']
            self.foils[-1].n_spoke1 = self.param['spoke']['n_spoke1']
            self.foils[-1].n_spoke2 = self.param['spoke']['n_spoke2']
            self.foils[-1].spoke1_wid = self.param['spoke']['spoke1_wid']
            self.foils[-1].spoke2_wid = self.param['spoke']['spoke2_wid']
            self.foils[-1].setUseFlag(self.use_foilid_list)
            self.foils[-1].surface_model = self.param['surface_model']
            self.foils[-1].showProperty()

            foil_geometric_area = (foil_parab_top_radius_cm**2 -
                                   foil_parab_bot_radius_cm**2) * np.pi

            total_geometric_area += foil_geometric_area
            total_geometric_area_obs1 += foil_geometric_area * self.foils[
                -1].getSpokeObsculation()
            subtraction = float(self.param['spoke']['n_spoke1']) * float(
                self.param['spoke']['spoke1_wid']) * 10.0 * (
                    self.foils[-1].top_radius_cm -
                    self.foils[-1].bottom_radius_cm) * 10.0
            subtraction += float(self.param['spoke']['n_spoke2']) * float(
                self.param['spoke']['spoke2_wid']) * 10.0 * (
                    self.foils[-1].top_radius_cm -
                    self.foils[-1].bottom_radius_cm) * 10.0
            value = foil_geometric_area - subtraction
            total_geometric_area_obs2 += value

        self.param['use_foilid_list'] = self.use_foilid_list
        self.param['numof_use_foils'] = len(self.param['use_foilid_list'])

        print("Total geometric area (cm2):", total_geometric_area)
        print("after subtracting spoke obsculation: ",
              total_geometric_area_obs2)
        obst_1 = float(self.param['spoke']['n_spoke1']) * float(
            self.param['spoke']['spoke1_wid']) * (
                self.foils[-1].top_radius_cm - self.foils[0].bottom_radius_cm)
        obst_2 = float(self.param['spoke']['n_spoke2']) * float(
            self.param['spoke']['spoke2_wid']) * (
                self.foils[-1].top_radius_cm - self.foils[0].bottom_radius_cm)
        print(
            "------------------------------------------------------------------------"
        )
    def _update_canvas(self):
        """
        Update the figure when the user changes an input value.
        :return:
        """
        # Set up the incident angles
        incident_angle = linspace(0., 0.5 * pi, 1000)

        # Set up the keyword args
        kwargs = {
            'frequency': float(self.frequency.text()),
            'incident_angle': incident_angle,
            'relative_permittivity': self.relative_permittivity,
            'relative_permeability': self.relative_permeability,
            'conductivity': self.conductivity
        }

        # Calculate the reflection and transmission coefficients
        reflection_coefficient_te, transmission_coefficient_te, reflection_coefficient_tm, \
        transmission_coefficient_tm = plane_waves.reflection_transmission(**kwargs)

        # Clear the axes for the updated plot
        self.axes1.clear()
        self.axes2.clear()

        # Display the reflection coefficients
        self.axes1.plot(degrees(incident_angle),
                        abs(reflection_coefficient_te),
                        'b',
                        label='|$\Gamma_{TE}$|')
        self.axes1.plot(degrees(incident_angle),
                        abs(reflection_coefficient_tm),
                        'b--',
                        label='|$\Gamma_{TM}$|')

        # Display the transmission coefficients
        self.axes2.plot(degrees(incident_angle),
                        abs(transmission_coefficient_te),
                        'r',
                        label='|$T_{TE}$|')
        self.axes2.plot(degrees(incident_angle),
                        abs(transmission_coefficient_tm),
                        'r--',
                        label='|$T_{TM}$|')

        # Set the plot title and labels
        self.axes1.set_title('Plane Wave Reflection and Transmission', size=14)
        self.axes1.set_xlabel('Incident Angle (degrees)', size=12)
        self.axes1.set_ylabel('|Reflection Coefficient|', size=12)
        self.axes2.set_ylabel('|Transmission Coefficient|', size=12)

        # Set the tick label size
        self.axes1.tick_params(labelsize=12)
        self.axes2.tick_params(labelsize=12)

        # Set the legend
        self.axes1.legend(loc='upper right', prop={'size': 10})
        self.axes2.legend(loc='upper left', prop={'size': 10})

        # Turn on the grid
        self.axes1.grid(linestyle=':', linewidth=0.5)

        # Update the canvas
        self.my_canvas.draw()
Пример #33
0
def nichols_grid(cl_mags=None, cl_phases=None):
    """Nichols chart grid

    Plots a Nichols chart grid on the current axis, or creates a new chart
    if no plot already exists.

    Parameters
    ----------
    cl_mags : array-like (dB), optional
        Array of closed-loop magnitudes defining the iso-gain lines on a
        custom Nichols chart.
    cl_phases : array-like (degrees), optional
        Array of closed-loop phases defining the iso-phase lines on a custom
        Nichols chart. Must be in the range -360 < cl_phases < 0

    Returns
    -------
    None
    """
    # Default chart size
    ol_phase_min = -359.99
    ol_phase_max = 0.0
    ol_mag_min = -40.0
    ol_mag_max = default_ol_mag_max = 50.0

    # Find bounds of the current dataset, if there is one.
    if plt.gcf().gca().has_data():
        ol_phase_min, ol_phase_max, ol_mag_min, ol_mag_max = plt.axis()

    # M-circle magnitudes.
    if cl_mags is None:
        # Default chart magnitudes
        # The key set of magnitudes are always generated, since this
        # guarantees a recognizable Nichols chart grid.
        key_cl_mags = np.array([-40.0, -20.0, -12.0, -6.0, -3.0, -1.0, -0.5, 0.0,
                                     0.25, 0.5, 1.0, 3.0, 6.0, 12.0])
        # Extend the range of magnitudes if necessary. The extended arange
        # will end up empty if no extension is required. Assumes that closed-loop
        # magnitudes are approximately aligned with open-loop magnitudes beyond
        # the value of np.min(key_cl_mags)
        cl_mag_step = -20.0 # dB
        extended_cl_mags = np.arange(np.min(key_cl_mags),
                                     ol_mag_min + cl_mag_step, cl_mag_step)
        cl_mags = np.concatenate((extended_cl_mags, key_cl_mags))

    # N-circle phases (should be in the range -360 to 0)
    if cl_phases is None:
        # Choose a reasonable set of default phases (denser if the open-loop
        # data is restricted to a relatively small range of phases).
        key_cl_phases = np.array([-0.25, -45.0, -90.0, -180.0, -270.0, -325.0, -359.75])
        if np.abs(ol_phase_max - ol_phase_min) < 90.0:
            other_cl_phases = np.arange(-10.0, -360.0, -10.0)
        else:
            other_cl_phases = np.arange(-10.0, -360.0, -20.0)
        cl_phases = np.concatenate((key_cl_phases, other_cl_phases))
    else:
        assert ((-360.0 < np.min(cl_phases)) and (np.max(cl_phases) < 0.0))

    # Find the M-contours
    m = m_circles(cl_mags, phase_min=np.min(cl_phases), phase_max=np.max(cl_phases))
    m_mag = 20*sp.log10(np.abs(m))
    m_phase = sp.mod(sp.degrees(sp.angle(m)), -360.0) # Unwrap

    # Find the N-contours
    n = n_circles(cl_phases, mag_min=np.min(cl_mags), mag_max=np.max(cl_mags))
    n_mag = 20*sp.log10(np.abs(n))
    n_phase = sp.mod(sp.degrees(sp.angle(n)), -360.0) # Unwrap

    # Plot the contours behind other plot elements.
    # The "phase offset" is used to produce copies of the chart that cover
    # the entire range of the plotted data, starting from a base chart computed
    # over the range -360 < phase < 0. Given the range
    # the base chart is computed over, the phase offset should be 0
    # for -360 < ol_phase_min < 0.
    phase_offset_min = 360.0*np.ceil(ol_phase_min/360.0)
    phase_offset_max = 360.0*np.ceil(ol_phase_max/360.0) + 360.0
    phase_offsets = np.arange(phase_offset_min, phase_offset_max, 360.0)

    for phase_offset in phase_offsets:
        # Draw M and N contours
        plt.plot(m_phase + phase_offset, m_mag, color='gray',
                 linestyle='dotted', zorder=0)
        plt.plot(n_phase + phase_offset, n_mag, color='gray',
                 linestyle='dotted', zorder=0)

        # Add magnitude labels
        for x, y, m in zip(m_phase[:][-1] + phase_offset, m_mag[:][-1], cl_mags):
            align = 'right' if m < 0.0 else 'left'
            plt.text(x, y, str(m) + ' dB', size='small', ha=align, color='gray')

    # Fit axes to generated chart
    plt.axis([phase_offset_min - 360.0, phase_offset_max - 360.0,
              np.min(cl_mags), np.max([ol_mag_max, default_ol_mag_max])])
Пример #34
0
    def __init__(self, like, model, withErrors=False, param1=False, param2=False):
        self.like   = like
        self.model  = model
        self.params = like.freeParameters()
        self.vpars  = [p.value for p in self.params]
        self.sigma  = sp.array([p.error for p in self.params])
        bounds = [p.bounds for p in self.params]
        print("Minimizing...", self.vpars, "with bounds", bounds)

        self.res = minimize(self.negloglike, self.vpars, bounds=bounds, method='L-BFGS-B')
        print(self.res, 'with noErrors =', withErrors)

        if (withErrors):
            hess    = nd.Hessian(self.negloglike)(self.res.x)
            eigvl, eigvc = la.eig(hess)
            print ('Hessian', hess, eigvl,)
            self.cov = la.inv(hess)
            print('Covariance matrix \n', self.cov)
            # set errors:
            for i, pars in enumerate(self.params):
                pars.setError(sp.sqrt(self.cov[i, i]))
        # update with the final result
        self.result(self.negloglike(self.res.x))


        if param1 and param2:
            for i, par in enumerate(self.like.freeParameters()):
                if param1 == par.name: par1 = i
                elif param2 == par.name: par2 = i


            fig = plt.figure(figsize=(6,6))
            ax = fig.add_subplot(111) #, aspect='equal')

            val,vec = la.eig(self.cov[[par1,par2], :][:, [par1,par2]])
            vec=vec.T
            mn = self.res.x

            vec[0]*=sp.sqrt(11.83*sp.real(val[0]))
            vec[1]*=sp.sqrt(11.83*sp.real(val[1]))

            plt.plot(mn[par1],mn[par2],'bo', label=self.model)
            plt.plot([mn[par1]-vec[0][0],mn[par1]+vec[0][0]],
                [mn[par2]-vec[0][1],mn[par2]+vec[0][1]],'r-')
            plt.plot([mn[par1]-vec[1][0],mn[par1]+vec[1][0]],
                [mn[par2]-vec[1][1],mn[par2]+vec[1][1]],'r-')

            def eigsorted(cov):
                vals, vecs = sp.linalg.eigh(cov)
                order = vals.argsort()[::-1]
                return vals[order], vecs[:,order]

            vals, vecs = eigsorted(self.cov[[par1,par2], :][:, [par1,par2]])
            theta = sp.degrees(np.arctan2(*vecs[:,0][::-1]))

            sigmas = [2.3, 5.99, 11.83]
            for sigs in sigmas:
                w, h = 2  * sp.sqrt(vals) * sp.sqrt(sigs)
                ell = Ellipse(xy=(mn[par1], mn[par2]),  width = w, height = h, angle=theta, color='green',  lw=4)
                ell.set_facecolor('none')
                ax.add_artist(ell)

            plt.legend(loc='best')
            plt.title('+'.join(self.like.compositeNames()), fontsize=10)
            plt.show()
Пример #35
0
    def _update_canvas(self):
        """
        Update the figure when the user changes an input value
        :return:
        """
        # Get the parameters from the form
        frequency = float(self.frequency.text())
        number_of_elements = int(self.number_of_elements.text())
        scan_angle_theta = float(self.scan_angle_theta.text())
        scan_angle_phi = float(self.scan_angle_phi.text())
        radius = float(self.radius.text())

        # Set up the theta and phi arrays
        n = 360
        m = int(n / 8)
        theta, phi = meshgrid(linspace(0.0 * pi, 0.5 * pi, n),
                              linspace(0.0, 2.0 * pi, n))

        # Set up the args
        kwargs = {
            'number_of_elements': number_of_elements,
            'scan_angle_theta': radians(scan_angle_theta),
            'scan_angle_phi': radians(scan_angle_phi),
            'radius': radius,
            'frequency': frequency,
            'theta': theta,
            'phi': phi
        }

        # Get the array factor
        af = circular_uniform.array_factor(**kwargs)

        # Remove the color bar
        try:
            self.cbar.remove()
        except:
            # Initial plot
            pass

        # Clear the axes for the updated plot
        self.axes1.clear()

        # U-V coordinates for plotting the antenna pattern
        uu = sin(theta) * cos(phi)
        vv = sin(theta) * sin(phi)

        if self.plot_type.currentIndex() == 0:

            # Display the results
            im = self.axes1.pcolor(uu, vv, abs(af), cmap="jet")
            self.cbar = self.fig.colorbar(im,
                                          ax=self.axes1,
                                          orientation='vertical')
            self.cbar.set_label("Normalized Electric Field (V/m)", size=10)

            # Set the x- and y-axis labels
            self.axes1.set_xlabel("U (sines)", size=12)
            self.axes1.set_ylabel("V (sines)", size=12)

        elif self.plot_type.currentIndex() == 1:

            # Create the contour plot
            self.axes1.contour(uu,
                               vv,
                               abs(af),
                               20,
                               cmap="jet",
                               vmin=-0.2,
                               vmax=1.0)

            # Turn on the grid
            self.axes1.grid(linestyle=':', linewidth=0.5)

            # Set the x- and y-axis labels
            self.axes1.set_xlabel("U (sines)", size=12)
            self.axes1.set_ylabel("V (sines)", size=12)

        else:

            # Create the line plot
            self.axes1.plot(degrees(theta[0]),
                            20.0 * log10(abs(af[m])),
                            '',
                            label='E Plane')
            self.axes1.plot(degrees(theta[0]),
                            20.0 * log10(abs(af[0])),
                            '--',
                            label='H Plane')

            # Set the y axis limit
            self.axes1.set_ylim(-60, 5)

            # Set the x and y axis labels
            self.axes1.set_xlabel("Theta (degrees)", size=12)
            self.axes1.set_ylabel("Array Factor (dB)", size=12)

            # Turn on the grid
            self.axes1.grid(linestyle=':', linewidth=0.5)

            # Place the legend
            self.axes1.legend(loc='upper right', prop={'size': 10})

        # Set the plot title and labels
        self.axes1.set_title('Circular Array - Array Factor', size=14)

        # Set the tick label size
        self.axes1.tick_params(labelsize=12)

        # Update the canvas
        self.my_canvas.draw()
Пример #36
0
    def _update_canvas(self):
        """
        Update the figure when the user changes an input value
        :return:
        """
        # Get the parameters from the form
        frequency = float(self.frequency.text())
        guide_width = float(self.guide_width.text())
        guide_height = float(self.guide_height.text())
        horn_width = float(self.horn_width.text())
        horn_height = float(self.horn_height.text())
        eplane_effective_length = float(self.eplane_effective_length.text())
        hplane_effective_length = float(self.hplane_effective_length.text())

        # Get the selected antenna from the form
        antenna_type = self.antenna_type.currentIndex()

        # Set the range and angular span
        r = 1.0e9

        # Set up the theta and phi arrays
        n = 400
        m = int(n / 4)
        theta, phi = meshgrid(linspace(0.0, 0.5 * pi, n),
                              linspace(0.0, 2.0 * pi, n))

        # Get the antenna parameters and antenna pattern for the selected antenna
        if antenna_type == 0:
            total_power_radiated = e_plane_sectoral.power_radiated(
                guide_width, horn_height)
            directivity = e_plane_sectoral.directivity(
                guide_width, horn_height, eplane_effective_length, frequency)
            _, et, ep, _, _, _ = e_plane_sectoral.far_fields(
                guide_width, horn_height, eplane_effective_length, frequency,
                r, theta, phi)
        elif antenna_type == 1:
            total_power_radiated = h_plane_sectoral.power_radiated(
                guide_height, horn_width)
            directivity = h_plane_sectoral.directivity(
                guide_height, horn_width, hplane_effective_length, frequency)
            _, et, ep, _, _, _ = h_plane_sectoral.far_fields(
                guide_height, horn_width, hplane_effective_length, frequency,
                r, theta, phi)
        else:
            total_power_radiated = pyramidal.power_radiated(
                horn_width, horn_height)
            directivity = pyramidal.directivity(horn_width, horn_height,
                                                eplane_effective_length,
                                                hplane_effective_length,
                                                frequency)
            _, et, ep, _, _, _ = pyramidal.far_fields(horn_width, horn_height,
                                                      eplane_effective_length,
                                                      hplane_effective_length,
                                                      frequency, r, theta, phi)

        # Populate the form with the correct values
        self.total_radiated_power.setText(
            '{:.2e}'.format(total_power_radiated))
        self.directivity.setText('{:.2f}'.format(directivity))

        # Remove the color bar
        try:
            self.cbar.remove()
        except:
            # Initial plot
            pass

        # Clear the axes for the updated plot
        self.axes1.clear()

        # U-V coordinates for plotting the antenna pattern
        uu = sin(theta) * cos(phi)
        vv = sin(theta) * sin(phi)

        # Normalized electric field magnitude for plotting
        e_mag = sqrt(abs(et * et + ep * ep))
        e_mag /= amax(e_mag)

        if self.plot_type.currentIndex() == 0:

            # Display the results
            im = self.axes1.pcolor(uu, vv, e_mag, cmap="jet")
            self.cbar = self.fig.colorbar(im,
                                          ax=self.axes1,
                                          orientation='vertical')
            self.cbar.set_label("Normalized Electric Field(V/m)", size=10)

            # Set the x- and y-axis labels
            self.axes1.set_xlabel("U (sines)", size=12)
            self.axes1.set_ylabel("V (sines)", size=12)

        elif self.plot_type.currentIndex() == 1:

            # Create the contour plot
            self.axes1.contour(uu,
                               vv,
                               e_mag,
                               20,
                               cmap="jet",
                               vmin=-0.2,
                               vmax=1.0)

            # Turn on the grid
            self.axes1.grid(linestyle=':', linewidth=0.5)

            # Set the x- and y-axis labels
            self.axes1.set_xlabel("U (sines)", size=12)
            self.axes1.set_ylabel("V (sines)", size=12)

        else:

            # Create the line plot
            self.axes1.plot(degrees(theta[0]),
                            20.0 * log10(e_mag[m]),
                            '',
                            label='E Plane')
            self.axes1.plot(degrees(theta[0]),
                            20.0 * log10(e_mag[0]),
                            '--',
                            label='H Plane')

            # Set the y axis limit
            self.axes1.set_ylim(-40, 5)

            # Set the x and y axis labels
            self.axes1.set_xlabel("Theta (degrees)", size=12)
            self.axes1.set_ylabel("Normalized |E| (dB)", size=12)

            # Turn on the grid
            self.axes1.grid(linestyle=':', linewidth=0.5)

            # Place the legend
            self.axes1.legend(loc='upper right', prop={'size': 10})

        # Set the plot title and labels
        self.axes1.set_title('Horn Antenna Pattern', size=14)

        # Set the tick label size
        self.axes1.tick_params(labelsize=12)

        # Update the canvas
        self.my_canvas.draw()
Пример #37
0
def nichols_grid(cl_mags=None, cl_phases=None):
    """Nichols chart grid
        Parameters
        ----------
        cl_mags : array-like (dB), optional
        Array of closed-loop magnitudes defining the iso-gain lines on a
        custom Nichols chart.
        cl_phases : array-like (degrees), optional
        Array of closed-loop phases defining the iso-phase lines on a custom
        Nichols chart. Must be in the range -360 < cl_phases < 0
        Returns
        -------
        None
        """
    # Default chart size
    ol_phase_min = -359.99
    ol_phase_max = 0.0
    ol_mag_min = -40.0
    ol_mag_max = default_ol_mag_max = 50.0

    # M-circle magnitudes.
    if cl_mags is None:
        # Default chart magnitudes
        key_cl_mags = np.array([
            -40.0,
            -20.0,
            -12.0,
            -6.0,
            -3.0,
            -1.0,
            -0.5,
            0.0,
            0.25,
            0.5,
            1.0,
            3.0,
            6.0,
            12.0,
        ])
        # Extend the range of magnitudes if necessary.
        cl_mag_step = -20.0  # dB
        extended_cl_mags = np.arange(np.min(key_cl_mags),
                                     ol_mag_min + cl_mag_step, cl_mag_step)
        cl_mags = np.concatenate((extended_cl_mags, key_cl_mags))
    else:
        cl_mags = np.array(cl_mags)

    # N-circle phases (should be in the range -360 to 0)
    if cl_phases is None:
        # Choose a reasonable set of default phases
        key_cl_phases = np.array(
            [-0.25, -45.0, -90.0, -180.0, -270.0, -325.0, -359.75])
        if np.abs(ol_phase_max - ol_phase_min) < 90.0:
            other_cl_phases = np.arange(-10.0, -360.0, -10.0)
        else:
            other_cl_phases = np.arange(-10.0, -360.0, -20.0)
        cl_phases = np.concatenate((key_cl_phases, other_cl_phases))
    else:
        cl_phases = np.array(cl_phases)
        assert (-360.0 < np.min(cl_phases)) and (np.max(cl_phases) < 0.0)

    # Find the M-contours
    m = m_circles(cl_mags,
                  phase_min=np.min(cl_phases),
                  phase_max=np.max(cl_phases))
    m_mag = 20 * sp.log10(np.abs(m))
    m_phase = sp.mod(sp.degrees(sp.angle(m)), -360.0)  # Unwrap

    # Find the N-contours
    n = n_circles(cl_phases, mag_min=np.min(cl_mags), mag_max=np.max(cl_mags))
    n_mag = 20 * sp.log10(np.abs(n))
    n_phase = sp.mod(sp.degrees(sp.angle(n)), -360.0)  # Unwrap

    # Plot the contours behind other plot elements.
    # The "phase offset" is used to produce copies of the chart
    phase_offset_min = 360.0 * np.ceil(ol_phase_min / 360.0)
    phase_offset_max = 360.0 * np.ceil(ol_phase_max / 360.0) + 360.0
    phase_offsets = np.arange(phase_offset_min, phase_offset_max, 360.0)

    data_m_mag = []
    data_n_mag = []
    for phase_offset in phase_offsets:
        for indice in range(m_mag.shape[1]):
            name = "{} dB".format(cl_mags[indice])
            data_m_mag.append({
                "x": m_phase[:, indice] + phase_offset,
                "y": m_mag[:, indice],
                "name": name,
            })
        for indice in range(n_mag.shape[1]):
            name = "{} deg".format(cl_phases[indice])
            data_n_mag.append({
                "x": n_phase[:, indice] + phase_offset,
                "y": n_mag[:, indice],
                "name": name,
            })

    return data_m_mag, data_n_mag
Пример #38
0
    def _update_canvas(self):
        """
        Update the figure when the user changes an input value.
        :return:
        """
        frequency = float(self.frequency.text())
        theta_inc = float(self.theta_inc.text())
        phi_inc = float(self.phi_inc.text())
        phi_obs = float(self.phi_obs.text())

        # Set the scattering angles
        theta = self.theta_obs.text().split(',')
        theta_obs = linspace(radians(float(theta[0])), radians(float(theta[1])), 721)

        # Monostatic or bistatic
        mb = self.type.currentText()

        rcs_theta = []
        rcs_phi = []

        kwargs = {'frequency': array([frequency]),
                  'vertices':  self.vertices,
                  'faces':     self.faces,
                  'phi_inc':   radians(phi_inc),
                  'phi_obs':   radians(phi_obs)}

        b = scattering_matrix.ScatteringMatrix(**kwargs)

        if mb == 'Monostatic':

            for to in theta_obs:

                b.theta_inc = to
                b.theta_obs = to

                sm = b.get_scattering_matrix()

                rcs_theta.append(20.0 * log10(abs(sm[0]) + 1e-10))
                rcs_phi.append(20.0 * log10(abs(sm[3]) + 1e-10))

        else:

            b.theta_inc = radians(theta_inc)

            for to in theta_obs:

                b.theta_obs = to

                sm = b.get_scattering_matrix()

                rcs_theta.append(20.0 * log10(abs(sm[0]) + 1e-10))
                rcs_phi.append(20.0 * log10(abs(sm[3]) + 1e-10))

        # Clear the axes for the updated plot
        self.axes1.clear()

        # Display the results
        self.axes1.plot(degrees(theta_obs), rcs_phi, '', label='TE$^z$')
        self.axes1.plot(degrees(theta_obs), rcs_theta, '--', label='TM$^z$')

        # Set the plot title and labels
        self.axes1.set_title('Physical Optics RCS vs Observation Angle', size=14)
        self.axes1.set_ylabel('RCS (dBsm)', size=12)
        self.axes1.set_xlabel('Observation Angle (deg)', size=12)
        self.axes1.set_ylim(-40, max(rcs_theta) + 3)

        # Set the tick label size
        self.axes1.tick_params(labelsize=12)

        # Set the legend
        self.axes1.legend(loc='best', prop={'size': 10})

        # Turn on the grid
        self.axes1.grid(linestyle=':', linewidth=0.5)

        # Update the canvas
        self.my_canvas.draw()
Пример #39
0
    def _update_canvas(self):
        """
        Update the figure when the user changes an input value
        :return:
        """
        # Get the parameters from the form
        frequency = float(self.frequency.text())
        width = float(self.width.text())
        height = float(self.height.text())

        # Get the selected antenna from the form
        antenna_type = self.antenna_type.currentIndex()

        # Set the range and angular span
        r = 1.0e9

        # Set up the theta and phi arrays
        n = 200
        m = int(n / 4)
        theta, phi = meshgrid(linspace(finfo(float).eps, 0.5 * pi, n),
                              linspace(finfo(float).eps, 2.0 * pi, n))

        # Get the antenna parameters and antenna pattern for the selected antenna
        if antenna_type == 0:
            half_power_eplane, half_power_hplane, first_null_eplane, first_null_hplane = \
                rectangular_uniform_ground_plane.beamwidth(width, height, frequency)
            directivity = rectangular_uniform_ground_plane.directivity(
                width, height, frequency)
            sidelobe_level_eplane = rectangular_uniform_ground_plane.side_lobe_level(
            )
            sidelobe_level_hplane = sidelobe_level_eplane
            _, et, ep, _, _, _ = rectangular_uniform_ground_plane.far_fields(
                width, height, frequency, r, theta, phi)
        elif antenna_type == 1:
            half_power_eplane, half_power_hplane, first_null_eplane, first_null_hplane = \
                rectangular_uniform_free_space.beamwidth(width, height, frequency)
            directivity = rectangular_uniform_free_space.directivity(
                width, height, frequency)
            sidelobe_level_eplane = rectangular_uniform_free_space.side_lobe_level(
            )
            sidelobe_level_hplane = sidelobe_level_eplane
            _, et, ep, _, _, _ = rectangular_uniform_free_space.far_fields(
                width, height, frequency, r, theta, phi)
        else:
            half_power_eplane, half_power_hplane, first_null_eplane, first_null_hplane = \
                rectangular_te10_ground_plane.beamwidth(width, height, frequency)
            directivity = rectangular_te10_ground_plane.directivity(
                width, height, frequency)
            sidelobe_level_eplane, sidelobe_level_hplane = rectangular_te10_ground_plane.side_lobe_level(
            )
            _, et, ep, _, _, _ = rectangular_te10_ground_plane.far_fields(
                width, height, frequency, r, theta, phi)

        # The the text boxes on the form to the correct values
        self.sll_eplane.setText('{:.2f}'.format(sidelobe_level_eplane))
        self.sll_hplane.setText('{:.2f}'.format(sidelobe_level_hplane))
        self.directivity.setText('{:.2f}'.format(directivity))

        # Remove the color bar
        try:
            self.cbar.remove()
        except:
            # Initial plot
            pass

        # Clear the axes for the updated plot
        self.axes1.clear()

        # U-V coordinates for plotting the antenna pattern
        uu = sin(theta) * cos(phi)
        vv = sin(theta) * sin(phi)

        # Normalized electric field magnitude for plotting
        e_mag = sqrt(abs(et * et + ep * ep))
        e_mag /= amax(e_mag)

        if self.plot_type.currentIndex() == 0:

            # Create the color plot
            im = self.axes1.pcolor(uu, vv, e_mag, cmap="jet")
            self.cbar = self.fig.colorbar(im,
                                          ax=self.axes1,
                                          orientation='vertical')
            self.cbar.set_label("Normalized Electric Field(V/m)")

            # Set the x- and y-axis labels
            self.axes1.set_xlabel("U (sines)", size=12)
            self.axes1.set_ylabel("V (sines)", size=12)

        elif self.plot_type.currentIndex() == 1:

            # Create the contour plot
            self.axes1.contour(uu,
                               vv,
                               e_mag,
                               20,
                               cmap="jet",
                               vmin=-0.2,
                               vmax=1.0)

            # Turn on the grid
            self.axes1.grid(linestyle=':', linewidth=0.5)

            # Set the x- and y-axis labels
            self.axes1.set_xlabel("U (sines)", size=12)
            self.axes1.set_ylabel("V (sines)", size=12)

        else:

            # Create the line plot
            self.axes1.plot(degrees(theta[0]),
                            20.0 * log10(e_mag[m]),
                            '',
                            label='E Plane')
            self.axes1.plot(degrees(theta[0]),
                            20.0 * log10(e_mag[0]),
                            '--',
                            label='H Plane')

            # Set the y axis limit
            self.axes1.set_ylim(-60, 5)

            # Set the x and y axis labels
            self.axes1.set_xlabel("Theta (degrees)", size=12)
            self.axes1.set_ylabel("Normalized |E| (dB)", size=12)

            # Turn on the grid
            self.axes1.grid(linestyle=':', linewidth=0.5)

            # Place the legend
            self.axes1.legend(loc='upper right', prop={'size': 10})

        # Set the plot title and labels
        self.axes1.set_title('Rectangular Aperture Antenna Pattern', size=14)

        # Set the tick label size
        self.axes1.tick_params(labelsize=12)

        # Update the canvas
        self.my_canvas.draw()
def nichols_grid(cl_mags=None, cl_phases=None):
    """Nichols chart grid

    Plots a Nichols chart grid on the current axis, or creates a new chart
    if no plot already exists.

    Parameters
    ----------
    cl_mags : array-like (dB), optional
        Array of closed-loop magnitudes defining the iso-gain lines on a
        custom Nichols chart.
    cl_phases : array-like (degrees), optional
        Array of closed-loop phases defining the iso-phase lines on a custom
        Nichols chart. Must be in the range -360 < cl_phases < 0

    Returns
    -------
    None
    """
    # Default chart size
    ol_phase_min = -359.99
    ol_phase_max = 0.0
    ol_mag_min = -40.0
    ol_mag_max = default_ol_mag_max = 50.0

    # Find bounds of the current dataset, if there is one.
    if plt.gcf().gca().has_data():
        ol_phase_min, ol_phase_max, ol_mag_min, ol_mag_max = plt.axis()

    # M-circle magnitudes.
    if cl_mags is None:
        # Default chart magnitudes
        # The key set of magnitudes are always generated, since this
        # guarantees a recognizable Nichols chart grid.
        key_cl_mags = np.array([
            -40.0, -20.0, -12.0, -6.0, -3.0, -1.0, -0.5, 0.0, 0.25, 0.5, 1.0,
            3.0, 6.0, 12.0
        ])
        # Extend the range of magnitudes if necessary. The extended arange
        # will end up empty if no extension is required. Assumes that closed-loop
        # magnitudes are approximately aligned with open-loop magnitudes beyond
        # the value of np.min(key_cl_mags)
        cl_mag_step = -20.0  # dB
        extended_cl_mags = np.arange(np.min(key_cl_mags),
                                     ol_mag_min + cl_mag_step, cl_mag_step)
        cl_mags = np.concatenate((extended_cl_mags, key_cl_mags))

    # N-circle phases (should be in the range -360 to 0)
    if cl_phases is None:
        # Choose a reasonable set of default phases (denser if the open-loop
        # data is restricted to a relatively small range of phases).
        key_cl_phases = np.array(
            [-0.25, -45.0, -90.0, -180.0, -270.0, -325.0, -359.75])
        if np.abs(ol_phase_max - ol_phase_min) < 90.0:
            other_cl_phases = np.arange(-10.0, -360.0, -10.0)
        else:
            other_cl_phases = np.arange(-10.0, -360.0, -20.0)
        cl_phases = np.concatenate((key_cl_phases, other_cl_phases))
    else:
        assert ((-360.0 < np.min(cl_phases)) and (np.max(cl_phases) < 0.0))

    # Find the M-contours
    m = m_circles(cl_mags,
                  phase_min=np.min(cl_phases),
                  phase_max=np.max(cl_phases))
    m_mag = 20 * sp.log10(np.abs(m))
    m_phase = sp.mod(sp.degrees(sp.angle(m)), -360.0)  # Unwrap

    # Find the N-contours
    n = n_circles(cl_phases, mag_min=np.min(cl_mags), mag_max=np.max(cl_mags))
    n_mag = 20 * sp.log10(np.abs(n))
    n_phase = sp.mod(sp.degrees(sp.angle(n)), -360.0)  # Unwrap

    # Plot the contours behind other plot elements.
    # The "phase offset" is used to produce copies of the chart that cover
    # the entire range of the plotted data, starting from a base chart computed
    # over the range -360 < phase < 0. Given the range
    # the base chart is computed over, the phase offset should be 0
    # for -360 < ol_phase_min < 0.
    phase_offset_min = 360.0 * np.ceil(ol_phase_min / 360.0)
    phase_offset_max = 360.0 * np.ceil(ol_phase_max / 360.0) + 360.0
    phase_offsets = np.arange(phase_offset_min, phase_offset_max, 360.0)

    for phase_offset in phase_offsets:
        # Draw M and N contours
        plt.plot(m_phase + phase_offset,
                 m_mag,
                 color='gray',
                 linestyle='dotted',
                 zorder=0)
        plt.plot(n_phase + phase_offset,
                 n_mag,
                 color='gray',
                 linestyle='dotted',
                 zorder=0)

        # Add magnitude labels
        for x, y, m in zip(m_phase[:][-1] + phase_offset, m_mag[:][-1],
                           cl_mags):
            align = 'right' if m < 0.0 else 'left'
            plt.text(x,
                     y,
                     str(m) + ' dB',
                     size='small',
                     ha=align,
                     color='gray')

    # Fit axes to generated chart
    plt.axis([
        phase_offset_min - 360.0, phase_offset_max - 360.0,
        np.min(cl_mags),
        np.max([ol_mag_max, default_ol_mag_max])
    ])
Пример #41
0
def nichols_plot(sys_list,
                 omega=None,
                 grid=True,
                 figure=None,
                 ax=None,
                 delay=False):
    """Nichols plot for a system

    Plots a Nichols plot for the system over a (optional) frequency range.

    Parameters
    ----------
    sys_list : list of LTI, or LTI
        List of linear input/output systems (single system is OK)
    omega : array_like
        Range of frequencies (list or bounds) in rad/sec
    grid : boolean, optional
        True if the plot should include a Nichols-chart grid. Default is True.

    Returns
    -------
    None
    """

    # If argument was a singleton, turn it into a list
    if not getattr(sys_list, '__iter__', False):
        sys_list = (sys_list, )

    if omega is None:
        omega = default_frequency_range(sys_list)

    for sys in sys_list:

        omega = np.asarray(omega)

        if sys.isdtime(strict=True):
            nyquistfrq = 2. * np.pi * 1. / sys.dt / 2.
            omega = omega[omega < nyquistfrq]

        # Get the magnitude and phase of the system
        mag_tmp, phase_tmp, omega = sys.freqresp(omega)
        mag = np.squeeze(mag_tmp)
        phase = np.atleast_1d(np.squeeze(phase_tmp))
        phase = unwrap(phase)

        if np.any((phase * 180.0 / np.pi) >= 180):
            phase = phase - 2 * np.pi

        # Convert to Nichols-plot format (phase in degrees,
        # and magnitude in dB)
        x = unwrap(sp.degrees(phase), 360)
        y = 20 * sp.log10(mag)

        # Generate the plot
        ax.plot(x, y)

        ax.xaxis.set_major_formatter(mticker.FormatStrFormatter("%.1f °"))
        ax.yaxis.set_major_formatter(mticker.FormatStrFormatter("%.1f dB"))

    ax.set_xlabel('Fase (deg)')
    ax.set_ylabel('Magnitud (dB)')
    ax.set_title('Nichols Plot')

    # Mark the -180 point
    ax.plot([-180], [0], 'r+')

    # Add grid
    if grid:
        nichols_grid(figure=figure, ax=ax, delay=delay)

    return x, y, omega
Пример #42
0
    def _update_canvas(self):
        """
        Update the figure when the user changes an input value.
        :return:
        """
        frequency = float(self.frequency.text())
        radius = self.radius.text().split(',')
        mu_r = self.mu_r.text().split(',')
        eps_r = self.eps_r.text().split(',')
        number_of_modes = int(self.number_of_modes.text())

        # To put the parameters in order
        nr = len(radius)

        mu = ones(nr + 1)
        eps = ones(nr + 1)
        ra = ones(nr)

        # Set up the parameters in the correct order
        i = 0
        for r in radius:
            ra[nr - 1 - i] = float(r)
            i += 1

        i = 0
        for m, e in zip(mu_r, eps_r):
            mu[nr - i] = float(m)
            eps[nr - i] = float(e)
            i += 1

        # Flag for PEC core
        pec = self.pec.currentText()

        pec_b = False
        if pec == 'True':
            pec_b = True

        # Set the observation angles
        observation_angle = linspace(0, pi, 721)

        An, Bn = coefficients(frequency, eps, mu, ra, number_of_modes, pec_b)

        et = array([radar_cross_section(frequency, oa, 0, An, Bn) for oa in observation_angle])
        ep = array([radar_cross_section(frequency, oa, 90, An, Bn) for oa in observation_angle])

        # Clear the axes for the updated plot
        self.axes1.clear()

        # Display the results
        self.axes1.plot(degrees(observation_angle), 20.0 * log10(abs(ep[:, 1])), '', label='TE')
        self.axes1.plot(degrees(observation_angle), 20.0 * log10(abs(et[:, 0])), '--', label='TM')

        # Set the plot title and labels
        self.axes1.set_title('RCS vs Bistatic Angle', size=14)
        self.axes1.set_ylabel('RCS (dBsm)', size=12)
        self.axes1.set_xlabel('Observation Angle (deg)', size=12)
        self.axes1.set_ylim(min(20.0 * log10(abs(et[:,0]))) - 3, max(20.0 * log10(abs(et[:,0]))) + 3)

        # Set the tick label size
        self.axes1.tick_params(labelsize=12)

        # Set the legend
        self.axes1.legend(loc='upper left', prop={'size': 10})

        # Turn on the grid
        self.axes1.grid(linestyle=':', linewidth=0.5)

        # Update the canvas
        self.my_canvas.draw()
Пример #43
0
 def __get_theta_deg(self):
     return scipy.degrees(self.theta)