def from_lat_long(cls, latitude, longitude, time_zone, month, day, hour, direct_normal_irradiance, diffuse_horizontal_irradiance, north_angle=0, ground_reflectance=0.2): """Create sky with certain illuminance. Args: latitude: Location latitude between -90 and 90. longitude: Location longitude between -180 (west) and 180 (east). time_zone: Time zone between -12 hours (west) and +14 hours (east). If None, the time will be interpreted as solar time at the given longitude. month: An intger between 1-12 for month. day: An intger between 1 to 28-31 depending on the input month. hour: A float number larger or equal to 0 and smaller than 24. direct_normal_irradiance: Direct normal irradiance (W/m2). diffuse_horizontal_irradiance: Diffuse horizontal irradiance (W/m2). north_angle: North angle in degrees. A number between -360 and 360 for the counterclockwise difference between the North and the positive Y-axis in degrees. 90 is West and 270 is East (Default: 0). ground_reflectance: Average ground reflectance (Default: 0.2). """ # calculate altitude and azimuth using ladybug's sunpath sp = Sunpath(latitude, longitude, time_zone, north_angle) sun = sp.calculate_sun(month, day, hour) return cls(sun.altitude, sun.azimuth_from_y_axis, direct_normal_irradiance, diffuse_horizontal_irradiance, ground_reflectance)
def from_lat_long( cls, latitude, longitude, time_zone, month, day, hour, sky_type=0, north_angle=0, ground_reflectance=0.2): """Create sky with certain illuminance. Args: latitude: Location latitude between -90 and 90. longitude:Location longitude between -180 (west) and 180 (east). timezone: Time zone between -12 hours (west) and +14 hours (east). month: An intger between 1-12 for month. day: An intger between 1 to 28-31 depending on the input month. hour: A float number larger or equal to 0 and smaller than 24. sky_type: An integer between 0..5 to indicate CIE Sky Type. * 0 = Sunny with sun. Sunny sky with sun. In addition to the sky distribution function, a source description of the sun is generated. * 1 = Sunny without sun. Sunny sky without sun. The sky distribution will correspond to a standard CIE clear day. * 2 = Intermediate with sun. In addition to the sky distribution, a (somewhat subdued) sun is generated. * 3 = Intermediate without sun. The sky will correspond to a standard CIE intermediate day. * 4 = Cloudy sky. The sky distribution will correspond to a standard CIE overcast day. * 5 = Uniform cloudy sky. The sky distribution will be completely uniform. north_angle: North angle in degrees. A number between -360 and 360 for the counterclockwise difference between the North and the positive Y-axis in degrees. 90 is West and 270 is East (Default: 0). ground_reflectance: Average ground reflectance (Default: 0.2). """ # calculate altitude and azimuth using ladybug's sunpath sp = Sunpath(latitude, longitude, time_zone, north_angle) sun = sp.calculate_sun(month, day, hour) return cls(sun.altitude, sun.azimuth_from_y_axis, sky_type, ground_reflectance)
def test_north_south_pole(): """Test to be sure we don't get a math domain error at the poles.""" loc = Location("Santa's House", None, 'North Pole', 90, 0, 0, 0) sp = Sunpath.from_location(loc) suns = sp.hourly_analemma_suns() assert len(suns) == 24 loc = Location("Santa's Other House", None, 'South Pole', -90, 0, 0, 0) sp = Sunpath.from_location(loc) suns = sp.hourly_analemma_suns() assert len(suns) == 24
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)
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
def from_location(cls, location, hoys=None, north=0, is_leap_year=False): """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). is_leap_year: A boolean to indicate if hours are for a leap year (default: False). """ sun_vectors = [] sun_up_hours = [] hoys = hoys or range(8760) north = north or 0 sp = Sunpath.from_location(location, north) sp.is_leap_year = is_leap_year 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)
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 } """ raise NotImplementedError() 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)
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
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
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
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)
def test_write_to_fie(): sp = Sunpath(location) lb_sp = LBSunpath.from_location(location) folder = './tests/assets/temp' filename = 'sunpath_annual' sp.to_file(folder, filename) sp_file = os.path.join(folder, '%s.rad' % filename) sp_mod_file = os.path.join(folder, '%s.mod' % filename) assert os.path.isfile(sp_file) assert os.path.isfile(sp_mod_file) with open(sp_mod_file) as inf: for count, _ in enumerate(inf): pass lb_tot = [ i for i in range(8760) if lb_sp.calculate_sun_from_hoy(i).is_during_day ] assert count == len(lb_tot) - 1 # number of suns - 1 with open(sp_file) as inf: for count, _ in enumerate(inf): pass assert count == len(lb_tot) - 1 # number of suns - 1 # check line info with open(sp_file) as inf: data = inf.readline().split() assert data[6] == data[6] == data[6] == '1000000.0' assert data[-1] == '0.533' assert float(data[-2]) < 0 # z vector is looking down
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
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)
def test_from_location(): """Test the initialization of Sunpath from a Location.""" 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
def test_vs_noaa_new_york(): """Test to be sure that the sun positions align with the NOAA formula.""" 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
def getSunVector(input_address, input_month, input_day, input_hour): geolocator = Nominatim(user_agent="UrbanInsight") location = geolocator.geocode(input_address) tf = TimezoneFinder() utc = pytz.utc def offset(target): today = datetime.now() tz_target = timezone( tf.certain_timezone_at(lat=target['lat'], lng=target['lng'])) # ATTENTION: tz_target could be None! handle error case today_target = tz_target.localize( datetime(2016, input_month, input_day)) today_utc = utc.localize(datetime(2016, input_month, input_day)) return (today_utc - today_target).total_seconds() / 60 # Create location. You can also extract location data from an epw file. lati = location.latitude long = location.longitude timez = dict({'lat': lati, 'lng': long}) tz = (offset(timez) / 60) # print(tz) city = Location('City', 'Country', latitude=lati, longitude=long, time_zone=tz) # Initiate sunpath sp = Sunpath.from_location(city) sun = sp.calculate_sun(month=input_month, day=input_day, hour=input_hour) # print('altitude: {}, azimuth: {}'.format(sun.altitude, sun.azimuth)) _year_ = 2016 _minute_ = 0 mydate = DateTime(input_month, input_day, input_hour) altitude = sun.altitude_in_radians azimuth = sun.azimuth_in_radians is_solar_time = "false" is_daylight_saving = "false" north_angle = 0 sn = Sun(DateTime, altitude, azimuth, is_solar_time, is_daylight_saving, north_angle, data=None) # print(sun.sun_vector) vector = str(sun.sun_vector) return vector
def test_from_location(self): sydney = Location('Sydney', 'AUS', latitude=-33.87, longitude=151.22, time_zone=10) sunpath = Sunpath.from_location(sydney) self.assertEqual(sunpath.latitude, -33.87) self.assertEqual(sunpath.longitude, 151.22) self.assertEqual(sunpath.time_zone, 10)
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
def test_init_sunpath(): """Test the initialization of Sunpath and basic properties.""" sunpath = Sunpath(latitude=40.72, longitude=-74.02) str(sunpath) # test the string representation assert sunpath.latitude == 40.72 assert sunpath.longitude == -74.02 assert sunpath.time_zone == approx(-4.9346, rel=1e-3) assert sunpath.north_angle == 0 assert sunpath.daylight_saving_period is None
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
def test_exact_solar_noon(): """Test to be sure we don't get a math domain error at solar noon.""" loc = Location('SHANGHAI', None, 'HONGQIAO', 31.17, 121.43, 8.0, 7.00) sp = Sunpath.from_location(loc) suns = [] for i in range(1, 13): sun = sp.calculate_sun(i, 21, 12, True) assert sun.azimuth == approx(180, rel=1e-2) suns.append(sun.sun_vector) assert len(suns) == 12
def test_solar_time(): """Test to be sure that solar time is being computed correctly.""" loc = Location('SHANGHAI', None, 'HONGQIAO', 31.17, 121.43, 8.0, 7.00) sp = Sunpath.from_location(loc) sun = sp.calculate_sun(3, 21, 12, True) assert sun.azimuth == approx(180, rel=1e-2) sun = sp.calculate_sun(3, 21, 6, True) assert sun.azimuth == approx(90, rel=1e-2) sun = sp.calculate_sun(3, 21, 18, True) assert sun.azimuth == approx(270, rel=1e-2)
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_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
def test_leap_year(): """Test the use of the sunpath with leap years.""" nyc = Location('New_York', country='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
def fromLocationAndHoys(cls, location, hoys, pointGroups, vectorGroups=[], timestep=1, hbObjects=None, subFolder='sunlighthour'): """Create sunlighthours recipe from Location and hours of year.""" sp = Sunpath.fromLocation(location) suns = (sp.calculateSunFromHOY(HOY) for HOY in hoys) sunVectors = tuple(s.sunVector for s in suns if s.isDuringDay) analysisGrids = cls.analysisGridsFromPointsAndVectors(pointGroups, vectorGroups) return cls(sunVectors, hoys, analysisGrids, timestep, hbObjects, subFolder)
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
def test_init_solar_envelope(): """Test the initialization of Sunpath and basic properties.""" # get sun positions sunpath = Sunpath(latitude=40.72, longitude=-74.02) sun_vecs = [] for hour in range(8, 16): sun = sunpath.calculate_sun(12, 21, hour) sun_vecs.append(sun.sun_vector) # load the site and the context site_mesh_file = './tests/assets/geo/mesh.json' with open(site_mesh_file) as json_file: site_mesh_data = json.load(json_file) site_mesh = Mesh3D.from_dict(site_mesh_data) context_file = './tests/assets/geo/faces.json' with open(context_file) as json_file: context_data = json.load(json_file) context_faces = [Face3D.from_dict(con) for con in context_data] # initialize solar envelope envelope = SolarEnvelope(site_mesh, context_faces, sun_vecs, solar_rights=True) str(envelope) # test the string representation envelope_mesh = envelope.envelope_mesh() assert isinstance(envelope_mesh, Mesh3D)
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)
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
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)
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)