def test_coord_unit_conversion_operators(operation, result_units): in_km = Coord(data=np.linspace(4000, 1000, 10), units='km', mask=None, title='something') scalar = 2. operator_km = in_km.__getattribute__(operation) combined = operator_km(scalar) debug_(f'{operation}, {combined}') assert_equal_units(combined.units, result_units)
def _polybase(data, **kwargs): # Automatic baseline correction if data.ndim == 1: dat = np.array([ data, ]) nbzone = kwargs.pop("nbzone", 64) mult = kwargs.pop("mult", 4) order = kwargs.pop("order", 6) npts = data.shape[-1] w = np.arange(npts) baseline = np.ma.masked_array(dat, mask=True) sigma = 1.0e6 nw = int(npts / nbzone) # print (nw) # unmask extremities of the baseline baseline[:, :nw].mask = False baseline[:, -nw:].mask = False for j in range(nbzone): s = dat[:, nw * j:min(nw * (j + 1), npts + 1)] sigma = min(s.std(), sigma) nw = nw * 2 # bigger window nw2 = int(nw / 2) found = False nb = 0 nstd = 2.0 while (not found) or (nb < nw * mult): nb = 0 for i in range(nw2, npts - nw2 + 1, 1): s1 = dat[:, max(i - 1 - nw2, 0):min(i - 1 + nw2, npts + 1)] s2 = dat[:, max(i - nw2, 0):min(i + nw2, npts + 1)] s3 = dat[:, max(i + 1 - nw2, 0):min(i + 1 + nw2, npts + 1)] mi1, mi2, mi3 = s1.min(), s2.min(), s3.min() ma1, ma2, ma3 = s1.max(), s2.max(), s3.max() if (abs(ma1 - mi1) < float(nstd) * sigma and abs(ma2 - mi2) < float(nstd) * sigma and abs(ma3 - mi3) < float(nstd) * sigma): found = True nb += 1 baseline[:1, i].mask = False # baseline points # increase nstd nstd = nstd * 1.1 debug_("basf optimized nstd: %.2F mult: %.2f" % (nstd, mult)) wm = np.array(list(zip(*np.argwhere(~baseline[:1].mask)))[1]) bm = baseline[:, wm] if data.ndim > 1: bm = smooth(bm.T, max(int(dat.shape[0] / 10), 3)).T bm = smooth(bm, max(int(dat.shape[-1] / 10), 3)) # if not polynom: # sr = pchip(wm, bm.real) # si = pchip(wm, bm.imag) # baseline = sr(w) + si(w) * 1.0j # baseline = smooth(baseline, window_len=int(nw / 4)) # else: # fit a polynom pf = np.polyfit(wm, bm.T, order).T for i, row in enumerate(pf[:]): poly = np.poly1d(row) baseline[i] = poly(w) if data.ndim == 1: baseline = baseline[0] return baseline
def test_coord(): # simple coords a = Coord([1, 2, 3], name='x') assert a.id is not None assert not a.is_empty assert not a.is_masked assert_array_equal(a.data, np.array([1, 2, 3])) assert not a.is_labeled assert a.units is None assert a.unitless debug_(a.meta) assert not a.meta assert a.name == 'x' # set properties a.title = 'xxxx' assert a.title == 'xxxx' a.name = 'y' assert a.name == 'y' a.meta = None a.meta = {'val': 125} # need to be an OrderedDic assert a.meta['val'] == 125 # now with labels x = np.arange(10) y = list('abcdefghij') a = Coord(x, labels=y, title='processors', name='x') assert a.title == 'processors' assert isinstance(a.data, np.ndarray) assert isinstance(a.labels, np.ndarray) # any kind of object can be a label assert a.labels.dtype == 'O' # even an array a._labels[3] = x assert a._labels[3][2] == 2 # coords can be defined only with labels y = list('abcdefghij') a = Coord(labels=y, title='processors') assert a.title == 'processors' assert isinstance(a.labels, np.ndarray) assert_array_equal(a.values, a.labels) # any kind of object can be a label assert a.labels.dtype == 'O' # even an array a._labels[3] = range(10) assert a._labels[3][2] == 2 # coords with datetime from datetime import datetime x = np.arange(10) y = [datetime(2017, 6, 2 * (i + 1)) for i in x] a = Coord(x, labels=y, title='time') assert a.title == 'time' assert isinstance(a.data, np.ndarray) assert isinstance(a.labels, np.ndarray) a._sort(by='label', descend=True) # but coordinates must be 1D with pytest.raises(ValueError): # should raise an error as coords must be 1D Coord(data=np.ones((2, 10))) # unitless coordinates coord0 = Coord(data=np.linspace(4000, 1000, 10), labels=list('abcdefghij'), mask=None, units=None, title='wavelength') assert coord0.units is None assert coord0.data[0] == 4000. assert repr(coord0) == 'Coord: [float64] unitless (size: 10)' # dimensionless coordinates coord0 = Coord(data=np.linspace(4000, 1000, 10), labels=list('abcdefghij'), mask=None, units=ur.dimensionless, title='wavelength') assert coord0.units.dimensionless assert coord0.units.scaling == 1. assert coord0.data[0] == 4000. assert repr(coord0) == 'Coord: [float64] (size: 10)' # scaled dimensionless coordinates coord0 = Coord(data=np.linspace(4000, 1000, 10), labels=list('abcdefghij'), mask=None, units='m/km', title='wavelength') assert coord0.units.dimensionless assert coord0.data[ 0] == 4000. # <- displayed data to be multiplied by the scale factor assert repr( coord0) == 'Coord: [float64] scaled-dimensionless (0.001) (size: 10)' coord0 = Coord(data=np.linspace(4000, 1000, 10), labels=list('abcdefghij'), mask=None, units=ur.m / ur.km, title='wavelength') assert coord0.units.dimensionless assert coord0.data[ 0] == 4000. # <- displayed data to be multiplied by the scale factor assert repr( coord0) == 'Coord: [float64] scaled-dimensionless (0.001) (size: 10)' coord0 = Coord(data=np.linspace(4000, 1000, 10), labels=list('abcdefghij'), mask=None, units="m^2/s", title='wavelength') assert not coord0.units.dimensionless assert coord0.units.scaling == 1. assert coord0.data[0] == 4000. assert repr(coord0) == 'Coord: [float64] m^2.s^-1 (size: 10)' # comparison coord0 = Coord(data=np.linspace(4000, 1000, 10), labels=list('abcdefghij'), mask=None, title='wavelength') coord0b = Coord(data=np.linspace(4000, 1000, 10), labels='a b c d e f g h i j'.split(), mask=None, title='wavelength') coord1 = Coord(data=np.linspace(4000, 1000, 10), labels='a b c d e f g h i j'.split(), mask=None, title='titi') coord2 = Coord(data=np.linspace(4000, 1000, 10), labels='b c d e f g h i j a'.split(), mask=None, title='wavelength') coord3 = Coord(data=np.linspace(4000, 1000, 10), labels=None, mask=None, title='wavelength') assert coord0 == coord0b assert coord0 != coord1 # different title assert coord0 != coord2 # different labels assert coord0 != coord3 # one coord has no label # init from another coord coord0 = Coord(data=np.linspace(4000, 1000, 10), labels=list('abcdefghij'), units='s', mask=None, title='wavelength') coord1 = Coord(coord0) assert coord1._data is coord0._data coord1 = Coord(coord0, copy=True) assert coord1._data is not coord0._data assert_array_equal(coord1._data, coord0._data) assert isinstance(coord0, Coord) assert isinstance(coord1, Coord) # sort coord0 = Coord(data=np.linspace(4000, 1000, 10), labels=list('abcdefghij'), units='s', mask=None, title='wavelength') assert coord0.is_labeled ax = coord0._sort() assert (ax.data[0] == 1000) coord0._sort(descend=True, inplace=True) assert (coord0.data[0] == 4000) ax1 = coord0._sort(by='label', descend=True) assert (ax1.labels[0] == 'j') # copy coord0 = Coord(data=np.linspace(4000, 1000, 10), labels=list('abcdefghij'), units='s', mask=None, title='wavelength') coord1 = coord0.copy() assert coord1 is not coord0 assert_array_equal(coord1.data, coord0.data) assert_array_equal(coord1.labels, coord0.labels) assert coord1.units == coord0.units coord2 = copy(coord0) assert coord2 is not coord0 assert_array_equal(coord2.data, coord0.data) assert_array_equal(coord2.labels, coord0.labels) assert coord2.units == coord0.units # automatic reversing for wavenumbers coord0 = Coord(data=np.linspace(4000, 1000, 10), units='cm^-1', mask=None, title='wavenumbers') assert coord0.reversed
def _read_topspin(*args, **kwargs): debug_("Bruker TOPSPIN file reading") dataset, path = args # content = kwargs.get('content', None) # is-it a processed dataset (1r, 2rr .... processed = True if path.match("pdata/*/*") else False # ------------------------------------------------------------------------ # start reading .... # ------------------------------------------------------------------------ parents = path.parents # Get data and acquisition parameters if not processed: # a fid or a ser has been selected f_expno = parents[0] expno = f_expno.name procno = kwargs.get("procno", "1") f_procno = f_expno / "pdata" / procno f_name = parents[1] else: # a processes spectra has been selected (1r, ....) f_procno = parents[0] procno = f_procno.name f_expno = parents[2] expno = f_expno.name f_name = parents[3] acqus_files = _get_files(f_expno, "acqu") procs_files = _get_files(f_procno, "proc") if not processed: dic, data = read_fid(f_expno, acqus_files=acqus_files, procs_files=procs_files) # apply a -90 phase shift to be compatible with topspin data = data * np.exp(-1j * np.pi / 2.0) # Look the case when the reshaping was not correct # for example, this happen when the number # of accumulated row was incomplete if path.name in ["ser"] and data.ndim == 1: # we must reshape using the acqu parameters td1 = dic["acqu2"]["TD"] try: data = data.reshape(td1, -1) except ValueError: try: td = dic["acqu"]["TD"] // 2 data = data.reshape(-1, td) except ValueError: raise KeyError("Inconsistency between TD's and data size") # reduce to td ntd = dic["acqus"]["TD"] // 2 data = data[..., :ntd] # Eliminate the digital filter if kwargs.get("remove_digital_filter", True) and dic["acqus"]["DECIM"] > 1: data = _remove_digital_filter(dic, data) else: dic, datalist = read_pdata( f_procno, acqus_files=acqus_files, procs_files=procs_files, all_components=True, ) if isinstance(datalist, list): if datalist[0].ndim == 2: data, dataRI, dataIR, dataII = datalist # make quaternion shape = data.shape data = as_quat_array( list( zip( data.flatten(), dataRI.flatten(), dataIR.flatten(), dataII.flatten(), ))) data = data.reshape(shape) elif datalist[0].ndim == 1: # make complex data, dataI = datalist data = data + dataI * 1.0j else: return None else: data = datalist # ........................................................................................................ # we now make some rearrangement of the dic to have something more user friendly # we assume that all experiments have similar (important) parameters so that the experiments are compatibles meta = Meta() # This is the parameter dictionary datatype = path.name.upper() if not processed else f"{data.ndim}D" keys = sorted(dic.keys()) # we need the ndim of the data parmode = int(dic["acqus"].get("PARMODE", data.ndim - 1)) if parmode + 1 != data.ndim: raise KeyError( f"The NMR data were not read properly as the PARMODE+1 parameter ({parmode + 1}) doesn't fit" f" the actual number of dimensions ({data.ndim})") # read the acqu and proc valid_keys = list(zip(*nmr_valid_meta))[0] keys_units = dict(nmr_valid_meta) for item in keys: if item[:4] in ["acqu", "proc"]: dim = parmode if len(item) > 4 and item[4] in ["2", "3"]: dim = parmode + 1 - int(item[4]) for key in sorted(dic[item]): if key.startswith("_") or key.lower() not in valid_keys: continue value = dic[item][key] units = ur(keys_units[key.lower()]) if keys_units[ key.lower()] else None if units is not None: if isinstance(value, (float, int)): value = value * units # make a quantity elif isinstance(value, list) and isinstance( value[0], (float, int)): value = np.array(value) * units if key.lower() not in meta: meta[key.lower()] = [None] * data.ndim try: meta[key.lower()][dim] = value except Exception: pass else: meta[item.lower()] = dic[item] # Warning: from now all parameter keys are lowercase. # correct some initial values meta.encoding = [0] * (parmode + 1) meta.iscomplex = [False] * (parmode + 1) if not processed: meta.isfreq = [False] meta.encoding[-1] = AQ_mod[meta.aq_mod[-1]] meta.iscomplex[-1] = meta.aq_mod[-1] > 0 if datatype in ["SER"]: meta.isfreq.insert(0, False) if meta.fnmode[-2] == 0: # For historical reasons, # MC2 is interpreted when the acquisition status # parameter FnMODE has the value undefined, i.e. 0 if meta.mc2 is not None: meta.fnmode[-2] = meta.mc2[-2] + 1 meta.encoding[-2] = FnMODE[meta.fnmode[-2]] meta.iscomplex[-2] = meta.fnmode[-2] > 1 if parmode == 2: meta.isfreq.insert(0, False) if meta.fnmode[-3] == 0 and meta.mc2 is not None: meta.fnmode[-3] = meta.mc2[-3] + 1 meta.encoding[-3] = FnMODE[meta.fnmode[-3]] meta.iscomplex[-3] = meta.fnmode[-3] > 1 # correct TD, so it is the number of complex points, not the number of data # not for the last dimension which is already correct meta.tdeff = meta.td[:] meta.td = list(data.shape) for axis in range(parmode + 1): if meta.iscomplex[axis]: if axis != parmode: # already done for last axis meta.td[axis] = meta.td[axis] // 2 meta.tdeff[axis] = meta.tdeff[axis] // 2 meta.sw_h = [(meta.sw[axis].m * meta.sfo1[axis] * 1e-6).to("Hz") for axis in range(parmode + 1)] if processed: meta.si = [si for si in data.shape] meta.isfreq = [True] * (parmode + 1) # at least we assume this meta.phc0 = [0] * data.ndim # this transformation is to make data coherent with bruker processing if meta.iscomplex[-1]: data = np.conj(data * np.exp(np.pi * 1j / 2.0)) # normalised amplitudes to ns=1 and rg=1 def _norm(dat): meta.ns = meta.get( "ns", [1] * data.ndim) # sometimes these parameters are not present meta.rg = meta.get("rg", [1.0] * data.ndim) fac = float(meta.ns[-1]) * float(meta.rg[-1]) meta.rgold = [meta.rg[-1]] meta.rg[-1] = 1.0 meta.nsold = [meta.ns[-1]] # store the old value of NS meta.ns[-1] = 1 dat /= fac return dat data = _norm(data) # add some additional information in meta meta.expno = [int(expno)] # and the metadata (and make them readonly) meta.datatype = datatype meta.pathname = str(path) # add two parameters needed for phasing meta.pivot = [0] * data.ndim meta.exptc = [0] * data.ndim # make the corresponding axis # debug_('Create coords...') coords = [] axe_range = list(range(parmode + 1)) for axis in axe_range: if not meta.isfreq[axis]: # the axis is in time units dw = (1.0 / meta.sw_h[axis]).to("us") # coordpoints = np.arange(meta.td[axis]) # coord = Coord(coordpoints * dw, # title=f"F{axis + 1} acquisition time") # TODO: use AQSEQ for >2D data coord = LinearCoord( offset=0.0, increment=dw, units="us", size=meta.td[axis], title=f"F{axis + 1} acquisition time", ) coord.meta.larmor = meta.sfo1[axis] coords.append(coord) else: size = meta.si[axis] sizem = max(size - 1, 1) deltaf = -meta.sw_h[axis] / sizem first = meta.sfo1[axis] - meta.sf[axis] - deltaf * sizem / 2.0 # coord = Coord(np.arange(size) * deltaf + first) coord = LinearCoord(offset=first, increment=deltaf, size=size) coord.meta.larmor = meta.sfo1[ axis] # needed for ppm transformation coord.ito("ppm") if meta.nuc1 is not None: nuc1 = meta.nuc1[axis] regex = r"([^a-zA-Z]+)([a-zA-Z]+)" m = re.match(regex, nuc1) mass = m[1] name = m[2] nucleus = "^{" + mass + "}" + name else: nucleus = "" coord.title = rf"$\delta\ {nucleus}$" coords.append(coord) dataset.data = data for axis, cplex in enumerate(meta.iscomplex[::-1]): if cplex and axis > 0: dataset.set_quaternion(inplace=True) dataset.meta.update(meta) dataset.meta.readonly = True dataset.set_coordset(*tuple(coords)) dataset.title = "intensity" dataset.origin = "topspin" dataset.name = f"{f_name.name} expno:{expno} procno:{procno} ({datatype})" dataset.filename = f_name return dataset
def _read_opus(*args, **kwargs): debug_("Bruker OPUS import") dataset, filename = args content = kwargs.get("content", None) if content: fid = io.BytesIO(content) else: fid = open(filename, "rb") opus_data = _read_data(fid) # data try: npt = opus_data["AB Data Parameter"]["NPT"] data = opus_data["AB"][:npt] dataset.data = np.array(data[np.newaxis], dtype="float32") except KeyError: raise IOError( f"{filename} is not an Absorbance spectrum. It cannot be read with the `read_opus` import method" ) # todo: read background # xaxis fxv = opus_data["AB Data Parameter"]["FXV"] lxv = opus_data["AB Data Parameter"]["LXV"] # xdata = linspace(fxv, lxv, npt) xaxis = LinearCoord.linspace(fxv, lxv, npt, title="wavenumbers", units="cm^-1") # yaxis name = opus_data["Sample"]["SNM"] acqdate = opus_data["AB Data Parameter"]["DAT"] acqtime = opus_data["AB Data Parameter"]["TIM"] gmt_offset_hour = float(acqtime.split("GMT")[1].split(")")[0]) if len(acqdate.split("/")[0]) == 2: date_time = datetime.strptime( acqdate + "_" + acqtime.split()[0], "%d/%m/%Y_%H:%M:%S.%f" ) elif len(acqdate.split("/")[0]) == 4: date_time = datetime.strptime( acqdate + "_" + acqtime.split()[0], "%Y/%m/%d_%H:%M:%S" ) utc_dt = date_time - timedelta(hours=gmt_offset_hour) utc_dt = utc_dt.replace(tzinfo=timezone.utc) timestamp = utc_dt.timestamp() yaxis = Coord( [timestamp], title="acquisition timestamp (GMT)", units="s", labels=([utc_dt], [name], [filename]), ) # set dataset's Coordset dataset.set_coordset(y=yaxis, x=xaxis) dataset.units = "absorbance" dataset.title = "absorbance" # Set name, origin, description and history dataset.name = filename.name dataset.origin = "opus" dataset.description = "Dataset from opus files. \n" dataset.history = str(datetime.now(timezone.utc)) + ": import from opus files \n" dataset._date = datetime.now(timezone.utc) dataset._modified = dataset.date return dataset
def _read_opus(*args, **kwargs): debug_('Bruker OPUS import') dataset, filename = args content = kwargs.get('content', None) if content: fid = io.BytesIO(content) else: fid = open(filename, 'rb') opus_data = _read_data(fid) # data try: npt = opus_data['AB Data Parameter']['NPT'] data = opus_data["AB"][:npt] dataset.data = np.array(data[np.newaxis], dtype='float32') except KeyError: raise IOError( f"{filename} is not an Absorbance spectrum. It cannot be read with the `read_opus` import method" ) # xaxis fxv = opus_data['AB Data Parameter']['FXV'] lxv = opus_data['AB Data Parameter']['LXV'] # xdata = linspace(fxv, lxv, npt) xaxis = LinearCoord.linspace(fxv, lxv, npt, title='wavenumbers', units='cm^-1') # yaxis name = opus_data["Sample"]['SNM'] acqdate = opus_data["AB Data Parameter"]["DAT"] acqtime = opus_data["AB Data Parameter"]["TIM"] gmt_offset_hour = float(acqtime.split('GMT')[1].split(')')[0]) date_time = datetime.strptime(acqdate + '_' + acqtime.split()[0], '%d/%m/%Y_%H:%M:%S.%f') utc_dt = date_time - timedelta(hours=gmt_offset_hour) utc_dt = utc_dt.replace(tzinfo=timezone.utc) timestamp = utc_dt.timestamp() yaxis = Coord([timestamp], title='acquisition timestamp (GMT)', units='s', labels=([utc_dt], [name])) # set dataset's Coordset dataset.set_coordset(y=yaxis, x=xaxis) dataset.units = 'absorbance' dataset.title = 'absorbance' # Set name, origin, description and history dataset.name = filename.name dataset.origin = "opus" dataset.description = 'Dataset from opus files. \n' dataset.history = str(datetime.now( timezone.utc)) + ': import from opus files \n' dataset._date = datetime.now(timezone.utc) dataset._modified = dataset.date return dataset
def nlssubprob(V, W, Hinit, tol, maxiter): """ Parameters ---------- V, W Constant matrices. Hinit initial solution. tol: stopping tolerance. maxiter: limit of iterations. Returns ------- H, grad Output solution and gradient. """ H = Hinit WtV = np.dot(W.T, V) WtW = np.dot(W.T, W) alpha = 1 beta = 0.1 for n_iter in range(1, maxiter + 1): grad = np.dot(WtW, H) - WtV if norm(grad * np.logical_or(grad < 0, H > 0)) < tol: break Hp = H # search step size for inner_iter in range(20): # gradient step Hn = H - alpha * grad # gradient step Hn *= Hn > 0 d = Hn - H gradd = np.dot(grad.ravel(), d.ravel()) dQd = np.dot(np.dot(WtW, d).ravel(), d.ravel()) suff_decr = 0.99 * gradd + 0.5 * dQd < 0 if inner_iter == 0: decr_alpha = not suff_decr Hp = H if decr_alpha: if suff_decr: H = Hn break alpha = alpha * beta else: if not suff_decr or (Hp == Hn).all(): H = Hp break alpha = alpha / beta Hp = Hn if n_iter == maxiter: debug_("Max iter in nlssubprob") return H, grad, n_iter
def test_coord(): # simple coords a = Coord([1, 2, 3], name="x") assert a.id is not None assert not a.is_empty assert not a.is_masked assert_array_equal(a.data, np.array([1, 2, 3])) assert not a.is_labeled assert a.units is None assert a.unitless debug_(a.meta) assert not a.meta assert a.name == "x" # set properties a.title = "xxxx" assert a.title == "xxxx" a.name = "y" assert a.name == "y" a.meta = None a.meta = {"val": 125} # need to be an OrderedDic assert a.meta["val"] == 125 # now with labels x = np.arange(10) y = list("abcdefghij") a = Coord(x, labels=y, title="processors", name="x") assert a.title == "processors" assert isinstance(a.data, np.ndarray) assert isinstance(a.labels, np.ndarray) # any kind of object can be a label assert a.labels.dtype == "O" # even an array a._labels[3] = x assert a._labels[3][2] == 2 # coords can be defined only with labels y = list("abcdefghij") a = Coord(labels=y, title="processors") assert a.title == "processors" assert isinstance(a.labels, np.ndarray) assert_array_equal(a.values, a.labels) # any kind of object can be a label assert a.labels.dtype == "O" # even an array a._labels[3] = range(10) assert a._labels[3][2] == 2 # coords with datetime from datetime import datetime x = np.arange(10) y = [datetime(2017, 6, 2 * (i + 1)) for i in x] a = Coord(x, labels=y, title="time") assert a.title == "time" assert isinstance(a.data, np.ndarray) assert isinstance(a.labels, np.ndarray) a._sort(by="label", descend=True) # but coordinates must be 1D with pytest.raises(ValueError): # should raise an error as coords must be 1D Coord(data=np.ones((2, 10))) # unitless coordinates coord0 = Coord( data=np.linspace(4000, 1000, 10), labels=list("abcdefghij"), mask=None, units=None, title="wavelength", ) assert coord0.units is None assert coord0.data[0] == 4000.0 assert repr(coord0) == "Coord: [float64] unitless (size: 10)" # dimensionless coordinates coord0 = Coord( data=np.linspace(4000, 1000, 10), labels=list("abcdefghij"), mask=None, units=ur.dimensionless, title="wavelength", ) assert coord0.units.dimensionless assert coord0.units.scaling == 1.0 assert coord0.data[0] == 4000.0 assert repr(coord0) == "Coord: [float64] dimensionless (size: 10)" # scaled dimensionless coordinates coord0 = Coord( data=np.linspace(4000, 1000, 10), labels=list("abcdefghij"), mask=None, units="m/km", title="wavelength", ) assert coord0.units.dimensionless assert (coord0.data[0] == 4000.0 ) # <- displayed data to be multiplied by the scale factor assert repr( coord0) == "Coord: [float64] scaled-dimensionless (0.001) (size: 10)" coord0 = Coord( data=np.linspace(4000, 1000, 10), labels=list("abcdefghij"), mask=None, units=ur.m / ur.km, title="wavelength", ) assert coord0.units.dimensionless assert (coord0.data[0] == 4000.0 ) # <- displayed data to be multiplied by the scale factor assert repr( coord0) == "Coord: [float64] scaled-dimensionless (0.001) (size: 10)" coord0 = Coord( data=np.linspace(4000, 1000, 10), labels=list("abcdefghij"), mask=None, units="m^2/s", title="wavelength", ) assert not coord0.units.dimensionless assert coord0.units.scaling == 1.0 assert coord0.data[0] == 4000.0 assert repr(coord0) == "Coord: [float64] m².s⁻¹ (size: 10)" # comparison coord0 = Coord( data=np.linspace(4000, 1000, 10), labels=list("abcdefghij"), mask=None, title="wavelength", ) coord0b = Coord( data=np.linspace(4000, 1000, 10), labels="a b c d e f g h i j".split(), mask=None, title="wavelength", ) coord1 = Coord( data=np.linspace(4000, 1000, 10), labels="a b c d e f g h i j".split(), mask=None, title="titi", ) coord2 = Coord( data=np.linspace(4000, 1000, 10), labels="b c d e f g h i j a".split(), mask=None, title="wavelength", ) coord3 = Coord(data=np.linspace(4000, 1000, 10), labels=None, mask=None, title="wavelength") assert coord0 == coord0b assert coord0 != coord1 # different title assert coord0 != coord2 # different labels assert coord0 != coord3 # one coord has no label # init from another coord coord0 = Coord( data=np.linspace(4000, 1000, 10), labels=list("abcdefghij"), units="s", mask=None, title="wavelength", ) coord1 = Coord(coord0) assert coord1._data is coord0._data coord1 = Coord(coord0, copy=True) assert coord1._data is not coord0._data assert_array_equal(coord1._data, coord0._data) assert isinstance(coord0, Coord) assert isinstance(coord1, Coord) # sort coord0 = Coord( data=np.linspace(4000, 1000, 10), labels=list("abcdefghij"), units="s", mask=None, title="wavelength", ) assert coord0.is_labeled ax = coord0._sort() assert ax.data[0] == 1000 coord0._sort(descend=True, inplace=True) assert coord0.data[0] == 4000 ax1 = coord0._sort(by="label", descend=True) assert ax1.labels[0] == "j" # copy coord0 = Coord( data=np.linspace(4000, 1000, 10), labels=list("abcdefghij"), units="s", mask=None, title="wavelength", ) coord1 = coord0.copy() assert coord1 is not coord0 assert_array_equal(coord1.data, coord0.data) assert_array_equal(coord1.labels, coord0.labels) assert coord1.units == coord0.units coord2 = copy(coord0) assert coord2 is not coord0 assert_array_equal(coord2.data, coord0.data) assert_array_equal(coord2.labels, coord0.labels) assert coord2.units == coord0.units # automatic reversing for wavenumbers coord0 = Coord(data=np.linspace(4000, 1000, 10), units="cm^-1", mask=None, title="wavenumbers") assert coord0.reversed assert not coord0.is_complex assert not coord0.is_empty assert coord0.T == coord0 assert_array_equal(coord0.masked_data, coord0.data)