Ejemplo n.º 1
0
def get_declination(app_long: FlexNum, oblique_corr: FlexNum):
    """ solar declination angle at ref_datetime"""

    sal = radians(app_long)
    oc = radians(oblique_corr)

    declination = degrees(arcsin((sin(oc) * sin(sal))))
    return declination
Ejemplo n.º 2
0
def get_right_ascension(app_long: FlexNum, oblique_corr: FlexNum):
    """ calculates the suns right ascension angle """

    sal = radians(app_long)
    oc = radians(oblique_corr)

    right_ascension = degrees(arctan2(cos(oc) * sin(sal), cos(sal)))
    return right_ascension
Ejemplo n.º 3
0
def get_zenith(declination: FlexNum, hour_angle: FlexNum, lat_r: FlexNum):
    """ calculates solar zenith angle at ref_datetime"""

    d = radians(declination)
    ha = radians(hour_angle)
    lat = lat_r

    zenith = degrees(arccos(sin(lat) * sin(d) + cos(lat) * cos(d) * cos(ha)))
    return zenith
Ejemplo n.º 4
0
def get_hour_angle_sunrise(declination: FlexNum, lat_r: FlexNum):
    """ calculates the hour angle of sunrise """

    d = radians(declination)
    lat = lat_r  # radians

    hour_angle_sunrise = degrees(
        arccos(
            (cos(radians(90.833)) / (cos(lat) * cos(d)) - tan(lat) * tan(d))))

    return hour_angle_sunrise
def normalize_asteroids(df):
    df.rename(columns={'e': 'ecce',
                       'i': 'incl',
                       'a': 'semiax',
                       'om': 'Omega',
                       'w': 'omegap'}, inplace=True)

    # it's ugly but it seems to work only in this way
    df['incl'] = radians(df['incl'])
    df['Omega'] = radians(df['Omega'])
    df['omegap'] = radians(df['omegap'])
    return df
Ejemplo n.º 6
0
def _polar_to_cartesian(phi: FlexNum, theta: FlexNum):
    """
    Converts polar to cartesian coordinate unit vector (vector length of one).

    :param phi: phi is measured as an azimuth or aspect angle in the x,y plane. (degrees)
    :param theta: theta is measured as an angle from vertical, as zenith or slope angle. (degrees)

    note that phi may be 'Nan' where theta is zero (perfect z vector)
    """
    theta_r = radians(theta)
    phi_r = radians(phi)

    y = np.sin(theta_r) * np.cos(phi_r)
    x = np.sin(theta_r) * np.sin(phi_r)
    z = np.cos(theta_r)
    return np.stack([x, y, z], axis=-1)
Ejemplo n.º 7
0
def get_oblique_corr(ajc: FlexNum, oblique_mean_ellipse: FlexNum):
    """ calculates the oblique correction """

    ome = oblique_mean_ellipse

    oblique_corr = ome + 0.00256 * cos(radians(125.04 - 1934.136 * ajc))
    return oblique_corr
Ejemplo n.º 8
0
def get_rad_vector(earth_eccent: FlexNum, true_anom: FlexNum):
    """ calculates incident radiation vector to surface at ref_datetime (AUs)"""

    ec = earth_eccent
    ta = radians(true_anom)

    rad_vector = (1.000001018 * (1 - ec**2)) / (1 + ec * cos(ta))
    return rad_vector
Ejemplo n.º 9
0
def get_equation_of_time(oblique_corr: FlexNum, geomean_long: FlexNum,
                         geomean_anom: FlexNum, earth_eccent: FlexNum):
    """ calculates the equation of time in minutes """

    oc = radians(oblique_corr)
    gml = radians(geomean_long)
    gma = radians(geomean_anom)
    ec = earth_eccent

    vary = tan(oc / 2)**2

    equation_of_time = 4 * degrees(
        vary * sin(2 * gml) - 2 * ec * sin(gma) + \
        4 * ec * vary * sin(gma) * cos(2 * gml) - \
        0.5 * vary * vary * sin(4 * gml) - \
        1.25 * ec * ec * sin(2 * gma))

    return equation_of_time
Ejemplo n.º 10
0
def get_sun_eq_of_center(ajc: FlexNum, geomean_anom: FlexNum):
    """calculates the suns equation of center"""

    gma = radians(geomean_anom)

    sun_eq_of_center = \
        sin(gma) * (1.914602 - ajc * (0.004817 + 0.000014 * ajc)) + \
        sin(2 * gma) * (0.019993 - 0.000101 * ajc) + \
        sin(3 * gma) * 0.000289
    return sun_eq_of_center
Ejemplo n.º 11
0
def get_elevation(zenith: FlexNum):
    """ calculates solar elevation angle at ref_datetime"""

    # perform an approximate atmospheric refraction correction

    # matrix hour_angle calculations
    # these equations are hideous, but im not sure how to improve them without adding computational complexity
    if isinstance(zenith, np.ndarray) and zenith.shape:
        e = 90.0 - zenith
        ar = e * 0

        ar[e > 85] = 0
        ar[(e > 5) & (e <= 85)] = 58.1 / tan(radians(e[(e > 5) & (e <= 85)])) - \
                                  0.07 / tan(radians(e[(e > 5) & (e <= 85)])) ** 3 + \
                                  0.000086 / tan(radians(e[(e > 5) & (e <= 85)])) ** 5
        ar[(e > -0.575) & (e <= 5)] = 1735 + e[(e > -0.575) & (e <= 5)] * \
                                             (103.4 + e[(e > -0.575) & (e <= 5)] * (
                                                 -12.79 + e[(e > -0.575) & (e <= 5)] * 0.711))
        ar[e <= -0.575] = -20.772 / tan(radians(e[e <= -0.575]))

    # scalar hour_angle calculations
    else:
        e = 90.0 - zenith
        er = radians(e)

        if e > 85:
            ar = 0
        elif e > 5:
            ar = 58.1 / tan(er) - 0.07 / tan(er)**3 + 0.000086 / tan(er)**5
        elif e > -0.575:
            ar = 1735 + e * (103.4 + e * (-12.79 + e * 0.711))
        else:
            ar = -20.772 / tan(er)

    elevation_noatmo = e
    atmo_refraction = ar / 3600
    elevation = elevation_noatmo + atmo_refraction

    return elevation
Ejemplo n.º 12
0
def get_air_mass(zenith: FlexNum, method: str = None):
    """
    air mass is a concept from the solar power world that accounts for the mass of air
    between a point on the earths surface and the sun as a function of zenith angle.

    This method implements the Kasten-Young formula as well as a simple spherical approximation
    https://www.osapublishing.org/ao/abstract.cfm?uri=ao-28-22-4735

    :param method: Either "kasten-young" or "spherical".
    """

    if method is None:
        method = "kasten-young"  # default

    if method == "spherical":
        z_r = radians(zenith)
        r = CONSTANTS.earth_radius / CONSTANTS.atm_height
        return (r * (cos(z_r)**2) + (2 * r) + 1)**0.5 - (r * cos(z_r))

    elif method == "kasten-young":
        z_r = radians(zenith)
        return 1.0 / (cos(z_r) + 0.50572 * (96.07995 - zenith)**(-1.6364))
Ejemplo n.º 13
0
def get_surf_norm_toa_irradiance(sun_surf_angle: FlexNum,
                                 sun_norm_irradiance: FlexNum):
    """
    gets the irradiance intensity normal to a surface.
    If slope and aspect inputs were used this accounts for the angle of the earths surface.
    """

    ssa_r = radians(sun_surf_angle)
    srf = cos(
        ssa_r
    ) * sun_norm_irradiance  # a theta of zero results in full norm irradiance

    # set negative values to zero.
    if isinstance(srf, np.ndarray) and srf.shape:
        srf[srf <= 0] = 0
        return srf
    else:
        return max([srf, 0.0])
Ejemplo n.º 14
0
 def get_all_pos(drawable: drawable_types, car_length: float = None, car_width: float = None) \
         -> List[Tuple[float, float]]:
     """
     Returns all corner points in anti-clockwise order.
     :param drawable: The objects whose corner positions have to be calculated.
     :param car_length: Only used if the drawable represents a car.
     :param car_width: Only used if the drawable represents a car.
     :return: The corner positions of the given object.
     """
     if isinstance(drawable, Rectangle):
         if car_length and car_width:
             right_bottom_pos: ndarray = asanyarray(drawable.get_xy())
             orientation: float = radians(drawable.angle)
             length_vec: ndarray = CoordsHelp.pol2cart(car_length, orientation)
             width_vec: ndarray = CoordsHelp.pol2cart(car_width, orientation + pi / 2)
             positions = [tuple(right_bottom_pos),
                          tuple(right_bottom_pos + length_vec),
                          tuple(right_bottom_pos + length_vec + width_vec),
                          tuple(right_bottom_pos + width_vec)]
         else:
             raise Exception("For calculating the points of a car the car length and width is needed.")
     else:
         raise Exception("Objects of type " + str(type(drawable)) + " are not supported.")
     return positions
Ejemplo n.º 15
0
 def test_radians(self):
     assert_almost_equal(ncu.radians(180.0), np.pi)
     assert_almost_equal(ncu.radians(-90.0), -0.5 * np.pi)
Ejemplo n.º 16
0
 def test_radians(self):
     assert_almost_equal(ncu.radians(180.0), np.pi)
     assert_almost_equal(ncu.radians(-90.0), -0.5 * np.pi)
Ejemplo n.º 17
0
 def check_radians(self):
     assert_almost_equal(ncu.radians(180.0), pi)
     assert_almost_equal(ncu.degrees(-90.0), -0.5 * pi)
Ejemplo n.º 18
0
 def check_radians(self):
     assert_almost_equal(ncu.radians(180.0), pi)
     assert_almost_equal(ncu.degrees(-90.0), -0.5 * pi)
Ejemplo n.º 19
0
def get_app_long(true_long: FlexNum, ajc: FlexNum):
    """ calculates apparent longitude of the sun"""
    app_long = true_long - 0.00569 - 0.00478 * sin(
        radians(125.04 - 1934.136 * ajc))
    return app_long
Ejemplo n.º 20
0
def get_azimuth(lat_r: FlexNum, declination: FlexNum, hour_angle: FlexNum,
                zenith: FlexNum) -> FlexNum:
    """
    calculates solar azimuth angle. Function requires special treatment
    of different cases of combine vectorize inputs

    Case 1: all scalar inputs
        all scalar inputs are simple, and a scalar will be output.

    Case 2: Time constant, spatial variation (declination is scalar)
        lat_r:          vector (x,y)
        declination:    scalar (z)
        hour_angle:     vector (x,y)
        zenith:         vector (x,y)
        azimuth output  vector (x,y)

    Case 3: Space constant, time variation (lat_r in radians is scalar)
        lat_r:          scalar (x)
        declination:    vector (y)
        hour_angle:     vector (y)
        zenith:         vector (y)
        azimuth output  vector (y)

    case 4: Both space and time variation
        lat_r:          vector (x,y,z)  # duplicated across z axis
        declination:    vector (z)      # will be duplicated to dims (x,y,z)
        hour_angle:     vector (x,y,z)  # duplicated across z axis
        zenith:         vector (x,y,z)  # duplicated across z axis
        azimuth output  vector (x,y,z)  # duplicated across z axis

    In either case 2 or 3, all vector inputs must be identical shapes.
    """

    lat = lat_r
    d = radians(declination)  # always returns numpy arrays, even if 1x1
    ha = radians(hour_angle)  # always returns numpy arrays, even if 1x1
    z = radians(zenith)  # always returns numpy arrays, even if 1x1

    # are the inputs vectorized in space? (lat_r will be a vector)
    if isinstance(lat_r, np.ndarray):
        if lat_r.shape:
            lat_vec = True
        else:
            lat_vec = False  # ndarray with no dimensions is a scalar!
    else:
        lat_vec = False

    if isinstance(d, np.ndarray):
        if d.shape:
            time_vec = True
        else:
            time_vec = False  # ndarray with no dimensions is a scalar!
    else:
        time_vec = False

    # Case 4: Both space and time variation
    if time_vec and lat_vec:
        # if both time and space are vectorized, we must cast declination(time)
        # to the third dimension. by duplicating for all lat/lon pairs.

        if len(lat_r.shape) == 3 and len(d.shape) == 1:
            if lat_r.shape[2] == d.shape[0]:
                d = np.repeat(d[np.newaxis, :], lat_r.shape[1], axis=0)
                d = np.repeat(d[np.newaxis, :], lat_r.shape[0], axis=0)

        az = ha * 0

        ha_p = (ha > 0)  # positive ha indices
        ha_n = (ha <= 0)  # negative ha indices

        az_ha_p = arccos(((sin(lat[ha_p]) * cos(z[ha_p])) - sin(d[ha_p])) /
                         (cos(lat[ha_p]) * sin(z[ha_p])))
        az[ha_p] = (degrees(az_ha_p) + 180) % 360

        az_ha_n = arccos(((sin(lat[ha_n]) * cos(z[ha_n])) - sin(d[ha_n])) /
                         (cos(lat[ha_n]) * sin(z[ha_n])))
        az[ha_n] = (540 - degrees(az_ha_n)) % 360
        azimuth = az

    # Case 3: Space constant, time variation (lat_r in radians is scalar)
    elif time_vec and not lat_vec:
        az = ha * 0

        ha_p = (ha > 0)  # positive ha indices
        ha_n = (ha <= 0)  # negative ha indices

        az_ha_p = arccos(((sin(lat) * cos(z[ha_p])) - sin(d[ha_p])) /
                         (cos(lat) * sin(z[ha_p])))
        az[ha_p] = (degrees(az_ha_p) + 180) % 360

        az_ha_n = arccos(((sin(lat) * cos(z[ha_n])) - sin(d[ha_n])) /
                         (cos(lat) * sin(z[ha_n])))
        az[ha_n] = (540 - degrees(az_ha_n)) % 360
        azimuth = az

    # Case 2: Time constant, spatial variation (declination is scalar)
    elif lat_vec and not time_vec:
        az = ha * 0

        ha_p = (ha > 0)  # positive ha indices
        ha_n = (ha <= 0)  # negative ha indices

        az_ha_p = arccos(((sin(lat[ha_p]) * cos(z[ha_p])) - sin(d)) /
                         (cos(lat[ha_p]) * sin(z[ha_p])))
        az[ha_p] = (degrees(az_ha_p) + 180) % 360

        az_ha_n = arccos(((sin(lat[ha_n]) * cos(z[ha_n])) - sin(d)) /
                         (cos(lat[ha_n]) * sin(z[ha_n])))
        az[ha_n] = (540 - degrees(az_ha_n)) % 360
        azimuth = az

    # case 1, all inputs are scalar.
    else:

        if ha > 0:
            azimuth = (degrees(
                arccos(((sin(lat) * cos(z)) - sin(d)) /
                       (cos(lat) * sin(z)))) + 180) % 360
        else:
            azimuth = (540 - degrees(
                arccos(((sin(lat) * cos(z)) - sin(d)) /
                       (cos(lat) * sin(z))))) % 360

    return azimuth