Exemple #1
0
 def test_vs_noaa_sydney(self):
     sydney = Location('Sydney', 'AUS', latitude=-33.87, longitude=151.22,
                       time_zone=10)
     sp = Sunpath.from_location(sydney)
     sun = sp.calculate_sun(month=11, day=15, hour=11.0)
     assert round(sun.altitude, 2) == 72.26
     assert round(sun.azimuth, 2) == 32.37
Exemple #2
0
 def test_vs_noaa_new_york(self):
     nyc = Location('New_York', 'USA', latitude=40.72, longitude=-74.02,
                    time_zone=-5)
     sp = Sunpath.from_location(nyc)
     sun = sp.calculate_sun(month=9, day=15, hour=11.0)
     assert round(sun.altitude, 2) == 50.35
     assert round(sun.azimuth, 2) == 159.72
Exemple #3
0
 def test_from_location(self):
     sydney = Location('Sydney', 'AUS', latitude=-33.87, longitude=151.22,
                       time_zone=10)
     sunpath = Sunpath.from_location(sydney)
     assert sunpath.latitude == -33.87
     assert sunpath.longitude == 151.22
     assert sunpath.time_zone == 10
Exemple #4
0
    def _calculate_solar_values(self):
        """Calculate solar values for requested hours of the year.

        This method is called everytime that output type is set.
        """
        wea = self.wea
        hoys_set = set(wea.hoys)
        output_type = self.output_type
        month_date_time = (DateTime.from_hoy(idx) for idx in self.hoys)

        sp = Sunpath.from_location(wea.location, self.north)

        # use gendaylit to calculate radiation values for each hour.
        print('Calculating solar values...')
        for timecount, dt in enumerate(month_date_time):
            if dt.hoy not in hoys_set:
                print('Warn: Wea data for {} is not available!'.format(dt))
                continue
            month, day, hour = dt.month, dt.day, dt.float_hour
            dnr, dhr = wea.get_radiation_values(month, day, hour)
            sun = sp.calculate_sun(month, day, hour)
            if sun.altitude < 0:
                continue
            if dnr == 0:
                solarradiance = 0
            else:
                solarradiance = \
                    int(gendaylit(sun.altitude, month, day, hour, dnr, dhr, output_type))

            self._solar_values.append(solarradiance)
            # keep the number of hour relative to hoys in this sun matrix
            self._sun_up_hours_indices.append(timecount)
Exemple #5
0
    def from_json(cls, rec_json):
        """Create the solar access recipe from json.
            {
              "id": "solar_access",
              "type": "gridbased",
              "location": null, // a honeybee location - see below
              "hoys": [], // list of hours of the year
              "surfaces": [], // list of honeybee surfaces
              "analysis_grids": [] // list of analysis grids
              "sun_vectors": [] // list of sun vectors if location is not provided
            }
        """
        hoys = rec_json["hoys"]
        if 'sun_vectors' not in rec_json or not rec_json['sun_vectors']:
            # create sun vectors from location inputs
            loc = Location.from_json(rec_json['location'])
            sp = Sunpath.from_location(loc)
            suns = (sp.calculate_sun_from_hoy(hoy) for hoy in hoys)
            sun_vectors = tuple(s.sun_vector for s in suns if s.is_during_day)
        else:
            sun_vectors = rec_json['sun_vectors']

        analysis_grids = \
            tuple(AnalysisGrid.from_json(ag) for ag in rec_json["analysis_grids"])
        hb_objects = tuple(HBSurface.from_json(srf) for srf in rec_json["surfaces"])
        return cls(sun_vectors, hoys, analysis_grids, 1, hb_objects)
Exemple #6
0
 def test_daylight_saving(self):
     nyc = Location('New_York', 'USA', latitude=40.72, longitude=-74.02,
                    time_zone=-5)
     sp = Sunpath.from_location(nyc)
     dt1 = DateTime(6, 21, 12, 0)
     dt2 = DateTime(12, 21, 12, 0)
     # TODO(mostapha): This is not implemented yet
     # assert sp.is_daylight_saving_hour(dt1) is True
     assert sp.is_daylight_saving_hour(dt1) is False
     assert sp.is_daylight_saving_hour(dt2) is False
Exemple #7
0
 def test_leap_year(self):
     nyc = Location('New_York', 'USA', latitude=40.72, longitude=-74.02,
                    time_zone=-5)
     sp = Sunpath.from_location(nyc)
     sp.is_leap_year = True
     sun = sp.calculate_sun(month=2, day=29, hour=11.0)
     assert sun.datetime == DateTime(2, 29, 11, leap_year=True)
     assert sun.datetime.year == 2016
     assert sun.datetime.month == 2
     assert sun.datetime.day == 29
     assert sun.datetime.hour == 11
Exemple #8
0
    def from_location_and_hoys(cls, location, hoys, point_groups, vector_groups=[],
                               timestep=1, hb_objects=None, sub_folder='sunlighthour'):
        """Create sunlighthours recipe from Location and hours of year."""
        sp = Sunpath.from_location(location)

        suns = (sp.calculate_sun_from_hoy(hoy) for hoy in hoys)

        sun_vectors = tuple(s.sun_vector for s in suns if s.is_during_day)

        analysis_grids = cls.analysis_grids_from_points_and_vectors(point_groups,
                                                                    vector_groups)
        return cls(sun_vectors, hoys, analysis_grids, timestep, hb_objects, sub_folder)
def test_daylight_saving():
    nyc = Location('New_York',
                   'USA',
                   latitude=40.72,
                   longitude=-74.02,
                   time_zone=-5)
    sp = Sunpath.from_location(nyc)
    dt1 = DateTime(6, 21, 12, 0)
    dt2 = DateTime(12, 21, 12, 0)
    # TODO(mostapha): This is not implemented yet
    # assert sp.is_daylight_saving_hour(dt1) is True
    assert sp.is_daylight_saving_hour(dt1) is False
    assert sp.is_daylight_saving_hour(dt2) is False
Exemple #10
0
def test_calculate_sun():
    """Test the varios calculate_sun methods to be sure they all give the same result."""
    nyc = Location('New_York', 'USA', latitude=40.72, longitude=-74.02, time_zone=-5)
    sp = Sunpath.from_location(nyc)

    dt1 = DateTime(3, 21, 9, 30)
    sun1 = sp.calculate_sun(dt1.month, dt1.day, dt1.float_hour)
    sun2 = sp.calculate_sun_from_hoy(dt1.hoy)
    sun3 = sp.calculate_sun_from_moy(dt1.moy)
    sun4 = sp.calculate_sun_from_date_time(dt1)

    assert sun1 == sun2 == sun3 == sun4
    assert round(sun1.altitude, 2) == 36.90
    assert round(sun1.azimuth, 2) == 129.23
Exemple #11
0
 def test_leap_year(self):
     nyc = Location('New_York',
                    'USA',
                    latitude=40.72,
                    longitude=-74.02,
                    time_zone=-5)
     sp = Sunpath.from_location(nyc)
     sp.is_leap_year = True
     sun = sp.calculate_sun(month=2, day=29, hour=11.0)
     assert sun.datetime == DateTime(2, 29, 11, leap_year=True)
     assert sun.datetime.year == 2016
     assert sun.datetime.month == 2
     assert sun.datetime.day == 29
     assert sun.datetime.hour == 11
Exemple #12
0
def test_north_angle():
    """Test the north_angle property on the sun path."""
    nyc = Location('New_York', country='USA', latitude=40.72, longitude=-74.02,
                   time_zone=-5)
    sp = Sunpath.from_location(nyc)

    sp.north_angle = 90
    assert sp.north_angle == 90

    sun = sp.calculate_sun(3, 21, 6, True)
    assert sun.azimuth == approx(90, rel=1e-2)
    assert sun.is_solar_time
    assert sun.north_angle == 90
    assert sun.position_3d(radius=1).y == approx(1, rel=1e-2)
    assert sun.position_3d(radius=1).x < 1e-9
def test_daylight_saving():
    nyc = Location('New_York',
                   'USA',
                   latitude=40.72,
                   longitude=-74.02,
                   time_zone=-5)
    daylight_saving = AnalysisPeriod(st_month=3,
                                     st_day=8,
                                     end_month=11,
                                     end_day=1)
    sp = Sunpath.from_location(nyc, daylight_saving_period=daylight_saving)
    dt1 = DateTime(6, 21, 12, 0)
    dt2 = DateTime(12, 21, 12, 0)
    assert sp.is_daylight_saving_hour(dt1)
    assert not sp.is_daylight_saving_hour(dt2)
Exemple #14
0
def test_vs_noaa_sydney():
    """Test to be sure that the sun positions align with the NOAA formula."""
    sydney = Location('Sydney',
                      country='AUS',
                      latitude=-33.87,
                      longitude=151.22,
                      time_zone=10)
    sp = Sunpath.from_location(sydney)
    sun = sp.calculate_sun(month=11, day=15, hour=11.0)
    assert round(sun.altitude, 2) == 72.26
    assert round(sun.azimuth, 2) == 32.37

    sun2 = sp.calculate_sun_from_date_time(datetime.datetime(2019, 6, 21, 9))
    assert round(sun2.altitude, 2) == 18.99
    assert round(sun2.azimuth, 2) == 42.54
Exemple #15
0
def test_analemma_geometry():
    """Test the analemma_suns method."""
    nyc = Location('New_York', country='USA', latitude=40.72, longitude=-74.02,
                   time_zone=-5)
    sp = Sunpath.from_location(nyc)

    radius = 100
    analemma_geo = sp.hourly_analemma_polyline3d(radius=radius)
    assert len(analemma_geo) == 15
    for pline in analemma_geo:
        assert isinstance(pline, Polyline3D)

    analemma_geo = sp.hourly_analemma_polyline2d(radius=radius)
    assert len(analemma_geo) == 15
    for pline in analemma_geo:
        assert isinstance(pline, Polyline2D)
Exemple #16
0
def test_analemma_daytime_with_linesegment():
    """Test the hourly_analemma_polyline3d with a latitude that yields a line segment."""
    test_loc = Location('Test Location', latitude=51, longitude=0)
    sp = Sunpath.from_location(test_loc)

    l_seg_count = 0
    for pline in sp.hourly_analemma_polyline3d():
        if isinstance(pline, LineSegment3D):
            l_seg_count += 1
    assert l_seg_count == 0

    l_seg_count = 0
    for pline in sp.hourly_analemma_polyline2d():
        if isinstance(pline, LineSegment2D):
            l_seg_count += 1
    assert l_seg_count == 0
Exemple #17
0
    def from_location_and_analysis_period(
        cls, location, analysis_period, point_groups, vector_groups=None,
            hb_objects=None, sub_folder='sunlighthour'):
        """Create sunlighthours recipe from Location and analysis period."""
        vector_groups = vector_groups or ()

        sp = Sunpath.from_location(location)

        suns = (sp.calculate_sun_from_hoy(hoy) for hoy in analysis_period.float_hoys)

        sun_vectors = tuple(s.sun_vector for s in suns if s.is_during_day)
        hoys = tuple(s.hoy for s in suns if s.is_during_day)

        analysis_grids = cls.analysis_grids_from_points_and_vectors(point_groups,
                                                                    vector_groups)
        return cls(sun_vectors, hoys, analysis_grids, analysis_period.timestep,
                   hb_objects, sub_folder)
Exemple #18
0
def test_body_dir_from_dir_normal():
    """Test body_solar_flux_from_parts gainst its horizontal counterpart."""
    wea_obj = Wea.from_epw_file('./tests/epw/chicago.epw')
    diff_hr = wea_obj.diffuse_horizontal_irradiance.values
    dir_nr = wea_obj.direct_normal_irradiance.values
    dir_hr = wea_obj.direct_horizontal_irradiance.values
    dts = wea_obj.datetimes
    sp = Sunpath.from_location(wea_obj.location)

    for i in xrange(8760):
        sun = sp.calculate_sun_from_date_time(dts[i])
        alt, az = sun.altitude, sun.azimuth
        sharp = sharp_from_solar_and_body_azimuth(az, 180)
        sflux1 = body_solar_flux_from_parts(diff_hr[i], dir_nr[i], alt, sharp)
        sflux2 = body_solar_flux_from_horiz_solar(diff_hr[i], dir_hr[i], alt,
                                                  sharp)
        assert sflux1 == pytest.approx(sflux2, rel=1e-2)
Exemple #19
0
    def _solar_calc(self,
                    hoys,
                    wea,
                    output_type,
                    leap_year=False,
                    reverse_vectors=False):
        """Calculate sun vectors and radiance values from the properties."""
        solar_calc = LBSunpath.from_location(self.location, self.north)
        solar_calc.is_leap_year = leap_year

        if not hoys:
            # set hours to an annual hourly sunpath
            hoys = range(8760) if not leap_year else range(8760 + 24)

        sun_up_hours = []
        sun_vectors = []
        radiance_values = []
        altitudes = []
        for hour in hoys:
            sun = solar_calc.calculate_sun_from_hoy(hour)
            if sun.altitude < 0:
                continue
            sun_vectors.append(sun.sun_vector)
            sun_up_hours.append(hour)
            altitudes.append(sun.altitude)
        # calculate irradiance value
        if wea:
            # this is a climate_based sunpath. Get the values from wea
            assert isinstance(wea, Wea), 'Expected Wea not %s' % type(wea)

            for altitude, hoy in zip(altitudes, sun_up_hours):
                dnr, dhr = wea.get_irradiance_value_for_hoy(hoy)
                if dnr == 0:
                    radiance_value = 0
                else:
                    radiance_value = gendaylit(altitude, hoy, dnr, dhr,
                                               output_type, leap_year)
                radiance_values.append(int(radiance_value))
        else:
            radiance_values = [1e6] * len(sun_up_hours)

        if reverse_vectors:
            sun_vectors = [v.reverse() for v in sun_vectors]

        return sun_vectors, sun_up_hours, radiance_values
    def draw_sunpath(self):
        """Calculate and draw sun path to Rhino."""
        self.clear_conduit()

        _location = self.epw.location
        north_ = 0
        _centerPt_ = None
        _scale_ = 1
        _sunScale_ = 1
        _annual_ = True

        daylight_saving_period = None  # temporary until we fully implement it
        _hoys_ = range(23)

        # initiate sunpath based on location
        sp = Sunpath.from_location(_location, north_, daylight_saving_period)

        # draw sunpath geometry
        sunpath_geo = \
            sp.draw_sunpath(_hoys_, _centerPt_, _scale_, _sunScale_, _annual_)

        analemma = sunpath_geo.analemma_curves
        compass = sunpath_geo.compass_curves
        daily = sunpath_geo.daily_curves

        sun_pts = sunpath_geo.sun_geos

        suns = sunpath_geo.suns
        vectors = (geo.vector(*sun.sun_vector) for sun in suns)
        altitudes = (sun.altitude for sun in suns)
        azimuths = (sun.azimuth for sun in suns)
        center_pt = _centerPt_ or geo.point(0, 0, 0)
        hoys = (sun.hoy for sun in suns)
        datetimes = (sun.datetime for sun in suns)

        # draw the curves to canvas
        self.conduit = DrawSunPath(
            list(analemma) + list(compass) + list(daily), sun_pts)
        self.conduit.Enabled = True
        # add lights
        for sun in suns:
            light = Rhino.Geometry.Light.CreateSunLight(
                north_, sun.azimuth - 90, sun.altitude)
            sc.doc.Lights.Add(light)
        sc.doc.Views.Redraw()
 def _get_altitudes_and_sharps(self):
     """Get altitudes and sharps from solar position."""
     sp = Sunpath.from_location(self._location)
     _altitudes = []
     if self._body_par.body_azimuth is None:
         _sharps = [self._body_par.sharp] * self._calc_length
         for t_date in self._base_collection.datetimes:
             sun = sp.calculate_sun_from_date_time(t_date)
             _altitudes.append(sun.altitude)
     else:
         _sharps = []
         for t_date in self._base_collection.datetimes:
             sun = sp.calculate_sun_from_date_time(t_date)
             sharp = sharp_from_solar_and_body_azimuth(
                 sun.azimuth, self._body_par.body_azimuth)
             _sharps.append(sharp)
             _altitudes.append(sun.altitude)
     return _altitudes, _sharps
Exemple #22
0
def test_sunrise_sunset():
    """Test to be sure that the sunrise/sunset aligns with the NOAA formula."""
    sydney = Location('Sydney', country='AUS', latitude=-33.87, longitude=151.22,
                      time_zone=10)
    sp = Sunpath.from_location(sydney)

    # use the depression for apparent sunrise/sunset
    srss_dict = sp.calculate_sunrise_sunset(6, 21, depression=0.8333)
    
    assert srss_dict['sunrise'] == DateTime(6, 21, 7, 0)
    assert srss_dict['noon'] == DateTime(6, 21, 11, 57)
    assert srss_dict['sunset'] == DateTime(6, 21, 16, 54)

    # use the depression for actual sunrise/sunset
    srss_dict = sp.calculate_sunrise_sunset(6, 21, depression=0.5334)
    assert srss_dict['sunrise'] == DateTime(6, 21, 7, 2)
    assert srss_dict['noon'] == DateTime(6, 21, 11, 57)
    assert srss_dict['sunset'] == DateTime(6, 21, 16, 52)
Exemple #23
0
    def from_location_and_analysis_period(
        cls, location, analysis_period, point_groups, vector_groups=None,
        hb_objects=None, sub_folder='sunlighthour'
    ):
        """Create sunlighthours recipe from Location and analysis period."""
        vector_groups = vector_groups or ()

        sp = Sunpath.from_location(location)

        suns = (sp.calculate_sun_from_hoy(hoy) for hoy in analysis_period.float_hoys)

        sun_vectors = tuple(s.sun_vector for s in suns if s.is_during_day)
        hoys = tuple(s.hoy for s in suns if s.is_during_day)

        analysis_grids = cls.analysis_grids_from_points_and_vectors(point_groups,
                                                                    vector_groups)
        return cls(sun_vectors, hoys, analysis_grids, analysis_period.timestep,
                   hb_objects, sub_folder)
Exemple #24
0
    def from_location_and_hoys(cls,
                               location,
                               hoys,
                               point_groups,
                               vector_groups=[],
                               timestep=1,
                               hb_objects=None,
                               sub_folder='sunlighthour'):
        """Create sunlighthours recipe from Location and hours of year."""
        sp = Sunpath.from_location(location)

        suns = tuple(sp.calculate_sun_from_hoy(hoy) for hoy in hoys)

        sun_vectors = tuple(s.sun_vector for s in suns if s.is_during_day)
        sun_up_hoys = tuple(s.hoy for s in suns if s.is_during_day)
        analysis_grids = cls.analysis_grids_from_points_and_vectors(
            point_groups, vector_groups)
        return cls(sun_vectors, sun_up_hoys, analysis_grids, timestep,
                   hb_objects, sub_folder)
Exemple #25
0
def test_analemma_suns():
    """Test the analemma_suns method."""
    nyc = Location('New_York', country='USA', latitude=40.72, longitude=-74.02,
                   time_zone=-5)
    sp = Sunpath.from_location(nyc)

    assert len(sp.analemma_suns(Time(12), True, True)) == 12
    assert len(sp.analemma_suns(Time(6), True, True)) == 7
    assert len(sp.analemma_suns(Time(0), True, True)) == 0
    assert len(sp.analemma_suns(Time(6), False, True)) == 12
    assert len(sp.analemma_suns(Time(0), False, True)) == 12

    for sun in sp.analemma_suns(Time(12)):
        assert isinstance(sun, Sun)
    
    assert len(sp.hourly_analemma_suns()) == 24
    for hr in sp.hourly_analemma_suns():
        for sun in hr:
            assert isinstance(sun, Sun)
Exemple #26
0
def test_daylight_saving():
    """Test the applicaiton of daylight saving time."""
    nyc = Location('New_York',
                   country='USA',
                   latitude=40.72,
                   longitude=-74.02,
                   time_zone=-5)
    daylight_saving = AnalysisPeriod(st_month=3,
                                     st_day=8,
                                     st_hour=2,
                                     end_month=11,
                                     end_day=1,
                                     end_hour=2)
    sp = Sunpath.from_location(nyc, daylight_saving_period=daylight_saving)
    dt1 = DateTime(6, 21, 12, 0)
    dt2 = DateTime(12, 21, 12, 0)
    dt3 = DateTime(6, 21, 0)
    dt4 = DateTime(12, 21, 0)

    assert sp.is_daylight_saving_hour(dt1)
    assert not sp.is_daylight_saving_hour(dt2)
    assert sp.is_daylight_saving_hour(dt3)
    assert not sp.is_daylight_saving_hour(dt4)

    sun1ds = sp.calculate_sun_from_date_time(dt1)
    sun2ds = sp.calculate_sun_from_date_time(dt2)
    sun3ds = sp.calculate_sun_from_date_time(dt3)
    sun4ds = sp.calculate_sun_from_date_time(dt4)

    sp.daylight_saving_period = None

    assert sun1ds != sp.calculate_sun_from_date_time(dt1)
    assert sun3ds != sp.calculate_sun_from_date_time(dt3)
    assert sun1ds.altitude == \
        approx(sp.calculate_sun_from_date_time(dt1.sub_hour(1)).altitude, rel=1e-2)
    assert sun3ds.altitude == \
        approx(sp.calculate_sun_from_date_time(dt3.sub_hour(1)).altitude, rel=1e-2)

    sun2 = sp.calculate_sun_from_date_time(dt2)
    sun4 = sp.calculate_sun_from_date_time(dt4)
    assert sun2 == sun2ds
    assert sun4 == sun4ds
Exemple #27
0
        def process(self):
            if not any(socket.is_linked for socket in self.outputs):
                return

            location_s = self.inputs['Location'].sv_get()
            month_s = self.inputs['Month'].sv_get()
            day_s = self.inputs['Day'].sv_get()
            hour_s = self.inputs['Hour'].sv_get()

            altitude_s, azimuth_s = [], []
            sun_pos = []
            for location, months, days, hours in zip_long_repeat(
                    location_s, month_s, day_s, hour_s):
                sp = Sunpath.from_location(location)

                # sp = Sunpath.from_location(location, north_angle=40)
                altitude, azimuth = [], []
                for mo, day, ho in zip_long_repeat(months, days, hours):

                    sun = sp.calculate_sun(month=mo, day=day, hour=ho)
                    alt_l = sun.altitude
                    azi_l = sun.azimuth
                    altitude.append(sun.altitude)
                    azimuth.append(sun.azimuth)
                    angles = (alt_l * pi / 180, 0,
                              -azi_l * pi / 180 + self.north_angle * pi / 180)
                    euler = Euler(angles, 'XYZ')
                    mat_r = euler.to_quaternion().to_matrix().to_4x4()
                    pos = mat_r @ Vector((0, self.sun_dist, 0))
                    mat_t = Matrix.Translation(pos)
                    angles = ((90 - alt_l) * pi / 180, 0,
                              (180 - azi_l) * pi / 180 +
                              self.north_angle * pi / 180)
                    euler = Euler(angles, 'XYZ')
                    mat_r = euler.to_quaternion().to_matrix().to_4x4()
                    m = mat_t @ mat_r
                    sun_pos.append(m)
                altitude_s.append(altitude)
                azimuth_s.append(azimuth)
            self.outputs['Altitude'].sv_set(altitude_s)
            self.outputs['Azimuth'].sv_set(azimuth_s)
            self.outputs['Sun Position'].sv_set(sun_pos)
Exemple #28
0
    def from_location_sun_up_hours(cls, location, sun_up_hours, north=0,
                                   is_leap_year=False):
        """Generate a radiance-based analemma for a location.

        Args:
            location: A ladybug location.
            sun_up_hours: A list of hours of the year to be included in analemma.
            north: North angle from Y direction (default: 0).
            is_leap_year: A boolean to indicate if hours are for a leap year
                (default: False).
        """
        sun_vectors = []
        north = north or 0

        sp = Sunpath.from_location(location, north)
        sp.is_leap_year = is_leap_year
        for hour in sun_up_hours:
            sun = sp.calculate_sun_from_hoy(hour)
            sun_vectors.append(sun.sun_vector)

        return cls(sun_vectors, sun_up_hours)
Exemple #29
0
    def from_location(cls, location, hoys=None, north=0):
        """Generate a radiance-based analemma for a location.

        Args:
            location: A ladybug location.
            hoys: A list of hours of the year (default: range(8760)).
            north: North angle from Y direction (default: 0).
        """
        sun_vectors = []
        sun_up_hours = []
        hoys = hoys or range(8760)
        north = north or 0

        sp = Sunpath.from_location(location, north)
        for hour in hoys:
            sun = sp.calculate_sun_from_hoy(hour)
            if sun.altitude < 0:
                continue
            sun_vectors.append(sun.sun_vector)
            sun_up_hours.append(hour)

        return cls(sun_vectors, sun_up_hours)
Exemple #30
0
    def _calculate_solar_values(wea,
                                hoys,
                                output_type,
                                north=0,
                                is_leap_year=False):
        """Calculate solar values for requested hours of the year.

        This method is called everytime that output type is set.
        """
        month_date_time = (DateTime.from_hoy(idx, is_leap_year)
                           for idx in hoys)

        sp = Sunpath.from_location(wea.location, north)
        sp.is_leap_year = is_leap_year
        solar_values = []
        sun_up_hours = []

        # use gendaylit to calculate radiation values for each hour.
        print('Calculating solar values...')
        for timecount, dt in enumerate(month_date_time):
            month, day, hour = dt.month, dt.day, dt.float_hour
            sun = sp.calculate_sun(month, day, hour)
            if sun.altitude < 0:
                continue
            else:
                dnr, dhr = wea.get_irradiance_value(month, day, hour)
                if dnr == 0:
                    solarradiance = 0
                else:
                    solarradiance = \
                        int(gendaylit(sun.altitude, month, day, hour, dnr, dhr,
                                      output_type))

                solar_values.append(solarradiance)
                # keep the number of hour relative to hoys in this sun matrix
                sun_up_hours.append(dt.hoy)

        return solar_values, sun_up_hours
Exemple #31
0
def test_day_arc_geometry():
    """Test the day_arc3d method."""
    nyc = Location('New_York', country='USA', latitude=40.72, longitude=-74.02,
                   time_zone=-5)
    sp = Sunpath.from_location(nyc)

    radius = 100

    arc_geo = sp.day_arc3d(3, 21, radius=radius)
    assert isinstance(arc_geo, Arc3D)
    assert arc_geo.length == approx(math.pi * radius, rel=1e-2)

    arc_geo = sp.day_polyline2d(3, 21, radius=radius)
    assert isinstance(arc_geo, Polyline2D)

    arc_geo = sp.monthly_day_arc3d(radius=radius)
    assert len(arc_geo) == 12
    for pline in arc_geo:
        assert isinstance(pline, Arc3D)

    arc_geo = sp.monthly_day_polyline2d(radius=radius)
    assert len(arc_geo) == 12
    for pline in arc_geo:
        assert isinstance(pline, Polyline2D)
Exemple #32
0
def test_split_modifiers():
    ap = AnalysisPeriod(timestep=4)
    sp = Sunpath(location)
    lb_sp = LBSunpath.from_location(location)
    folder = './tests/assets/temp'
    filename = 'sunpath_timestep_4'
    sp.to_file(folder, filename, hoys=ap.hoys)
    sp_file = os.path.join(folder, '%s.rad' % filename)
    sp_mod_files = [
        os.path.join(folder, '%s_%d.mod' % (filename, count))
        for count in range(2)
    ]
    assert os.path.isfile(sp_file)

    lb_tot = [
        i for i in ap.hoys if lb_sp.calculate_sun_from_hoy(i).is_during_day
    ]
    sun_count = [int(len(lb_tot) / 2) - 1, int(len(lb_tot) / 2)]
    for sp_count, sp_mod_file in enumerate(sp_mod_files):
        assert os.path.isfile(sp_mod_file)
        with open(sp_mod_file) as inf:
            for count, _ in enumerate(inf):
                pass
        assert count == sun_count[sp_count]
Exemple #33
0
def oiko_make_epw(api_key, city, country, latitude, longitude, year):
    '''
    Args:}
        api_key: User API key for OikoLab.
        city: city name as string
        country: country name as string.
        latitude: Location latitude between -90 and 90
        longitude: Location longitude between -180 (west) and 180 (east)
        year: year between 1980 and 2019
    '''

    parameters = [
        'temperature', 'dewpoint_temperature', 'surface_solar_radiation',
        'surface_thermal_radiation', 'surface_direct_solar_radiation',
        'surface_diffuse_solar_radiation', 'relative_humidity', 'wind_speed',
        'surface_pressure', 'total_cloud_cover'
    ]
    location = Location(city=city,
                        country=country,
                        latitude=latitude,
                        longitude=longitude)

    # create the payload
    payload = {
        'param': parameters,
        'start': '{}-01-01T00:00:00'.format(year),
        'end': '{}-12-31T23:00:00'.format(year),
        'lat': location.latitude,
        'lon': location.longitude,
    }

    # make the request
    r = requests.get('https://api.oikolab.com/weather',
                     params=payload,
                     headers={
                         'content-encoding': 'gzip',
                         'Connection': 'close',
                         'api-key': '{}'.format(api_key)
                     })

    if r.status_code == 200:
        attributes = r.json()['attributes']
        weather_data = json.loads(r.json()['data'])
    else:
        print(r.text)
        return None

    # set the UTC offset on the location based on the request
    location.time_zone = attributes['utc_offset']
    leap_yr = True if year % 4 == 0 else False

    # create a dictionary of timeseries data streams
    data_dict = {}
    data_values = zip(*weather_data['data'])
    for param, data in zip(parameters, data_values):
        data_dict[param] = data

    # compute solar radiation components and estimate illuminance from irradiance
    datetimes = AnalysisPeriod(is_leap_year=leap_yr).datetimes

    direct_normal_irr = []
    gh_ill = []
    dn_ill = []
    dh_ill = []
    sp = Sunpath.from_location(location)
    sp.is_leap_year = leap_yr
    for dt, glob_hr, dir_hr, dif_hr, dp in zip(
            datetimes, data_dict['surface_solar_radiation'],
            data_dict['surface_direct_solar_radiation'],
            data_dict['surface_diffuse_solar_radiation'],
            data_dict['dewpoint_temperature']):
        sun = sp.calculate_sun_from_date_time(dt)
        alt = sun.altitude
        dir_nr = dir_hr / math.sin(math.radians(alt)) if alt > 1 else 0
        direct_normal_irr.append(dir_nr)
        gh, dn, dh, z = estimate_illuminance_from_irradiance(
            alt, glob_hr, dir_nr, dif_hr, dp)
        gh_ill.append(gh)
        dn_ill.append(dn)
        dh_ill.append(dh)

    # create the EPW object and set properties
    epw = EPW.from_missing_values(is_leap_year=leap_yr)
    epw.location = location
    epw.years.values = [year] * 8760 if not leap_yr else [year] * 8784
    epw.dry_bulb_temperature.values = data_dict['temperature']
    epw.dew_point_temperature.values = data_dict['dewpoint_temperature']
    epw.global_horizontal_radiation.values = data_dict[
        'surface_solar_radiation']
    epw.direct_normal_radiation.values = direct_normal_irr
    epw.diffuse_horizontal_radiation.values = data_dict[
        'surface_diffuse_solar_radiation']
    epw.global_horizontal_illuminance.values = gh_ill
    epw.direct_normal_illuminance.values = dn_ill
    epw.diffuse_horizontal_illuminance.values = dh_ill
    epw.horizontal_infrared_radiation_intensity.values = data_dict[
        'surface_thermal_radiation']
    epw.relative_humidity.values = [
        val * 100.0 for val in data_dict['relative_humidity']
    ]
    epw.atmospheric_station_pressure.values = data_dict['surface_pressure']
    epw.total_sky_cover.values = data_dict['total_cloud_cover']
    epw.wind_speed.values = data_dict['wind_speed']

    # write EPW to a file
    file_path = os.path.join(folders.default_epw_folder,
                             '{}_{}.epw'.format(location.city, year))
    epw.save(file_path)
    print('EPW file generated and saved to - %s' % file_path)

    return file_path
Exemple #34
0
    projection_ = projection_.title() if projection_ is not None else None

    # create a intersection of the input hoys_ and the data hoys
    if len(data_) > 0 and len(hoys_) > 0:
        all_aligned = all(data_[0].is_collection_aligned(d) for d in data_[1:])
        assert all_aligned, 'All collections input to data_ must be aligned for ' \
            'each Sunpath.\nGrafting the data_ and suplying multiple grafted ' \
            '_center_pt_ can be used to view each data on its own path.'
        if statement_ is not None:
            data_ = HourlyContinuousCollection.filter_collections_by_statement(
                data_, statement_)
        data_hoys = set(dt.hoy for dt in data_[0].datetimes)
        hoys_ = list(data_hoys.intersection(set(hoys_)))

    # initialize sunpath based on location
    sp = Sunpath.from_location(_location, north_, dl_saving_)

    # process all of the input hoys into altitudes, azimuths and vectors
    altitudes, azimuths, datetimes, moys, hoys, vectors, suns = [], [], [], [], [], [], []
    for hoy in hoys_:
        sun = sp.calculate_sun_from_hoy(hoy, solar_time_)
        if sun.is_during_day:
            altitudes.append(sun.altitude)
            azimuths.append(sun.azimuth)
            datetimes.append(sun.datetime)
            moys.append(sun.datetime.moy)
            hoys.append(sun.datetime.hoy)
            vectors.append(from_vector3d(sun.sun_vector))
            suns.append(sun)

    if len(data_) > 0 and len(
Exemple #35
0
def sun_altitude(epw_file):
    epw = EPW(epw_file)
    sun_path = Sunpath.from_location(epw.location)
    return np.array(
        [sun_path.calculate_sun_from_hoy(i).altitude for i in range(8760)])
    def execute(self, working_dir, reuse=True):
        """Generate sun matrix.

        Args:
            working_dir: Folder to execute and write the output.
            reuse: Reuse the matrix if already existed in the folder.

        Returns:
            Full path to analemma, sunlist and sun_matrix.
        """
        fp = os.path.join(working_dir, self.analemmafile)
        lfp = os.path.join(working_dir, self.sunlistfile)
        mfp = os.path.join(working_dir, self.sunmtxfile)
        hrf = os.path.join(working_dir, self.name + '.hrs')
        output_type = self.sky_type

        if reuse:
            if self.hours_match(hrf):
                for f in (fp, lfp, mfp):
                    if not os.path.isfile(f):
                        break
                else:
                    return fp, lfp, mfp

        with open(hrf, 'wb') as outf:
            outf.write(','.join(str(h) for h in self.hoys) + '\n')

        wea = self.wea
        month_date_time = (DateTime.from_hoy(idx) for idx in self.hoys)
        latitude, longitude = wea.location.latitude, -wea.location.longitude

        sp = Sunpath.from_location(wea.location, self.north)
        solarradiances = []
        sun_values = []
        sun_up_hours = []  # collect hours that sun is up
        solarstring = \
            'void light solar{0} 0 0 3 {1} {1} {1} ' \
            'solar{0} source sun 0 0 4 {2:.6f} {3:.6f} {4:.6f} 0.533'

        # use gendaylit to calculate radiation values for each hour.
        print('Calculating sun positions and radiation values.')
        count = 0
        for timecount, timeStamp in enumerate(month_date_time):
            month, day, hour = timeStamp.month, timeStamp.day, timeStamp.hour + 0.5
            dnr, dhr = int(wea.direct_normal_radiation[timeStamp.int_hoy]), \
                int(wea.diffuse_horizontal_radiation[timeStamp.int_hoy])
            if dnr == 0:
                continue
            count += 1
            sun = sp.calculate_sun(month, day, hour)
            if sun.altitude < 0:
                continue
            x, y, z = sun.sun_vector
            solarradiance = \
                int(gendaylit(sun.altitude, month, day, hour, dnr, dhr, output_type))
            cur_sun_definition = solarstring.format(count, solarradiance, -x,
                                                    -y, -z)
            solarradiances.append(solarradiance)
            sun_values.append(cur_sun_definition)
            # keep the number of hour relative to hoys in this sun matrix
            sun_up_hours.append(timecount)

        sun_count = len(sun_up_hours)

        assert sun_count > 0, ValueError('There is 0 sun up hours!')

        print('# Number of sun up hours: %d' % sun_count)
        print('Writing sun positions and radiation values to {}'.format(fp))
        # create solar discs.
        with open(fp, 'w') as annfile:
            annfile.write("\n".join(sun_values))
            annfile.write('\n')

        print('Writing list of suns to {}'.format(lfp))
        # create list of suns.
        with open(lfp, 'w') as sunlist:
            sunlist.write("\n".join(
                ("solar%s" % (idx + 1) for idx in xrange(sun_count))))
            sunlist.write('\n')

        # Start creating header for the sun matrix.
        file_header = ['#?RADIANCE']
        file_header += ['Sun matrix created by Honeybee']
        file_header += ['LATLONG= %s %s' % (latitude, -longitude)]
        file_header += ['NROWS=%s' % sun_count]
        file_header += ['NCOLS=%s' % len(self.hoys)]
        file_header += ['NCOMP=3']
        file_header += ['FORMAT=ascii']

        print('Writing sun matrix to {}'.format(mfp))
        # Write the matrix to file.
        with open(mfp, 'w') as sunMtx:
            sunMtx.write('\n'.join(file_header) + '\n' + '\n')
            for idx, sunValue in enumerate(solarradiances):
                sun_rad_list = ['0 0 0'] * len(self.hoys)
                sun_rad_list[sun_up_hours[idx]] = '{0} {0} {0}'.format(
                    sunValue)
                sunMtx.write('\n'.join(sun_rad_list) + '\n\n')

            sunMtx.write('\n')

        return fp, lfp, mfp
def post_process_solar_tracking(result_folders,
                                sun_up_file,
                                location,
                                north=0,
                                tracking_increment=5,
                                destination_folder=None):
    """Postprocess a list of result folders to account for dynamic solar tracking.

    This function essentially takes .ill files for each state of a dynamic tracking
    system and produces a single .ill file that models the tracking behavior.

    Args:
        result_folders: A list of folders containing .ill files and each representing
            a state of the dynamic solar tracking system. These file should be
            ordered from eastern-most to wester-most, tracing the path of the
            tracking system over the day. The names of the .ill files should be
            the same in each folder (representing the same sensor grid in a
            different state).
        sun_up_file: Path to a sun-up-hours.txt that contains the sun-up hours of
            the simulation.
        location: A Ladybug Location object to be used to generate sun poisitions.
        north_: A number between -360 and 360 for the counterclockwise difference
            between the North and the positive Y-axis in degrees. (Default: 0).
        tracking_increment: An integer for the increment angle of each state in
            degrees. (Default: 5).
        destination_folder: A path to a destination folder where the final .ill
            files of the dynamic tracking system will be written. If None, all
            files will be written into the directory above the first result_folder.
            (Default: None).
    """
    # get the orientation angles of the panels for each model
    st_angle = int(90 - (len(result_folders) * tracking_increment / 2)) + 1
    end_angle = int(90 + (len(result_folders) * tracking_increment / 2))
    angles = list(range(st_angle, end_angle, tracking_increment))

    # create a sun path ang get the sun-up hours to be used to get solar positions
    sp = Sunpath.from_location(location, north)
    with open(sun_up_file) as suh_file:
        sun_up_hours = [float(hour) for hour in suh_file.readlines()]

    # for each hour of the sun_up_hours, figure out which file is the one to use
    mtx_to_use, ground_vec = [], Vector3D(1, 0, 0)
    for hoy in sun_up_hours:
        sun = sp.calculate_sun_from_hoy(hoy)
        vec = Vector3D(sun.sun_vector_reversed.x, 0, sun.sun_vector_reversed.z)
        orient = math.degrees(ground_vec.angle(vec))
        for i, ang in enumerate(angles):
            if ang > orient:
                mtx_to_use.append(i)
                break
        else:
            mtx_to_use.append(-1)

    # parse the grids_info in the first folder to understand the sensor grids
    grids_info_file = os.path.join(result_folders[0], 'grids_info.json')
    with open(grids_info_file) as gi_file:
        grids_data = json.load(gi_file)
    grid_ids = [g['full_id'] for g in grids_data]

    # prepare the destination folder and copy the grids_info to it
    if destination_folder is None:
        destination_folder = os.path.dirname(result_folders[0])
    if not os.path.isdir(destination_folder):
        os.mkdir(destination_folder)
    shutil.copyfile(grids_info_file,
                    os.path.join(destination_folder, 'grids_info.json'))

    # convert the .ill files of each sensor grid into a single .ill file
    for grid_id in grid_ids:
        grid_mtx = []
        for i, model in enumerate(result_folders):
            grid_file = os.path.join(model, '{}.ill'.format(grid_id))
            with open(grid_file) as ill_file:
                grid_mtx.append([lin.split() for lin in ill_file])
        grid_ill = []
        for i, hoy_mtx in enumerate(mtx_to_use):
            hoy_vals = []
            for pt in range(len(grid_mtx[0])):
                hoy_vals.append(grid_mtx[hoy_mtx][pt][i])
            grid_ill.append(hoy_vals)
        dest_file = os.path.join(destination_folder, '{}.ill'.format(grid_id))
        with open(dest_file, 'w') as ill_file:
            for row in zip(*grid_ill):
                ill_file.write('  '.join(row) + '\n')
    )

    # create the points representing the human geometry
    human_points = []
    human_line = []
    for pos in _position:
        hpts, hlin = human_height_points(pos, _height_, _pt_count_)
        human_points.extend(hpts)
        human_line.append(hlin)

    if _run:
        # mesh the context for the intersection calculation
        shade_mesh = join_geometry_to_mesh(_context)

        # generate the sun vectors for each sun-up hour of the year
        sp = Sunpath.from_location(_location, north_)
        sun_vecs = []
        day_pattern = []
        for hoy in range(8760):
            sun = sp.calculate_sun_from_hoy(hoy)
            day_pattern.append(sun.is_during_day)
            if sun.is_during_day:
                sun_vecs.append(from_vector3d(sun.sun_vector_reversed))

        # intersect the sun vectors with the context and compute fraction exposed
        sun_int_matrix, angles = intersect_mesh_rays(shade_mesh,
                                                     human_points,
                                                     sun_vecs,
                                                     cpu_count=workers)
        fract_body_exp = []
        for i in range(0, len(human_points), _pt_count_):
Exemple #39
0
north_, _location, _hoys_, _centerPt_, _scale_, _sunScale_, _annual_ = IN
vectors = altitudes = azimuths = sunPts = analemma = compass = daily = centerPt = hoys = datetimes = None

try:
    from ladybug.sunpath import Sunpath
    import ladybug.geometry as geo
except ImportError as e:
    raise ImportError('\nFailed to import ladybug:\n\t{}'.format(e))

if _location:

    daylightSavingPeriod = None  # temporary until we fully implement it
    _hoys_ = _hoys_ or ()

    # initiate sunpath based on location
    sp = Sunpath.from_location(_location, north_, daylightSavingPeriod)

    # draw sunpath geometry
    sunpath_geo = \
        sp.draw_sunpath(_hoys_, _centerPt_, _scale_, _sunScale_, _annual_)

    analemma = sunpath_geo.analemma_curves
    compass = sunpath_geo.compass_curves
    daily = sunpath_geo.daily_curves

    sunPts = sunpath_geo.sun_geos

    suns = sunpath_geo.suns
    vectors = (geo.vector(*sun.sun_vector) for sun in suns)
    altitudes = (sun.altitude for sun in suns)
    azimuths = (sun.azimuth for sun in suns)
Exemple #40
0
def shortwave_mrt_map(location,
                      longwave_data,
                      sun_up_hours,
                      total_ill,
                      direct_ill,
                      ref_ill=None,
                      solarcal_par=None):
    """Get MRT data collections adjusted for shortwave using Radiance .ill files.

    Args:
        location: A ladybug Location object to dictate the solar positions used
            in the calculation.
        longwave_data: An array of data collections for each point within a thermal
            map. All collections must be aligned with one another. The analysis
            period on the collections does not have to be annual.
        sun_up_hours: File path to a sun-up-hours.txt file output by Radiance.
        total_ill: Path to an .ill file output by Radiance containing total
            irradiance for each longwave_data collection.
        direct_ill: Path to an .ill file output by Radiance containing direct
            irradiance for each longwave_data collection.
        ref_ill: Path to an .ill file output by Radiance containing total ground-
            reflected irradiance for each longwave_data collection. If None, a
            default ground reflectance of 0.25 will be assumed.
        solarcal_par: Optional SolarCalParameter object to account for
            properties of the human geometry.
    """
    # determine the analysis period and open the sun_up_hours file
    a_per = longwave_data[0].header.analysis_period
    is_annual, t_step, lp_yr = a_per.is_annual, a_per.timestep, a_per.is_leap_year
    with open(sun_up_hours) as soh_f:
        sun_indices = [int(float(h) * t_step) for h in soh_f]

    # parse each of the .ill files into annual irradiance data collections
    total = _ill_file_to_data(total_ill, sun_indices, t_step, lp_yr)
    direct = _ill_file_to_data(direct_ill, sun_indices, t_step, lp_yr)
    ref = _ill_file_to_data(ref_ill, sun_indices, t_step, lp_yr) \
        if ref_ill is not None else None

    # if the analysis is not annual, apply analysis periods
    if not is_annual:
        total = [data.filter_by_analysis_period(a_per) for data in total]
        direct = [data.filter_by_analysis_period(a_per) for data in direct]
        if ref is not None:
            ref = [data.filter_by_analysis_period(a_per) for data in ref]

    # convert total irradiance into indirect irradiance
    indirect = [t_rad - d_rad for t_rad, d_rad in zip(total, direct)]

    # compute solar altitudes and sharps
    body_par = SolarCalParameter() if solarcal_par is None else solarcal_par
    sp = Sunpath.from_location(location)
    _altitudes = []
    if body_par.body_azimuth is None:
        _sharps = [body_par.sharp] * len(a_per)
        for t_date in a_per.datetimes:
            sun = sp.calculate_sun_from_date_time(t_date)
            _altitudes.append(sun.altitude)
    else:
        _sharps = []
        for t_date in a_per.datetimes:
            sun = sp.calculate_sun_from_date_time(t_date)
            sharp = sharp_from_solar_and_body_azimuth(sun.azimuth,
                                                      body_par.body_azimuth)
            _sharps.append(sharp)
            _altitudes.append(sun.altitude)

    # pass all data through the solarcal collections and return MRT data collections
    mrt_data = []
    if ref is not None:  # fully-detailed SolarCal with ground reflectance
        for l_mrt, d_rad, i_rad, r_rad in zip(longwave_data, direct, indirect,
                                              ref):
            scl_obj = _HorizontalRefSolarCalMap(_altitudes, _sharps, d_rad,
                                                i_rad, r_rad, l_mrt, None,
                                                body_par)
            mrt_data.append(scl_obj.mean_radiant_temperature)
    else:  # simpler SolarCal assuming default ground reflectance
        for l_mrt, d_rad, i_rad in zip(longwave_data, direct, indirect):
            scl_obj = _HorizontalSolarCalMap(_altitudes, _sharps, d_rad, i_rad,
                                             l_mrt, None, None, body_par)
            mrt_data.append(scl_obj.mean_radiant_temperature)
    return mrt_data