Пример #1
0
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)
Пример #2
0
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
Пример #3
0
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
Пример #4
0
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
Пример #5
0
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
Пример #6
0
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
Пример #7
0
    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
Пример #8
0
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)