def lonlat2xyz(lons, lats): """Convert lons and lats to cartesian coordinates.""" R = 6370997.0 x_coords = R * da.cos(da.deg2rad(lats)) * da.cos(da.deg2rad(lons)) y_coords = R * da.cos(da.deg2rad(lats)) * da.sin(da.deg2rad(lons)) z_coords = R * da.sin(da.deg2rad(lats)) return x_coords, y_coords, z_coords
def transform_lonlats(self, lons, lats): R = 6370997.0 x_coords = R * da.cos(da.deg2rad(lats)) * da.cos(da.deg2rad(lons)) y_coords = R * da.cos(da.deg2rad(lats)) * da.sin(da.deg2rad(lons)) z_coords = R * da.sin(da.deg2rad(lats)) return da.stack((x_coords, y_coords, z_coords), axis=-1)
def ross_part(self, angle_info, global_args): """ Calculates the main part of Ross kernel """ RossKernelOutputs = namedtuple( 'RossKernelOutputs', 'cos_vza cos_sza sin_vza sin_sza cos_raa ross_element cos_phase_angle phase_angle sin_phase_angle ross' ) cos_vza = da.cos(angle_info.vza_rad) cos_sza = da.cos(angle_info.sza_rad) sin_vza = da.sin(angle_info.vza_rad) sin_sza = da.sin(angle_info.sza_rad) cos_raa = da.cos(angle_info.raa_rad) cos_phase_angle, phase_angle, sin_phase_angle = self.get_phaang( cos_vza, cos_sza, sin_vza, sin_sza, cos_raa) ross_element = (global_args.m_pi / 2.0 - phase_angle) * cos_phase_angle + sin_phase_angle return RossKernelOutputs(cos_vza=cos_vza, cos_sza=cos_sza, sin_vza=sin_vza, sin_sza=sin_sza, cos_raa=cos_raa, ross_element=ross_element, cos_phase_angle=cos_phase_angle, phase_angle=phase_angle, sin_phase_angle=sin_phase_angle, ross=None)
def lonlat2xyz(lons, lats): """Convert geographic coordinates to cartesian 3D coordinates.""" R = 6370997.0 x_coords = R * da.cos(da.deg2rad(lats)) * da.cos(da.deg2rad(lons)) y_coords = R * da.cos(da.deg2rad(lats)) * da.sin(da.deg2rad(lons)) z_coords = R * da.sin(da.deg2rad(lats)) return da.stack( (x_coords.ravel(), y_coords.ravel(), z_coords.ravel()), axis=-1)
def lonlat2xyz(lons, lats): R = 6370997.0 x_coords = R * da.cos(da.deg2rad(lats)) * da.cos(da.deg2rad(lons)) y_coords = R * da.cos(da.deg2rad(lats)) * da.sin(da.deg2rad(lons)) z_coords = R * da.sin(da.deg2rad(lats)) return da.stack( (x_coords.ravel(), y_coords.ravel(), z_coords.ravel()), axis=-1)
def lonlat2xyz(lons, lats): R = 6370997.0 x_coords = R * da.cos(da.deg2rad(lats)) * da.cos(da.deg2rad(lons)) y_coords = R * da.cos(da.deg2rad(lats)) * da.sin(da.deg2rad(lons)) z_coords = R * da.sin(da.deg2rad(lats)) return da.stack((x_coords.ravel(), y_coords.ravel(), z_coords.ravel()), axis=-1)
def cos_zen(utc_time, lon, lat): """Cosine of the sun-zenith angle for *lon*, *lat* at *utc_time*. utc_time: datetime.datetime instance of the UTC time lon and lat in degrees. """ lon = da.deg2rad(lon) lat = da.deg2rad(lat) r_a, dec = sun_ra_dec(utc_time) h__ = _local_hour_angle(utc_time, lon, r_a) return (da.sin(lat) * da.sin(dec) + da.cos(lat) * da.cos(dec) * da.cos(h__))
def haversine_distance(pickup_latitude, pickup_longitude, dropoff_latitude, dropoff_longitude): x_1 = pi / 180 * pickup_latitude y_1 = pi / 180 * pickup_longitude x_2 = pi / 180 * dropoff_latitude y_2 = pi / 180 * dropoff_longitude dlon = y_2 - y_1 dlat = x_2 - x_1 a = sin(dlat / 2)**2 + cos(x_1) * cos(x_2) * sin(dlon / 2)**2 c = 2 * arcsin(sqrt(a)) r = 6371 # Radius of earth in kilometers return c * r
def get_alt_az(utc_time, lon, lat): """Return sun altitude and azimuth from *utc_time*, *lon*, and *lat*. lon,lat in degrees What is the unit of the returned angles and heights!? FIXME! """ lon = da.deg2rad(lon) lat = da.deg2rad(lat) ra_, dec = sun_ra_dec(utc_time) h__ = _local_hour_angle(utc_time, lon, ra_) return (da.arcsin( da.sin(lat) * np.sin(dec) + da.cos(lat) * np.cos(dec) * np.cos(h__)), da.arctan2( -np.sin(h__), (da.cos(lat) * np.tan(dec) - da.sin(lat) * np.cos(h__))))
def phase_rotation(self, darray, rotation, preview=None): """ Description ----------- Rotate the phase of the seismic data by a specified angle Parameters ---------- darray : Array-like, acceptable inputs include Numpy, HDF5, or Dask Arrays rotation : Number (degrees), angle of rotation Keywork Arguments ----------------- preview : str, enables or disables preview mode and specifies direction Acceptable inputs are (None, 'inline', 'xline', 'z') Optimizes chunk size in different orientations to facilitate rapid screening of algorithm output Returns ------- result : Dask Array """ phi = np.deg2rad(rotation) kernel = (1,1,25) darray, chunks_init = self.create_array(darray, kernel, preview=preview) analytical_trace = darray.map_blocks(signal.hilbert, dtype=darray.dtype) result = analytical_trace.real * da.cos(phi) - analytical_trace.imag * da.sin(phi) result = util.trim_dask_array(result, kernel) result[da.isnan(result)] = 0 return(result)
def radiance_to_toar(radiance, solar_za, global_args): """ Converts radiance to top-of-atmosphere reflectance Args: radiance (DataArray): The radiance data to calibrate. solar_za (DataArray): The solar zenith angle. global_args (namedtuple): Global arguments. Returns: ``xarray.DataArray`` """ attrs = radiance.attrs.copy() solar_zenith_angle = solar_za * 0.01 toar_data = (global_args.pi * radiance * global_args.d**2) / ( global_args.esun * da.cos(solar_zenith_angle)) attrs['calibration'] = 'top-of-atmosphere reflectance' toar_data.attrs = attrs return toar_data
def randoms(ns): zmin = 0 zmax = ns.zmax dNdZ = read_Nz(ns.nz, ns.ncol, zmin, zmax) zedges = numpy.linspace(zmin, zmax, 12) zcenters = 0.5 * (zedges[1:] + zedges[:-1]) dNdZ_ran = lambda z: dNdZ(z) * ns.boost icdf, Ntotal = geticdf(dNdZ_ran, numpy.linspace(zmin, zmax, 1024)) # drop about 20% of samples to give it enough freedom. cat = RandomCatalog(csize=int(Ntotal), seed=SEED * 20 + 19) if cat.comm.rank == 0: cat.logger.info("Total = %d" % Ntotal) # generate points uniformly on a sphere. # FIXME: add uniform sphere to nbodykit's RandomCatalog z = cat.rng.uniform(-1., 1.) r = abs(1 - z**2)**0.5 phi = cat.rng.uniform(0, 2 * numpy.pi) x = da.cos(phi) * r y = da.sin(phi) * r z = z ra, dec = transform.CartesianToEquatorial(da.stack((x, y, z), axis=1), frame='galactic') z = icdf(cat.rng.uniform(0, 1)) cat['RA'] = ra.compute() cat['DEC'] = dec.compute() cat['Z'] = z cat['Aemit'] = (1 / (z + 1)) ntarget = numpy.ones_like(z, dtype='i4') randoms = ArrayCatalog( { 'RA': cat['RA'].compute().repeat(ntarget, axis=0), 'DEC': cat['DEC'].compute().repeat(ntarget, axis=0), 'Z': cat['Z'].compute().repeat(ntarget, axis=0), 'Aemit': cat['Aemit'].compute().repeat(ntarget, axis=0), }, comm=cat.comm) randoms = randoms.sort(('Aemit', ), usecols=['RA', 'DEC', 'Z', 'Aemit']) randoms.save(ns.output, dataset=ns.odataset)
def SkyToUnitSphere(ra, dec, degrees=True): """ Convert sky coordinates (``ra``, ``dec``) to Cartesian coordinates on the unit sphere. Parameters ---------- ra : :class:`dask.array.Array`; shape: (N,) the right ascension angular coordinate dec : :class:`dask.array.Array`; ; shape: (N,) the declination angular coordinate degrees : bool, optional specifies whether ``ra`` and ``dec`` are in degrees or radians Returns ------- pos : :class:`dask.array.Array`; shape: (N,3) the cartesian position coordinates, where columns represent ``x``, ``y``, and ``z`` Raises ------ TypeError If the input columns are not dask arrays """ if not all(isinstance(col, da.Array) for col in [ra, dec]): raise TypeError("both ``ra`` and ``dec`` must be dask arrays") # put into radians from degrees if degrees: ra = da.deg2rad(ra) dec = da.deg2rad(dec) # cartesian coordinates x = da.cos( dec ) * da.cos( ra ) y = da.cos( dec ) * da.sin( ra ) z = da.sin( dec ) return da.vstack([x,y,z]).T
def match_lists(ra1, dec1, ra2, dec2, dist, numNei=1): """Crossmatches the list of objects (ra1, dec1) with another list of objects (ra2, dec2) with the matching radius "dist". The routine searches for up to numNei closest neighbors the routine, returns the distance to the neighbor and the list of indices of the neighbor. Everything is in degrees. If no match is found, the distance is NaN. Example: .. code-block:: python dist, ind = match_lists(ra1,dec1,ra2,dec2, 1./3600) goodmatch_ind = numpy.isfinite(dist) plot(ra1[goodmatch_ind],ra2[ind[goodmatch_ind]]) Another example: .. code-block:: python print match_lists( [1,1], [2,3], [1.1,1.2,6,], [2.1,2.2,10], 0.3,numNei=2) (array([[ 0.1413761 , 0.28274768], [ inf, inf]]), array([[0, 1], [3, 3]])) """ cosd = lambda x: da.cos(x * np.pi / 180) sind = lambda x: da.sin(x * np.pi / 180) mindist = 2 * sind(dist / 2.0) getxyz = lambda r, d: [cosd(r) * cosd(d), sind(r) * cosd(d), sind(d)] xyz1 = numpy.array(getxyz(ra1, dec1)) xyz2 = numpy.array(getxyz(ra2, dec2)) if (int(scipy_version[0]) == 0) and (int(scipy_version[1]) < 8): # If old scipy version is detected then we use KDTree instead of # cKDTtree because there is a bug in the cKDTree # http://projects.scipy.org/scipy/ticket/1178 tree2 = scipy.spatial.KDTree(xyz2.T) else: tree2 = scipy.spatial.cKDTree(xyz2.T) del xyz2 ret = tree2.query(xyz1.T, numNei, 0, 2, mindist) del xyz1 dist, ind = ret finite = numpy.isfinite(dist) dist[finite] = (2 * arcsin(dist[finite] / 2)) * 180 / np.pi return dist, ind
def get_li(self, kernel_type, li_recip): # relative azimuth angle # ensure it is in a [0,2] pi range phi = da.fabs( (self.angle_info.raa_rad % (2.0 * self.global_args.m_pi))) cos_phi = da.cos(phi) sin_phi = da.sin(phi) tanti = da.tan(self.angle_info.sza_rad) tantv = da.tan(self.angle_info.vza_rad) cos1, sin1, tan1 = self.get_pangles(tantv, self.global_args.br, self.global_args.nearly_zero) cos2, sin2, tan2 = self.get_pangles(tanti, self.global_args.br, self.global_args.nearly_zero) # sets cos & sin phase angle terms cos_phaang, phaang, sin_phaang = self.get_phaang( cos1, cos2, sin1, sin2, cos_phi) distance = self.get_distance(tan1, tan2, cos_phi) overlap_info = self.get_overlap(cos1, cos2, tan1, tan2, sin_phi, distance, self.global_args.hb, self.global_args.m_pi) if kernel_type.lower() == 'sparse': if li_recip: li = overlap_info.overlap - overlap_info.temp + 0.5 * ( 1.0 + cos_phaang) / cos1 / cos2 else: li = overlap_info.overlap - overlap_info.temp + 0.5 * ( 1.0 + cos_phaang) / cos1 else: if kernel_type.lower() == 'dense': if li_recip: li = (1.0 + cos_phaang) / ( cos1 * cos2 * (overlap_info.temp - overlap_info.overlap)) - 2.0 else: li = (1.0 + cos_phaang) / ( cos1 * (overlap_info.temp - overlap_info.overlap)) - 2.0 return li
def haversines(x1, x2, y1, y2, z1=None, z2=None): x1, x2 = da.deg2rad(x1), da.deg2rad(x2) y1, y2 = da.deg2rad(y1), da.deg2rad(y2) x = (x2 - x1) * da.cos((y1 + y2) * 0.5) * cst.r_earth y = (y2 - y1) * cst.r_earth * da.ones_like(x1) * da.ones_like(x2) if z1 is None or z2 is None: return da.stack((x, y), axis=-1) else: z1 = da.where(da.isnan(z1), 0, z1) z2 = da.where(da.isnan(z2), 0, z2) z = (z2 - z1) * da.ones_like(x) return da.stack((x, y, z), axis=-1)
def get_pangles(tan1, br, nearly_zero): """ Get the prime angles """ tanp = br * tan1 tanp = da.where(tanp < 0, 0, tanp) angp = da.arctan(tanp) sinp = da.sin(angp) cosp = da.cos(angp) # have to make sure c is not 0 cosp = da.where(cosp == 0, nearly_zero, cosp) return cosp, sinp, tanp
def gcj02_to_wgs84_dask(lng, lat): """ GCJ02(火星坐标系)转GPS84 :param lng:火星坐标系的经度 :param lat:火星坐标系纬度 :return: """ dlat = _transformlat_dask(lng - 105.0, lat - 35.0) dlng = _transformlng_dask(lng - 105.0, lat - 35.0) radlat = lat / 180.0 * pi magic = da.sin(radlat) magic = 1 - ee * magic * magic sqrtmagic = da.sqrt(magic) dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi) dlng = (dlng * 180.0) / (a / sqrtmagic * da.cos(radlat) * pi) mglat = lat + dlat mglng = lng + dlng return lng * 2 - mglng, lat * 2 - mglat
def run_crefl(refl, coeffs, lon, lat, sensor_azimuth, sensor_zenith, solar_azimuth, solar_zenith, avg_elevation=None, percent=False, use_abi=False): """Run main crefl algorithm. All input parameters are per-pixel values meaning they are the same size and shape as the input reflectance data, unless otherwise stated. :param reflectance_bands: tuple of reflectance band arrays :param coefficients: tuple of coefficients for each band (see `get_coefficients`) :param lon: input swath longitude array :param lat: input swath latitude array :param sensor_azimuth: input swath sensor azimuth angle array :param sensor_zenith: input swath sensor zenith angle array :param solar_azimuth: input swath solar azimuth angle array :param solar_zenith: input swath solar zenith angle array :param avg_elevation: average elevation (usually pre-calculated and stored in CMGDEM.hdf) :param percent: True if input reflectances are on a 0-100 scale instead of 0-1 scale (default: False) """ # FUTURE: Find a way to compute the average elevation before hand # Get digital elevation map data for our granule, set ocean fill value to 0 if avg_elevation is None: LOG.debug("No average elevation information provided in CREFL") #height = np.zeros(lon.shape, dtype=np.float) height = 0. else: LOG.debug("Using average elevation information provided to CREFL") lat[(lat <= -90) | (lat >= 90)] = np.nan lon[(lon <= -180) | (lon >= 180)] = np.nan row = ((90.0 - lat) * avg_elevation.shape[0] / 180.0).astype(np.int32) col = ((lon + 180.0) * avg_elevation.shape[1] / 360.0).astype(np.int32) space_mask = da.isnull(lon) | da.isnull(lat) row[space_mask] = 0 col[space_mask] = 0 def _avg_elevation_index(avg_elevation, row, col): return avg_elevation[row, col] height = da.map_blocks(_avg_elevation_index, avg_elevation, row, col, dtype=avg_elevation.dtype) height = xr.DataArray(height, dims=['y', 'x']) # negative heights aren't allowed, clip to 0 height = height.where((height >= 0.) & ~space_mask, 0.0) del lat, lon, row, col mus = da.cos(da.deg2rad(solar_zenith)) mus = mus.where(mus >= 0) muv = da.cos(da.deg2rad(sensor_zenith)) phi = solar_azimuth - sensor_azimuth if use_abi: LOG.debug("Using ABI CREFL algorithm") a_O3 = [268.45, 0.5, 115.42, -3.2922] a_H2O = [0.0311, 0.1, 92.471, -1.3814] a_O2 = [0.4567, 0.007, 96.4884, -1.6970] G_O3 = G_calc(solar_zenith, a_O3) + G_calc(sensor_zenith, a_O3) G_H2O = G_calc(solar_zenith, a_H2O) + G_calc(sensor_zenith, a_H2O) G_O2 = G_calc(solar_zenith, a_O2) + G_calc(sensor_zenith, a_O2) # Note: bh2o values are actually ao2 values for abi sphalb, rhoray, TtotraytH2O, tOG = get_atm_variables_abi( mus, muv, phi, height, G_O3, G_H2O, G_O2, *coeffs) else: LOG.debug("Using original VIIRS CREFL algorithm") sphalb, rhoray, TtotraytH2O, tOG = get_atm_variables( mus, muv, phi, height, *coeffs) del solar_azimuth, solar_zenith, sensor_zenith, sensor_azimuth # Note: Assume that fill/invalid values are either NaN or we are dealing # with masked arrays if percent: corr_refl = ((refl / 100.) / tOG - rhoray) / TtotraytH2O else: corr_refl = (refl / tOG - rhoray) / TtotraytH2O corr_refl /= (1.0 + corr_refl * sphalb) return corr_refl.clip(REFLMIN, REFLMAX)
def G_calc(zenith, a_coeff): return (da.cos(da.deg2rad(zenith)) + (a_coeff[0] * (zenith**a_coeff[1]) * (a_coeff[2] - zenith)**a_coeff[3]))**-1
def chand(phi, muv, mus, taur): # FROM FUNCTION CHAND # phi: azimuthal difference between sun and observation in degree # (phi=0 in backscattering direction) # mus: cosine of the sun zenith angle # muv: cosine of the observation zenith angle # taur: molecular optical depth # rhoray: molecular path reflectance # constant xdep: depolarization factor (0.0279) # xfd = (1-xdep/(2-xdep)) / (1 + 2*xdep/(2-xdep)) = 2 * (1 - xdep) / (2 + xdep) = 0.958725775 # */ xfd = 0.958725775 xbeta2 = 0.5 # float pl[5]; # double fs01, fs02, fs0, fs1, fs2; as0 = [ 0.33243832, 0.16285370, -0.30924818, -0.10324388, 0.11493334, -6.777104e-02, 1.577425e-03, -1.240906e-02, 3.241678e-02, -3.503695e-02 ] as1 = [0.19666292, -5.439061e-02] as2 = [0.14545937, -2.910845e-02] # float phios, xcos1, xcos2, xcos3; # float xph1, xph2, xph3, xitm1, xitm2; # float xlntaur, xitot1, xitot2, xitot3; # int i, ib; xph1 = 1.0 + (3.0 * mus * mus - 1.0) * (3.0 * muv * muv - 1.0) * xfd / 8.0 xph2 = -xfd * xbeta2 * 1.5 * mus * muv * da.sqrt( 1.0 - mus * mus) * da.sqrt(1.0 - muv * muv) xph3 = xfd * xbeta2 * 0.375 * (1.0 - mus * mus) * (1.0 - muv * muv) # pl[0] = 1.0 # pl[1] = mus + muv # pl[2] = mus * muv # pl[3] = mus * mus + muv * muv # pl[4] = mus * mus * muv * muv fs01 = as0[0] + (mus + muv) * as0[1] + (mus * muv) * as0[2] + ( mus * mus + muv * muv) * as0[3] + (mus * mus * muv * muv) * as0[4] fs02 = as0[5] + (mus + muv) * as0[6] + (mus * muv) * as0[7] + ( mus * mus + muv * muv) * as0[8] + (mus * mus * muv * muv) * as0[9] # for (i = 0; i < 5; i++) { # fs01 += (double) (pl[i] * as0[i]); # fs02 += (double) (pl[i] * as0[5 + i]); # } # for refl, (ah2o, bh2o, ao3, tau) in zip(reflectance_bands, coefficients): # ib = find_coefficient_index(center_wl) # if ib is None: # raise ValueError("Can't handle band with wavelength '{}'".format(center_wl)) xlntaur = da.log(taur) fs0 = fs01 + fs02 * xlntaur fs1 = as1[0] + xlntaur * as1[1] fs2 = as2[0] + xlntaur * as2[1] del xlntaur, fs01, fs02 trdown = da.exp(-taur / mus) trup = da.exp(-taur / muv) xitm1 = (1.0 - trdown * trup) / 4.0 / (mus + muv) xitm2 = (1.0 - trdown) * (1.0 - trup) xitot1 = xph1 * (xitm1 + xitm2 * fs0) xitot2 = xph2 * (xitm1 + xitm2 * fs1) xitot3 = xph3 * (xitm1 + xitm2 * fs2) del xph1, xph2, xph3, xitm1, xitm2, fs0, fs1, fs2 phios = da.deg2rad(phi + 180.0) xcos1 = 1.0 xcos2 = da.cos(phios) xcos3 = da.cos(2.0 * phios) del phios rhoray = xitot1 * xcos1 + xitot2 * xcos2 * 2.0 + xitot3 * xcos3 * 2.0 return rhoray, trdown, trup
def new_grid_mapping_from_coords( x_coords: xr.DataArray, y_coords: xr.DataArray, crs: Union[str, pyproj.crs.CRS], *, tile_size: Union[int, Tuple[int, int]] = None, tolerance: float = DEFAULT_TOLERANCE, ) -> GridMapping: crs = _normalize_crs(crs) assert_instance(x_coords, xr.DataArray, name='x_coords') assert_instance(y_coords, xr.DataArray, name='y_coords') assert_true(x_coords.ndim in (1, 2), 'x_coords and y_coords must be either 1D or 2D arrays') assert_instance(tolerance, float, name='tolerance') assert_true(tolerance > 0.0, 'tolerance must be greater zero') if x_coords.name and y_coords.name: xy_var_names = str(x_coords.name), str(y_coords.name) else: xy_var_names = _default_xy_var_names(crs) tile_size = _normalize_int_pair(tile_size, default=None) is_lon_360 = None # None means "not yet known" if crs.is_geographic: is_lon_360 = bool(np.any(x_coords > 180)) x_res = 0 y_res = 0 if x_coords.ndim == 1: # We have 1D x,y coordinates cls = Coords1DGridMapping assert_true(x_coords.size >= 2 and y_coords.size >= 2, 'sizes of x_coords and y_coords 1D arrays must be >= 2') size = x_coords.size, y_coords.size x_dim, y_dim = x_coords.dims[0], y_coords.dims[0] x_diff = _abs_no_zero(x_coords.diff(dim=x_dim).values) y_diff = _abs_no_zero(y_coords.diff(dim=y_dim).values) if not is_lon_360 and crs.is_geographic: is_anti_meridian_crossed = np.any(np.nanmax(x_diff) > 180) if is_anti_meridian_crossed: x_coords = to_lon_360(x_coords) x_diff = _abs_no_zero(x_coords.diff(dim=x_dim)) is_lon_360 = True x_res, y_res = x_diff[0], y_diff[0] x_diff_equal = np.allclose(x_diff, x_res, atol=tolerance) y_diff_equal = np.allclose(y_diff, y_res, atol=tolerance) is_regular = x_diff_equal and y_diff_equal if is_regular: x_res = round_to_fraction(x_res, 5, 0.25) y_res = round_to_fraction(y_res, 5, 0.25) else: x_res = round_to_fraction(float(np.nanmedian(x_diff)), 2, 0.5) y_res = round_to_fraction(float(np.nanmedian(y_diff)), 2, 0.5) if tile_size is None \ and x_coords.chunks is not None \ and y_coords.chunks is not None: tile_size = (max(0, *x_coords.chunks[0]), max(0, *y_coords.chunks[0])) # Guess j axis direction is_j_axis_up = bool(y_coords[0] < y_coords[-1]) else: # We have 2D x,y coordinates cls = Coords2DGridMapping assert_true( x_coords.shape == y_coords.shape, 'shapes of x_coords and y_coords' ' 2D arrays must be equal') assert_true( x_coords.dims == y_coords.dims, 'dimensions of x_coords and y_coords' ' 2D arrays must be equal') y_dim, x_dim = x_coords.dims height, width = x_coords.shape size = width, height x = da.asarray(x_coords) y = da.asarray(y_coords) x_x_diff = _abs_no_nan(da.diff(x, axis=1)) x_y_diff = _abs_no_nan(da.diff(x, axis=0)) y_x_diff = _abs_no_nan(da.diff(y, axis=1)) y_y_diff = _abs_no_nan(da.diff(y, axis=0)) if not is_lon_360 and crs.is_geographic: is_anti_meridian_crossed = da.any(da.max(x_x_diff) > 180) \ or da.any(da.max(x_y_diff) > 180) if is_anti_meridian_crossed: x_coords = to_lon_360(x_coords) x = da.asarray(x_coords) x_x_diff = _abs_no_nan(da.diff(x, axis=1)) x_y_diff = _abs_no_nan(da.diff(x, axis=0)) is_lon_360 = True is_regular = False if da.all(x_y_diff == 0) and da.all(y_x_diff == 0): x_res = x_x_diff[0, 0] y_res = y_y_diff[0, 0] is_regular = \ da.allclose(x_x_diff[0, :], x_res, atol=tolerance) \ and da.allclose(x_x_diff[-1, :], x_res, atol=tolerance) \ and da.allclose(y_y_diff[:, 0], y_res, atol=tolerance) \ and da.allclose(y_y_diff[:, -1], y_res, atol=tolerance) if not is_regular: # Let diff arrays have same shape as original by # doubling last rows and columns. x_x_diff_c = da.concatenate([x_x_diff, x_x_diff[:, -1:]], axis=1) y_x_diff_c = da.concatenate([y_x_diff, y_x_diff[:, -1:]], axis=1) x_y_diff_c = da.concatenate([x_y_diff, x_y_diff[-1:, :]], axis=0) y_y_diff_c = da.concatenate([y_y_diff, y_y_diff[-1:, :]], axis=0) # Find resolution via area x_abs_diff = da.sqrt(da.square(x_x_diff_c) + da.square(x_y_diff_c)) y_abs_diff = da.sqrt(da.square(y_x_diff_c) + da.square(y_y_diff_c)) if crs.is_geographic: # Convert degrees into meters x_abs_diff_r = da.radians(x_abs_diff) y_abs_diff_r = da.radians(y_abs_diff) x_abs_diff = _ER * da.cos(x_abs_diff_r) * y_abs_diff_r y_abs_diff = _ER * y_abs_diff_r xy_areas = (x_abs_diff * y_abs_diff).flatten() xy_areas = da.where(xy_areas > 0, xy_areas, np.nan) # Get indices of min and max area xy_area_index_min = da.nanargmin(xy_areas) xy_area_index_max = da.nanargmax(xy_areas) # Convert area to edge length xy_res_min = math.sqrt(xy_areas[xy_area_index_min]) xy_res_max = math.sqrt(xy_areas[xy_area_index_max]) # Empirically weight min more than max xy_res = 0.7 * xy_res_min + 0.3 * xy_res_max if crs.is_geographic: # Convert meters back into degrees # print(f'xy_res in meters: {xy_res}') xy_res = math.degrees(xy_res / _ER) # print(f'xy_res in degrees: {xy_res}') # Because this is an estimation, we can round to a nice number xy_res = round_to_fraction(xy_res, digits=1, resolution=0.5) x_res, y_res = float(xy_res), float(xy_res) if tile_size is None and x_coords.chunks is not None: j_chunks, i_chunks = x_coords.chunks tile_size = max(0, *i_chunks), max(0, *j_chunks) if tile_size is not None: tile_width, tile_height = tile_size x_coords = x_coords.chunk((tile_height, tile_width)) y_coords = y_coords.chunk((tile_height, tile_width)) # Guess j axis direction is_j_axis_up = np.all(y_coords[0, :] < y_coords[-1, :]) or None assert_true(x_res > 0 and y_res > 0, 'internal error: x_res and y_res could not be determined', exception_type=RuntimeError) x_res, y_res = _to_int_or_float(x_res), _to_int_or_float(y_res) x_res_05, y_res_05 = x_res / 2, y_res / 2 x_min = _to_int_or_float(x_coords.min() - x_res_05) y_min = _to_int_or_float(y_coords.min() - y_res_05) x_max = _to_int_or_float(x_coords.max() + x_res_05) y_max = _to_int_or_float(y_coords.max() + y_res_05) return cls(x_coords=x_coords, y_coords=y_coords, crs=crs, size=size, tile_size=tile_size, xy_bbox=(x_min, y_min, x_max, y_max), xy_res=(x_res, y_res), xy_var_names=xy_var_names, xy_dim_names=(str(x_dim), str(y_dim)), is_regular=is_regular, is_lon_360=is_lon_360, is_j_axis_up=is_j_axis_up)
def apply(self, df): alpha = ((df[self.column] / 100) * 60 + (df[self.column] % 100)) / 1440 df["cyclic_cos_" + self.column] = da.cos(2 * np.pi * alpha) df["cyclic_sin_" + self.column] = da.sin(2 * np.pi * alpha) return df
# Filter min_P = 0.5 # Displey vecScale = 1 DISP_TimeZoom = [['2018-04-17T20:00', '2018-04-18T00:00']] maxGsumMinus1 = 0.3 # 0.1 TimeShiftedFromUTC_s = 0 # Angles in radians: fPitch = lambda Gxyz: -da.arctan2(Gxyz[0, :], da.sqrt(da.sum(da.square(Gxyz[1:, :]), 0))) fRoll = lambda Gxyz: da.arctan2(Gxyz[1, :], Gxyz[2, :]) # da.arctan2(Gxyz[1,:], da.sqrt(da.sum(da.square(Gxyz[(0,2),:]), 0))) #=da.arctan2(Gxyz[1,:], da.sqrt(da.square(Gxyz[0,:])+da.square(Gxyz[2,:])) ) fInclination = lambda Gxyz: da.arctan2(da.sqrt(da.sum(da.square(Gxyz[:-1, :]), 0)), Gxyz[2, :]) fHeading = lambda H, p, r: da.arctan2(H[2, :] * da.sin(r) - H[1, :] * da.cos(r), H[0, :] * da.cos(p) + (H[1, :] * da.sin(r) + H[2, :] * da.cos(r)) * da.sin(p)) fG = lambda Axyz, Ag, Cg: da.dot(Ag.T, (Axyz - Cg[0, :]).T) fGi = lambda Ax, Ay, Az, Ag, Cg, i: da.dot(Ag.T, (da.column_stack((Ax, Ay, Az))[slice(*i)] - Cg[0, :]).T) fbinningClip = lambda x, bin2_iStEn, bin1_nAverage: da.mean(da.reshape(x[slice(*bin2_iStEn)], (-1, bin1_nAverage)), 1) fbinning = lambda x, bin1_nAverage: da.mean(da.reshape(x, (-1, bin1_nAverage)), 1) repeat3shift1 = lambda A2: [A2[t:(len(A2) - 2 + t)] for t in range(3)] median3cols = lambda a, b, c: da.where(a < b, da.where(c < a, a, da.where(b < c, b, c)), da.where(a < c, a, da.where(c < b, b, c))) median3 = lambda x: da.hstack((np.NaN, median3cols(*repeat3shift1(x)), np.NaN)) # not convertable to dask easily: fVabs_old = lambda Gxyz, kVabs: np.polyval(kVabs.flat, np.sqrt(np.tan(fInclination(Gxyz)))) rep2mean = lambda x, bOk: np.interp(np.arange(len(x)), np.flatnonzero(bOk), x[bOk], np.NaN, np.NaN) fForce2Vabs_fitted = lambda x: da.where(x > 2, 2, da.where(x < 1, 0.25 * x, 0.25 * x + 0.3 * (x - 1) ** 4))
def norm_topo(self, data, elev, solar_za, solar_az, slope=None, aspect=None, method='empirical-rotation', slope_thresh=2, nodata=0, elev_nodata=-32768, scale_factor=1, angle_scale=0.01, n_jobs=1, robust=False, min_samples=100, slope_kwargs=None, aspect_kwargs=None, band_coeffs=None): """ Applies topographic normalization Args: data (2d or 3d DataArray): The data to normalize, in the range 0-1. elev (2d DataArray): The elevation data. solar_za (2d DataArray): The solar zenith angles (degrees). solar_az (2d DataArray): The solar azimuth angles (degrees). slope (2d DataArray): The slope data. If not given, slope is calculated from ``elev``. aspect (2d DataArray): The aspect data. If not given, aspect is calculated from ``elev``. method (Optional[str]): The method to apply. Choices are ['c', 'empirical-rotation']. slope_thresh (Optional[float or int]): The slope threshold. Any samples with values < ``slope_thresh`` are not adjusted. nodata (Optional[int or float]): The 'no data' value for ``data``. elev_nodata (Optional[float or int]): The 'no data' value for ``elev``. scale_factor (Optional[float]): A scale factor to apply to the input data. angle_scale (Optional[float]): The angle scale factor. n_jobs (Optional[int]): The number of parallel workers for ``LinearRegression.fit``. robust (Optional[bool]): Whether to fit a robust regression. min_samples (Optional[int]): The minimum number of samples required to fit a regression. slope_kwargs (Optional[dict]): Keyword arguments passed to ``gdal.DEMProcessingOptions`` to calculate the slope. aspect_kwargs (Optional[dict]): Keyword arguments passed to ``gdal.DEMProcessingOptions`` to calculate the aspect. band_coeffs (Optional[dict]): Slope and intercept coefficients for each band. References: See :cite:`teillet_etal_1982` for the C-correction method. See :cite:`tan_etal_2010` for the Empirical Rotation method. Returns: ``xarray.DataArray`` Examples: >>> import geowombat as gw >>> from geowombat.radiometry import Topo >>> >>> topo = Topo() >>> >>> # Example where pixel angles are stored in separate GeoTiff files >>> with gw.config.update(sensor='l7', scale_factor=0.0001, nodata=0): >>> >>> with gw.open('landsat.tif') as src, >>> gw.open('srtm') as elev, >>> gw.open('solarz.tif') as solarz, >>> gw.open('solara.tif') as solara: >>> >>> src_norm = topo.norm_topo(src, elev, solarz, solara, n_jobs=-1) """ method = method.strip().lower() if method not in ['c', 'empirical-rotation']: logger.exception(" Currently, the only supported methods are 'c' and 'empirical-rotation'.") raise NameError attrs = data.attrs.copy() if not nodata: nodata = data.gw.nodata if scale_factor == 1.0: scale_factor = data.gw.scale_factor # Scale the reflectance data if scale_factor != 1: data = data * scale_factor if not slope_kwargs: slope_kwargs = dict(format='MEM', computeEdges=True, alg='ZevenbergenThorne', slopeFormat='degree') if not aspect_kwargs: aspect_kwargs = dict(format='MEM', computeEdges=True, alg='ZevenbergenThorne', trigonometric=False, zeroForFlat=True) slope_kwargs['format'] = 'MEM' slope_kwargs['slopeFormat'] = 'degree' aspect_kwargs['format'] = 'MEM' # Force to SRTM resolution proc_dims = (int((data.gw.ncols*data.gw.cellx) / 30.0), int((data.gw.nrows*data.gw.celly) / 30.0)) w = int((5 * 30.0) / data.gw.celly) if w % 2 == 0: w += 1 if isinstance(slope, xr.DataArray): slope_deg_fd = slope.squeeze().data else: slope_deg = calc_slope_delayed(elev.squeeze().data, proc_dims=proc_dims, w=w, **slope_kwargs) slope_deg_fd = da.from_delayed(slope_deg, (data.gw.nrows, data.gw.ncols), dtype='float64') if isinstance(aspect, xr.DataArray): aspect_deg_fd = aspect.squeeze().data else: aspect_deg = calc_aspect_delayed(elev.squeeze().data, proc_dims=proc_dims, w=w, **aspect_kwargs) aspect_deg_fd = da.from_delayed(aspect_deg, (data.gw.nrows, data.gw.ncols), dtype='float64') nodata_samps = da.where((elev.data == elev_nodata) | (data.max(dim='band').data == nodata) | (slope_deg_fd < slope_thresh), 1, 0) slope_rad = da.deg2rad(slope_deg_fd) aspect_rad = da.deg2rad(aspect_deg_fd) # Convert degrees to radians solar_za = da.deg2rad(solar_za.squeeze().data * angle_scale) solar_az = da.deg2rad(solar_az.squeeze().data * angle_scale) cos_z = da.cos(solar_za) # Calculate the illumination angle il = da.cos(slope_rad) * cos_z + da.sin(slope_rad) * da.sin(solar_za) * da.cos(solar_az - aspect_rad) sr_adj = list() for band in data.band.values.tolist(): if method == 'c': sr_adj.append(self._method_c(data.sel(band=band).data, il, cos_z, nodata_samps, min_samples, n_jobs, robust, band_coeffs, band)) else: sr_adj.append(self._method_empirical_rotation(data.sel(band=band).data, il, cos_z, nodata_samps, min_samples, n_jobs, robust, band_coeffs, band)) adj_data = xr.DataArray(data=da.concatenate(sr_adj).reshape((data.gw.nbands, data.gw.nrows, data.gw.ncols)), coords={'band': data.band.values.tolist(), 'y': data.y.values, 'x': data.x.values}, dims=('band', 'y', 'x'), attrs=data.attrs) attrs['calibration'] = 'Topographic-adjusted' attrs['nodata'] = nodata attrs['drange'] = (0, 1) adj_data.attrs = attrs return adj_data
def get_reflectance(self, sun_zenith, sat_zenith, azidiff, bandname, redband=None): """Get the reflectance from the three sun-sat angles""" # Get wavelength in nm for band: if isinstance(bandname, float): LOG.warning('A wavelength is provided instead of band name - ' + 'disregard the relative spectral responses and assume ' + 'it is the effective wavelength: %f (micro meter)', bandname) wvl = bandname * 1000.0 else: wvl = self.get_effective_wavelength(bandname) wvl = wvl * 1000.0 rayl, wvl_coord, azid_coord, satz_sec_coord, sunz_sec_coord = self.get_reflectance_lut() # force dask arrays compute = False if HAVE_DASK and not isinstance(sun_zenith, Array): compute = True sun_zenith = from_array(sun_zenith, chunks=sun_zenith.shape) sat_zenith = from_array(sat_zenith, chunks=sat_zenith.shape) azidiff = from_array(azidiff, chunks=azidiff.shape) if redband is not None: redband = from_array(redband, chunks=redband.shape) clip_angle = rad2deg(arccos(1. / sunz_sec_coord.max())) sun_zenith = clip(sun_zenith, 0, clip_angle) sunzsec = 1. / cos(deg2rad(sun_zenith)) clip_angle = rad2deg(arccos(1. / satz_sec_coord.max())) sat_zenith = clip(sat_zenith, 0, clip_angle) satzsec = 1. / cos(deg2rad(sat_zenith)) shape = sun_zenith.shape if not(wvl_coord.min() < wvl < wvl_coord.max()): LOG.warning( "Effective wavelength for band %s outside 400-800 nm range!", str(bandname)) LOG.info( "Set the rayleigh/aerosol reflectance contribution to zero!") if HAVE_DASK: chunks = sun_zenith.chunks if redband is None else redband.chunks res = zeros(shape, chunks=chunks) return res.compute() if compute else res else: return zeros(shape) idx = np.searchsorted(wvl_coord, wvl) wvl1 = wvl_coord[idx - 1] wvl2 = wvl_coord[idx] fac = (wvl2 - wvl) / (wvl2 - wvl1) raylwvl = fac * rayl[idx - 1, :, :, :] + (1 - fac) * rayl[idx, :, :, :] tic = time.time() smin = [sunz_sec_coord[0], azid_coord[0], satz_sec_coord[0]] smax = [sunz_sec_coord[-1], azid_coord[-1], satz_sec_coord[-1]] orders = [ len(sunz_sec_coord), len(azid_coord), len(satz_sec_coord)] f_3d_grid = atleast_2d(raylwvl.ravel()) if HAVE_DASK and isinstance(smin[0], Array): # compute all of these at the same time before passing to the interpolator # otherwise they are computed separately smin, smax, orders, f_3d_grid = da.compute(smin, smax, orders, f_3d_grid) minterp = MultilinearInterpolator(smin, smax, orders) minterp.set_values(f_3d_grid) if HAVE_DASK: ipn = map_blocks(self._do_interp, minterp, sunzsec, azidiff, satzsec, dtype=raylwvl.dtype, chunks=azidiff.chunks) else: ipn = self._do_interp(minterp, sunzsec, azidiff, satzsec) LOG.debug("Time - Interpolation: {0:f}".format(time.time() - tic)) ipn *= 100 res = ipn if redband is not None: res = where(redband < 20., res, (1 - (redband - 20) / 80) * res) res = clip(res, 0, 100) if compute: res = res.compute() return res
def sinfit(array, periods, dim=None, coord=None, unit='s'): """ Least squares sinusoidal fit. Fit sinusoidal functions ``y = A[p] * sin(2 * pi * ax * f[1] + phi[1])`` Parameters ---------- array : xarray.DataArray Data to be fitted periods: float or list of float The periods of the sinusoidal functions to be fitted dim : str, optional The dimension along which the data will be fitted. If not precised, the first dimension will be used unit : {'D', 'h', 'm', 's', 'ms', 'us', 'ns'}, optional If the fit uses a datetime dimension, the unit of the period may be specified here. Returns ------- modes : Dataset A Dataset with the amplitude and the phase for each periods """ if dim is None: dim = array.dims[0] if _utils.is_scalar(periods): periods = [ periods, ] n = 2 * len(periods) + 1 # Sort frequencies in ascending order periods.sort(reverse=True) # Re-order the array to place the fitting dimension as the first dimension # + stack the other dimensions array_stacked = _order_and_stack(array, dim) dim_chunk = array.chunks[array.get_axis_num(dim)][0] # Check if the dimension is associated with a numpy.datetime # and normalize to use periods and time in seconds if coord is None: coord = array[dim] if _utils.is_datetime(coord): # Use the 1e-9 to scale nanoseconds to seconds (by default, xarray use # datetime in nanoseconds t = coord.data.astype('f8') * 1e-9 freqs = 1. / pd.to_timedelta(periods, unit=unit).total_seconds() else: t = coord.data freqs = 1. / periods # Build coefficient matrix for the fit using the exponential form x = da.vstack([da.cos(2 * np.pi * f * t) for f in reversed(freqs)] + [ da.ones(len(t), chunks=dim_chunk), ] + [da.sin(2 * np.pi * f * t) for f in freqs]).T x = x.rechunk((dim_chunk, n)) # Solve the least-square system c, _, _, _ = da.linalg.lstsq(x, array_stacked.data) # Get cosine (a) and sine (b) ampitudes b = c[0:n // 2, ][::-1] a = c[n // 2 + 1:, ] # Compute amplitude and phase amplitude = da.sqrt(a**2 + b**2) phase = da.arctan2(b, a) * 180. / np.pi # Store the results new_dims = ('periods', ) + array_stacked.dims[1:] new_coords = { co: array_stacked.coords[co] for co in array_stacked.coords if co != dim } var_dict = { 'amplitude': (new_dims, amplitude), 'phase': (new_dims, phase), 'offset': (array_stacked.dims[1:], c[n // 2, ]) } ds = xr.Dataset(var_dict, coords=new_coords) ds = ds.assign_coords(periods=periods) ds['periods'].attrs['units'] = unit # Unstack the data modes = _unstack(ds) return modes
def SkyToUnitSphere(ra, dec, degrees=True, frame='icrs'): """ Convert sky coordinates (``ra``, ``dec``) to Cartesian coordinates on the unit sphere. Parameters ---------- ra : :class:`dask.array.Array`; shape: (N,) the right ascension angular coordinate dec : :class:`dask.array.Array`; ; shape: (N,) the declination angular coordinate degrees : bool, optional specifies whether ``ra`` and ``dec`` are in degrees or radians frame : string ('icrs' or 'galactic') speciefies which frame the Cartesian coordinates is. Useful if you know the simulation (usually cartesian) is in galactic units but you want to convert to the icrs (ra, dec) usually used in surveys. Returns ------- pos : :class:`dask.array.Array`; shape: (N,3) the cartesian position coordinates, where columns represent ``x``, ``y``, and ``z`` Raises ------ TypeError If the input columns are not dask arrays """ ra, dec = da.broadcast_arrays(ra, dec) if frame == 'icrs': # no frame transformation # put into radians from degrees if degrees: ra = da.deg2rad(ra) dec = da.deg2rad(dec) # cartesian coordinates x = da.cos( dec ) * da.cos( ra ) y = da.cos( dec ) * da.sin( ra ) z = da.sin( dec ) return da.vstack([x,y,z]).T else: from astropy.coordinates import SkyCoord if degrees: ra = da.deg2rad(ra) dec = da.deg2rad(dec) def eq_to_cart(ra, dec): try: sc = SkyCoord(ra, dec, unit='rad', representation_type='unitspherical', frame='icrs') except: sc = SkyCoord(ra, dec, unit='rad', representation='unitspherical', frame='icrs') scg = sc.transform_to(frame=frame) scg = scg.cartesian x, y, z = scg.x.value, scg.y.value, scg.z.value return numpy.stack([x, y, z], axis=1) arr = da.apply_gufunc(eq_to_cart, '(),()->(p)', ra, dec, output_dtypes=[ra.dtype], output_sizes={'p': 3}) return arr
def get_reflectance(self, sun_zenith, sat_zenith, azidiff, bandname, redband=None): """Get the reflectance from the three sun-sat angles""" # Get wavelength in nm for band: if isinstance(bandname, float): LOG.warning('A wavelength is provided instead of band name - ' + 'disregard the relative spectral responses and assume ' + 'it is the effective wavelength: %f (micro meter)', bandname) wvl = bandname * 1000.0 else: wvl = self.get_effective_wavelength(bandname) if wvl is None: LOG.error("Can't get effective wavelength for band %s on platform %s and sensor %s", str(bandname), self.platform_name, self.sensor) return None else: wvl = wvl * 1000.0 rayl, wvl_coord, azid_coord, satz_sec_coord, sunz_sec_coord = \ self.get_reflectance_lut() # force dask arrays compute = False if HAVE_DASK and not isinstance(sun_zenith, Array): compute = True sun_zenith = from_array(sun_zenith, chunks=sun_zenith.shape) sat_zenith = from_array(sat_zenith, chunks=sat_zenith.shape) azidiff = from_array(azidiff, chunks=azidiff.shape) if redband is not None: redband = from_array(redband, chunks=redband.shape) clip_angle = rad2deg(arccos(1. / sunz_sec_coord.max())) sun_zenith = clip(sun_zenith, 0, clip_angle) sunzsec = 1. / cos(deg2rad(sun_zenith)) clip_angle = rad2deg(arccos(1. / satz_sec_coord.max())) sat_zenith = clip(sat_zenith, 0, clip_angle) satzsec = 1. / cos(deg2rad(sat_zenith)) shape = sun_zenith.shape if not(wvl_coord.min() < wvl < wvl_coord.max()): LOG.warning( "Effective wavelength for band %s outside 400-800 nm range!", str(bandname)) LOG.info( "Set the rayleigh/aerosol reflectance contribution to zero!") if HAVE_DASK: chunks = sun_zenith.chunks if redband is None \ else redband.chunks res = zeros(shape, chunks=chunks) return res.compute() if compute else res else: return zeros(shape) idx = np.searchsorted(wvl_coord, wvl) wvl1 = wvl_coord[idx - 1] wvl2 = wvl_coord[idx] fac = (wvl2 - wvl) / (wvl2 - wvl1) raylwvl = fac * rayl[idx - 1, :, :, :] + (1 - fac) * rayl[idx, :, :, :] tic = time.time() smin = [sunz_sec_coord[0], azid_coord[0], satz_sec_coord[0]] smax = [sunz_sec_coord[-1], azid_coord[-1], satz_sec_coord[-1]] orders = [ len(sunz_sec_coord), len(azid_coord), len(satz_sec_coord)] f_3d_grid = atleast_2d(raylwvl.ravel()) if HAVE_DASK and isinstance(smin[0], Array): # compute all of these at the same time before passing to the interpolator # otherwise they are computed separately smin, smax, orders, f_3d_grid = da.compute(smin, smax, orders, f_3d_grid) minterp = MultilinearInterpolator(smin, smax, orders) minterp.set_values(f_3d_grid) def _do_interp(minterp, sunzsec, azidiff, satzsec): interp_points2 = np.vstack((sunzsec.ravel(), 180 - azidiff.ravel(), satzsec.ravel())) res = minterp(interp_points2) return res.reshape(sunzsec.shape) if HAVE_DASK: ipn = map_blocks(_do_interp, minterp, sunzsec, azidiff, satzsec, dtype=raylwvl.dtype, chunks=azidiff.chunks) else: ipn = _do_interp(minterp, sunzsec, azidiff, satzsec) LOG.debug("Time - Interpolation: {0:f}".format(time.time() - tic)) ipn *= 100 res = ipn if redband is not None: res = where(redband < 20., res, (1 - (redband - 20) / 80) * res) res = clip(res, 0, 100) if compute: res = res.compute() return res
def lengths_and_angles_to_box_vectors(a_length, b_length, c_length, alpha, beta, gamma): """Convert from the lengths/angles of the unit cell to the box vectors (Bravais vectors). The angles should be in degrees. Mimics mdtraj.core.unitcell.lengths_and_angles_to_box_vectors() Parameters ---------- a_length : scalar or ndarray length of Bravais unit vector **a** b_length : scalar or ndarray length of Bravais unit vector **b** c_length : scalar or ndarray length of Bravais unit vector **c** alpha : scalar or ndarray angle between vectors **b** and **c**, in degrees. beta : scalar or ndarray angle between vectors **c** and **a**, in degrees. gamma : scalar or ndarray angle between vectors **a** and **b**, in degrees. Returns ------- a : dask.array If the inputs are scalar, the vectors will one dimensional (length 3). If the inputs are one dimension, shape=(n_frames, ), then the output will be (n_frames, 3) b : dask.array If the inputs are scalar, the vectors will one dimensional (length 3). If the inputs are one dimension, shape=(n_frames, ), then the output will be (n_frames, 3) c : dask.array If the inputs are scalar, the vectors will one dimensional (length 3). If the inputs are one dimension, shape=(n_frames, ), then the output will be (n_frames, 3) This code is adapted from gyroid, which is licensed under the BSD http://pythonhosted.org/gyroid/_modules/gyroid/unitcell.html """ # Fix for da that requires angles and lengths to be arrays lengths = [a_length, b_length, c_length] for i, e in enumerate(lengths): # Use python logic shortcutting to not compute dask Arrays if not isinstance(e, da.core.Array) and np.isscalar(e): lengths[i] = np.array([e]) a_length, b_length, c_length = tuple(lengths) angles = [alpha, beta, gamma] for i, e in enumerate(angles): if not isinstance(e, da.core.Array) and np.isscalar(e): angles[i] = np.array([e]) alpha, beta, gamma = tuple(angles) if da.all(alpha < 2 * np.pi) and ( da.all(beta < 2 * np.pi) and da.all(gamma < 2 * np.pi) ): warnings.warn( "All your angles were less than 2*pi." " Did you accidentally give me radians?" ) alpha = alpha * np.pi / 180 beta = beta * np.pi / 180 gamma = gamma * np.pi / 180 a = da.stack([a_length, da.zeros_like(a_length), da.zeros_like(a_length)]) b = da.stack( [b_length * da.cos(gamma), b_length * da.sin(gamma), da.zeros_like(b_length)] ) cx = c_length * da.cos(beta) cy = c_length * (da.cos(alpha) - da.cos(beta) * da.cos(gamma)) / da.sin(gamma) cz = da.sqrt(c_length * c_length - cx * cx - cy * cy) c = da.stack([cx, cy, cz]) if not a.shape == b.shape == c.shape: raise TypeError("Shape is messed up.") # Make sure that all vector components that are _almost_ 0 are set exactly # to 0 tol = 1e-6 a[da.logical_and(a > -tol, a < tol)] = 0.0 b[da.logical_and(b > -tol, b < tol)] = 0.0 c[da.logical_and(c > -tol, c < tol)] = 0.0 return a.T, b.T, c.T
def test_arithmetic(): x = np.arange(5).astype('f4') + 2 y = np.arange(5).astype('i8') + 2 z = np.arange(5).astype('i4') + 2 a = da.from_array(x, chunks=(2, )) b = da.from_array(y, chunks=(2, )) c = da.from_array(z, chunks=(2, )) assert eq(a + b, x + y) assert eq(a * b, x * y) assert eq(a - b, x - y) assert eq(a / b, x / y) assert eq(b & b, y & y) assert eq(b | b, y | y) assert eq(b ^ b, y ^ y) assert eq(a // b, x // y) assert eq(a**b, x**y) assert eq(a % b, x % y) assert eq(a > b, x > y) assert eq(a < b, x < y) assert eq(a >= b, x >= y) assert eq(a <= b, x <= y) assert eq(a == b, x == y) assert eq(a != b, x != y) assert eq(a + 2, x + 2) assert eq(a * 2, x * 2) assert eq(a - 2, x - 2) assert eq(a / 2, x / 2) assert eq(b & True, y & True) assert eq(b | True, y | True) assert eq(b ^ True, y ^ True) assert eq(a // 2, x // 2) assert eq(a**2, x**2) assert eq(a % 2, x % 2) assert eq(a > 2, x > 2) assert eq(a < 2, x < 2) assert eq(a >= 2, x >= 2) assert eq(a <= 2, x <= 2) assert eq(a == 2, x == 2) assert eq(a != 2, x != 2) assert eq(2 + b, 2 + y) assert eq(2 * b, 2 * y) assert eq(2 - b, 2 - y) assert eq(2 / b, 2 / y) assert eq(True & b, True & y) assert eq(True | b, True | y) assert eq(True ^ b, True ^ y) assert eq(2 // b, 2 // y) assert eq(2**b, 2**y) assert eq(2 % b, 2 % y) assert eq(2 > b, 2 > y) assert eq(2 < b, 2 < y) assert eq(2 >= b, 2 >= y) assert eq(2 <= b, 2 <= y) assert eq(2 == b, 2 == y) assert eq(2 != b, 2 != y) assert eq(-a, -x) assert eq(abs(a), abs(x)) assert eq(~(a == b), ~(x == y)) assert eq(~(a == b), ~(x == y)) assert eq(da.logaddexp(a, b), np.logaddexp(x, y)) assert eq(da.logaddexp2(a, b), np.logaddexp2(x, y)) assert eq(da.exp(b), np.exp(y)) assert eq(da.log(a), np.log(x)) assert eq(da.log10(a), np.log10(x)) assert eq(da.log1p(a), np.log1p(x)) assert eq(da.expm1(b), np.expm1(y)) assert eq(da.sqrt(a), np.sqrt(x)) assert eq(da.square(a), np.square(x)) assert eq(da.sin(a), np.sin(x)) assert eq(da.cos(b), np.cos(y)) assert eq(da.tan(a), np.tan(x)) assert eq(da.arcsin(b / 10), np.arcsin(y / 10)) assert eq(da.arccos(b / 10), np.arccos(y / 10)) assert eq(da.arctan(b / 10), np.arctan(y / 10)) assert eq(da.arctan2(b * 10, a), np.arctan2(y * 10, x)) assert eq(da.hypot(b, a), np.hypot(y, x)) assert eq(da.sinh(a), np.sinh(x)) assert eq(da.cosh(b), np.cosh(y)) assert eq(da.tanh(a), np.tanh(x)) assert eq(da.arcsinh(b * 10), np.arcsinh(y * 10)) assert eq(da.arccosh(b * 10), np.arccosh(y * 10)) assert eq(da.arctanh(b / 10), np.arctanh(y / 10)) assert eq(da.deg2rad(a), np.deg2rad(x)) assert eq(da.rad2deg(a), np.rad2deg(x)) assert eq(da.logical_and(a < 1, b < 4), np.logical_and(x < 1, y < 4)) assert eq(da.logical_or(a < 1, b < 4), np.logical_or(x < 1, y < 4)) assert eq(da.logical_xor(a < 1, b < 4), np.logical_xor(x < 1, y < 4)) assert eq(da.logical_not(a < 1), np.logical_not(x < 1)) assert eq(da.maximum(a, 5 - a), np.maximum(a, 5 - a)) assert eq(da.minimum(a, 5 - a), np.minimum(a, 5 - a)) assert eq(da.fmax(a, 5 - a), np.fmax(a, 5 - a)) assert eq(da.fmin(a, 5 - a), np.fmin(a, 5 - a)) assert eq(da.isreal(a + 1j * b), np.isreal(x + 1j * y)) assert eq(da.iscomplex(a + 1j * b), np.iscomplex(x + 1j * y)) assert eq(da.isfinite(a), np.isfinite(x)) assert eq(da.isinf(a), np.isinf(x)) assert eq(da.isnan(a), np.isnan(x)) assert eq(da.signbit(a - 3), np.signbit(x - 3)) assert eq(da.copysign(a - 3, b), np.copysign(x - 3, y)) assert eq(da.nextafter(a - 3, b), np.nextafter(x - 3, y)) assert eq(da.ldexp(c, c), np.ldexp(z, z)) assert eq(da.fmod(a * 12, b), np.fmod(x * 12, y)) assert eq(da.floor(a * 0.5), np.floor(x * 0.5)) assert eq(da.ceil(a), np.ceil(x)) assert eq(da.trunc(a / 2), np.trunc(x / 2)) assert eq(da.degrees(b), np.degrees(y)) assert eq(da.radians(a), np.radians(x)) assert eq(da.rint(a + 0.3), np.rint(x + 0.3)) assert eq(da.fix(a - 2.5), np.fix(x - 2.5)) assert eq(da.angle(a + 1j), np.angle(x + 1j)) assert eq(da.real(a + 1j), np.real(x + 1j)) assert eq((a + 1j).real, np.real(x + 1j)) assert eq(da.imag(a + 1j), np.imag(x + 1j)) assert eq((a + 1j).imag, np.imag(x + 1j)) assert eq(da.conj(a + 1j * b), np.conj(x + 1j * y)) assert eq((a + 1j * b).conj(), (x + 1j * y).conj()) assert eq(da.clip(b, 1, 4), np.clip(y, 1, 4)) assert eq(da.fabs(b), np.fabs(y)) assert eq(da.sign(b - 2), np.sign(y - 2)) l1, l2 = da.frexp(a) r1, r2 = np.frexp(x) assert eq(l1, r1) assert eq(l2, r2) l1, l2 = da.modf(a) r1, r2 = np.modf(x) assert eq(l1, r1) assert eq(l2, r2) assert eq(da.around(a, -1), np.around(x, -1))
def test_arithmetic(): x = np.arange(5).astype('f4') + 2 y = np.arange(5).astype('i8') + 2 z = np.arange(5).astype('i4') + 2 a = da.from_array(x, chunks=(2,)) b = da.from_array(y, chunks=(2,)) c = da.from_array(z, chunks=(2,)) assert eq(a + b, x + y) assert eq(a * b, x * y) assert eq(a - b, x - y) assert eq(a / b, x / y) assert eq(b & b, y & y) assert eq(b | b, y | y) assert eq(b ^ b, y ^ y) assert eq(a // b, x // y) assert eq(a ** b, x ** y) assert eq(a % b, x % y) assert eq(a > b, x > y) assert eq(a < b, x < y) assert eq(a >= b, x >= y) assert eq(a <= b, x <= y) assert eq(a == b, x == y) assert eq(a != b, x != y) assert eq(a + 2, x + 2) assert eq(a * 2, x * 2) assert eq(a - 2, x - 2) assert eq(a / 2, x / 2) assert eq(b & True, y & True) assert eq(b | True, y | True) assert eq(b ^ True, y ^ True) assert eq(a // 2, x // 2) assert eq(a ** 2, x ** 2) assert eq(a % 2, x % 2) assert eq(a > 2, x > 2) assert eq(a < 2, x < 2) assert eq(a >= 2, x >= 2) assert eq(a <= 2, x <= 2) assert eq(a == 2, x == 2) assert eq(a != 2, x != 2) assert eq(2 + b, 2 + y) assert eq(2 * b, 2 * y) assert eq(2 - b, 2 - y) assert eq(2 / b, 2 / y) assert eq(True & b, True & y) assert eq(True | b, True | y) assert eq(True ^ b, True ^ y) assert eq(2 // b, 2 // y) assert eq(2 ** b, 2 ** y) assert eq(2 % b, 2 % y) assert eq(2 > b, 2 > y) assert eq(2 < b, 2 < y) assert eq(2 >= b, 2 >= y) assert eq(2 <= b, 2 <= y) assert eq(2 == b, 2 == y) assert eq(2 != b, 2 != y) assert eq(-a, -x) assert eq(abs(a), abs(x)) assert eq(~(a == b), ~(x == y)) assert eq(~(a == b), ~(x == y)) assert eq(da.logaddexp(a, b), np.logaddexp(x, y)) assert eq(da.logaddexp2(a, b), np.logaddexp2(x, y)) assert eq(da.exp(b), np.exp(y)) assert eq(da.log(a), np.log(x)) assert eq(da.log10(a), np.log10(x)) assert eq(da.log1p(a), np.log1p(x)) assert eq(da.expm1(b), np.expm1(y)) assert eq(da.sqrt(a), np.sqrt(x)) assert eq(da.square(a), np.square(x)) assert eq(da.sin(a), np.sin(x)) assert eq(da.cos(b), np.cos(y)) assert eq(da.tan(a), np.tan(x)) assert eq(da.arcsin(b/10), np.arcsin(y/10)) assert eq(da.arccos(b/10), np.arccos(y/10)) assert eq(da.arctan(b/10), np.arctan(y/10)) assert eq(da.arctan2(b*10, a), np.arctan2(y*10, x)) assert eq(da.hypot(b, a), np.hypot(y, x)) assert eq(da.sinh(a), np.sinh(x)) assert eq(da.cosh(b), np.cosh(y)) assert eq(da.tanh(a), np.tanh(x)) assert eq(da.arcsinh(b*10), np.arcsinh(y*10)) assert eq(da.arccosh(b*10), np.arccosh(y*10)) assert eq(da.arctanh(b/10), np.arctanh(y/10)) assert eq(da.deg2rad(a), np.deg2rad(x)) assert eq(da.rad2deg(a), np.rad2deg(x)) assert eq(da.logical_and(a < 1, b < 4), np.logical_and(x < 1, y < 4)) assert eq(da.logical_or(a < 1, b < 4), np.logical_or(x < 1, y < 4)) assert eq(da.logical_xor(a < 1, b < 4), np.logical_xor(x < 1, y < 4)) assert eq(da.logical_not(a < 1), np.logical_not(x < 1)) assert eq(da.maximum(a, 5 - a), np.maximum(a, 5 - a)) assert eq(da.minimum(a, 5 - a), np.minimum(a, 5 - a)) assert eq(da.fmax(a, 5 - a), np.fmax(a, 5 - a)) assert eq(da.fmin(a, 5 - a), np.fmin(a, 5 - a)) assert eq(da.isreal(a + 1j * b), np.isreal(x + 1j * y)) assert eq(da.iscomplex(a + 1j * b), np.iscomplex(x + 1j * y)) assert eq(da.isfinite(a), np.isfinite(x)) assert eq(da.isinf(a), np.isinf(x)) assert eq(da.isnan(a), np.isnan(x)) assert eq(da.signbit(a - 3), np.signbit(x - 3)) assert eq(da.copysign(a - 3, b), np.copysign(x - 3, y)) assert eq(da.nextafter(a - 3, b), np.nextafter(x - 3, y)) assert eq(da.ldexp(c, c), np.ldexp(z, z)) assert eq(da.fmod(a * 12, b), np.fmod(x * 12, y)) assert eq(da.floor(a * 0.5), np.floor(x * 0.5)) assert eq(da.ceil(a), np.ceil(x)) assert eq(da.trunc(a / 2), np.trunc(x / 2)) assert eq(da.degrees(b), np.degrees(y)) assert eq(da.radians(a), np.radians(x)) assert eq(da.rint(a + 0.3), np.rint(x + 0.3)) assert eq(da.fix(a - 2.5), np.fix(x - 2.5)) assert eq(da.angle(a + 1j), np.angle(x + 1j)) assert eq(da.real(a + 1j), np.real(x + 1j)) assert eq((a + 1j).real, np.real(x + 1j)) assert eq(da.imag(a + 1j), np.imag(x + 1j)) assert eq((a + 1j).imag, np.imag(x + 1j)) assert eq(da.conj(a + 1j * b), np.conj(x + 1j * y)) assert eq((a + 1j * b).conj(), (x + 1j * y).conj()) assert eq(da.clip(b, 1, 4), np.clip(y, 1, 4)) assert eq(da.fabs(b), np.fabs(y)) assert eq(da.sign(b - 2), np.sign(y - 2)) l1, l2 = da.frexp(a) r1, r2 = np.frexp(x) assert eq(l1, r1) assert eq(l2, r2) l1, l2 = da.modf(a) r1, r2 = np.modf(x) assert eq(l1, r1) assert eq(l2, r2) assert eq(da.around(a, -1), np.around(x, -1))