Changeset 2463 in lmdz_wrf for trunk/tools
- Timestamp:
- Apr 23, 2019, 8:56:35 PM (7 years ago)
- File:
-
- 1 edited
-
trunk/tools/generic_tools.py (modified) (18 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/tools/generic_tools.py
r2462 r2463 118 118 # files_folder_HMT: Function to retrieve a list of files from a folder [fold] and files with [head]*[middle]*[tail] 119 119 # fill_Narray: Function to fill a n-dimensional array with an arrary of lesser rank 120 # fix_CFdates: Fixing CF-time values with wrong setting 121 # gen_impose_gregorian: Function to impose gregorian calendar to a series of times with a 122 # non-standard calendar independently from datetime (imposes yr > 1900) 120 123 # gen_leapdays: Function to provide how many leap days are between two years avoiding datetime 121 124 # generate_CFtimes: Function to generate CFtimes for a given period, frequency and units … … 519 522 return combos 520 523 524 def sign(number): 525 """ Function to provide the sign of a number 526 num: number to provide the sign 527 >>> sign(7109) 528 1 529 >>> sign(-3.43512) 530 -1.0 531 """ 532 fname = 'sign' 533 534 sign = np.abs(number)/number 535 536 return sign 537 538 ## 539 #### 540 ###### 541 ####### Temporal functions ####### 542 ##### 543 ### 544 # 521 545 def days_month(year,month): 522 546 """ Function to give the number of days of a month of a given year … … 592 616 593 617 return Nleapdays 618 619 def juliandate(yr,mo,dd,hr,mi,ss): 620 """ Function to provide the julian date (in days since -4712 January 1st 00 UTC) 621 for any greogiran date 622 refdate: 1 January 4713 BC (= -4712 January 1), Greenwich mean noon (= 12h UT). 623 FROM: https://aa.usno.navy.mil/faq/docs/JD_Formula.php 624 after 1990 edition of the U.S. Naval Observatory's Almanac for Computers 625 >>> juliandate(1877,8,11,7,30,0) 626 2406843.3125 627 >>> juliandate(877,8,11,7,30,0) 628 2041601.3125 629 >>> juliandate(1970,1,1,0,0,0) 630 2440588.0 631 >>> juliandate(1978,1,1,0,0,0) 632 2443510.0 633 >>> juliandate(1978,7,21,15,0,0) 634 2443712.625 635 >>> juliandate(2000,1,1,0,0,0) 636 2451545.0 637 """ 638 fname = 'juliandate' 639 640 sec1 = dd - 32075. 641 sec2 = 1461.*(yr+4800.+(mo-14)/12.)/4. 642 sec3 = 367.*(mo-2-(mo-14)/12.*12)/12. 643 sec4 = 3.*((yr+4900.+(mo-14.)/12.)/100.)/4. 644 645 juliand = int(sec1 + sec2 + sec3 - sec4) 646 647 juliand = juliand*1. + (hr + mi/60. + ss/3600.)/24. 648 649 # Alternative (without full agreement, just kept in case) 650 #K = yr + 0 651 #M = mo + 0 652 #I = dd + 0 653 #UT = hr*1. + mi/60. + ss/3600. 654 655 #sec1 = 367.*K 656 #sec2 = int((7.*(K+int((M+9)/12.)))/4.) 657 #sec3 = int((275.*M)/9.) 658 #sec4 = I*1. 659 #sec5 = 1721013.5 660 #sec6 = UT/24. 661 #sec7 = 0.5*sign(100.*K+M*1.-190002.5) 662 #sec8 = 0.5 663 664 #juliand = sec1 - sec2 + sec3 + sec4 + sec5 + sec6 - sec7 + sec8 665 #print ' juliand:', juliand 666 667 return juliand 668 669 def juliandate_gregorian(juliand): 670 """ Function to convert from julian date (days since -4712 January 1st 00 UTC) 671 to the equivalent greogiran date 672 juliand: julian date to convert 673 FROM: https://aa.usno.navy.mil/faq/docs/JD_Formula.php 674 after 1990 edition of the U.S. Naval Observatory's Almanac for Computers 675 >>> juliandate_gregorian(2406843.3125) 676 [1877, 8.0, 11, 7, 30, 0.0] 677 >>> juliandate_gregorian(2041601.3125) 678 [877, 8.0, 11, 7, 30, 0.0] 679 >>> juliandate_gregorian(2440588.0) 680 [1970, 1.0, 1, 0, 0, 0.0] 681 >>> juliandate_gregorian(2443510.0) 682 [1978, 1.0, 1, 0, 0, 0.0] 683 >>> juliandate_gregorian(2443712.625) 684 [1978, 7.0, 22, 15, 0, 0.0] 685 """ 686 fname = 'juliandate_gregorian' 687 688 L = int(juliand+68569) 689 N = 4*L/146097 690 L = L-(146097*N+3)/4 691 I = 4000*(L+1)/1461001 692 L = L-1461*I/4+31 693 J = 80*L/2447 694 K = L-2447*J/80 695 L = J/11 696 J = J+2.-12.*L 697 I = 100*(N-49)+I+L 698 699 yr = I 700 mo = J 701 dd = K 702 703 # hr, mi, ss 704 ut = juliand - int(juliand) 705 utsecs = ut*24.*3600. 706 hh = int(utsecs/3600.) 707 mi = int((utsecs - hh*3600.)/60.) 708 ss = utsecs - hh*3600. - mi*60. 709 710 return [yr, mo, dd, hh, mi, ss] 594 711 595 712 def datetimeStr_datetime(StringDT): … … 1957 2074 Tunits: CF units of time [Tunits] since [DateRef] 1958 2075 cal: non standard calendar 1959 >>> impose_gregorian(np. range(800,10000,100), 'days since 1949-12-01 00:00:00',2076 >>> impose_gregorian(np.arange(800,10000,100), 'days since 1949-12-01 00:00:00', 1960 2077 'noleap') 1961 2078 [ 800. 901.] … … 2058 2175 Tunits: CF units of time [Tunits] since [DateRef] 2059 2176 cal: non standard calendar 2060 >>> gen_impose_gregorian(np. range(800,10000,100), 'days since 1850-01-01 00:00:00',2177 >>> gen_impose_gregorian(np.arange(800,1000,100), 'days since 1850-01-01 00:00:00', 2061 2178 'noleap') 2062 [ 80 0. 901.]2179 [ 801. 901.] 2063 2180 >>> gen_impose_gregorian(-7277.460938, 'days since 1949-12-01 00:00:00', 'noleap') 2064 2181 [-7272.460938] … … 2080 2197 Srefdate = lTunits[2] + ' ' + lTunits[3] 2081 2198 refdate = [int(Srefdate[0:4]), int(Srefdate[5:7]), int(Srefdate[8:10]), \ 2082 int(Srefdate[11:13]), int(Srefdate[14 ,16]), int(Srefdate[17:19]) ]2199 int(Srefdate[11:13]), int(Srefdate[14:16]), int(Srefdate[17:19]) ] 2083 2200 2084 2201 if type(timev) == type(range(2)): … … 2101 2218 2102 2219 if Tu == 'weeks': 2103 timev secs = timev * 24. * 7 * 3600.2220 timevdays = timev * 7 2104 2221 elif Tu == 'days': 2105 timev secs = timev * 24. * 3600.2222 timevdays = timev * 1. 2106 2223 elif Tu == 'hours': 2107 timev secs = timev * 3600.2224 timevdays = timev / 24. 2108 2225 elif Tu == 'minutes': 2109 timev secs = timev * 60.2226 timevdays = timev / (24.*60.) 2110 2227 elif Tu == 'seconds': 2111 timev secs = timev * 1.2228 timevdays = timev / (24.*3600.) 2112 2229 else: 2113 2230 print errormsg … … 2118 2235 newtimes = np.zeros((dimt), dtype=np.float64) 2119 2236 2120 refsecs = juliandate(refdate[0], refdate[1], refdate[2], refdate[3], refdate[4], refdate[5]) 2121 refsecs = refsecs*3600. 2237 refdays = juliandate(refdate[0], refdate[1], refdate[2], refdate[3], refdate[4], refdate[5]) 2122 2238 2123 2239 yrref = refdate[0] 2124 2240 if cal == 'noleap' or cal == '365d': 2125 2241 for it in range(dimt): 2126 # Some issues in implementations/machines ... 2127 # FROM: https://stackoverflow.com/questions/33566939/timedelta-error-with-numpy-longdouble-dtype 2128 tv = int(timevsecs[it]) 2129 deltaT = dt.timedelta(seconds=tv) 2130 datetime = refdate + deltaT 2131 yr = datetime.year 2242 tdays = refdays + timevdays[it] 2243 gdatev = juliandate_gregorian(tdays) 2244 2245 yr = gdatev[0] 2246 mon = gdatev[1] 2132 2247 if yr > yrref: 2133 Nleapd = leapdays(yrref, yr)2248 Nleapd = gen_leapdays(yrref, yr) 2134 2249 else: 2135 Nleapd = leapdays(yr, yrref) 2136 if datetime.month <= 2 and days_month(yr, 2) > 28: Nleapd = Nleapd - 1 2137 newtimes[it] = timevsecs[it] + Nleapd*24*3600. 2250 Nleapd = gen_leapdays(yr, yrref) 2251 if mon <= 2 and leapyr(yr): Nleapd = Nleapd - 1 2252 2253 newtimes[it] = timevdays[it] + Nleapd 2138 2254 else: 2139 2255 print errormsg … … 2144 2260 # Re-transforming to the original units 2145 2261 if Tu == 'weeks': 2146 newtimes = newtimes/( 24.*7*3600.)2262 newtimes = newtimes/(7.) 2147 2263 elif Tu == 'days': 2148 newtimes = newtimes /(24.*3600.)2264 newtimes = newtimes*1. 2149 2265 elif Tu == 'hours': 2150 newtimes = newtimes /(3600.)2266 newtimes = newtimes*60. 2151 2267 elif Tu == 'minutes': 2152 newtimes = newtimes /(60.)2268 newtimes = newtimes*24.*3600. 2153 2269 2154 2270 return newtimes … … 15954 16070 # print ' ' , '(', inds[i,j,0], ',', inds[i,j,1], ')' 15955 16071 15956 def sign(number): 15957 """ Function to provide the sign of a number 15958 num: number to provide the sign 15959 >>> sign(7109) 15960 1 15961 >>> sign(-3.43512) 15962 -1.0 15963 """ 15964 fname = 'sign' 15965 15966 sign = np.abs(number)/number 15967 15968 return sign 15969 15970 def juliandate(yr,mo,dd,hr,mi,ss): 15971 """ Function to provide the julian date (in days since -4712 January 1st 00 UTC) 15972 for any greogiran date 15973 refdate: 1 January 4713 BC (= -4712 January 1), Greenwich mean noon (= 12h UT). 15974 FROM: https://aa.usno.navy.mil/faq/docs/JD_Formula.php 15975 after 1990 edition of the U.S. Naval Observatory's Almanac for Computers 15976 >>> juliandate(1877,8,11,7,30,0) 15977 2406843.3125 15978 >>> juliandate(877,8,11,7,30,0) 15979 2041601.3125 15980 >>> juliandate(1970,1,1,0,0,0) 15981 2440588.0 15982 >>> juliandate(1978,1,1,0,0,0) 15983 2443510.0 15984 >>> juliandate(1978,7,21,15,0,0) 15985 2443712.625 15986 """ 15987 fname = 'juliandate' 15988 15989 sec1 = dd - 32075. 15990 sec2 = 1461.*(yr+4800.+(mo-14)/12.)/4. 15991 sec3 = 367.*(mo-2-(mo-14)/12.*12)/12. 15992 sec4 = 3.*((yr+4900.+(mo-14.)/12.)/100.)/4. 15993 15994 juliand = int(sec1 + sec2 + sec3 - sec4) 15995 15996 juliand = juliand*1. + (hr + mi/60. + ss/3600.)/24. 15997 15998 # Alternative (without full agreement, just kept in case) 15999 #K = yr + 0 16000 #M = mo + 0 16001 #I = dd + 0 16002 #UT = hr*1. + mi/60. + ss/3600. 16003 16004 #sec1 = 367.*K 16005 #sec2 = int((7.*(K+int((M+9)/12.)))/4.) 16006 #sec3 = int((275.*M)/9.) 16007 #sec4 = I*1. 16008 #sec5 = 1721013.5 16009 #sec6 = UT/24. 16010 #sec7 = 0.5*sign(100.*K+M*1.-190002.5) 16011 #sec8 = 0.5 16012 16013 #juliand = sec1 - sec2 + sec3 + sec4 + sec5 + sec6 - sec7 + sec8 16014 #print ' juliand:', juliand 16015 16016 return juliand 16017 16018 def juliandate_gregorian(juliand): 16019 """ Function to convert from julian date (days since -4712 January 1st 00 UTC) 16020 to the equivalent greogiran date 16021 juliand: julian date to convert 16022 FROM: https://aa.usno.navy.mil/faq/docs/JD_Formula.php 16023 after 1990 edition of the U.S. Naval Observatory's Almanac for Computers 16024 >>> juliandate_gregorian(2406843.3125) 16025 [1877, 8.0, 11, 7, 30, 0.0] 16026 >>> juliandate_gregorian(2041601.3125) 16027 [877, 8.0, 11, 7, 30, 0.0] 16028 >>> juliandate_gregorian(2440588.0) 16029 [1970, 1.0, 1, 0, 0, 0.0] 16030 >>> juliandate_gregorian(2443510.0) 16031 [1978, 1.0, 1, 0, 0, 0.0] 16032 >>> juliandate_gregorian(2443712.625) 16033 [1978, 7.0, 22, 15, 0, 0.0] 16034 """ 16035 fname = 'juliandate_gregorian' 16036 16037 L = int(juliand+68569) 16038 N = 4*L/146097 16039 L = L-(146097*N+3)/4 16040 I = 4000*(L+1)/1461001 16041 L = L-1461*I/4+31 16042 J = 80*L/2447 16043 K = L-2447*J/80 16044 L = J/11 16045 J = J+2.-12.*L 16046 I = 100*(N-49)+I+L 16047 16048 yr = I 16049 mo = J 16050 dd = K 16051 16052 # hr, mi, ss 16053 ut = juliand - int(juliand) 16054 utsecs = ut*24.*3600. 16055 hh = int(utsecs/3600.) 16056 mi = int((utsecs - hh*3600.)/60.) 16057 ss = utsecs - hh*3600. - mi*60. 16058 16059 return [yr, mo, dd, hh, mi, ss] 16072 #print juliandate_gregorian(2453408.5) 16073 #print juliandate_gregorian(2453683.5) 16074 16075 #quit() 16060 16076 16061 16077 def fix_CFdates(timevals, origcftimeu, origcal, \ … … 16070 16086 >>> fix_CFdates(times, 'days since 1850-01-01 00:00:00', 'noleap', 16071 16087 'days since 1949-12-01 00:00:00') 16072 [-36477.5 -36448. -36418.5 -36388. -36357.5 -36327. -36296.5 -36265.5 16073 -36235. -36204.5 -36174. ] 16088 [-36478.5 -36449. -36419.5 -36389. -36358.5 -36328. -36297.5 -36266.5 16089 -36236. -36205.5 -36175. ] 16090 >>> times = [56649.5, 56680, 56710.5, 56741, 56771.5, 56802.5, 56833, 56863.5, 56894, 56924.5] 16091 >>> fix_CFdates(times, 'days since 1850-01-01 00:00:00', 'noleap', 16092 'days since 1949-12-01 00:00:00') 16093 [ 20193.5 20224. 20254.5 20285. 20315.5 20346.5 20377. 20407.5 16094 20438. 20468.5] 16074 16095 """ 16075 16096 import datetime as dt … … 16085 16106 origSrefdate = origtv[2] 16086 16107 16087 yrref =origSrefdate[0:4]16088 monref =origSrefdate[5:7]16089 dayref =origSrefdate[8:10]16108 yrref = int(origSrefdate[0:4]) 16109 monref = int(origSrefdate[5:7]) 16110 dayref = int(origSrefdate[8:10]) 16090 16111 16091 16112 if int(yrref) < 1970: origsing = -1. … … 16110 16131 secref = 0 16111 16132 16112 seconds = juliandate(yrref,monref,dayref,horref,minref,secref) 16113 seconds = seconds*24.*3600. 16133 origdays = juliandate(yrref,monref,dayref,horref,minref,secref) 16114 16134 16115 16135 # new … … 16118 16138 newSrefdate = newtv[2] 16119 16139 16120 yrnew =newSrefdate[0:4]16121 monnew =newSrefdate[5:7]16122 daynew =newSrefdate[8:10]16140 yrnew = int(newSrefdate[0:4]) 16141 monnew = int(newSrefdate[5:7]) 16142 daynew = int(newSrefdate[8:10]) 16123 16143 16124 16144 if int(yrnew) < 1970: newsing = -1. … … 16143 16163 secnew = 0 16144 16164 16145 seconds = juliandate(yrnew,monnew,daynew,hornew,minnew,secnew)16165 newdays = juliandate(yrnew,monnew,daynew,hornew,minnew,secnew) 16146 16166 16147 16167 # Using shell date `coreutil' (a relic of the past...) … … 16150 16170 #newsecondsdiff = np.float64(seconds.communicate()[0].replace('\n','')) 16151 16171 16152 # If the calendar is not gregorian, it needs to be fixed from origSrefdate!16153 if origcal == 'noleap' or origcal == '365d':16154 print ' ' + fname + ": found non-standard calendar '" + origcal + "' !!"16155 # Imposing to gregorian calendar16156 newtimevals = gen_impose_gregorian(timevals, origcftimeu, origcal)16157 16158 # Seconds difference respect new date16159 secsdiff = origsecondsdiff - newsecondsdiff16160 16161 16172 if origtunits == 'years': 16162 secsdtr = 365 * 24 * 3600.16173 daysdtr = 365. 16163 16174 elif origtunits == 'weeks': 16164 secsdtr = 7 * 24 * 3600.16175 daysdtr = 7. 16165 16176 elif origtunits == 'days': 16166 secsdtr = 24 * 3600.16177 daysdtr = 1. 16167 16178 elif origtunits == 'hours': 16168 secsdtr = 3600.16179 daysdtr = 1./24. 16169 16180 elif origtunits == 'minutes': 16170 secsdtr = 60.16181 daysdtr = 1./(24.*60.) 16171 16182 elif origtunits == 'seconds': 16172 secsdtr = 1.16183 daysdtr = 1./(24.*3600.) 16173 16184 else: 16174 16185 print errormsg … … 16177 16188 quit(-1) 16178 16189 16190 # If the calendar is not gregorian, it needs to be fixed from origSrefdate! 16191 if origcal == 'noleap' or origcal == '365d': 16192 print ' ' + fname + ": found non-standard calendar '" + origcal + "' !!" 16193 # Imposing to gregorian calendar 16194 timevals = gen_impose_gregorian(timevals, origcftimeu, origcal) 16195 16196 # Seconds difference respect new date 16197 daysdiff = origdays - newdays 16198 16179 16199 if type(timevals) != type(np.ones((2), dtype=int)): 16180 16200 newtimevals = np.array(timevals, dtype=np.float64) 16181 newtimevals = newtimevals* secsdtr16201 newtimevals = newtimevals*daysdtr 16182 16202 else: 16183 newtimevals = timevals*secsdtr 16184 16185 newtimevals = newtimevals + origsecondsdiff 16186 newtimevals = newtimevals - newsecondsdiff 16203 newtimevals = timevals*daysdtr 16204 16205 # Re-scaling to the absolute reference 16206 newtimevals = newtimevals + origdays 16207 16208 # Re-scaling to the CF-time reference 16209 newtimevals = newtimevals - newdays 16187 16210 16188 16211 # Re-scaling to the new time units 16189 16212 if newtunits == 'years': 16190 secsdtr = 365 * 24 * 3600.16213 daysdtr = 1. / (365.) 16191 16214 elif newtunits == 'weeks': 16192 secsdtr = 7 * 24 * 3600.16215 daysdtr = 1. / 7. 16193 16216 elif newtunits == 'days': 16194 secsdtr = 24 * 3600.16217 daysdtr = 1. 16195 16218 elif newtunits == 'hours': 16196 secsdtr = 3600.16219 daysdtr = 24. 16197 16220 elif newtunits == 'minutes': 16198 secsdtr =60.16221 daysdtr = 24. * 60. 16199 16222 elif newtunits == 'seconds': 16200 secsdtr = 1.16223 daysdtr = 24. * 3600. 16201 16224 else: 16202 16225 print errormsg … … 16204 16227 print ' available ones: ', availtu 16205 16228 quit(-1) 16206 newtimevals = newtimevals / secsdtr16229 newtimevals = newtimevals * daysdtr 16207 16230 16208 16231 return newtimevals 16209 16232 16210 16233 #times = [15.5, 45, 74.5, 105, 135.5, 166, 196.5, 227.5, 258, 288.5, 319] 16211 #times = [56649.5, 56680, 56710.5, 56741, 56771.5, 56802.5, 56833, 56863.5, 56894, 56924.5]16212 #print fix_CFdates(times, 'days since 1850-01-01 00:00:00', 'noleap', \16213 #'days since 1949-12-01 00:00:00')16234 times = [56649.5, 56680, 56710.5, 56741, 56771.5, 56802.5, 56833, 56863.5, 56894, 56924.5] 16235 print fix_CFdates(times, 'days since 1850-01-01 00:00:00', 'noleap', \ 16236 'days since 1949-12-01 00:00:00') 16214 16237 16215 16238 #quit()
Note: See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/LMDZ_WRF/chrome/site/your_project_logo.png)