Module crepyscule_tools
[hide private]
[frames] | no frames]

Source Code for Module crepyscule_tools

   1  #!/usr/bin/env python 
   2  # -*- coding: iso-8859-1 -*- 
   3   
   4  # Copyright 2005,2008  Miguel Tremblay 
   5   
   6  # This program is free software; you can redistribute it and/or modify 
   7  # it under the terms of the GNU General Public License as published by 
   8  # the Free Software Foundation; either version 3 of the License, or 
   9  # (at your option) any later version. 
  10   
  11  # This program is distributed in the hope that it will be useful, 
  12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  14  # GNU General Public License for more details. 
  15   
  16  # You should have received a copy of the GNU General Public License 
  17  # along with this program; if not see  <http://www.gnu.org/licenses/>. 
  18  ############################################################################ 
  19   
  20  """ 
  21  Usefull methods regarding time, sun, math, strings and CSV format 
  22  for crepyscule module. 
  23   
  24  Project home page is U{http://ptaff.ca/crepyscule/} 
  25                 
  26   - Name:        crepyscule_tools.py 
  27   - Author:      U{Miguel Tremblay<http://ptaff.ca/miguel/>} 
  28   - Date:        February 20th  2005 
  29   
  30   
  31  """ 
  32   
  33  import sys 
  34  import time 
  35  import string 
  36  import calendar 
  37  import datetime 
  38   
  39  import math 
  40  import Sun 
  41  import numpy 
  42   
  43  import crepyscule_summer_time 
  44   
  45  # Set the place where to fetch languages dependant messages 
  46  import gettext 
  47  t = gettext.translation('crepyscule_tools', sys.path[0] + '/locale') 
  48  _ = t.gettext 
  49   
  50   
  51  HALF_YEAR = 365.24/2 
  52  OBLIQUITY_OF_ECLIPTIC = 23.439 
  53   
  54  ####################################################################### 
  55  # Time methods 
  56   
57 -def ctime_to_iso8601(ctime):
58 """ 59 Convert a ctime value in iso8601. 60 61 @type ctime: float 62 @param ctime: ctime value to be converted in iso8601 63 64 @rtype: string 65 @return: iso9601 date in the format YYYY-MM-DDTHH:mm:ssZ. 66 See L{get_iso_8601} 67 """ 68 # lDate is in the format (2005, 3, 29, 18, 42, 28, 1, 88, 0) 69 (nYear, nMonth, nDay, nHour, nMinute, nSecond, nWeekDay, nJulian, bDst) =\ 70 time.gmtime(ctime) 71 72 sIso8601 = get_iso_8601(nYear, nMonth, nDay, nHour, nMinute, nSecond) 73 return sIso8601
74 75
76 -def get_iso_8601(nYear, nMonth, nDay, nHour=0, nMinute=0, nSecond=0):
77 """ 78 Convert numbers of date in the iso 8601 format. 79 We assume UTC time zone. 80 81 @type nYear: int 82 @param nYear: year for this date 83 @type nMonth: int 84 @param nMonth: month for this date 85 @type nDay: int 86 @param nDay: day for this date 87 @type nHour: int 88 @param nHour: hour for this date 89 @type nMinute: int 90 @param nMinute: minute for this date 91 @type nSecond: int 92 @param nSecond: second for this date 93 94 @rtype: string 95 @return: iso9601 date in the format YYYY-MM-DDTHH:mm:ssZ. 96 """ 97 98 sYear = str_to_at_least_two_digits(nYear) 99 sMonth = str_to_at_least_two_digits(nMonth) 100 sDay = str_to_at_least_two_digits(nDay) 101 102 if (nHour == nMinute == nSecond == 0): 103 sIso = sYear + '-' + sMonth + '-' + sDay 104 else: 105 sHour = str_to_at_least_two_digits(nHour) 106 sMinute = str_to_at_least_two_digits(nMinute) 107 sSecond = str_to_at_least_two_digits(nSecond) 108 sIso = sYear + '-' + sMonth + '-' + sDay+ 'T' +\ 109 sHour + ':' + sMinute + ':' + sSecond + 'Z' 110 111 return sIso
112
113 -def tranform_decimal_hour_in_minutes(fTimeHour, sRound=''):
114 """ 115 Description: Return an array containing the hour, 116 the minutes and the secondes, respectively. 117 118 @type fTimeHour: float 119 @param fTimeHour: Time in decimal form. Eg 1.90 for 1h54:00 120 121 @type sRound: string 122 @param sRound: Round the result to the minutes (seconds =0) 123 or hours (seconds =0, minutes=0). 124 Must be in ['minute', 'hour'], 125 126 @rtype: tuple 127 @return: (nHour, nMinute, nSecond) 128 """ 129 130 lRound = ['minute', 'hours', ''] 131 132 if sRound not in lRound: 133 sSUNRISE_SUNSET_ERRORS = "Cannot round time to %s" % ((sRound)) 134 raise sSUNRISE_SUNSET_ERRORS 135 136 # Extract decimal from integer part 137 tModHour = math.modf(fTimeHour) 138 nHour = int(tModHour[1]) 139 fDecimalHour = tModHour[0] 140 # Transform decimal in minutes 141 fMinute = fDecimalHour*60 142 # Again, extract the decimal and the integer part 143 tModMinute = math.modf(fMinute) 144 nMinute = int(tModMinute[1]) 145 fDecimalMinute = tModMinute[0] 146 # Transform decimal in seconds 147 fSecond = fDecimalMinute*60 148 # Again, extract the decimal and the integer part 149 tModSecond = math.modf(fSecond) 150 nSecond = int(tModSecond[1]) 151 152 # Check if we are rounding. 153 if sRound == 'minute': 154 if tModSecond[1] > 30: 155 if nMinute == 59: 156 nMinute = 0 157 nHour = nHour + 1 158 else: 159 nMinute = nMinute + 1 160 nSecond = 0 161 elif sRound == 'hour': 162 if tModMinute[1] > 30: 163 nHour = nHour + 1 164 nMinute = 0 165 nSecond = 0 166 167 sHour = str_to_at_least_two_digits(nHour) 168 sMinute = str_to_at_least_two_digits(nMinute) 169 sSecond = str_to_at_least_two_digits(nSecond) 170 171 return (sHour, sMinute, sSecond)
172
173 -def get_one_year_of_iso8601(ctime):
174 """ 175 Return a list containing all the dates to the year 176 corresponding to the ctime in in iso8601 format. 177 178 @type ctime: float 179 @param ctime: Any ctime in the year of the result. 180 181 @rtype: list 182 @return: List with all the dates for one year. 183 """ 184 lDateISO8601 = [] 185 186 lMonth = range(1,13) 187 tToday = time.gmtime(ctime) 188 nYear = tToday[0] 189 190 for nMonth in lMonth: 191 # Get a list of the number of days in each month 192 lrange = calendar.monthrange(nYear, nMonth) 193 lDay = range(1,lrange[1]+1) 194 for nDay in lDay: 195 sDay = get_iso_8601(nYear, nMonth, nDay) 196 lDateISO8601.append(sDay) 197 198 return lDateISO8601
199
200 -def get_yesterday(nYear, nMonth, nDay):
201 """ 202 Given a tuple containing (nYear, nMonth, nDay), remove one day 203 and returns the tuple. 204 205 @type nYear: int 206 @param nYear: year for this date 207 @type nMonth: int 208 @param nMonth: month for this date 209 @type nDay: int 210 @param nDay: day for this date 211 212 @rtype: tuple 213 @return: (nYear, nMonth, nDay-1) 214 """ 215 216 # Create a ctime 217 ctime = time.mktime((nYear, nMonth, nDay,0,0,0,0,0,0)) 218 219 # Remove the rigth number of seconds 220 ctimeYesterday = ctime - 24*3600 221 222 # Convert back a again 223 (nYear, nMonth, nDay, nHour, nMinute, nSecond, nWeekDay, nJulian, bDst) =\ 224 time.gmtime(ctimeYesterday) 225 226 return (nYear, nMonth, nDay)
227 228 ######################################################################## 229 # Sun methods 230
231 -def get_one_year_data(fLat, fLon, ctime, fUTC, sTimezone):
232 """ 233 Generate the information (sunset, sunrise, altitude) for one year. 234 235 @type fLat: float 236 @param fLat: Latitude in decimal. 237 @type fLon: float 238 @param fLon: Longitude in decimal. West longitude are negative 239 East longitude are positive. 240 @type ctime: float 241 @param ctime: Any ctime in the year of the result. 242 @type fUTC: float 243 @param fUTC: Time to add/substract for each time values. Usually used 244 for UTC value of place. 245 @type sTimezone: string 246 @param sTimezone: This variable is a 2 letters code indicating 247 when is the daylight saving time (DST) starting and ending in the year 248 for the first place. 249 250 @rtype: tuple 251 @return: (lSunrise, lSunset, lSunAltitude, tToday) 252 253 """ 254 lMonth = range(1,13) 255 cSun = Sun.Sun() 256 tToday = time.gmtime(ctime) 257 nYear = tToday[0] 258 259 # Create list to record sunset and sunrise 260 lSunset = [] 261 lSunrise = [] 262 # List for sun max altitude 263 lSunAltitude = [] 264 265 for nMonth in lMonth: 266 # Get a list of the number of days in each month 267 lrange = calendar.monthrange(nYear, nMonth) 268 lDay = range(1,lrange[1]+1) 269 fMonthlyLight = 0 270 for nDay in lDay: 271 tCurrentDay = (nYear, nMonth, nDay) 272 # Sun altitude 273 fAltitude = get_one_value("altitude", fLat, fLon, tCurrentDay, fUTC) 274 lSunAltitude.append(fAltitude) 275 # Sunrise and sunset 276 fSunriseTime = get_one_value("sunrise", fLat, fLon, tCurrentDay,\ 277 fUTC, sTimezone) 278 fSunsetTime = get_one_value("sunset", fLat, fLon, tCurrentDay,\ 279 fUTC, sTimezone) 280 lSunrise.append(fSunriseTime) 281 lSunset.append(fSunsetTime) 282 283 return (lSunrise, lSunset, lSunAltitude, tToday)
284
285 -def check_value_over_24(lSunset):
286 """ 287 Check the value of sunset to see if there is some values over 24. 288 289 @type lSunset: list 290 @param lSunset: list containing all the value of sunset. 291 292 @rtype: tuple 293 @return: (nStart, nEnd) where nStart is the value where the 294 curve goes over 24 and nEnd is the value where the curve goes 295 under 24. 296 """ 297 TWENTY_FOUR = 24 298 nStart = 0 299 nEnd = len(lSunset)-1 300 301 npSunset = numpy.array(lSunset) 302 # No value over 24 303 if npSunset.max() < TWENTY_FOUR: 304 return (nStart, nEnd) 305 # if all the value are > 24, there is a funny who have entered an 306 # impossible UTC for this longitude. Curve wont be on the graph, 307 # too bad for him. 308 elif npSunset.min() > TWENTY_FOUR: 309 return (nStart, nEnd) 310 else: 311 # Get the last indice of value over 24 312 for i in range(0,len(npSunset)-1): 313 if npSunset[i] > TWENTY_FOUR and npSunset[i+1] < TWENTY_FOUR : 314 nEnd = i + 1 315 break 316 # Get the first indice of value over 24 317 for i in range(len(npSunset)-1, 0, -1): 318 if npSunset[i] > TWENTY_FOUR and npSunset[i-1]< TWENTY_FOUR : 319 nStart = i 320 break 321 322 return (nStart, nEnd)
323 324
325 -def check_value_under_0(lSunrise):
326 """ 327 Check the value of sunset to see if there is some values over 24. 328 329 @type lSunrise: list 330 @param lSunrise: list containing all the value of sunset. 331 332 @rtype: tuple 333 @return: (nStart, nEnd) where nStart is the value where the 334 curve goes under 0 and nEnd is the value where the curve goes 335 over 0. 336 """ 337 ZERO = 0 338 npSunrise = numpy.array(lSunrise) 339 # if all the value are < 0, there is a funny who have entered an 340 # impossible UTC for this longitude. Curve wont be on the graph, 341 # too bad for him. 342 if npSunrise.min() > ZERO or npSunrise.max() < ZERO: 343 nStart = 0 344 nEnd = len(npSunrise)-1 345 else: 346 # Get the last indice of value under 0 347 for i in range(0,len(npSunrise)-1): 348 if npSunrise[i] < ZERO and npSunrise[i+1] > ZERO: 349 nEnd = i 350 break 351 # Get the first indice of value under 0 352 for i in range(len(npSunrise)-1,0,-1): 353 if npSunrise[i] < ZERO and npSunrise[i-1] > ZERO: 354 nStart = i 355 break 356 357 return (nStart, nEnd)
358 359
360 -def correct_sun_bugs(lSunrise, lSunset):
361 """ 362 Correct some bugs related to time of Sun file. 363 364 @type lSunrise: list 365 @param lSunrise: list containing the sunrise value 366 @type lSunset: list 367 @param lSunset: list containing the sunset value 368 369 @rtype: tuple 370 @return: tuple containing the corrected value (npSunrise, npSunset), 371 """ 372 npSunrise = numpy.array(lSunrise) 373 npSunset = numpy.array(lSunset) 374 375 # Identify segment above 24 376 # Remove value under 0 before, because it can have 377 # some strange behaviour from Sun.py 378 npSunset = numpy.where(npSunset < npSunset.mean()-10,\ 379 npSunset+24, npSunset) 380 npSunset = numpy.where(npSunset > 24, npSunset-24, npSunset) 381 # Identify segment under 0 382 npSunrise = numpy.where(npSunrise > 24, npSunrise - 24, npSunrise) 383 npSunrise = numpy.where(npSunrise < 0, npSunrise + 24, npSunrise) 384 385 return (npSunrise, npSunset)
386
387 -def get_one_year_max_sf(nYear, fLat):
388 """ 389 Get the solar flux for a whole year. 390 391 @type nYear: int 392 @param nYear: Year for which to get the solar flux. 393 @type fLat: float 394 @param fLat: Latitude in decimal for the place. 395 396 @rtype: list 397 @return: List of the daily maximal solar fluxes. 398 """ 399 400 cSun = Sun.Sun() 401 lFlux = [] 402 403 # Get the max number of days for each month of this year 404 for nMonth in range(1,13): 405 nNumberDaysInMonth = calendar.monthrange(nYear, nMonth)[1] 406 for nDay in range(1, nNumberDaysInMonth+1): 407 fFlux = cSun.get_max_solar_flux(fLat, nYear, nMonth, nDay) 408 lFlux.append(fFlux) 409 410 return lFlux
411 412
413 -def is_summer_time(nJulianDay, nYear, sSummerTime):
414 """ 415 Is this julian day during summer time? 416 417 @type nJulianDay: int 418 @param nJulianDay: Julian day, january 1st is '1', last day of year is 419 '365' in a non-bisextil year. 420 @type nYear: int 421 @param nYear: Year in which the julian day belongs 422 @type sSummerTime: string 423 @param sSummerTime: This variable is a 2 letters code indicating 424 when is the daylight saving time (DST) starting and ending in the year 425 for the first place. 426 427 @rtype: bool 428 @return: True if the Julian day is during summertime, False otherwise. 429 """ 430 # If no summer time is define, we are never in summer time 431 if sSummerTime == '' or sSummerTime == '--': 432 return False 433 434 (nFirstDay, nLastDay) = crepyscule_summer_time.\ 435 get_summer_time_days(sSummerTime, nYear) 436 if nJulianDay < nFirstDay or nJulianDay > nLastDay: 437 return False 438 else: 439 return True
440 441
442 -def get_daylight_variation(lDaylightInOneDay):
443 """ 444 Compute the time gained or lost for each day. 445 446 @type lDaylightInOneDay: list 447 @param lDaylightInOneDay: Contains the length of day, i.e. sunset-sunrise. 448 449 @rtype: list 450 @return: Result in a list in minutes. 451 """ 452 # Compute the differences 453 lDiffSunTime = [] 454 for i in range(len(lDaylightInOneDay)): 455 fTimeMinute = (lDaylightInOneDay[i]-lDaylightInOneDay[i-1])*60 456 lDiffSunTime.append(fTimeMinute) 457 458 return lDiffSunTime
459
460 -def get_dictionary(sValue, fLat, fLon, ctime, fUTC=None, sSummerTime=""):
461 """ 462 Compute the values indicated by sValue and return a dictionnary with 463 the date in iso8601 as keys. 464 465 @type sValue: string 466 @param sValue: Any string in lPossibleValues 467 @type fLat: float 468 @param fLat: latitude of the first place. Latitude is in decimal 469 degrees. Example: 30°30' should be 30.5 470 @type fLon: float 471 @param fLon: longitude of the first place. Longitude is in decimal 472 degrees. Example: 30°30' should be 30.5. West longitude are negative 473 East longitude are positive. 474 @type ctime: float 475 @param ctime: Any ctime in the day for the wanted value. If a graphic is 476 created and there is only one place, a line is drawn with the values 477 written at the intersection for this specific day. 478 @type fUTC: float 479 @param fUTC: Time to add/substract for each time values for the first place. 480 Usually used for UTC value of place. 481 @type sSummerTime: string 482 @param sSummerTime: This variable is a 2 letters code indicating 483 when is the daylight saving time (DST) starting and ending in the year 484 for the first place. 485 Default is no DST. For a list of DST code, 486 see L{crepyscule_summer_time.lTimezone}. 487 488 @rtype: dictionnary 489 @return: Dictionnary with key in iso8601 format like 'YYYY-MM-DD' and 490 the corresponding value. 491 """ 492 lPossibleValues = ["sunrise", "sunset", "altitude", "variation", "sf", \ 493 "daylength", "twilight"] 494 dValues = {} 495 496 if sValue not in lPossibleValues: 497 sError = sValue + _(" is not a good value for get_dictionary.") +\ 498 _("Possible values are:") + str(lPossibleValues) 499 sys.stderr.write(sError) 500 return None 501 502 503 (lSunrise, lSunset, lSunAltitude, tToday) = \ 504 get_one_year_data(fLat, fLon, ctime, fUTC, sSummerTime) 505 506 lDateISO8601 = get_one_year_of_iso8601(ctime) 507 if sValue == "sunrise": 508 lValue = lSunrise 509 elif sValue == "sunset": 510 lValue = lSunset 511 elif sValue == "altitude": 512 lValue = lSunAltitude 513 elif sValue == "variation": 514 lSuntime = get_daylength(ctime, fLat, fLon) 515 lValue = get_daylight_variation(lSuntime) 516 elif sValue == "sf": 517 nYear = int(lDateISO8601[0][0:4]) 518 lValue = get_one_year_max_sf(nYear, fLat) 519 elif sValue == "daylength": 520 lValue = get_daylength(ctime, fLat, fLon) 521 elif sValue == "twilight": 522 lValue = get_twilight_length_year(ctime, fLat) 523 524 for i in range(len(lDateISO8601)): 525 dValues[lDateISO8601[i]] = round(lValue[i], 2) 526 527 return dValues
528 529
530 -def get_one_value(sValue, fLat, fLon, tuple_or_ctime, fUTC=0, sSummerTime=""):
531 """ 532 Compute the value indicated by sValue and return it. 533 534 @type sValue: string 535 @param sValue: Any string in lPossibleValues 536 @type fLat: float 537 @param fLat: latitude of the first place. Latitude is in decimal 538 degrees. Example: 30°30' should be 30.5 539 @type fLon: float 540 @param fLon: longitude of the first place. Longitude is in decimal 541 degrees. Example: 30°30' should be 30.5. West longitude are negative 542 East longitude are positive. 543 @type tuple_or_ctime: tuple or float 544 @param tuple_or_ctime: can be called either with a ctime value or a tuple 545 with (nYear, nMonth, nDay) for the specific day. 546 @type fUTC: float 547 @param fUTC: Time to add/substract for each time values for the first place. 548 Usually used for UTC value of place. 549 @type sSummerTime: string 550 @param sSummerTime: This variable is a 2 letters code indicating 551 when is the daylight saving time (DST) starting and ending in the year 552 for the first place. 553 Default is no DST. For a list of DST code, 554 see L{crepyscule_summer_time.lTimezone}. 555 556 @rtype: float 557 @return: Value corresponding to the date and the key 558 """ 559 lPossibleValues = ["sunrise", "sunset", "altitude", "variation", "sf"] 560 cSun = Sun.Sun() 561 fValue = None 562 563 # Get time values 564 if type(tuple_or_ctime) == type(()): 565 (nYear, nMonth, nDay) = tuple_or_ctime 566 else: # Not a tuple but a ctime 567 (nYear, nMonth, nDay, nHour, nMinute, nSecond, nWeekDay, nJulian, bDst) =\ 568 time.gmtime(tuple_or_ctime) 569 tDay = (nYear, nMonth, nDay) 570 571 572 if sValue == "sunrise": 573 fValue = cSun.sunRiseSet(nYear, nMonth, nDay, fLon, fLat)[0] + fUTC 574 fValue = crepyscule_summer_time.\ 575 adjust_summer_time_one_day(tDay, fValue, sSummerTime) 576 if fValue < 0: 577 fValue = fValue + 24 578 elif fValue > 24: 579 fValue = fValue - 24 580 elif sValue == "sunset": 581 fValue = cSun.sunRiseSet(nYear, nMonth, nDay, fLon, fLat)[1] + fUTC 582 fValue = crepyscule_summer_time.\ 583 adjust_summer_time_one_day(tDay, fValue, sSummerTime) 584 if fValue < 0: 585 fValue = fValue + 24 586 elif fValue > 24: 587 fValue = fValue - 24 588 elif sValue == "altitude": 589 fValue = cSun.solar_altitude(fLat, nYear, nMonth, nDay) 590 elif sValue == "variation": 591 # Get value sunrise & sunset for today 592 fSunrise2 = get_one_value("sunrise", fLat, fLon, \ 593 tDay, fUTC, sSummerTime) 594 fSunset2 = get_one_value("sunset", fLat, fLon, \ 595 tDay, fUTC, sSummerTime) 596 fDay2 = fSunset2 - fSunrise2 597 # Get sunrise & sunset for yesteray 598 tYesterday = get_yesterday(tDay[0], tDay[1], tDay[2]) 599 fSunrise1 = get_one_value("sunrise", fLat, fLon, \ 600 tYesterday, fUTC, sSummerTime) 601 fSunset1 = get_one_value("sunset", fLat, fLon, \ 602 tYesterday, fUTC, sSummerTime) 603 fDay1 = fSunset1 - fSunrise1 604 fValue = (fDay2 - fDay1)*60 605 606 return fValue
607 608 609 ######################################################################## 610 # String methods 611
612 -def str_to_at_least_two_digits(nNumber):
613 """ 614 Take an int and return '01' instead of '1'. 615 616 @type nNumber: int 617 @param nNumber: Number to return with at least 2 digits. 618 619 @rtype: string 620 @return: a string with 2 digits. 621 """ 622 sRes ="%02d" % nNumber 623 return sRes
624 625
626 -def remove_extension(sFilename):
627 """ 628 Remove the extension of a string file. 629 Extension is defined as the letters after the right most '.' 630 631 @type sFilename: string 632 @param sFilename: The filename from which the extension must be removed. 633 634 @rtype: string 635 @return: A string with the filename without the extension. 636 """ 637 # Remove the extension 638 nIndice = sFilename.rfind('.') 639 if nIndice < 0: 640 sFilenameShort = sFilename 641 else: 642 sFilenameShort = sFilename[:sFilename.rfind('.')] 643 644 return sFilenameShort
645
646 -def save_info_flat_file(sFilename, lDateISO8601, \ 647 lSunrise1, lSunset1, lDaylength1, fLat1, fLon1, fUTC1,\ 648 sSummerTime1, lSunrise2=None, lSunset2=None, \ 649 lDaylength2=None, fLat2=None, \ 650 fLon2=None,fUTC2=None, sSummerTime2=None):
651 """ 652 Simply call L{get_sunrise_sunset_as_csv} and save it into a text file. 653 654 @type sFilename: string 655 @param sFilename: Filename for the text file to be written. 656 657 For other params, see L{get_sunrise_sunset_as_csv} 658 """ 659 660 lLines = get_sunrise_sunset_as_csv(lDateISO8601, lSunrise1, lSunset1,\ 661 lDaylength1,\ 662 fLat1, fLon1, fUTC1, sSummerTime1,\ 663 lSunrise2, lSunset2, lDaylength2, 664 fLat2, fLon2,\ 665 fUTC2, sSummerTime2) 666 667 # Use file or stdout 668 if sFilename is not None: 669 sFilenameFlatFile = remove_extension(sFilename) + '.txt' 670 file_txt = open(sFilenameFlatFile, 'w') 671 file_txt.writelines(x+'\n' for x in lLines) 672 file_txt.close() 673 print "filename", sFilenameFlatFile 674 else: 675 for i in range(len(lLines)): 676 printlLines[i].strip()
677 678 ########################################################################## 679 # CSV format 680
681 -def get_sunrise_sunset_as_csv(lDateISO8601, \ 682 lSunrise1, lSunset1, lDaylength1, fLat1, fLon1,\ 683 fUTC1, \ 684 sSummerTime1,\ 685 lSunrise2=None, lSunset2=None, lDaylength2=None,\ 686 fLat2=None, fLon2=None,\ 687 fUTC2=None, sSummerTime2=None):
688 """ 689 Returns a list containing the date, sunrise, sunset, daylength, 690 like the CSV file. 691 header (first element): year place1 lat1 lon1 UTC1 summer_time_code1 692 (optional) place2 lat2 lon2 UTC2 summer_time_code2 693 data: date, sunrise1, sunset1, (optional) sunrise2, sunset2 694 695 @type lDateISO8601: list 696 @param lDateISO8601: List of strings for one year in iso8601 format. 697 @type lSunrise1: list 698 @param lSunrise1: list containing the values of sunrise for the first place. 699 @type lSunset1: list 700 @param lSunset1: list containing the values of sunset for the first place. 701 @type lDaylength1: list 702 @param lDaylength1: list containing the values of daylight in 703 hours for the first place 704 @type fLat1: float 705 @param fLat1: latitude of the first place. Latitude is in decimal 706 degrees. Example: 30°30' should be 30.5 707 @type fLon1: float 708 @param fLon1: longitude of the first place. Longitude is in decimal 709 degrees. Example: 30°30' should be 30.5. West longitude are negative 710 East longitude are positive. 711 @type fUTC1: float 712 @param fUTC1: Time to add/substract for each time values for the first place. 713 Usually used for UTC value of place. 714 @type sSummerTime1: string 715 @param sSummerTime1: This variable is a 2 letters code indicating 716 when is the daylight saving time (DST) starting and ending in the year 717 for the first place. 718 Default is no DST. For a list of DST code, 719 see L{crepyscule_summer_time.lTimezone}. 720 @type lSunrise2: list 721 @param lSunrise2: list containing the values of sunrise for the first place. 722 @type lSunset2: list 723 @param lSunset2: list containing the values of sunset for the first place. 724 @type lDaylength2: list 725 @param lDaylength2: list containing the values of daylight in 726 hours for the second place 727 @type fLat2: float 728 @param fLat2: latitude of the second place. See fLat1. 729 @type fLon2: float 730 @param fLon2: longitude of the second place. See fLon1. 731 @type sSummerTime2: string 732 @param sSummerTime2: This variable is a 2 letters code indicating 733 when is the daylight saving time (DST) starting and ending in the year 734 for the seconde place. 735 Default is no DST. For a list of DST code, 736 see L{crepyscule_summer_time.lTimezone}. 737 @type fUTC2: float 738 @param fUTC2: Time to add/substract for each time values for the second 739 place. 740 741 @rtype: list 742 @return: A list containing the sunrise/sunset/length CSV values. 743 One line per element of list. 744 """ 745 lDateSunriseSunset = [] 746 # Write the header: "Date", "Sunrise for XX.xxN YY.yyW UTC code", 747 # "Sunset for XX.xxN YY.yyW UTC code" 748 sDate = "Date" 749 sSunriseHeader = string.join((_('"Sunrise for'), str(fLat1), str(fLon1), \ 750 str(fUTC1) , str(sSummerTime1) + '"')) 751 sSunsetHeader = string.join((_('"Sunset for'), str(fLat1), str(fLon1), \ 752 str(fUTC1), str(sSummerTime1) + '"')) 753 sDaylengthHeader = string.join((_('"Day length for'), str(fLat1), str(fLon1), \ 754 str(fUTC1), str(sSummerTime1) + '"')) 755 sHeader = string.join((sDate, sSunriseHeader, sSunsetHeader, \ 756 sDaylengthHeader), sep=',') 757 if lSunrise2 != None: 758 sSunriseHeader = string.join((_('"Sunrise for'), str(fLat2), str(fLon2), \ 759 str(fUTC2) , str(sSummerTime2) + '"')) 760 sSunsetHeader = string.join((_('"Sunset for'), str(fLat2), str(fLon2), \ 761 str(fUTC2), str(sSummerTime2) + '"')) 762 sDaylengthHeader = string.join((_('"Day length for'), str(fLat2), str(fLon2), \ 763 str(fUTC2), str(sSummerTime2) + '"')) 764 765 sHeader = string.join((sHeader, sSunriseHeader, sSunsetHeader,\ 766 sDaylengthHeader), sep=',') 767 768 lDateSunriseSunset.append(sHeader) 769 770 # Body 771 lListOfSunsetSunrise = [lSunrise1, lSunset1, lDaylength1] 772 if lSunrise2 != None: 773 lListOfSunsetSunrise = lListOfSunsetSunrise + \ 774 [lSunrise2, lSunset2, lDaylength2 ] 775 776 for i in range(len(lSunrise1)): 777 sDate = lDateISO8601[i][:10] 778 sLine = sDate 779 for lList in lListOfSunsetSunrise: 780 (nHour, nMinute, nSecond) = tranform_decimal_hour_in_minutes(\ 781 lList[i], 'minute') 782 sTime = str(nHour) + ':' + str(nMinute) 783 sLine = string.join((sLine, sTime), sep=',') 784 lDateSunriseSunset.append(sLine) 785 786 return lDateSunriseSunset
787
788 -def get_sun_altitude_as_csv(lDateISO8601, fLat1, lAltitude1,\ 789 fLat2=None, lAltitude2=None):
790 """ 791 Returns a list containing the date, sun altitude like the CSV file. 792 header (first element): year place1 lat1 place2 lat2 793 data: date, sun_altitude1 (optional), sun_altitude2 794 795 @type lDateISO8601: list 796 @param lDateISO8601: List of strings for one year in iso8601 format. 797 @type fLat1: float 798 @param fLat1: latitude of the first place. Latitude is in decimal 799 @type lAltitude1: list 800 @param lAltitude1: list containing the values of sun altitude 801 for the first place. 802 @type fLat2: float 803 @param fLat2: latitude of the second place. See fLat1. 804 @type lAltitude2: list 805 @param lAltitude2: list containing the values of sun altitude 806 for the second place. 807 808 @rtype: list 809 @return: A list containing the altitude values in the CSV format. 810 One line per element of list. 811 """ 812 813 lDateAltitude = [] 814 # Write the header: "Date", "Sun altitude for XX.xxN", 815 sDate = "Date" 816 sHeader = string.join((_('"Sun altitude for'), str(fLat1) + '"')) 817 sHeader = string.join((sDate, sHeader), sep=',') 818 if lAltitude2 != None: 819 sHeader2 = string.join((_('"Sun altitude for'), str(fLat2) + '"')) 820 sHeader = string.join((sHeader, sHeader2), sep=',') 821 822 lDateAltitude.append(sHeader) 823 824 # Body 825 if lAltitude2 != None: 826 lListOfAltitude = [lAltitude1, lAltitude2] 827 else: 828 lListOfAltitude = [lAltitude1] 829 830 for i in range(len(lAltitude1)): 831 sDate = lDateISO8601[i][:10] 832 sLine = sDate 833 for lList in lListOfAltitude: 834 sAltitude = str(round(lList[i],2)) 835 sLine = string.join((sLine, sAltitude), sep=',') 836 lDateAltitude.append(sLine) 837 838 return lDateAltitude
839
840 -def get_daylight_variation_as_csv(lDateISO8601, lDaylength1, fLat1, \ 841 lDaylength2=None, fLat2=None):
842 """ 843 Returns a list containing the date and the daylight variation in minutes. 844 header (first element): year place1 lat1 place2 lat2 845 846 847 @type lDateISO8601: list 848 @param lDateISO8601: List of strings for one year in iso8601 format. 849 @type lDaylength1: list 850 @param lDaylength1: list containing the values of daylight in 851 hours for the first place 852 @type fLat1: float 853 @param fLat1: latitude of the first place. Latitude is in decimal 854 @type lDaylength2: list 855 @param lDaylength2: list containing the values of daylight in 856 hours for the second place 857 @type fLat2: float 858 @param fLat2: latitude of the second place. See fLat1. 859 860 @rtype: list 861 @return: A list containing the daylight variation values in the CSV format. 862 One line per element of list. 863 """ 864 865 lDaylightVariation= [] 866 # Write the header: "Date", "Daily variation for XX.xxN", 867 sDate = "Date" 868 sHeader = string.join((_('"Daily variation of light for'), str(fLat1), '"')) 869 sHeader = string.join((sDate, sHeader), sep=',') 870 lVariation1 = get_daylight_variation(lDaylength1) 871 if lDaylength2 != None: 872 sHeader2 = string.join((_('"Daily variation of light for'), str(fLat2)\ 873 , '"')) 874 sHeader = string.join((sHeader, sHeader2), sep=',') 875 lVariation2 = get_daylight_variation(lDaylength2) 876 877 lDaylightVariation.append(sHeader) 878 879 # Body 880 if lDaylength2 != None: 881 lListOfVariation = [lVariation1, lVariation2] 882 else: 883 lListOfVariation = [lVariation1] 884 885 for i in range(len(lVariation1)): 886 sDate = lDateISO8601[i][:10] 887 sLine = sDate 888 for lList in lListOfVariation: 889 sVariation = str(round(lList[i],2)) 890 sLine = string.join((sLine, sVariation), sep=',') 891 lDaylightVariation.append(sLine) 892 893 return lDaylightVariation
894 895
896 -def get_solar_flux_as_csv(lDateISO8601, fLat1, lFlux1,\ 897 fLat2=None, lFlux2=None):
898 """ 899 Returns a list containing the date, maximal solar flux for each day. 900 header (first element): year place1 lat1 place2 lat2 901 data: date, max_solar_flux1 (optional), max_solar_flux2 902 903 @type lDateISO8601: list 904 @param lDateISO8601: List of strings for one year in iso8601 format. 905 @type fLat1: float 906 @param fLat1: latitude of the first place. Latitude is in decimal 907 @type lFlux1: list 908 @param lFlux1: list containing the values of maximal solar fluxes 909 for the first place. 910 @type fLat2: float 911 @param fLat2: latitude of the second place. See fLat1. 912 @type lFlux2: list 913 @param lFlux2: list containing the values of maximal solar fluxes 914 for the second place 915 916 @rtype: list 917 @return: A list containing the daily maximal solar fluxes in the CSV format. 918 One line per element of list. 919 """ 920 921 lDateFlux = [] 922 # Write the header: "Date", "Sun altitude for XX.xxN", 923 sDate = "Date" 924 sHeader = string.join((_('"Daily maximal solar flux for'), str(fLat1) + '"')) 925 sHeader = string.join((sDate, sHeader), sep=',') 926 if lFlux2 != None: 927 sHeader2 = string.join((_('"Daily maximal solar flux for'), str(fLat2) +\ 928 '"')) 929 sHeader = string.join((sHeader, sHeader2), sep=',') 930 931 lDateFlux.append(sHeader) 932 933 # Body 934 if lFlux2 != None: 935 lListOfFlux = [lFlux1, lFlux2] 936 else: 937 lListOfFlux = [lFlux1] 938 939 for i in range(len(lFlux1)): 940 sDate = lDateISO8601[i][:10] 941 sLine = sDate 942 for lList in lListOfFlux: 943 sFlux = str(round(lList[i],2)) 944 sLine = string.join((sLine, sFlux), sep=',') 945 lDateFlux.append(sLine) 946 947 return lDateFlux
948
949 -def get_twilight_length_as_csv(lDateISO8601, fLat1, lLength1,\ 950 fLat2=None, lLength2=None):
951 """ 952 Returns a list containing the date, twilight length in minute for each day. 953 header (first element): year place1 lat1 place2 lat2 954 data: date, twilight_length1, twilight_length2 (optional) 955 956 @type lDateISO8601: list 957 @param lDateISO8601: List of strings for one year in iso8601 format. 958 @type fLat1: float 959 @param fLat1: latitude of the first place. Latitude is in decimal 960 @type lLength1: list 961 @param lLength1: list containing the twilight length for the first place. 962 @type fLat2: float 963 @param fLat2: latitude of the second place. See fLat1. 964 @type lLength2: list 965 @param lLength2: list containing the twilitght for the second place 966 967 @rtype: list 968 @return: A list containing the twilight in the CSV format. 969 One line per element of list. 970 """ 971 972 lDateTwilightLength = [] 973 # Write the header: "Date", "Sun altitude for XX.xxN", 974 sDate = "Date" 975 sHeader = string.join((_('"Twilight length for'), str(fLat1) + '"')) 976 sHeader = string.join((sDate, sHeader), sep=',') 977 if lLength2 != None: 978 sHeader2 = string.join((_('"Twilight length for'), str(fLat2) +\ 979 '"')) 980 sHeader = string.join((sHeader, sHeader2), sep=',') 981 982 lDateTwilightLength.append(sHeader) 983 984 # Body 985 if lLength2 != None: 986 lListOfLength = [lLength1, lLength2] 987 else: 988 lListOfLength = [lLength1] 989 990 for i in range(len(lLength1)): 991 sDate = lDateISO8601[i][:10] 992 sLine = sDate 993 for lList in lListOfLength: 994 sLength = str(round(lList[i],4)) 995 sLine = string.join((sLine, sLength), sep=',') 996 lDateTwilightLength.append(sLine) 997 998 return lDateTwilightLength
999 1000 1001
1002 -def get_max_solar_flux(ctime, fLat):
1003 """ 1004 Get the maximum solar flux value for this day. 1005 1006 @type ctime: float 1007 @param ctime: Any ctime in the year of the result. 1008 @type fLat: float 1009 @param fLat: Latitude in decimal for the place. 1010 1011 @rtype: float 1012 @return: Maximum solar flux for this day in float. Solar flux is in 1013 watt per meter square. 1014 """ 1015 1016 cSun = Sun.Sun() 1017 1018 (nYear, nMonth, nDay, nHour, nMinute, nSecond, nWeekDay, nJulian, bDst) = \ 1019 time.gmtime(ctime) 1020 1021 fFlux = cSun.get_max_solar_flux(fLat, nYear, nMonth, nDay) 1022 1023 return fFlux
1024
1025 -def get_daylength(ctime, fLat, fLon):
1026 """ 1027 Get the daylength for all the year corresponding to this ctime. 1028 1029 @type ctime: float 1030 @param ctime: ctime value 1031 @type fLat: float 1032 @param fLat: Latitude in decimal for the place. 1033 @type fLon: float 1034 @param fLon: longitude of the first place. Longitude is in decimal 1035 degrees. Example: 30°30' should be 30.5. West longitude are negative 1036 1037 @rtype: list 1038 @return: List of daylength, in hour 1039 """ 1040 lDaylength = [] 1041 cSun = Sun.Sun() 1042 1043 lMonth = range(1,13) 1044 tToday = time.gmtime(ctime) 1045 nYear = tToday[0] 1046 1047 for nMonth in lMonth: 1048 # Get a list of the number of days in each month 1049 lrange = calendar.monthrange(nYear, nMonth) 1050 lDay = range(1,lrange[1]+1) 1051 for nDay in lDay: 1052 fDaylength = cSun.dayLength(nYear, nMonth, nDay, fLon, fLat) 1053 lDaylength.append(fDaylength) 1054 1055 return lDaylength
1056
1057 -def get_daylength_day(ctime, fLat, fLon):
1058 """ 1059 Get the daylength for the day corresponding to this ctime. 1060 1061 @type ctime: float 1062 @param ctime: ctime value 1063 @type fLat: float 1064 @param fLat: Latitude in decimal for the place. 1065 @type fLon: float 1066 @param fLon: longitude of the first place. Longitude is in decimal 1067 degrees. Example: 30°30' should be 30.5. West longitude are negative 1068 1069 @rtype: float 1070 @return: Daylength, in hour 1071 """ 1072 cSun = Sun.Sun() 1073 1074 tToday = time.gmtime(ctime) 1075 nYear = tToday[0] 1076 nMonth = tToday[1] 1077 nDay = tToday[2] 1078 fDaylength = cSun.dayLength(nYear, nMonth, nDay, fLon, fLat) 1079 1080 return fDaylength
1081 1082
1083 -def get_twilight_length(nYear, nMonth, nDay, fLat):
1084 """ 1085 Get the twilight length in minute for this day and latitude. 1086 1087 @type nYear: int 1088 @param nYear: year for this date 1089 @type nMonth: int 1090 @param nMonth: month for this date 1091 @type nDay: int 1092 @param nDay: day for this date 1093 1094 @rtype: float 1095 @return: Twilight length, in minute 1096 """ 1097 cSun = Sun.Sun() 1098 1099 fStandardDaylength = cSun.dayLength(nYear, nMonth, nDay, 0.0, fLat) 1100 fDaylengthWithTwilight = cSun.dayNauticalTwilightLength\ 1101 (nYear, nMonth, nDay, 0.0, fLat) 1102 1103 # *30 is there because twilight is morning and night (/2) and that 1104 # we want the result in minutes (*60). 60/2=30 1105 fTwilightLength = (fDaylengthWithTwilight - fStandardDaylength)*30 1106 1107 return fTwilightLength
1108 1109
1110 -def get_twilight_length_day(ctime, fLat):
1111 """ 1112 Get the twilight length in minute for this day and latitude. 1113 1114 @type ctime: float 1115 @param ctime: ctime value 1116 @type fLat: float 1117 @param fLat: Latitude in decimal for the place. 1118 1119 @rtype: float 1120 @return: Twilight length, in minute 1121 """ 1122 cSun = Sun.Sun() 1123 tToday = time.gmtime(ctime) 1124 1125 nYear = tToday[0] 1126 nMonth = tToday[1] 1127 nDay = tToday[2] 1128 1129 fTwilightLength = get_twilight_length(nYear, nMonth, nDay, fLat) 1130 1131 return fTwilightLength
1132 1133
1134 -def get_twilight_length_year(ctime, fLat):
1135 """ 1136 Get the twilight length in minute for the year of this day and latitude. 1137 1138 @type ctime: float 1139 @param ctime: ctime value 1140 @type fLat: float 1141 @param fLat: Latitude in decimal for the place. 1142 1143 @rtype: list 1144 @return: list containing the twilight length in minute 1145 """ 1146 lTwilightLength = [] 1147 lMonth = range(1,13) 1148 tToday = time.gmtime(ctime) 1149 nYear = tToday[0] 1150 1151 for nMonth in lMonth: 1152 # Get a list of the number of days in each month 1153 lrange = calendar.monthrange(nYear, nMonth) 1154 lDay = range(1,lrange[1]+1) 1155 for nDay in lDay: 1156 fTwilightLength = get_twilight_length(nYear, nMonth, nDay, fLat) 1157 lTwilightLength.append(fTwilightLength) 1158 1159 return lTwilightLength
1160