Conditions | 7 |
Total Lines | 100 |
Code Lines | 44 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
1 | # -*- coding: utf-8 -*- |
||
131 | def subsol(datetime): |
||
132 | """Finds subsolar geocentric latitude and longitude. |
||
133 | |||
134 | Parameters |
||
135 | ---------- |
||
136 | datetime : :class:`datetime.datetime` or :class:`numpy.ndarray[datetime64]` |
||
137 | Date and time in UTC (naive objects are treated as UTC) |
||
138 | |||
139 | Returns |
||
140 | ------- |
||
141 | sbsllat : float |
||
142 | Latitude of subsolar point |
||
143 | sbsllon : float |
||
144 | Longitude of subsolar point |
||
145 | |||
146 | Notes |
||
147 | ----- |
||
148 | Based on formulas in Astronomical Almanac for the year 1996, p. C24. |
||
149 | (U.S. Government Printing Office, 1994). Usable for years 1601-2100, |
||
150 | inclusive. According to the Almanac, results are good to at least 0.01 |
||
151 | degree latitude and 0.025 degrees longitude between years 1950 and 2050. |
||
152 | Accuracy for other years has not been tested. Every day is assumed to have |
||
153 | exactly 86400 seconds; thus leap seconds that sometimes occur on December |
||
154 | 31 are ignored (their effect is below the accuracy threshold of the |
||
155 | algorithm). |
||
156 | |||
157 | After Fortran code by A. D. Richmond, NCAR. Translated from IDL |
||
158 | by K. Laundal. |
||
159 | |||
160 | """ |
||
161 | # Convert to year, day of year and seconds since midnight |
||
162 | if isinstance(datetime, dt.datetime): |
||
163 | year = np.asanyarray([datetime.year]) |
||
164 | doy = np.asanyarray([datetime.timetuple().tm_yday]) |
||
165 | ut = np.asanyarray([datetime.hour * 3600 + datetime.minute * 60 |
||
166 | + datetime.second]) |
||
167 | elif isinstance(datetime, np.ndarray): |
||
168 | # This conversion works for datetime of wrong precision or unit epoch |
||
169 | times = datetime.astype('datetime64[s]') |
||
170 | year_floor = times.astype('datetime64[Y]') |
||
171 | day_floor = times.astype('datetime64[D]') |
||
172 | year = year_floor.astype(int) + 1970 |
||
173 | doy = (day_floor - year_floor).astype(int) + 1 |
||
174 | ut = (times.astype('datetime64[s]') - day_floor).astype(float) |
||
175 | else: |
||
176 | raise ValueError("input must be datetime.datetime or numpy array") |
||
177 | |||
178 | if not (np.all(1601 <= year) and np.all(year <= 2100)): |
||
179 | raise ValueError('Year must be in [1601, 2100]') |
||
180 | |||
181 | yr = year - 2000 |
||
182 | |||
183 | nleap = np.floor((year - 1601.0) / 4.0).astype(int) |
||
184 | nleap -= 99 |
||
185 | mask_1900 = year <= 1900 |
||
186 | if np.any(mask_1900): |
||
187 | ncent = np.floor((year[mask_1900] - 1601.0) / 100.0).astype(int) |
||
188 | ncent = 3 - ncent |
||
189 | nleap[mask_1900] = nleap[mask_1900] + ncent |
||
190 | |||
191 | l0 = -79.549 + (-0.238699 * (yr - 4.0 * nleap) + 3.08514e-2 * nleap) |
||
192 | g0 = -2.472 + (-0.2558905 * (yr - 4.0 * nleap) - 3.79617e-2 * nleap) |
||
193 | |||
194 | # Days (including fraction) since 12 UT on January 1 of IYR: |
||
195 | df = (ut / 86400.0 - 1.5) + doy |
||
196 | |||
197 | # Mean longitude of Sun: |
||
198 | lmean = l0 + 0.9856474 * df |
||
199 | |||
200 | # Mean anomaly in radians: |
||
201 | grad = np.radians(g0 + 0.9856003 * df) |
||
202 | |||
203 | # Ecliptic longitude: |
||
204 | lmrad = np.radians(lmean + 1.915 * np.sin(grad) |
||
205 | + 0.020 * np.sin(2.0 * grad)) |
||
206 | sinlm = np.sin(lmrad) |
||
207 | |||
208 | # Obliquity of ecliptic in radians: |
||
209 | epsrad = np.radians(23.439 - 4e-7 * (df + 365 * yr + nleap)) |
||
210 | |||
211 | # Right ascension: |
||
212 | alpha = np.degrees(np.arctan2(np.cos(epsrad) * sinlm, np.cos(lmrad))) |
||
213 | |||
214 | # Declination, which is also the subsolar latitude: |
||
215 | sslat = np.degrees(np.arcsin(np.sin(epsrad) * sinlm)) |
||
216 | |||
217 | # Equation of time (degrees): |
||
218 | etdeg = lmean - alpha |
||
219 | nrot = np.round(etdeg / 360.0) |
||
220 | etdeg = etdeg - 360.0 * nrot |
||
221 | |||
222 | # Subsolar longitude calculation. Earth rotates one degree every 240 s. |
||
223 | sslon = 180.0 - (ut / 240.0 + etdeg) |
||
224 | nrot = np.round(sslon / 360.0) |
||
225 | sslon = sslon - 360.0 * nrot |
||
226 | |||
227 | # Return a single value from the output if the input was a single value |
||
228 | if isinstance(datetime, dt.datetime): |
||
229 | return sslat[0], sslon[0] |
||
230 | return sslat, sslon |
||
231 |