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 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 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 slerp(self, val, low, high): """Code from https://github.com/soumith/dcgan.torch/issues/14""" omega = da.arccos(da.clip(da.dot(low / da.linalg.norm(low), high.transpose() / da.linalg.norm(high)), -1, 1)) so = da.sin(omega) if so == 0: return (1.0-val) * low + val * high # L'Hopital's rule/LERP return da.sin((1.0 - val) * omega) / so * low + da.sin(val * omega) / so * high
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 test_dask_sin(df): X = np.array(df) Xdv = df.to_dask_array() sines = np.sin(Xdv).compute() assert sines[:, 0].tolist() == np.sin(df.x).tolist() assert sines[:, 1].tolist() == np.sin(df.y).tolist() # on a column x = df.x.to_numpy() xd = da.sin(df['x'].to_dask_array(chunks=(5, ))).compute() assert xd.tolist() == np.sin(df.x).tolist()
def get_phaang(cos_vza, cos_sza, sin_vza, sin_sza, cos_raa): """ Gets the phase angle """ cos_phase_angle = da.clip( cos_vza * cos_sza + sin_vza * sin_sza * cos_raa, -1, 1) phase_angle = da.arccos(cos_phase_angle) sin_phase_angle = da.sin(phase_angle) return cos_phase_angle, phase_angle, sin_phase_angle
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 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 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 _transformlng_dask(lng, lat): ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \ 0.1 * lng * lat + 0.1 * da.sqrt(da.fabs(lng)) ret += (20.0 * da.sin(6.0 * lng * pi) + 20.0 * da.sin(2.0 * lng * pi)) * 2.0 / 3.0 ret += (20.0 * da.sin(lng * pi) + 40.0 * da.sin(lng / 3.0 * pi)) * 2.0 / 3.0 ret += (150.0 * da.sin(lng / 12.0 * pi) + 300.0 * da.sin(lng / 30.0 * pi)) * 2.0 / 3.0 return ret
def _transformlat_dask(lng, lat): ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \ 0.1 * lng * lat + 0.2 * da.sqrt(da.fabs(lng)) ret += (20.0 * da.sin(6.0 * lng * pi) + 20.0 * da.sin(2.0 * lng * pi)) * 2.0 / 3.0 ret += (20.0 * da.sin(lat * pi) + 40.0 * da.sin(lat / 3.0 * pi)) * 2.0 / 3.0 ret += (160.0 * da.sin(lat / 12.0 * pi) + 320 * da.sin(lat * pi / 30.0)) * 2.0 / 3.0 return ret
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 test_dtype_complex(): x = np.arange(24).reshape((4, 6)).astype('f4') y = np.arange(24).reshape((4, 6)).astype('i8') z = np.arange(24).reshape((4, 6)).astype('i2') a = da.from_array(x, chunks=(2, 3)) b = da.from_array(y, chunks=(2, 3)) c = da.from_array(z, chunks=(2, 3)) def eq(a, b): return (isinstance(a, np.dtype) and isinstance(b, np.dtype) and str(a) == str(b)) assert eq(a._dtype, x.dtype) assert eq(b._dtype, y.dtype) assert eq((a + 1)._dtype, (x + 1).dtype) assert eq((a + b)._dtype, (x + y).dtype) assert eq(a.T._dtype, x.T.dtype) assert eq(a[:3]._dtype, x[:3].dtype) assert eq((a.dot(b.T))._dtype, (x.dot(y.T)).dtype) assert eq(stack([a, b])._dtype, np.vstack([x, y]).dtype) assert eq(concatenate([a, b])._dtype, np.concatenate([x, y]).dtype) assert eq(b.std()._dtype, y.std().dtype) assert eq(c.sum()._dtype, z.sum().dtype) assert eq(a.min()._dtype, a.min().dtype) assert eq(b.std()._dtype, b.std().dtype) assert eq(a.argmin(axis=0)._dtype, a.argmin(axis=0).dtype) assert eq(da.sin(c)._dtype, np.sin(z).dtype) assert eq(da.exp(b)._dtype, np.exp(y).dtype) assert eq(da.floor(a)._dtype, np.floor(x).dtype) assert eq(da.isnan(b)._dtype, np.isnan(y).dtype) with ignoring(ImportError): assert da.isnull(b)._dtype == 'bool' assert da.notnull(b)._dtype == 'bool' x = np.array([('a', 1)], dtype=[('text', 'S1'), ('numbers', 'i4')]) d = da.from_array(x, chunks=(1,)) assert eq(d['text']._dtype, x['text'].dtype) assert eq(d[['numbers', 'text']]._dtype, x[['numbers', 'text']].dtype)
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 test_dtype_complex(): x = np.arange(24).reshape((4, 6)).astype('f4') y = np.arange(24).reshape((4, 6)).astype('i8') z = np.arange(24).reshape((4, 6)).astype('i2') a = da.from_array(x, chunks=(2, 3)) b = da.from_array(y, chunks=(2, 3)) c = da.from_array(z, chunks=(2, 3)) def eq(a, b): return (isinstance(a, np.dtype) and isinstance(b, np.dtype) and str(a) == str(b)) assert eq(a._dtype, x.dtype) assert eq(b._dtype, y.dtype) assert eq((a + 1)._dtype, (x + 1).dtype) assert eq((a + b)._dtype, (x + y).dtype) assert eq(a.T._dtype, x.T.dtype) assert eq(a[:3]._dtype, x[:3].dtype) assert eq((a.dot(b.T))._dtype, (x.dot(y.T)).dtype) assert eq(stack([a, b])._dtype, np.vstack([x, y]).dtype) assert eq(concatenate([a, b])._dtype, np.concatenate([x, y]).dtype) assert eq(b.std()._dtype, y.std().dtype) assert eq(c.sum()._dtype, z.sum().dtype) assert eq(a.min()._dtype, a.min().dtype) assert eq(b.std()._dtype, b.std().dtype) assert eq(a.argmin(axis=0)._dtype, a.argmin(axis=0).dtype) assert eq(da.sin(c)._dtype, np.sin(z).dtype) assert eq(da.exp(b)._dtype, np.exp(y).dtype) assert eq(da.floor(a)._dtype, np.floor(x).dtype) assert eq(da.isnan(b)._dtype, np.isnan(y).dtype) with ignoring(ImportError): assert da.isnull(b)._dtype == 'bool' assert da.notnull(b)._dtype == 'bool' x = np.array([('a', 1)], dtype=[('text', 'S1'), ('numbers', 'i4')]) d = da.from_array(x, chunks=(1, )) assert eq(d['text']._dtype, x['text'].dtype) assert eq(d[['numbers', 'text']]._dtype, x[['numbers', 'text']].dtype)
def get_overlap(cos1, cos2, tan1, tan2, sin3, distance, hb, m_pi): """ Applies the HB ratio transformation """ OverlapInfo = namedtuple('OverlapInfo', 'tvar sint overlap temp') temp = (1.0 / cos1) + (1.0 / cos2) cost = da.clip( hb * da.sqrt(distance * distance + tan1 * tan1 * tan2 * tan2 * sin3 * sin3) / temp, -1, 1) tvar = da.arccos(cost) sint = da.sin(tvar) overlap = 1.0 / m_pi * (tvar - sint * cost) * temp overlap = da.maximum(overlap, 0) return OverlapInfo(tvar=tvar, sint=sint, overlap=overlap, temp=temp)
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 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))
# 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 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 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 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
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 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