def get_sun_position(ref_point, tim): """Get sun position for reference point and time at 10km distance reprojected on l72 ref_point -- a 3d vector in Lambert72 tim -- a datetime returns a records.SunPosition """ utc_time = tim.astimezone(utc) px, py, pz = ref_point lon, lat, z = transform(l72, wgs, px, py, pz) azimut = solar.get_azimuth(lat, lon, utc_time, z) altitude = solar.get_altitude(lat, lon, utc_time, z) saa = azimut - 180 # solar azimuth angle (degrees between -180 to +180, 0 at South) sza = 90 - altitude # solar zenit angle (0 = zenit, 90 = horizon) if altitude < 1: return SunPosition([0, 0, 0], 0, 0, False, tim, 0, 0) coords = _get_coords_from_angles(ref_point, np.deg2rad(altitude), np.deg2rad(azimut)) return SunPosition(coords, azimut, altitude, True, tim, sza, saa)
def get_flux_surface( coords, date, sigma, phi_C ): """ coords: gps deg ( ) date: datetime object Surface orientation : sigma : deg, vertical angle of the surface, ref. to the horizontal phi_C : deg, azimuth, relative to south, with positive values in the southeast direction and negative values in the southwest return: flux solaire (W/m2) """ # Sun position phi_S_deg = solar.get_azimuth( *coords, date ) # deg, azimuth of the sun,relative to south beta_deg = solar.get_altitude( *coords, date ) # deg, altitude angle of the sun I0 = radiation.get_radiation_direct( date, beta_deg ) # W/m2 I0 = I0* isUpperHorizon( phi_S_deg, beta_deg ) # Projection: beta = beta_deg*math.pi/180 # rad phi_S = phi_S_deg*math.pi/180 #rad sigma = sigma*math.pi/180 phi_C = phi_C*math.pi/180 cosTheta = math.cos(beta)*math.cos( phi_S - phi_C )*math.sin( sigma ) + math.cos( sigma )*math.sin( beta ) if cosTheta >0 : Isurf = I0*cosTheta # flux projeté, W/m2 else: Isurf = 0 # mais diffuse... ? return Isurf
def find_solar_angles(parameters, year=2017, localzone='US/Eastern'): hour = int(parameters['timeUTC']) #Computes the hour from the given time minute = int( (parameters['timeUTC'] - hour) * 60) #Converts decimal min to minute #Instanciates the date based on the given time and daynumber given in UTC date = datetime.datetime(year, 1, 1, hour, minute, 0, tzinfo=pytz.utc) + \ datetime.timedelta(parameters['dayNumber'] - 1) #Converts the UTC date to the local Timezone and takes care of daylight savings timestampEST = date.astimezone(pytz.timezone(localzone)) latitude = parameters['latitude'] #Pulls the latitude from the parameters longitude = parameters[ 'longitude'] #Pulls the longitude from the parameters #Computes the solar altitude above the horizon altitude = ps.get_altitude(latitude, -1 * longitude, timestampEST) zenith = 90 - altitude #Converts the solar altitude to zenith angle #Computes the azimuth angle from the south azimuth = ps.get_azimuth(latitude, -1 * longitude, timestampEST) azimuth = (180 - azimuth) % 360 #Converts azimuth to be measured from the north solarAngles = {"solarZenith": zenith, "solarAzimuth": azimuth} return solarAngles
def compute_sun_angle( position, pose, utc_datetime, sensor_orientation, ): """ compute the sun angle using pysolar functions""" altitude = 0 azimuth = 0 import warnings with warnings.catch_warnings( ): # Ignore pysolar leap seconds offset warning warnings.simplefilter("ignore") try: altitude = pysolar.get_altitude(position[0], position[1], utc_datetime) azimuth = pysolar.get_azimuth(position[0], position[1], utc_datetime) except AttributeError: # catch 0.6 version of pysolar required for python 2.7 support altitude = pysolar.GetAltitude(position[0], position[1], utc_datetime) azimuth = 180 - pysolar.GetAzimuth(position[0], position[1], utc_datetime) sunAltitude = np.radians(np.array(altitude)) sunAzimuth = np.radians(np.array(azimuth)) sunAzimuth = sunAzimuth % (2 * np.pi) # wrap range 0 to 2*pi nSun = ned_from_pysolar(sunAzimuth, sunAltitude) nSensor = np.array(get_orientation(pose, sensor_orientation)) angle = np.arccos(np.dot(nSun, nSensor)) return nSun, nSensor, angle, sunAltitude, sunAzimuth
def compute_radiation_at_45_deg_angle(timestamp, total_radiation, diffuse_radiation): direct_radiation = total_radiation - diffuse_radiation # Pysolar: south is zero degree, clockwise negative, e.g. south east = - 315 degree, south west = -45 degree azimuth = get_azimuth(when=datetime.datetime.fromtimestamp(timestamp), latitude_deg=LATITUDE_DEG, longitude_deg=LONGITUDE_DEG, elevation=EVALUATION) # In the calculation north is defined as zero degree, clockwise positive, the following conversion is required if azimuth < -180: azimuth = abs(azimuth) - 180 else: azimuth = abs(azimuth) + 180 altitude = get_altitude(when=datetime.datetime.fromtimestamp(timestamp), latitude_deg=LATITUDE_DEG, longitude_deg=LONGITUDE_DEG, elevation=EVALUATION) # Formula from "Lehrbuch der Bauphysik, Fischer, 2008, Page 651" radiation_at_45_deg_angle = diffuse_radiation + direct_radiation * ( cos(radians(ALPHA)) + sin(radians(ALPHA)) * (cos(radians(azimuth - BETA)) / tan(radians(altitude)))) if radiation_at_45_deg_angle < 0.0: radiation_at_45_deg_angle = 0.0 return radiation_at_45_deg_angle
def payload(self, time): ts = time lat = self.config.latitude lng = self.config.longitude paz = self.config.panel_azimuth palt = self.config.panel_altitude effective_area = self.config.system_efficiency * self.config.panel_count * self.config.panel_area fields = dict(self.default_fields) fields['altitude'] = solar.get_altitude(lat, lng, ts) fields['azimuth'] = solar.get_azimuth(lat, lng, ts) % 360 az_diff = paz - fields['azimuth'] az_projection = max(0, math.cos(math.pi * az_diff / 180.0)) alt_diff = (90 - palt) - fields['altitude'] alt_projection = max(0, math.cos(math.pi * alt_diff / 180.0)) fields['alt_projection'] = float(alt_projection) fields['az_projection'] = float(az_projection) fields['total_projection'] = float(az_projection * alt_projection) if fields['altitude'] > 0: fields['direct_flux'] = solar.radiation.get_radiation_direct( ts, fields['altitude']) fields['projected_flux'] = fields['direct_flux'] * fields[ 'total_projection'] fields['max_direct_power'] = effective_area * fields['direct_flux'] fields['projected_direct_power'] = effective_area * fields[ 'projected_flux'] tags = { 'location': self.config.location_tag, } return PySolarPayload(tags, fields, time)
def process_solar_lines(): PATH = "/Users/matt/Downloads/solar-generation-and-demand-italy-20152016/TimeSeries_TotalSolarGen_and_Load_IT_2016.csv" LAT = 42.6711769 LONG = 12.4625580 result = [[]] with open(PATH) as f: first_line = True spot = -1 for line in csv.reader(f): if not first_line: t = datetime.datetime.strptime(line[0], '%Y-%m-%dT%H:%M:%SZ') args = [LAT, LONG, pytz.UTC.localize(t)] alt, az = solar.get_altitude_fast(*args), solar.get_azimuth(*args) if az < spot: result.append([]) result[-1].append({'altitude': alt, 'azimuth': az, 'power': line[2]}) spot = az else: first_line = False json.dump(result, open('solar.json', 'w+'))
def calculateMaxSunLight(self): # Calculates the max sun radiation at given positions and dates (and returns zero for night time) # # The method is using the third party library PySolar : https://pysolar.readthedocs.io/en/latest/# # # # some other available options: # https://pypi.org/project/solarpy/ # https://github.com/trondkr/pyibm/blob/master/light.py # use calclight from Kino Module here : https://github.com/trondkr/KINO-ROMS/tree/master/Romagnoni-2019-OpenDrift/kino # ERcore : dawn and sunset times : https://github.com/metocean/ercore/blob/ercore_opensrc/ercore/lib/suncalc.py # https://nasa-develop.github.io/dnppy/modules/solar.html#examples # from pysolar import solar date = self.time date = date.replace( tzinfo=timezone.utc ) # make the datetime object aware of timezone, set to UTC logger.debug('Assuming UTC time for solar calculations') # longitude convention in pysolar, consistent with Opendrift : negative reckoning west from prime meridian in Greenwich, England # the particle longitude should be converted to the convention [-180,180] if that is not the case sun_altitude = solar.get_altitude(self.elements.lat, self.elements.lon, date) # get sun altitude in degrees sun_azimut = solar.get_azimuth(self.elements.lat, self.elements.lon, date) # get sun azimuth in degrees sun_radiation = np.zeros(len(sun_azimut)) # not ideal get_radiation_direct doesnt accept arrays... for elem_i, alt in enumerate(sun_altitude): sun_radiation[elem_i] = solar.radiation.get_radiation_direct( date, alt) # watts per square meter [W/m2] for that time of day # save compute light for each particle self.elements.light = sun_radiation * 4.6 #Converted from W/m2 to umol/m2/s-1"" - 1 W/m2 ≈ 4.6 μmole.m2/s logger.debug('Solar radiation from %s to %s [W/m2]' % (sun_radiation.min(), sun_radiation.max()))
def sunposition(request, year, month, day, hour, minute, lat, long, elevation): # do some sanity checks # TODO: ... # perform the calculation via pysolar # FIXME: what to do with the timezone? (make it configurable in the settings or selectable in the client?) date = datetime.datetime(int(year), int(month), int(day), int(hour), int(minute), 0, 0, tzinfo=datetime.timezone.utc) azimuth = solar.get_azimuth(float(lat), float(long), date, float(elevation)) altitude = solar.get_altitude(float(lat), float(long), date, float(elevation)) # construct the answer result = { 'azimuth': azimuth, 'altitude': altitude, } return JsonResponse(result)
def solar_position(date_time, lattitude, longitude): """Returns solar position.""" return ( get_altitude(lattitude, longitude, date_time.datetime), get_azimuth(lattitude, longitude, date_time.datetime), )
def shade_factor(lat_deg, lon_deg, dx, dy, t): altitude = np.pi * solar.get_altitude(lat_deg, lon_deg, t) / 180. azimuth = np.pi * solar.get_azimuth(lat_deg, lon_deg, t) / 180. theta_a = np.zeros(dx.shape) theta_a[dx >= 0] = np.arctan2(dy[dx >= 0], dx[dx >= 0]) theta_a[dx < 0] = np.pi - np.arctan2(dy[dx < 0], np.abs(dx[dx < 0])) return 0.5 * (1 - np.sin(theta_a + azimuth)) * np.cos(altitude)
def get_data(lat, lon, date_): data = { 'altitude': sol.get_altitude(lat, lon, date_), 'azimuth': sol.get_azimuth(lat, lon, date_), 'timestamp': date_.timestamp() } return data
def calc_yaw_from_ellipse(imagePath, date, lon, lat, threshold=0.5, makePlots=True): #Read image and convert to grayscale image = cv2.imread(imagePath) image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if makePlots: plt.figure() plt.imshow(image) plt.pause(1) #Very dark images probably don't have any glitter... if np.max(image) < 100: #intensity: 100 out of 255 return None #Calculate scaledThreshold (relative to max image brightness, so compensates to some extent for different exposure or brightness) scaledThreshold = threshold * np.max(image) #Blur image and apply threshold image = cv2.GaussianBlur(image, (201, 201), 0) #plt.figure(); plt.imshow(image); plt.pause(1); imageMask = np.zeros(image.shape, dtype=np.uint8) imageMask[image > scaledThreshold] = 200 #plt.figure(); plt.imshow(imageMask); plt.pause(1); edges = cv2.Canny(imageMask, 1.0, scaledThreshold * 2) #plt.figure(); plt.imshow(edges); #Extract contour from mask and fit ellipse img, contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) if len(contours) == 0: #Some images may not be above glitter. return None contourLengths = np.array([len(contours[i]) for i in range(len(contours))]) contourIndex = contourLengths.argmax() points = contours[contourIndex] ellipse = cv2.fitEllipse(points) cv2.ellipse(imageMask, ellipse, 240, 2) if makePlots: plt.figure() plt.imshow(imageMask) plt.pause(1) #Extract the long axis angle. ellipseAngle = ellipse[2] #Clockwise from North. This is the angle of the long axis #Calculate azimuth of the sun. #date = datetime.datetime(2007, 2, 18, 15, 13, 1, 130320, tzinfo=datetime.timezone.utc); azimuth = pysol.get_azimuth(lat, lon, date) #Azimuth should match the major axis angle of the ellipse #Calculate yaw from ellipse and return it. yaw = azimuth - ellipseAngle #Yaw is difference from what azimuth should be and what it is in the photo. return yaw
def check_next_sunrise(self): """Check azimuth of next sunrise""" new_date = self.date while(solar.get_altitude(self.latitude, self.longitude, new_date) < 15.0): print(new_date) new_date += datetime.timedelta(minutes=10) return self.offset(solar.get_azimuth(self.latitude, self.longitude, new_date))
def azimuth(self): """ Get the azimuth of the sun position based on the latitude, longitude and date""" if self.manual: return self._azimuth if self.simulation: self.add_time() return get_azimuth(self.latitude_deg, self.longitude_deg, self.date)
def test_scalar_with_numpy(): pysolar.use_numpy() lat = 50.63 lon = 3.05 time = datetime(2018, 5, 8, 12, 0, 0, tzinfo=pytz.UTC) print(solar.get_altitude(lat, lon, time)) print(solar.get_azimuth(lat, lon, time))
def testGetAzimuthFast(self): day = datetime.datetime( 2016, 12, 19, 0, 0, tzinfo=datetime.timezone(datetime.timedelta(hours=12))) for hour in range(7, 19): when = day + datetime.timedelta(hours=hour) az = solar.get_azimuth_fast(-43, 172, when) az_expected = solar.get_azimuth(-43, 172, when) self.assertAlmostEqual(az, az_expected, delta=1.5)
def test_scalar_with_math(): pysolar.use_math() lat = 45. lon = 3. time = datetime(2018, 5, 8, 12, 0, 0, tzinfo=pytz.UTC) print(solar.get_altitude(lat, lon, time)) print(solar.get_azimuth(lat, lon, time))
def getpos(lat, lon, date, elevation=0): date = _pd.to_datetime(date) alt = _np.deg2rad( _solar.get_altitude(lat, lon, date, elevation=elevation)) azi = _np.deg2rad( _np.mod( abs(_solar.get_azimuth(lat, lon, date, elevation=elevation)) - 180, 360)) airmass = 1 / _np.sin(alt) return alt, azi, airmass
def undistort(self, rgb=True, day_only=True): """ Undistort the raw image, set rgb, red, rbr, cos_g Input: rgb and day_only flags Output: rgb, red, rbr, cos_g will be specified. """ #####get the image acquisition time, this need to be adjusted whenever the naming convention changes t_cur=datetime.strptime(self.fn[-18:-4],'%Y%m%d%H%M%S'); t_std = t_cur-timedelta(hours=5) #####adjust UTC time into local standard time sz = 90-ps.get_altitude(self.cam.lat,self.cam.lon,t_std); sz*=deg2rad; self.sz = sz if day_only and sz>85*deg2rad: return saz = 360-ps.get_azimuth(self.cam.lat,self.cam.lon,t_std); saz=(saz%360)*deg2rad; self.saz = saz try: im0=plt.imread(self.fn); except: print('Cannot read file:', self.fn) return None im0=im0[self.cam.roi] im0[~self.cam.valid0,:]=0 cos_sz=np.cos(sz) cos_g=cos_sz*np.cos(self.cam.theta0)+np.sin(sz)*np.sin(self.cam.theta0)*np.cos(self.cam.phi0-saz); red0=im0[:,:,0].astype(np.float32); red0[red0<=0]=np.nan rbr0=(red0-im0[:,:,2])/(im0[:,:,2]+red0) if np.nanmean(red0[(cos_g>0.995) & (red0>=1)])>230: mk=cos_g>0.98 red0[mk]=np.nan rbr0[mk]=np.nan rbr=st.fast_bin_average2(rbr0,self.cam.weights); rbr=st.fill_by_mean2(rbr,7, mask=(np.isnan(rbr)) & self.cam.valid) self.rbr=rbr red0-=st.rolling_mean2(red0,300,ignore=np.nan) red=st.fast_bin_average2(red0,self.cam.weights); red=st.fill_by_mean2(red,7, mask=(np.isnan(red)) & self.cam.valid) red[red>50]=50; red[red<-50]=-50 red=(red+51)*2.5+0.5; self.red=red.astype(np.uint8) if rgb: im=np.zeros((self.cam.ny,self.cam.nx,3),dtype=im0.dtype) for i in range(3): im[:,:,i]=st.fast_bin_average2(im0[:,:,i],self.cam.weights); im[:,:,i]=st.fill_by_mean2(im[:,:,i],7, ignore=0, mask=(im[:,:,i]==0) & (self.cam.valid)) # im[:,:,i]=st.fill_by_mean2(im[:,:,i],7, ignore=0, mask=np.isnan(red)) im[red<=0]=0 self.rgb=im
def test_with_fixed_time(): """ get_altitude and get_azimuth, with scalar date """ pysolar.use_numpy() lat = np.array([45., 40.]) lon = np.array([3., 4.]) time = datetime(2018, 5, 8, 12, 0, 0, tzinfo=pytz.UTC) print(solar.get_altitude(lat, lon, time)) print(solar.get_azimuth(lat, lon, time)) print(solar.get_altitude_fast(lat, lon, time)) print(solar.get_azimuth_fast(lat, lon, time))
def get_solarposition(arg_time, arg_lat, arg_long): return_data = {} arg_date = arg_time.astimezone(pytz.timezone('US/Pacific')) zenith = (90 - solar.get_altitude(arg_lat, arg_long, arg_date)) azimuth = solar.get_azimuth(arg_lat, arg_long, arg_date) return_data['zenith'] = zenith return_data['azimuth'] = azimuth return return_data
def trackSolar(self): logger = SysLog.getLogger() self.__stop_increment_angle = False # print("This is self.__current_angle", self.__current_angle) while True: # logger.debugs("SolarThread") if self.get_stop_thread(): # logger.debugs("THREAD STOPPED") self.set_stop_thread(False) self.set_thread(None) break current_azimuth = get_azimuth( self.__latitude, self.__longitude, SolarThread.get_time()) #gps_lat, gps_lng, current_time, 0) # print("current azimuth", current_azimuth) new_angle = current_azimuth - self.AZIMUTH_TO_SOLAR_OFFSET # change back to 180!!!! if self.__track_angle_east < new_angle < self.__track_angle_west: #when we would start moving the panel self.__reset_called = False # reset...reset for next day self.__max_angle_check = False # print("This is new angle: ", new_angle) # print("This is current angle: ", self.__current_angle) difference = new_angle - self.__current_angle # print("This is difference: ", difference) if difference >= self.__increment_angle: # print("Larger than") self.increment_panel_angle(difference, self.__turn_on_west_relay) elif difference < (-1 * self.__increment_angle): # print("Smaller than") self.increment_panel_angle(difference, self.__turn_on_east_relay) time.sleep(self.__sleep) elif current_azimuth > self.__azimuth_angle_stop and current_azimuth < self.__azimuth_angle_stop + 100 and not self.__max_angle_check: #make sure panel is all the way west # print("notreset") difference = self.__track_angle_west - self.__current_angle + Constants.ST_DEGREE_BUFFER self.increment_panel_angle(difference, self.__turn_on_west_relay) self.__max_angle_check = True elif ( current_azimuth < self.__azimuth_angle_start or current_azimuth > self.__azimuth_angle_stop + 100 ) and not self.__reset_called: #make sure panel is all the way east # print("reset 0") difference = self.__track_angle_east - self.__current_angle - Constants.ST_DEGREE_BUFFER self.increment_panel_angle(difference, self.__turn_on_east_relay) self.__reset_called = True else: #where checks have already been done time.sleep(self.__sleep)
def _add_sunposition_to_df(self, df): ''' ''' dts = pd.to_datetime( df['utc_timestamps'], infer_datetime_format=True, ) df['altitude'] = [ 90 - solar.get_altitude(self.lat, self.lon, utc_dt) for utc_dt in dts ] df['azimuth'] = [ solar.get_azimuth(self.lat, self.lon, utc_dt) for utc_dt in dts ] return df
def process_messing(): PATH = "/Users/matt/Downloads/solar-generation-and-demand-italy-20152016/TimeSeries_TotalSolarGen_and_Load_IT_2016.csv" LAT = 42.6711769 LONG = 12.4625580 with open(PATH) as f, open('alt_az_pwr.csv','w+') as o: o.write('altitude,azimuth,power\n') first_line = True for line in csv.reader(f): if not first_line: t = datetime.datetime.strptime(line[0], '%Y-%m-%dT%H:%M:%SZ') args = [LAT, LONG, pytz.UTC.localize(t)] o.write('{},{},{}\n'.format(solar.get_altitude_fast(*args), solar.get_azimuth(*args), line[2])) else: first_line = False
def cost_sun_match(params,dx0,dy0,nx0,ny0): cost=0; rotation = params dx0=int(dx0); dy0=int(dy0); nr0=(nx0+ny0)/4.0 ##### radius of the valid image #####compute the zenith and azimuth angles for each pixel x0,y0=np.meshgrid(np.arange(nx0),np.arange(ny0)) r0=np.sqrt((x0-nx0/2)**2+(y0-ny0/2)**2); # theta=np.pi/2*(r0/nr0); theta=2*np.arcsin(r0/(np.sqrt(2)*nr0)) phi=rotation+np.arctan2(1-x0/nr0,y0/nr0-1) ####phi (i.e., azimuth) is reckoned with -pi corresponding to north, increasing clockwise, NOTE: pysolar use sub-standard definition phi=phi%(2*np.pi) theta_filter = theta>max_theta; theta[theta_filter]=np.nan; # for f in sorted(glob.glob(inpath+'HD*2018010317*jpg')): # for f in sorted(glob.glob(inpath+'HD1*201802141908*jpg')): # for f in sorted(glob.glob(inpath+camera+'*20180214185005*jpg')): for f in sorted(glob.glob(inpath+camera+'*20180219173840*jpg')): ####get the image acquisition time, this need to be adjusted whenever the naming convention changes t_cur=datetime.strptime(f[-18:-4],'%Y%m%d%H%M%S'); t_std = t_cur-timedelta(hours=5) #####adjust UTC time into daylight saving time or standard time #####solar zenith and azimuth angles. NOTE: the azimuth from pysolar is #####reckoned with 0 corresponding to south, increasing counterclockwise sz, saz = 90-ps.get_altitude(lat,lon,t_std), ps.get_azimuth(lat,lon,t_std) sz*=deg2rad; saz=(saz%360)*deg2rad; im0=plt.imread(f).astype(np.float32); ####get the spatial pattern of sky radiance from an empirical sky radiance model cos_g=np.cos(sz)*np.cos(theta)+np.sin(sz)*np.sin(theta)*np.cos(phi-saz); gamma = np.arccos(cos_g); denom=(0.91+10*np.exp(-3*sz)+0.45*np.cos(sz)**2)*(1-np.exp(-0.32)) rad = (0.91+10*np.exp(-3*gamma)+0.45*cos_g**2)*(1-np.exp(-0.32/np.cos(theta)))/denom ######read the image to array im0=st.shift_2d(im0,-dx0,-dy0); im0=im0[:ny0,:nx0]; ####cut the appropriate subset of the original image im0[theta_filter,:]=np.nan # #####sun glare removal glare = rad>(np.nanmean(rad)+np.nanstd(rad)*2.5); # im0[glare,:]=np.nan; # plt.figure(); plt.imshow(im0[:,:,0]) cost += np.nanmean(im0[glare,0]) print(dx0,dy0,rotation/deg2rad,cost) return -cost
def angles_by_lnglat_date(lnglat: list, date: list): moments = [ datetime.datetime(*date, i, tzinfo=datetime.timezone.utc) for i in range(24) ] angles = list() for mom in moments: altitude = solar.get_altitude(lnglat[1], lnglat[0], mom) if altitude > 0: azimuth = solar.get_azimuth(lnglat[1], lnglat[0], mom) angle = [altitude, azimuth] angles.append(angle) return angles
def test_solar(self): latitude_deg = 42.364908 longitude_deg = -71.112828 d = datetime.datetime.utcnow() thirty_minutes = datetime.timedelta(hours=0.5) for i in range(48): timestamp = d.ctime() altitude_deg = solar.get_altitude(latitude_deg, longitude_deg, d) azimuth_deg = solar.get_azimuth(latitude_deg, longitude_deg, d) power = radiation.get_radiation_direct(d, altitude_deg) if altitude_deg > 0: # TODO: save results as a fixture and apply assertion # print(timestamp, "UTC", altitude_deg, azimuth_deg, power) pass d = d + thirty_minutes
def sun_positionAndFlux( coords, date ): """ Obtient la position et le flux solaire pour une date particulière coords: tuple gps date: datetime object return: ( flux solaire (W/m2), sunAzimuth, sunAltitude ) """ # Sun position phi_S_deg = solar.get_azimuth( *coords, date ) # deg, azimuth of the sun,relative to south beta_deg = solar.get_altitude( *coords, date ) # deg, altitude angle of the sun if isUpperHorizon( phi_S_deg, beta_deg ): I0 = radiation.get_radiation_direct( date, beta_deg ) # W/m2 else: I0 = 0 return (I0, phi_S_deg, beta_deg)
def getRadiation(day_sample, interval): secs = interval * 60 * sample_interval_minutes day = day_sample * sample_interval_days dt = start_date + d.timedelta(day, secs) alt = get_altitude(lat, lon, dt) azi = get_azimuth(lat, lon, dt) if (alt < 0): direct_radiation = 0 else: direct_radiation = get_radiation_direct(dt, alt) # get_azimuth returns bearing with respect to north, positive clockwise. Rotate so x is west, y is south azi_rad = math.radians(270 - azi) alt_rad = math.radians(alt) sun_vec = np.array( (math.cos(alt_rad) * math.cos(azi_rad), math.cos(alt_rad) * math.sin(azi_rad), math.sin(alt_rad))) rad = [max(0, sun_vec @ v * direct_radiation) for v in tilt_vecs] return rad
def get_sun_position(ts): # Date date = datetime.datetime.strptime(ts, "%Y%m%d%H%M%S") tz = timezone("UTC") date = tz.localize(date) # Sun angles location = (LOCATION.latitude, LOCATION.longitude) azimuth = get_azimuth(*location, date) zenith = 90 - get_altitude(*location, date) # Position in image center = (220, 220) radius = 220 alpha = 90 sun_x = int(center[0] - radius * np.sin(np.radians(azimuth)) * zenith / alpha) sun_y = int(center[1] + radius * np.cos(np.radians(azimuth)) * zenith / alpha) sun = (sun_x, sun_y) return sun
def sunPosFromCoord(latitude, longitude, time_, elevation=0): """ Find azimuth annd elevation of the sun using the pysolar library. Takes latitude(deg), longitude(deg) and a datetime object. Return tuple conaining (elevation, azimuth) TODO verify if timezone influences the results. """ # import datetime # time_ = datetime.datetime(2014, 10, 11, 9, 55, 28) azim = solar.get_azimuth(latitude, longitude, time_, elevation) alti = solar.get_altitude(latitude, longitude, time_, elevation) # Convert to radians azim = np.radians(-azim) elev = np.radians(90-alti) if azim > np.pi: azim = azim - 2*np.pi if elev > np.pi: elev = elev - 2*np.pi return elev, azim
def testGetAzimuth(self): az = solar.get_azimuth(-43, 172, TestApi.test_when) self.assertAlmostEqual(az, 50.5003507)