Conditions | 7 |
Total Lines | 101 |
Code Lines | 45 |
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 -*- |
||
158 | def subsol(datetime): |
||
159 | """Finds subsolar geocentric latitude and longitude. |
||
160 | |||
161 | Parameters |
||
162 | ---------- |
||
163 | datetime : :class:`datetime.datetime` or :class:`numpy.ndarray[datetime64]` |
||
164 | Date and time in UTC (naive objects are treated as UTC) |
||
165 | |||
166 | Returns |
||
167 | ------- |
||
168 | sbsllat : float |
||
169 | Latitude of subsolar point |
||
170 | sbsllon : float |
||
171 | Longitude of subsolar point |
||
172 | |||
173 | Notes |
||
174 | ----- |
||
175 | Based on formulas in Astronomical Almanac for the year 1996, p. C24. |
||
176 | (U.S. Government Printing Office, 1994). Usable for years 1601-2100, |
||
177 | inclusive. According to the Almanac, results are good to at least 0.01 |
||
178 | degree latitude and 0.025 degrees longitude between years 1950 and 2050. |
||
179 | Accuracy for other years has not been tested. Every day is assumed to have |
||
180 | exactly 86400 seconds; thus leap seconds that sometimes occur on December |
||
181 | 31 are ignored (their effect is below the accuracy threshold of the |
||
182 | algorithm). |
||
183 | |||
184 | After Fortran code by A. D. Richmond, NCAR. Translated from IDL |
||
185 | by K. Laundal. |
||
186 | |||
187 | """ |
||
188 | # Convert to year, day of year and seconds since midnight |
||
189 | if isinstance(datetime, dt.datetime): |
||
190 | year = np.asanyarray([datetime.year]) |
||
191 | doy = np.asanyarray([datetime.timetuple().tm_yday]) |
||
192 | ut = np.asanyarray([datetime.hour * 3600 + datetime.minute * 60 |
||
193 | + datetime.second + datetime.microsecond / 1.0e6]) |
||
194 | elif isinstance(datetime, np.ndarray): |
||
195 | # This conversion works for datetime of wrong precision or unit epoch |
||
196 | times = datetime.astype('datetime64[us]') |
||
197 | year_floor = times.astype('datetime64[Y]') |
||
198 | day_floor = times.astype('datetime64[D]') |
||
199 | year = year_floor.astype(int) + 1970 |
||
200 | doy = (day_floor - year_floor).astype(int) + 1 |
||
201 | ut = (times.astype('datetime64[us]') - day_floor).astype(float) |
||
202 | ut /= 1e6 |
||
203 | else: |
||
204 | raise ValueError("input must be datetime.datetime or numpy array") |
||
205 | |||
206 | if not (np.all(1601 <= year) and np.all(year <= 2100)): |
||
207 | raise ValueError('Year must be in [1601, 2100]') |
||
208 | |||
209 | yr = year - 2000 |
||
210 | |||
211 | nleap = np.floor((year - 1601.0) / 4.0).astype(int) |
||
212 | nleap -= 99 |
||
213 | mask_1900 = year <= 1900 |
||
214 | if np.any(mask_1900): |
||
215 | ncent = np.floor((year[mask_1900] - 1601.0) / 100.0).astype(int) |
||
216 | ncent = 3 - ncent |
||
217 | nleap[mask_1900] = nleap[mask_1900] + ncent |
||
218 | |||
219 | l0 = -79.549 + (-0.238699 * (yr - 4.0 * nleap) + 3.08514e-2 * nleap) |
||
220 | g0 = -2.472 + (-0.2558905 * (yr - 4.0 * nleap) - 3.79617e-2 * nleap) |
||
221 | |||
222 | # Days (including fraction) since 12 UT on January 1 of IYR: |
||
223 | df = (ut / 86400.0 - 1.5) + doy |
||
224 | |||
225 | # Mean longitude of Sun: |
||
226 | lmean = l0 + 0.9856474 * df |
||
227 | |||
228 | # Mean anomaly in radians: |
||
229 | grad = np.radians(g0 + 0.9856003 * df) |
||
230 | |||
231 | # Ecliptic longitude: |
||
232 | lmrad = np.radians(lmean + 1.915 * np.sin(grad) |
||
233 | + 0.020 * np.sin(2.0 * grad)) |
||
234 | sinlm = np.sin(lmrad) |
||
235 | |||
236 | # Obliquity of ecliptic in radians: |
||
237 | epsrad = np.radians(23.439 - 4e-7 * (df + 365 * yr + nleap)) |
||
238 | |||
239 | # Right ascension: |
||
240 | alpha = np.degrees(np.arctan2(np.cos(epsrad) * sinlm, np.cos(lmrad))) |
||
241 | |||
242 | # Declination, which is also the subsolar latitude: |
||
243 | sslat = np.degrees(np.arcsin(np.sin(epsrad) * sinlm)) |
||
244 | |||
245 | # Equation of time (degrees): |
||
246 | etdeg = lmean - alpha |
||
247 | nrot = np.round(etdeg / 360.0) |
||
248 | etdeg = etdeg - 360.0 * nrot |
||
249 | |||
250 | # Subsolar longitude calculation. Earth rotates one degree every 240 s. |
||
251 | sslon = 180.0 - (ut / 240.0 + etdeg) |
||
252 | nrot = np.round(sslon / 360.0) |
||
253 | sslon = sslon - 360.0 * nrot |
||
254 | |||
255 | # Return a single value from the output if the input was a single value |
||
256 | if isinstance(datetime, dt.datetime): |
||
257 | return sslat[0], sslon[0] |
||
258 | return sslat, sslon |
||
259 |