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