Package ivs :: Package observations :: Module visibility
[hide private]
[frames] | no frames]

Source Code for Module ivs.observations.visibility

  1  """ 
  2  This module allows to calculate the altitude and airmass of an object in the sky, to determine whether it is 'observable' during day or night time, 
  3  and to get the separation to the moon. 
  4   
  5  Examples: 
  6   
  7  Plot the visibility of an object for 10 days, every 10 minutes. 
  8   
  9  >>> eph = Ephemeris() 
 10  >>> eph.set_objects(objects=['HD50230']) 
 11  >>> eph.set_date(startdate='2011/09/27 12:00:00.0',dt=10.,days=10) 
 12  >>> eph.set_site(sitename='lapalma') 
 13  >>> eph.visibility() 
 14  >>> eph.plot(fmt='bo') 
 15   
 16  ]]include figure]]severalnightsvisibility.png] 
 17   
 18  You can get the same behaviour in less commands: 
 19   
 20  >>> eph = Ephemeris(objects=['HD50230'],startdate='2011/09/27 12:00:00.0',dt=10.,days=10,sitename='lapalma') 
 21  >>> eph.visibility() 
 22   
 23  Or, equivalently, 
 24   
 25  >>> eph = Ephemeris() 
 26  >>> eph.visibility(objects=['HD50230'],startdate='2011/09/27 12:00:00.0',dt=10.,days=10) 
 27   
 28  Get the visibility of 2 objects and the moon only for a certain date: 
 29   
 30  >>> eph = Ephemeris(objects=['HD163506','HD143454']) 
 31  >>> eph.visibility(startdate=2456084.01922,days=1,sitename='palomar') 
 32  >>> eph.plot(moon=True,lw=2) 
 33   
 34  ]]include figure]]nightvisibility.png] 
 35   
 36  One can also get the visibility of an object in a random capital at the middle of the night throughout the year: 
 37   
 38  >>> eph = Ephemeris(objects=['V* V441 Her']) 
 39  >>> eph.visibility(midnight=True,sitename='Paris') 
 40  >>> eph.plot(moon=False) 
 41   
 42  ]]include figure]]yearvisibility.png] 
 43   
 44  Calculate visibility for a list of objects, sites and times: 
 45   
 46  >>> eph = Ephemeris() 
 47  >>> days = np.array([2456084.0,2456085.02,2456085.29,2456085.55,2456095.6321]) 
 48  >>> objectnames = np.array(['HD163506','HD163506','HD163506','HD143454','HD143454']) 
 49  >>> sitenames = np.array(['lapalma','lapalma','palomar','palomar','lapalma']) 
 50  >>> eph.visibility(multiple=True,startdate=days,objects=objectnames,sitename=sitenames) 
 51  >>> eph.plot(moon=True) 
 52   
 53  ]]include figure]]multiple1.png] 
 54   
 55  Note that only the last point is plotted, this is because the other given times correspond to day time. This can be deduced from the color ordering of the day 
 56  (yellow) and night (grey) which are plotted nevertheless. 
 57  Mixing sites can result in ugly plots quite rapidly. So we can also just keep the site fixed (also works for the objects and times): 
 58   
 59  >>> eph = Ephemeris() 
 60  >>> days = np.array([2456084.73,2456085.58,2456085.69,2456085.74,2456095.8321,2456132.978]) 
 61  >>> objectnames = np.array(['HD163506','HD163506','HD163506','HD143454','HD143454','HD163506']) 
 62  >>> eph.visibility(multiple=True,startdate=days,objects=objectnames,sitename='palomar') 
 63  >>> eph.plot(moon=True) 
 64   
 65  ]]include figure]]multiple2.png] 
 66   
 67  Note that in this case, the last point is not plotted although the color coding says it corresponds to night time. Logically, this is because the object is simply 
 68  below the horizon. 
 69   
 70  """ 
 71  import pylab as pl 
 72  from matplotlib.dates import date2num,num2date,DayLocator,HourLocator,DateFormatter 
 73  import numpy as np 
 74  from numpy import sqrt,pi,cos,sin 
 75  import sys 
 76  import time 
 77  import pytz 
 78  import logging 
 79  import ephem 
 80   
 81  from ivs.units import conversions 
 82  from ivs.catalogs import sesame 
 83  from ivs.observations import airmass as obs_airmass 
 84  from ivs.aux import decorators 
 85   
 86  logger = logging.getLogger("OBS.VIS") 
87 88 89 -class Ephemeris(object):
90 - def __init__(self,**kwargs):
91 """ 92 Initialize an Ephemeris object. 93 94 You can set the site, date and objects via the keyword arguments of the functions 'set_objects', 'set_site' and 'set_date'. 95 Defaults are 'no objects', 'la palma' and 'the current time'. 96 97 You can also give the same information when calling 'visibility'. 98 """ 99 self.set_site(**kwargs) 100 self.set_date(**kwargs) 101 self.set_objects(**kwargs)
102
103 - def __set_object(self,objectname):
104 """ 105 Retrieve coordinates for an object in 'ephem'-style. 106 """ 107 try: 108 jpos = sesame.search(objectname,db='S')['jpos'] 109 logger.info('Found object %s at %s'%(objectname,jpos)) 110 except KeyError: 111 logger.warning('Object %s not found in SIMBAD, trying NED.'%(objectname)) 112 try: 113 jpos = sesame.search(objectname,db='N')['jpos'] 114 except KeyError: 115 logger.warning('Object %s not found in NED either.'%(objectname)) 116 raise IOError, 'No coordinates retrieved for object %s.'%(objectname) 117 myobject = ephem.readdb("%s,f|M|A0,%s,8.0,2000"%(objectname,','.join(jpos.split()))) 118 return myobject
119 120 #{ Set object, site and dates 121 @decorators.filter_kwargs
122 - def set_objects(self,objects=None,**kwargs):
123 """ 124 Initializes a list of objects by searching their coordinates on SIMBAD or NED. 125 126 @keyword objects: a list of object names, resolved by SIMBAD or NED. 127 @type objects: iterable 128 """ 129 if objects is not None: 130 objects = [self.__set_object(name) for name in objects] 131 self.objects = objects
132
133 - def get_objectnames(self):
134 """ 135 Return the names of the objects. 136 """ 137 return [member.name for member in self.objects]
138 139 @decorators.filter_kwargs
140 - def set_site(self,sitename='lapalma',sitelat=None,sitelong=None,siteelev=None):
141 """ 142 Set the observing site. 143 144 Supported are: 'lapalma', 'lasilla', 'palomar' and a bunch of capitals defined in pyephem. 145 The other keywords allow to manually define a site or change one or more of the parameters of a manually defined site (always enter a sitename though!). 146 If sitename is None, the site is left unchanged. 147 148 @keyword sitename: the name of the site or city 149 @keyword sitelong: longitude (EAST) of site 150 @type sitelong: string 151 @keyword sitelat: latitude (NORTH) of site 152 @type sitelat: string 153 @keyword siteelev: site elevation above sea level (m) 154 @type siteelev: integer or float 155 """ 156 # changing the site should not have an influence on the date! 157 if hasattr(self,'thesite'): 158 date = self.thesite.date 159 else: 160 date = time.strftime('%Y/%m/%d %H:%M:%S',time.gmtime()) 161 162 if sitename == None: 163 mysite = self.thesite 164 elif sitename == 'lapalma': 165 #-- La Palma 166 mysite = ephem.Observer() 167 #mysite.long = '-17:%.3f'%(52+42/60.) # 17:52:42 WEST 168 mysite.long = '342.1184' # 342.1184 EAST 169 mysite.lat = '28:%.3f'%(45+44/60.) # 28:45:44 NORTH 170 mysite.elevation = 2326 171 mysite.name = sitename 172 elif sitename == 'lasilla': 173 mysite = ephem.Observer() 174 mysite.long = '-70:43.8' # WEST 175 mysite.lat = '-29:15.4' # SOUTH 176 mysite.elevation = 2347 177 mysite.name = sitename 178 elif sitename == 'palomar': 179 mysite = ephem.Observer() 180 mysite.long = '-116:51:46.80' # WEST 181 mysite.lat = '33:21:21.6' # NORTH 182 mysite.elevation = 1706 183 mysite.name = sitename 184 else: 185 try: 186 mysite = ephem.city(sitename) 187 except: 188 logger.critical('Site %s not known, using user definitions'%(sitename)) 189 if hasattr(self,'thesite'): 190 mysite = self.thesite 191 logger.critical('Previous site edited with new values!') 192 else: 193 mysite = ephem.Observer() 194 logger.critical('No site previously defined, so all keywords needed!') 195 if sitename != None: 196 mysite.name = sitename 197 logger.info('Site name set to %s'%(sitename)) 198 if siteelevation != None: 199 mysite.elevation = siteelev 200 logger.info('Site elevation set to %s'%(sitename)) 201 if sitelat != None: 202 mysite.lat = sitelat 203 logger.info('Site latitude set to %s'%(sitename)) 204 if sitelong != None: 205 mysite.long = sitelong 206 logger.info('Site longitude set to %s'%(sitename)) 207 self.thesite = mysite 208 self.thesite.date = ephem.Date(date) 209 logger.info('Set site to %s (long=%s EAST, lat=%s NORTH, elev=%s m)'%(mysite.name,mysite.long,mysite.lat,mysite.elevation))
210 211 @decorators.filter_kwargs
212 - def set_date(self,startdate='today',days=20,dt=10.):
213 """ 214 Set the start date for ephemeris calculations. 215 216 'startdate' can take the following formats: 217 Format 1: Calendar date: '2010/08/16 12:00:00.0' , 218 Format 2: Julian Date: 2455832.25 , 219 Format 3: None: no change, or 'today': the current date (=default) 220 221 Careful: all times are UTC, they do not take care of time zones. 222 default values are also set in UTC (gmtime) 223 224 @keyword startdate: the exact time of the first visibility calculation 225 @type startdate: string or float 226 @keyword days: total number of days on which to calculate visibilities (if visibility keyword 'multiple' = False) 227 @type days: float 228 @keyword dt: sampling time in minutes 229 @type dt: float 230 231 """ 232 if startdate is None: 233 startdate = self.thesite.date 234 elif startdate is 'today': 235 startdate = time.strftime('%Y/%m/%d %H:%M:%S',time.gmtime()) 236 elif not isinstance(startdate,str): 237 YYYY,MM,DD = conversions.convert('JD','CD',startdate) 238 DD,frac = np.floor(DD),DD-np.floor(DD) 239 hh = frac*24. 240 hh,frac = np.floor(hh),hh-np.floor(hh) 241 mm = frac*60. 242 mm,frac = np.floor(mm),mm - np.floor(mm) 243 ss = frac*60. 244 ss,frac = np.floor(ss),ss - np.floor(ss) 245 startdate = '%4d/%02d/%02d %02d:%02d:%.1f'%(YYYY,MM,DD,hh,mm,ss) 246 if days is None: 247 days = self.days 248 if dt is None: 249 dt = self.dt 250 self.thesite.date = ephem.Date(startdate) 251 self.dt = dt 252 self.days = days 253 254 if self.dt is None and self.days is None: 255 logger.info('Set start date to %s'%(startdate)) 256 else: 257 logger.info('Set start date to %s, covering %d days per %d minutes'%(startdate,days,dt))
258
259 - def get_date(self):
260 """ 261 Return the currently set date at the currently set site. 262 """ 263 return self.thesite.date
264 265 #} 266 267 #{ Get output objects, output object names, output sites and output site names
268 - def get_out_objects(self,indexes):
269 """ 270 Return the ephem object(s) (in a list) corresponding to the rows defined by indexes in the arrays of the "vis" dictionary. 271 """ 272 return self.objects[self._objectIndices[index]]
273
274 - def get_out_objectnames(self,indexes):
275 """ 276 Return the object names (in an array) corresponding to the rows defined by indexes in the arrays of the "vis" dictionary. 277 """ 278 return array([member.name for member in get_out_objects(indexes)])
279
280 - def get_out_sites(self,indexes):
281 """ 282 Return the ephem site(s) (in a list) corresponding to the rows defined by indexes in the arrays of the "vis" dictionary. 283 """ 284 return self._uniqueSites[self._siteIndices[indexes]]
285
286 - def get_out_sitenames(self,indexes):
287 """ 288 Return the names of the sites (in an array) corresponding to the rows defined by indexes in the arrays of the "vis" dictionary. 289 """ 290 return array([site.name for site in get_out_sites(indexes)])
291 292 #} 293 294 #{ Compute and plot visibilities 295
296 - def visibility(self,multiple=False,midnight=None,airmassmodel='Pickering2002',**kwargs):
297 """ 298 Calculate ephemeri. 299 300 *If 'multiple' = False, a single site definition and startdate (and/or values for the days and dt keywords) are expected. If one (or more) of these 301 keywords is not given a value, it is assumed that it should not change its current value. 302 If several astrophysical objects are given, ephemeri will be given for each object at the defined site and times. 303 If 'midnight' is not None, ephemeri are calculated in the middle of each night, for the whole year. 304 305 *If 'multiple' = True, a list/array of site names and startdates can be given. Note: the length of keywords 'sitename', 'startdate' and 'objects' 306 can be either N or 1 and should be in the same format as previously. In this case, ephemeri are only calculated at the times given in 'startdate', 307 and thus the keywords 'days', 'dt' and 'midnight' are not used. Sites are currently only accessible throught the keyword 'sitename'. 308 309 The result of this function is an attribute 'vis', a dictionary containing: 310 - MJDs: Modified Julian Dates 311 - dates calendar dates (Format 1) 312 - alts: altitudes 313 - moon_alts: altitudes of the moon 314 - airmass 315 - moon_airmass: airmasses of the moon 316 - moon_separation: separation to moon 317 - during_night: night time / day time (boolean 1-0) 318 - sun_prevrise: time of previous sun rise 319 - sun_nextrise: time of next sun rise 320 - sun_prevset: time of previous sun set 321 - sun_nextset: time of next sun set 322 323 NOTE: use the 'get_out_objects', 'get_out_objectnames', 'get_out_sites' and 'get_out_sitenames' functions to retrieve the object, name of the object, 324 site and name of the site corresponding to a particular row in each of the arrays 'vis' contains. 325 326 """ 327 #-- if no values are given for these keywords, this means nothing should change --> None 328 kwargs.setdefault('sitename',None) 329 kwargs.setdefault('startdate',None) 330 kwargs.setdefault('dt',None) 331 kwargs.setdefault('days',None) 332 333 #-- set optional additional keywords 334 sun = ephem.Sun() 335 moon = ephem.Moon() 336 #moon_theta = 34.1 # minutes 337 338 if not multiple: 339 #-- set the site, date and objects 340 self.set_site(**kwargs) 341 self.set_date(**kwargs) 342 self.set_objects(**kwargs) 343 344 #-- set stuff for calculations 345 timestep_minutes = self.dt 346 total_days = self.days 347 if midnight is None: 348 total_minutes = int(total_days*24*60./timestep_minutes) 349 else: 350 total_minutes = 365 351 352 #-- set initial arrays 353 alts = np.zeros((len(self.objects),total_minutes)) 354 rawdates = np.zeros(total_minutes) 355 during_night = np.zeros(total_minutes,int) 356 moon_separation = np.zeros((len(self.objects),total_minutes)) 357 moon_alts = np.zeros(total_minutes) 358 sun_prevrise = np.zeros(total_minutes) 359 sun_prevset = np.zeros(total_minutes) 360 sun_nextrise = np.zeros(total_minutes) 361 sun_nextset = np.zeros(total_minutes) 362 363 #-- run over all timesteps 364 if midnight is None: 365 for i in range(total_minutes): 366 sun_prevset[i] = float(self.thesite.previous_setting(sun)) 367 sun_prevrise[i] = float(self.thesite.previous_rising(sun)) 368 sun_nextset[i] = float(self.thesite.next_setting(sun)) 369 sun_nextrise[i] = float(self.thesite.next_rising(sun)) 370 rawdates[i] = float(self.thesite.date) 371 #-- compute the moon position 372 moon.compute(self.thesite) 373 moon_alts[i] = float(moon.alt) 374 if (sun_prevrise[i]<=sun_prevset[i]): 375 during_night[i] = 1 376 for j,star in enumerate(self.objects): 377 star.compute(self.thesite) 378 alts[j,i] = float(star.alt) 379 moon_separation[j,i] = ephem.separation(moon,star) 380 self.thesite.date += ephem.minute*timestep_minutes 381 382 else: 383 i = 0 384 while i<365: 385 sun_nextrise[i] = float(self.thesite.next_rising(sun)) 386 sun_prevset[i] = float(self.thesite.previous_setting(sun)) 387 sun_prevrise[i] = float(self.thesite.previous_rising(sun)) 388 sun_nextset[i] = float(self.thesite.next_setting(sun)) 389 if sun_prevrise[i]<=sun_prevset[i]: # now we're in a night 390 self.thesite.date = ephem.Date((sun_nextrise[i]+sun_prevset[i])/2.) 391 else: 392 #-- set 4 hours forwards 393 self.thesite.date += ephem.minute*60*4 394 continue 395 rawdates[i] = float(self.thesite.date) 396 during_night[i] = 1 397 for j,star in enumerate(self.objects): 398 star.compute(self.thesite) 399 alts[j,i] = float(star.alt) 400 i += 1 401 #-- set 1 day forwards 402 self.thesite.date += ephem.minute*60*24 403 404 alts = alts.ravel() 405 rawdates = np.outer(np.ones(len(self.objects)),rawdates).ravel() 406 during_night = np.outer(np.ones(len(self.objects),int),during_night).ravel() 407 moon_separation = moon_separation.ravel() # 408 moon_alts = np.outer(np.ones(len(self.objects)),moon_alts).ravel() 409 sun_nextrise = np.outer(np.ones(len(self.objects)),sun_nextrise).ravel() 410 sun_prevrise = np.outer(np.ones(len(self.objects)),sun_prevrise).ravel() 411 sun_nextset = np.outer(np.ones(len(self.objects)),sun_nextset).ravel() 412 sun_prevset = np.outer(np.ones(len(self.objects)),sun_prevset).ravel() 413 414 self._objectIndices = np.outer(np.arange(len(self.objects)),np.ones(total_minutes)).ravel() 415 self._siteIndices = np.zeros_like(alts) 416 self._uniqueSites = [self.thesite] 417 418 else: 419 startdate = kwargs.get('startdate',None) 420 sitename = kwargs.get('sitename','lapalma') 421 objects = kwargs.get('objects',None) 422 if objects is None: 423 objects = self.get_objectnames() 424 425 # the other option is to iterate over given 'dates' and/or sites and objects 426 if not type(startdate) == np.ndarray: startdate = np.array([startdate]) 427 if not type(sitename) == np.ndarray: sitename = np.array([sitename]) 428 if not type(objects) == np.ndarray: objects = np.array([objects]).ravel() 429 430 uniqueObjectNames = np.unique(objects) 431 uniqueSiteNames = np.unique(sitename) 432 self.set_objects(uniqueObjectNames) 433 self._objectIndices = np.zeros_like(objects,int) 434 self._siteIndices = np.zeros_like(sitename,int) 435 self._uniqueSites = [] 436 for i in range(len(uniqueObjectNames)): 437 self._objectIndices = np.where(objects == uniqueObjectNames[i],i,self._objectIndices) 438 for i in range(len(uniqueSiteNames)): 439 self._siteIndices = np.where(sitename == uniqueSiteNames[i],i,self._siteIndices) 440 self.set_site(uniqueSiteNames[i]) 441 self._uniqueSites.append(self.thesite) 442 443 #-- define the iterator 444 it = np.broadcast(startdate,self._siteIndices,self._objectIndices) 445 446 #-- set initial arrays 447 alts = np.zeros(it.shape[0]) 448 rawdates = np.zeros(it.shape[0]) 449 during_night = np.zeros(it.shape[0],int) 450 moon_separation = np.zeros(it.shape[0]) 451 moon_alts = np.zeros(it.shape[0]) 452 sun_prevrise = np.zeros(it.shape[0]) 453 sun_prevset = np.zeros(it.shape[0]) 454 sun_nextrise = np.zeros(it.shape[0]) 455 sun_nextset = np.zeros(it.shape[0]) 456 457 #-- run over all elements 458 for i,element in enumerate(it): 459 #-- set the site and date 460 self.thesite = self._uniqueSites[element[1]] 461 self.set_date(startdate=element[0],days=None,dt=None) 462 #-- determine whether the time corresponds to night or day 463 sun_prevset[i] = float(self.thesite.previous_setting(sun)) 464 sun_prevrise[i] = float(self.thesite.previous_rising(sun)) 465 sun_nextset[i] = float(self.thesite.next_setting(sun)) 466 sun_nextrise[i] = float(self.thesite.next_rising(sun)) 467 if (sun_prevrise[i]<=sun_prevset[i]): 468 during_night[i] = 1 469 rawdates[i] = float(self.thesite.date) 470 #-- compute the moon position 471 moon.compute(self.thesite) 472 moon_alts[i] = float(moon.alt) 473 #-- compute the star's position 474 star = self.objects[element[2]] 475 star.compute(self.thesite) 476 alts[i] = float(star.alt) 477 moon_separation[i] = ephem.separation(moon,star) 478 479 #-- calculate airmass 480 airmass = obs_airmass.airmass(90-alts/pi*180,model=airmassmodel) 481 moon_airmass = obs_airmass.airmass(90-moon_alts/pi*180,model=airmassmodel) 482 483 #-- calculate dates for plotting and output 484 self._plotdates = np.array([date2num(ephem.Date(h).datetime()) for h in rawdates]) 485 self._sun_prevset = np.array([date2num(ephem.Date(h).datetime()) for h in sun_prevset]) 486 self._sun_prevrise = np.array([date2num(ephem.Date(h).datetime()) for h in sun_prevrise]) 487 self._sun_nextset = np.array([date2num(ephem.Date(h).datetime()) for h in sun_nextset]) 488 self._sun_nextrise = np.array([date2num(ephem.Date(h).datetime()) for h in sun_nextrise]) 489 dates = np.array([str(ephem.Date(h).datetime()) for h in rawdates]) 490 MJDs = rawdates+15019.499999 # the zeropoint of ephem is 1899/12/31 12:00:00.0 15019.499585 491 492 #-- the output dictionary 493 self.vis = dict(MJDs=MJDs,dates=dates,alts=alts,airmass=airmass,during_night=during_night,moon_alts=moon_alts,moon_airmass=moon_airmass,moon_separation=moon_separation) 494 self.vis.update(dict(sun_prevrise=np.array(num2date(self._sun_prevrise),dtype='|S19'),sun_prevset=np.array(num2date(self._sun_prevset),dtype='|S19'),sun_nextrise=np.array(num2date(self._sun_nextrise),dtype='|S19'),sun_nextset=np.array(num2date(self._sun_nextset),dtype='|S19'))) 495 for i,obj in enumerate(self.objects): 496 keep = (self._objectIndices == i) & (during_night==1) & (0<=airmass) & (airmass<=2.5) 497 logger.info('Object %s: %s visible during night time (%.1f<airmass<%.1f)'%(obj.name,~np.any(keep) and 'not' or '',sum(keep) and airmass[keep].min() or np.nan,sum(keep) and airmass[keep].max() or np.nan))
498 499
500 - def plot(self,plot_daynight=True,**kwargs):
501 """ 502 Make a plot of the result of 'visibility'. 503 """ 504 #-- input 505 moon = kwargs.pop('moon',True) 506 alts = self.vis['alts'] 507 airmass = self.vis['airmass'] 508 moon_airmass = self.vis['moon_airmass'] 509 during_night = self.vis['during_night'] 510 yaxis = kwargs.pop('yaxis','airmass') # or 'alts' 511 512 factor = (yaxis=='alts') and 180./pi or 1. 513 #kwargs.setdefault('ms',2.) 514 515 #-- plot 516 fmt = kwargs.pop('fmt',False) 517 plotcolors = ['b','g','r','c','m','k'] 518 plotsymbols = ['o','s','p','*','h','H','d','v','+','^','<','>','.'] 519 520 pl.figure(figsize=(16,8)) 521 522 #-- run over all objects and plot them 523 for i in range(len(self.objects)): 524 for j in range(len(self._uniqueSites)): 525 #-- only keep times during the night and with an airmass between 0 and 2.5 526 keep = (self._objectIndices == i) & (self._siteIndices == j) & (during_night==1) & (0<=airmass) & (airmass<=3.5) 527 #plotindex = i*len(self._uniqueSites) + j 528 529 ifmt = fmt and fmt or plotsymbols[np.fmod(i,14)]+plotcolors[np.fmod(j,6)] 530 ilabel = len(self._uniqueSites)-1 and self.objects[i].name + '@' + self._uniqueSites[j].name or self.objects[i].name 531 532 pl.plot_date(self._plotdates[keep],self.vis[yaxis][keep]*factor,xdate=True,tz=pytz.utc,fmt=ifmt,label=ilabel,**kwargs) 533 534 if moon: 535 keep = (self._objectIndices == i) & (during_night==1) & (0<=moon_airmass) & (moon_airmass<=3.5) 536 537 #-- check the moon separation! 538 if keep.sum(): 539 index = np.argmin(self.vis['moon_separation'][keep]*factor) 540 closest = (self.vis['moon_separation'][keep]*factor)[index] 541 if closest<40.: 542 t = self._plotdates[keep][index] 543 time_closest = pytz.datetime.datetime.fromordinal(int(t)) + pytz.datetime.timedelta(days=t-int(t)) 544 logger.warning('Object-moon distance is %.1f deg at %s'%(closest,time_closest)) 545 546 if moon: 547 for j in range(len(self._uniqueSites)): 548 keep = (self._siteIndices == j) & (during_night==1) & (0<=moon_airmass) & (moon_airmass<=3.5) 549 if len(self._uniqueSites) > 1: 550 ifmt = 'D' + plotcolors[np.fmod(j,6)] 551 else: 552 ifmt = 'yD' 553 ilabel = len(self._uniqueSites)-1 and 'Moon@'+self._uniqueSites[j].name or 'Moon' 554 pl.plot_date(self._plotdates[keep],self.vis['moon_'+yaxis][keep]*factor,xdate=True,tz=pytz.utc,fmt=ifmt,label=ilabel) 555 556 #-- take care of labels and direction of the y-axis 557 if yaxis=='airmass': 558 pl.ylabel('Airmass') 559 pl.ylim((3.5,0.6)) 560 ymin,ymax = 1.0,3.5 561 elif yaxis=='alts': 562 pl.ylabel('Altitude (degrees)') 563 pl.ylim((0.,108.)) 564 ymin,ymax = 0.,90. 565 566 #-- plot whether it is day or night 567 if plot_daynight: 568 indices1 = np.where(np.diff(np.array(self._sun_prevset,int)) != 0)[0] 569 indices2 = np.where(np.diff(np.array(self._sun_prevrise,int)) != 0)[0] 570 indices = np.unique(np.concatenate((indices1,indices1+1,indices2,indices2+1))) 571 indices = np.concatenate((indices,np.array([0,len(self._sun_prevset)-1]))) 572 573 for prevset,prevrise,nextset,nextrise in zip(self._sun_prevset[indices],self._sun_prevrise[indices],self._sun_nextset[indices],self._sun_nextrise[indices]): 574 if prevset<prevrise: 575 #pl.fill([prevset,prevset,prevrise,prevrise],[ymin,ymax,ymax,ymin],'k',alpha=0.35) 576 #pl.fill([prevrise,prevrise,nextset,nextset],[ymin,ymax,ymax,ymin],'y',alpha=0.25) 577 #pl.fill([nextset,nextset,nextrise,nextrise],[ymin,ymax,ymax,ymin],'k',alpha=0.35) 578 pl.axvspan(prevset,prevrise,color='k',alpha=0.35) 579 pl.axvspan(prevrise,nextset,color='y',alpha=0.25) 580 pl.axvspan(nextset,nextrise,color='k',alpha=0.35) 581 else: 582 #pl.fill([prevrise,prevrise,prevset,prevset],[ymin,ymax,ymax,ymin],'y',alpha=0.25) 583 #pl.fill([prevset,prevset,nextrise,nextrise],[ymin,ymax,ymax,ymin],'k',alpha=0.35) 584 #pl.fill([nextrise,nextrise,nextset,nextset],[ymin,ymax,ymax,ymin],'y',alpha=0.25) 585 pl.axvspan(prevrise,prevset,color='y',alpha=0.25) 586 pl.axvspan(prevset,nextrise,color='k',alpha=0.35) 587 pl.axvspan(nextrise,nextset,color='y',alpha=0.25) 588 589 #-- add a grid and legend 590 pl.grid() 591 nrlegendcolumns = len(self._uniqueSites)-1 and 5 or 8 592 pl.legend(loc='upper right',numpoints=1,borderpad=0.2,labelspacing=0.2,handlelength=0.2,ncol=nrlegendcolumns,columnspacing=0.25) 593 594 #-- take care of the x-axis labelling format 595 pl.gca().xaxis.set_major_formatter(DateFormatter("%d %b '%y %H:%M")) 596 pl.gcf().autofmt_xdate() 597 pl.xlabel('time (UTC)')
598 599 #} 600 601 602 if __name__=="__main__": 603 if len(sys.argv)<2: 604 import doctest 605 doctest.testmod() 606 pl.show() 607 else: 608 from ivs.aux import loggers 609 logger = loggers.get_basic_logger() 610 611 eph = Ephemeris(objects=sys.argv[1].split(',')) 612 eph.visibility() 613 eph.plot() 614 pl.show() 615