Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
arrayprint.py1780 linesDownload Raw Back to _core
1"""Array printing function
2
3$Id: arrayprint.py,v 1.9 2005/09/13 13:58:44 teoliphant Exp $
4
5"""
6__all__ = ["array2string", "array_str", "array_repr",
7           "set_printoptions", "get_printoptions", "printoptions",
8           "format_float_positional", "format_float_scientific"]
9__docformat__ = 'restructuredtext'
10
11#
12# Written by Konrad Hinsen <hinsenk@ere.umontreal.ca>
13# last revision: 1996-3-13
14# modified by Jim Hugunin 1997-3-3 for repr's and str's (and other details)
15# and by Perry Greenfield 2000-4-1 for numarray
16# and by Travis Oliphant  2005-8-22 for numpy
17
18
19# Note: Both scalartypes.c.src and arrayprint.py implement strs for numpy
20# scalars but for different purposes. scalartypes.c.src has str/reprs for when
21# the scalar is printed on its own, while arrayprint.py has strs for when
22# scalars are printed inside an ndarray. Only the latter strs are currently
23# user-customizable.
24
25import functools
26import numbers
27import sys
28
29try:
30    from _thread import get_ident
31except ImportError:
32    from _dummy_thread import get_ident
33
34import contextlib
35import operator
36import warnings
37
38import numpy as np
39
40from . import numerictypes as _nt
41from .fromnumeric import any
42from .multiarray import (
43    array,
44    datetime_as_string,
45    datetime_data,
46    dragon4_positional,
47    dragon4_scientific,
48    ndarray,
49)
50from .numeric import asarray, concatenate, errstate
51from .numerictypes import complex128, flexible, float64, int_
52from .overrides import array_function_dispatch, set_module
53from .printoptions import format_options
54from .umath import absolute, isfinite, isinf, isnat
55
56
57def _make_options_dict(precision=None, threshold=None, edgeitems=None,
58                       linewidth=None, suppress=None, nanstr=None, infstr=None,
59                       sign=None, formatter=None, floatmode=None, legacy=None,
60                       override_repr=None):
61    """
62    Make a dictionary out of the non-None arguments, plus conversion of
63    *legacy* and sanity checks.
64    """
65
66    options = {k: v for k, v in list(locals().items()) if v is not None}
67
68    if suppress is not None:
69        options['suppress'] = bool(suppress)
70
71    modes = ['fixed', 'unique', 'maxprec', 'maxprec_equal']
72    if floatmode not in modes + [None]:
73        raise ValueError("floatmode option must be one of " +
74                         ", ".join(f'"{m}"' for m in modes))
75
76    if sign not in [None, '-', '+', ' ']:
77        raise ValueError("sign option must be one of ' ', '+', or '-'")
78
79    if legacy is False:
80        options['legacy'] = sys.maxsize
81    elif legacy == False:  # noqa: E712
82        warnings.warn(
83            f"Passing `legacy={legacy!r}` is deprecated.",
84            FutureWarning, stacklevel=3
85        )
86        options['legacy'] = sys.maxsize
87    elif legacy == '1.13':
88        options['legacy'] = 113
89    elif legacy == '1.21':
90        options['legacy'] = 121
91    elif legacy == '1.25':
92        options['legacy'] = 125
93    elif legacy == '2.1':
94        options['legacy'] = 201
95    elif legacy == '2.2':
96        options['legacy'] = 202
97    elif legacy is None:
98        pass  # OK, do nothing.
99    else:
100        warnings.warn(
101            "legacy printing option can currently only be '1.13', '1.21', "
102            "'1.25', '2.1', '2.2' or `False`", stacklevel=3)
103
104    if threshold is not None:
105        # forbid the bad threshold arg suggested by stack overflow, gh-12351
106        if not isinstance(threshold, numbers.Number):
107            raise TypeError("threshold must be numeric")
108        if np.isnan(threshold):
109            raise ValueError("threshold must be non-NAN, try "
110                             "sys.maxsize for untruncated representation")
111
112    if precision is not None:
113        # forbid the bad precision arg as suggested by issue #18254
114        try:
115            options['precision'] = operator.index(precision)
116        except TypeError as e:
117            raise TypeError('precision must be an integer') from e
118
119    return options
120
121
122@set_module('numpy')
123def set_printoptions(precision=None, threshold=None, edgeitems=None,
124                     linewidth=None, suppress=None, nanstr=None,
125                     infstr=None, formatter=None, sign=None, floatmode=None,
126                     *, legacy=None, override_repr=None):
127    """
128    Set printing options.
129
130    These options determine the way floating point numbers, arrays and
131    other NumPy objects are displayed.
132
133    Parameters
134    ----------
135    precision : int or None, optional
136        Number of digits of precision for floating point output (default 8).
137        May be None if `floatmode` is not `fixed`, to print as many digits as
138        necessary to uniquely specify the value.
139    threshold : int, optional
140        Total number of array elements which trigger summarization
141        rather than full repr (default 1000).
142        To always use the full repr without summarization, pass `sys.maxsize`.
143    edgeitems : int, optional
144        Number of array items in summary at beginning and end of
145        each dimension (default 3).
146    linewidth : int, optional
147        The number of characters per line for the purpose of inserting
148        line breaks (default 75).
149    suppress : bool, optional
150        If True, always print floating point numbers using fixed point
151        notation, in which case numbers equal to zero in the current precision
152        will print as zero.  If False, then scientific notation is used when
153        absolute value of the smallest number is < 1e-4 or the ratio of the
154        maximum absolute value to the minimum is > 1e3. The default is False.
155    nanstr : str, optional
156        String representation of floating point not-a-number (default nan).
157    infstr : str, optional
158        String representation of floating point infinity (default inf).
159    sign : string, either '-', '+', or ' ', optional
160        Controls printing of the sign of floating-point types. If '+', always
161        print the sign of positive values. If ' ', always prints a space
162        (whitespace character) in the sign position of positive values.  If
163        '-', omit the sign character of positive values. (default '-')
164
165        .. versionchanged:: 2.0
166             The sign parameter can now be an integer type, previously
167             types were floating-point types.
168
169    formatter : dict of callables, optional
170        If not None, the keys should indicate the type(s) that the respective
171        formatting function applies to.  Callables should return a string.
172        Types that are not specified (by their corresponding keys) are handled
173        by the default formatters.  Individual types for which a formatter
174        can be set are:
175
176        - 'bool'
177        - 'int'
178        - 'timedelta' : a `numpy.timedelta64`
179        - 'datetime' : a `numpy.datetime64`
180        - 'float'
181        - 'longfloat' : 128-bit floats
182        - 'complexfloat'
183        - 'longcomplexfloat' : composed of two 128-bit floats
184        - 'numpystr' : types `numpy.bytes_` and `numpy.str_`
185        - 'object' : `np.object_` arrays
186
187        Other keys that can be used to set a group of types at once are:
188
189        - 'all' : sets all types
190        - 'int_kind' : sets 'int'
191        - 'float_kind' : sets 'float' and 'longfloat'
192        - 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat'
193        - 'str_kind' : sets 'numpystr'
194    floatmode : str, optional
195        Controls the interpretation of the `precision` option for
196        floating-point types. Can take the following values
197        (default maxprec_equal):
198
199        * 'fixed': Always print exactly `precision` fractional digits,
200                even if this would print more or fewer digits than
201                necessary to specify the value uniquely.
202        * 'unique': Print the minimum number of fractional digits necessary
203                to represent each value uniquely. Different elements may
204                have a different number of digits. The value of the
205                `precision` option is ignored.
206        * 'maxprec': Print at most `precision` fractional digits, but if
207                an element can be uniquely represented with fewer digits
208                only print it with that many.
209        * 'maxprec_equal': Print at most `precision` fractional digits,
210                but if every element in the array can be uniquely
211                represented with an equal number of fewer digits, use that
212                many digits for all elements.
213    legacy : string or `False`, optional
214        If set to the string ``'1.13'`` enables 1.13 legacy printing mode. This
215        approximates numpy 1.13 print output by including a space in the sign
216        position of floats and different behavior for 0d arrays. This also
217        enables 1.21 legacy printing mode (described below).
218
219        If set to the string ``'1.21'`` enables 1.21 legacy printing mode. This
220        approximates numpy 1.21 print output of complex structured dtypes
221        by not inserting spaces after commas that separate fields and after
222        colons.
223
224        If set to ``'1.25'`` approximates printing of 1.25 which mainly means
225        that numeric scalars are printed without their type information, e.g.
226        as ``3.0`` rather than ``np.float64(3.0)``.
227
228        If set to ``'2.1'``, shape information is not given when arrays are
229        summarized (i.e., multiple elements replaced with ``...``).
230
231        If set to ``'2.2'``, the transition to use scientific notation for
232        printing ``np.float16`` and ``np.float32`` types may happen later or
233        not at all for larger values.
234
235        If set to `False`, disables legacy mode.
236
237        Unrecognized strings will be ignored with a warning for forward
238        compatibility.
239
240        .. versionchanged:: 1.22.0
241        .. versionchanged:: 2.2
242
243    override_repr: callable, optional
244        If set a passed function will be used for generating arrays' repr.
245        Other options will be ignored.
246
247    See Also
248    --------
249    get_printoptions, printoptions, array2string
250
251
252    Notes
253    -----
254
255    * ``formatter`` is always reset with a call to `set_printoptions`.
256    * Use `printoptions` as a context manager to set the values temporarily.
257    * These print options apply only to NumPy ndarrays, not to scalars.
258
259    **Concurrency note:** see :ref:`text_formatting_options`
260
261    Examples
262    --------
263    Floating point precision can be set:
264
265    >>> import numpy as np
266    >>> np.set_printoptions(precision=4)
267    >>> np.array([1.123456789])
268    [1.1235]
269
270    Long arrays can be summarised:
271
272    >>> np.set_printoptions(threshold=5)
273    >>> np.arange(10)
274    array([0, 1, 2, ..., 7, 8, 9], shape=(10,))
275
276    Small results can be suppressed:
277
278    >>> eps = np.finfo(float).eps
279    >>> x = np.arange(4.)
280    >>> x**2 - (x + eps)**2
281    array([-4.9304e-32, -4.4409e-16,  0.0000e+00,  0.0000e+00])
282    >>> np.set_printoptions(suppress=True)
283    >>> x**2 - (x + eps)**2
284    array([-0., -0.,  0.,  0.])
285
286    A custom formatter can be used to display array elements as desired:
287
288    >>> np.set_printoptions(formatter={'all':lambda x: 'int: '+str(-x)})
289    >>> x = np.arange(3)
290    >>> x
291    array([int: 0, int: -1, int: -2])
292    >>> np.set_printoptions()  # formatter gets reset
293    >>> x
294    array([0, 1, 2])
295
296    To put back the default options, you can use:
297
298    >>> np.set_printoptions(edgeitems=3, infstr='inf',
299    ... linewidth=75, nanstr='nan', precision=8,
300    ... suppress=False, threshold=1000, formatter=None)
301
302    Also to temporarily override options, use `printoptions`
303    as a context manager:
304
305    >>> with np.printoptions(precision=2, suppress=True, threshold=5):
306    ...     np.linspace(0, 10, 10)
307    array([ 0.  ,  1.11,  2.22, ...,  7.78,  8.89, 10.  ], shape=(10,))
308
309    """
310    _set_printoptions(precision, threshold, edgeitems, linewidth, suppress,
311                      nanstr, infstr, formatter, sign, floatmode,
312                      legacy=legacy, override_repr=override_repr)
313
314
315def _set_printoptions(precision=None, threshold=None, edgeitems=None,
316                      linewidth=None, suppress=None, nanstr=None,
317                      infstr=None, formatter=None, sign=None, floatmode=None,
318                      *, legacy=None, override_repr=None):
319    new_opt = _make_options_dict(precision, threshold, edgeitems, linewidth,
320                                 suppress, nanstr, infstr, sign, formatter,
321                                 floatmode, legacy)
322    # formatter and override_repr are always reset
323    new_opt['formatter'] = formatter
324    new_opt['override_repr'] = override_repr
325
326    updated_opt = format_options.get() | new_opt
327    updated_opt.update(new_opt)
328
329    if updated_opt['legacy'] == 113:
330        updated_opt['sign'] = '-'
331
332    return format_options.set(updated_opt)
333
334
335@set_module('numpy')
336def get_printoptions():
337    """
338    Return the current print options.
339
340    Returns
341    -------
342    print_opts : dict
343        Dictionary of current print options with keys
344
345        - precision : int
346        - threshold : int
347        - edgeitems : int
348        - linewidth : int
349        - suppress : bool
350        - nanstr : str
351        - infstr : str
352        - sign : str
353        - formatter : dict of callables
354        - floatmode : str
355        - legacy : str or False
356
357        For a full description of these options, see `set_printoptions`.
358
359    Notes
360    -----
361    These print options apply only to NumPy ndarrays, not to scalars.
362
363    **Concurrency note:** see :ref:`text_formatting_options`
364
365    See Also
366    --------
367    set_printoptions, printoptions
368
369    Examples
370    --------
371    >>> import numpy as np
372
373    >>> np.get_printoptions()
374    {'edgeitems': 3, 'threshold': 1000, ..., 'override_repr': None}
375
376    >>> np.get_printoptions()['linewidth']
377    75
378    >>> np.set_printoptions(linewidth=100)
379    >>> np.get_printoptions()['linewidth']
380    100
381
382    """
383    opts = format_options.get().copy()
384    opts['legacy'] = {
385        113: '1.13', 121: '1.21', 125: '1.25', 201: '2.1',
386        202: '2.2', sys.maxsize: False,
387    }[opts['legacy']]
388    return opts
389
390
391def _get_legacy_print_mode():
392    """Return the legacy print mode as an int."""
393    return format_options.get()['legacy']
394
395
396@set_module('numpy')
397@contextlib.contextmanager
398def printoptions(*args, **kwargs):
399    """Context manager for setting print options.
400
401    Set print options for the scope of the `with` block, and restore the old
402    options at the end. See `set_printoptions` for the full description of
403    available options.
404
405    Examples
406    --------
407    >>> import numpy as np
408
409    >>> from numpy.testing import assert_equal
410    >>> with np.printoptions(precision=2):
411    ...     np.array([2.0]) / 3
412    array([0.67])
413
414    The `as`-clause of the `with`-statement gives the current print options:
415
416    >>> with np.printoptions(precision=2) as opts:
417    ...      assert_equal(opts, np.get_printoptions())
418
419    See Also
420    --------
421    set_printoptions, get_printoptions
422
423    Notes
424    -----
425    These print options apply only to NumPy ndarrays, not to scalars.
426
427    **Concurrency note:** see :ref:`text_formatting_options`
428
429    """
430    token = _set_printoptions(*args, **kwargs)
431
432    try:
433        yield get_printoptions()
434    finally:
435        format_options.reset(token)
436
437
438def _leading_trailing(a, edgeitems, index=()):
439    """
440    Keep only the N-D corners (leading and trailing edges) of an array.
441
442    Should be passed a base-class ndarray, since it makes no guarantees about
443    preserving subclasses.
444    """
445    axis = len(index)
446    if axis == a.ndim:
447        return a[index]
448
449    if a.shape[axis] > 2 * edgeitems:
450        return concatenate((
451            _leading_trailing(a, edgeitems, index + np.index_exp[:edgeitems]),
452            _leading_trailing(a, edgeitems, index + np.index_exp[-edgeitems:])
453        ), axis=axis)
454    else:
455        return _leading_trailing(a, edgeitems, index + np.index_exp[:])
456
457
458def _object_format(o):
459    """ Object arrays containing lists should be printed unambiguously """
460    if type(o) is list:
461        fmt = 'list({!r})'
462    else:
463        fmt = '{!r}'
464    return fmt.format(o)
465
466def repr_format(x):
467    if isinstance(x, (np.str_, np.bytes_)):
468        return repr(x.item())
469    return repr(x)
470
471def str_format(x):
472    if isinstance(x, (np.str_, np.bytes_)):
473        return str(x.item())
474    return str(x)
475
476def _get_formatdict(data, *, precision, floatmode, suppress, sign, legacy,
477                    formatter, **kwargs):
478    # note: extra arguments in kwargs are ignored
479
480    # wrapped in lambdas to avoid taking a code path
481    # with the wrong type of data
482    formatdict = {
483        'bool': lambda: BoolFormat(data),
484        'int': lambda: IntegerFormat(data, sign),
485        'float': lambda: FloatingFormat(
486            data, precision, floatmode, suppress, sign, legacy=legacy),
487        'longfloat': lambda: FloatingFormat(
488            data, precision, floatmode, suppress, sign, legacy=legacy),
489        'complexfloat': lambda: ComplexFloatingFormat(
490            data, precision, floatmode, suppress, sign, legacy=legacy),
491        'longcomplexfloat': lambda: ComplexFloatingFormat(
492            data, precision, floatmode, suppress, sign, legacy=legacy),
493        'datetime': lambda: DatetimeFormat(data, legacy=legacy),
494        'timedelta': lambda: TimedeltaFormat(data),
495        'object': lambda: _object_format,
496        'void': lambda: str_format,
497        'numpystr': lambda: repr_format}
498
499    # we need to wrap values in `formatter` in a lambda, so that the interface
500    # is the same as the above values.
501    def indirect(x):
502        return lambda: x
503
504    if formatter is not None:
505        fkeys = [k for k in formatter.keys() if formatter[k] is not None]
506        if 'all' in fkeys:
507            for key in formatdict.keys():
508                formatdict[key] = indirect(formatter['all'])
509        if 'int_kind' in fkeys:
510            for key in ['int']:
511                formatdict[key] = indirect(formatter['int_kind'])
512        if 'float_kind' in fkeys:
513            for key in ['float', 'longfloat']:
514                formatdict[key] = indirect(formatter['float_kind'])
515        if 'complex_kind' in fkeys:
516            for key in ['complexfloat', 'longcomplexfloat']:
517                formatdict[key] = indirect(formatter['complex_kind'])
518        if 'str_kind' in fkeys:
519            formatdict['numpystr'] = indirect(formatter['str_kind'])
520        for key in formatdict.keys():
521            if key in fkeys:
522                formatdict[key] = indirect(formatter[key])
523
524    return formatdict
525
526def _get_format_function(data, **options):
527    """
528    find the right formatting function for the dtype_
529    """
530    dtype_ = data.dtype
531    dtypeobj = dtype_.type
532    formatdict = _get_formatdict(data, **options)
533    if dtypeobj is None:
534        return formatdict["numpystr"]()
535    elif issubclass(dtypeobj, _nt.bool):
536        return formatdict['bool']()
537    elif issubclass(dtypeobj, _nt.integer):
538        if issubclass(dtypeobj, _nt.timedelta64):
539            return formatdict['timedelta']()
540        else:
541            return formatdict['int']()
542    elif issubclass(dtypeobj, _nt.floating):
543        if issubclass(dtypeobj, _nt.longdouble):
544            return formatdict['longfloat']()
545        else:
546            return formatdict['float']()
547    elif issubclass(dtypeobj, _nt.complexfloating):
548        if issubclass(dtypeobj, _nt.clongdouble):
549            return formatdict['longcomplexfloat']()
550        else:
551            return formatdict['complexfloat']()
552    elif issubclass(dtypeobj, (_nt.str_, _nt.bytes_)):
553        return formatdict['numpystr']()
554    elif issubclass(dtypeobj, _nt.datetime64):
555        return formatdict['datetime']()
556    elif issubclass(dtypeobj, _nt.object_):
557        return formatdict['object']()
558    elif issubclass(dtypeobj, _nt.void):
559        if dtype_.names is not None:
560            return StructuredVoidFormat.from_data(data, **options)
561        else:
562            return formatdict['void']()
563    else:
564        return formatdict['numpystr']()
565
566
567def _recursive_guard(fillvalue='...'):
568    """
569    Like the python 3.2 reprlib.recursive_repr, but forwards *args and **kwargs
570
571    Decorates a function such that if it calls itself with the same first
572    argument, it returns `fillvalue` instead of recursing.
573
574    Largely copied from reprlib.recursive_repr
575    """
576
577    def decorating_function(f):
578        repr_running = set()
579
580        @functools.wraps(f)
581        def wrapper(self, *args, **kwargs):
582            key = id(self), get_ident()
583            if key in repr_running:
584                return fillvalue
585            repr_running.add(key)
586            try:
587                return f(self, *args, **kwargs)
588            finally:
589                repr_running.discard(key)
590
591        return wrapper
592
593    return decorating_function
594
595
596# gracefully handle recursive calls, when object arrays contain themselves
597@_recursive_guard()
598def _array2string(a, options, separator=' ', prefix=""):
599    # The formatter __init__s in _get_format_function cannot deal with
600    # subclasses yet, and we also need to avoid recursion issues in
601    # _formatArray with subclasses which return 0d arrays in place of scalars
602    data = asarray(a)
603    if a.shape == ():
604        a = data
605
606    if a.size > options['threshold']:
607        summary_insert = "..."
608        data = _leading_trailing(data, options['edgeitems'])
609    else:
610        summary_insert = ""
611
612    # find the right formatting function for the array
613    format_function = _get_format_function(data, **options)
614
615    # skip over "["
616    next_line_prefix = " "
617    # skip over array(
618    next_line_prefix += " " * len(prefix)
619
620    lst = _formatArray(a, format_function, options['linewidth'],
621                       next_line_prefix, separator, options['edgeitems'],
622                       summary_insert, options['legacy'])
623    return lst
624
625
626def _array2string_dispatcher(
627        a, max_line_width=None, precision=None,
628        suppress_small=None, separator=None, prefix=None,
629        *, formatter=None, threshold=None,
630        edgeitems=None, sign=None, floatmode=None, suffix=None,
631        legacy=None):
632    return (a,)
633
634
635@array_function_dispatch(_array2string_dispatcher, module='numpy')
636def array2string(a, max_line_width=None, precision=None,
637                 suppress_small=None, separator=' ', prefix="",
638                 *, formatter=None, threshold=None,
639                 edgeitems=None, sign=None, floatmode=None, suffix="",
640                 legacy=None):
641    """
642    Return a string representation of an array.
643
644    Parameters
645    ----------
646    a : ndarray
647        Input array.
648    max_line_width : int, optional
649        Inserts newlines if text is longer than `max_line_width`.
650        Defaults to ``numpy.get_printoptions()['linewidth']``.
651    precision : int or None, optional
652        Floating point precision.
653        Defaults to ``numpy.get_printoptions()['precision']``.
654    suppress_small : bool, optional
655        Represent numbers "very close" to zero as zero; default is False.
656        Very close is defined by precision: if the precision is 8, e.g.,
657        numbers smaller (in absolute value) than 5e-9 are represented as
658        zero.
659        Defaults to ``numpy.get_printoptions()['suppress']``.
660    separator : str, optional
661        Inserted between elements.
662    prefix : str, optional
663    suffix : str, optional
664        The length of the prefix and suffix strings are used to respectively
665        align and wrap the output. An array is typically printed as::
666
667          prefix + array2string(a) + suffix
668
669        The output is left-padded by the length of the prefix string, and
670        wrapping is forced at the column ``max_line_width - len(suffix)``.
671        It should be noted that the content of prefix and suffix strings are
672        not included in the output.
673    formatter : dict of callables, optional
674        If not None, the keys should indicate the type(s) that the respective
675        formatting function applies to.  Callables should return a string.
676        Types that are not specified (by their corresponding keys) are handled
677        by the default formatters.  Individual types for which a formatter
678        can be set are:
679
680        - 'bool'
681        - 'int'
682        - 'timedelta' : a `numpy.timedelta64`
683        - 'datetime' : a `numpy.datetime64`
684        - 'float'
685        - 'longfloat' : 128-bit floats
686        - 'complexfloat'
687        - 'longcomplexfloat' : composed of two 128-bit floats
688        - 'void' : type `numpy.void`
689        - 'numpystr' : types `numpy.bytes_` and `numpy.str_`
690
691        Other keys that can be used to set a group of types at once are:
692
693        - 'all' : sets all types
694        - 'int_kind' : sets 'int'
695        - 'float_kind' : sets 'float' and 'longfloat'
696        - 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat'
697        - 'str_kind' : sets 'numpystr'
698    threshold : int, optional
699        Total number of array elements which trigger summarization
700        rather than full repr.
701        Defaults to ``numpy.get_printoptions()['threshold']``.
702    edgeitems : int, optional
703        Number of array items in summary at beginning and end of
704        each dimension.
705        Defaults to ``numpy.get_printoptions()['edgeitems']``.
706    sign : string, either '-', '+', or ' ', optional
707        Controls printing of the sign of floating-point types. If '+', always
708        print the sign of positive values. If ' ', always prints a space
709        (whitespace character) in the sign position of positive values.  If
710        '-', omit the sign character of positive values.
711        Defaults to ``numpy.get_printoptions()['sign']``.
712
713        .. versionchanged:: 2.0
714             The sign parameter can now be an integer type, previously
715             types were floating-point types.
716
717    floatmode : str, optional
718        Controls the interpretation of the `precision` option for
719        floating-point types.
720        Defaults to ``numpy.get_printoptions()['floatmode']``.
721        Can take the following values:
722
723        - 'fixed': Always print exactly `precision` fractional digits,
724          even if this would print more or fewer digits than
725          necessary to specify the value uniquely.
726        - 'unique': Print the minimum number of fractional digits necessary
727          to represent each value uniquely. Different elements may
728          have a different number of digits.  The value of the
729          `precision` option is ignored.
730        - 'maxprec': Print at most `precision` fractional digits, but if
731          an element can be uniquely represented with fewer digits
732          only print it with that many.
733        - 'maxprec_equal': Print at most `precision` fractional digits,
734          but if every element in the array can be uniquely
735          represented with an equal number of fewer digits, use that
736          many digits for all elements.
737    legacy : string or `False`, optional
738        If set to the string ``'1.13'`` enables 1.13 legacy printing mode. This
739        approximates numpy 1.13 print output by including a space in the sign
740        position of floats and different behavior for 0d arrays. If set to
741        `False`, disables legacy mode. Unrecognized strings will be ignored
742        with a warning for forward compatibility.
743
744    Returns
745    -------
746    array_str : str
747        String representation of the array.
748
749    Raises
750    ------
751    TypeError
752        if a callable in `formatter` does not return a string.
753
754    See Also
755    --------
756    array_str, array_repr, set_printoptions, get_printoptions
757
758    Notes
759    -----
760    If a formatter is specified for a certain type, the `precision` keyword is
761    ignored for that type.
762
763    This is a very flexible function; `array_repr` and `array_str` are using
764    `array2string` internally so keywords with the same name should work
765    identically in all three functions.
766
767    Examples
768    --------
769    >>> import numpy as np
770    >>> x = np.array([1e-16,1,2,3])
771    >>> np.array2string(x, precision=2, separator=',',
772    ...                       suppress_small=True)
773    '[0.,1.,2.,3.]'
774
775    >>> x  = np.arange(3.)
776    >>> np.array2string(x, formatter={'float_kind':lambda x: "%.2f" % x})
777    '[0.00 1.00 2.00]'
778
779    >>> x  = np.arange(3)
780    >>> np.array2string(x, formatter={'int':lambda x: hex(x)})
781    '[0x0 0x1 0x2]'
782
783    """
784
785    overrides = _make_options_dict(precision, threshold, edgeitems,
786                                   max_line_width, suppress_small, None, None,
787                                   sign, formatter, floatmode, legacy)
788    options = format_options.get().copy()
789    options.update(overrides)
790
791    if options['legacy'] <= 113:
792        if a.shape == () and a.dtype.names is None:
793            return repr(a.item())
794
795    if options['legacy'] > 113:
796        options['linewidth'] -= len(suffix)
797
798    # treat as a null array if any of shape elements == 0
799    if a.size == 0:
800        return "[]"
801
802    return _array2string(a, options, separator, prefix)
803
804
805def _extendLine(s, line, word, line_width, next_line_prefix, legacy):
806    needs_wrap = len(line) + len(word) > line_width
807    if legacy > 113:
808        # don't wrap lines if it won't help
809        if len(line) <= len(next_line_prefix):
810            needs_wrap = False
811
812    if needs_wrap:
813        s += line.rstrip() + "\n"
814        line = next_line_prefix
815    line += word
816    return s, line
817
818
819def _extendLine_pretty(s, line, word, line_width, next_line_prefix, legacy):
820    """
821    Extends line with nicely formatted (possibly multi-line) string ``word``.
822    """
823    words = word.splitlines()
824    if len(words) == 1 or legacy <= 113:
825        return _extendLine(s, line, word, line_width, next_line_prefix, legacy)
826
827    max_word_length = max(len(word) for word in words)
828    if (len(line) + max_word_length > line_width and
829            len(line) > len(next_line_prefix)):
830        s += line.rstrip() + '\n'
831        line = next_line_prefix + words[0]
832        indent = next_line_prefix
833    else:
834        indent = len(line) * ' '
835        line += words[0]
836
837    for word in words[1::]:
838        s += line.rstrip() + '\n'
839        line = indent + word
840
841    suffix_length = max_word_length - len(words[-1])
842    line += suffix_length * ' '
843
844    return s, line
845
846def _formatArray(a, format_function, line_width, next_line_prefix,
847                 separator, edge_items, summary_insert, legacy):
848    """formatArray is designed for two modes of operation:
849
850    1. Full output
851
852    2. Summarized output
853
854    """
855    def recurser(index, hanging_indent, curr_width):
856        """
857        By using this local function, we don't need to recurse with all the
858        arguments. Since this function is not created recursively, the cost is
859        not significant
860        """
861        axis = len(index)
862        axes_left = a.ndim - axis
863
864        if axes_left == 0:
865            return format_function(a[index])
866
867        # when recursing, add a space to align with the [ added, and reduce the
868        # length of the line by 1
869        next_hanging_indent = hanging_indent + ' '
870        if legacy <= 113:
871            next_width = curr_width
872        else:
873            next_width = curr_width - len(']')
874
875        a_len = a.shape[axis]
876        show_summary = summary_insert and 2 * edge_items < a_len
877        if show_summary:
878            leading_items = edge_items
879            trailing_items = edge_items
880        else:
881            leading_items = 0
882            trailing_items = a_len
883
884        # stringify the array with the hanging indent on the first line too
885        s = ''
886
887        # last axis (rows) - wrap elements if they would not fit on one line
888        if axes_left == 1:
889            # the length up until the beginning of the separator / bracket
890            if legacy <= 113:
891                elem_width = curr_width - len(separator.rstrip())
892            else:
893                elem_width = curr_width - max(
894                    len(separator.rstrip()), len(']')
895                )
896
897            line = hanging_indent
898            for i in range(leading_items):
899                word = recurser(index + (i,), next_hanging_indent, next_width)
900                s, line = _extendLine_pretty(
901                    s, line, word, elem_width, hanging_indent, legacy)
902                line += separator
903
904            if show_summary:
905                s, line = _extendLine(
906                    s, line, summary_insert, elem_width, hanging_indent, legacy
907                )
908                if legacy <= 113:
909                    line += ", "
910                else:
911                    line += separator
912
913            for i in range(trailing_items, 1, -1):
914                word = recurser(index + (-i,), next_hanging_indent, next_width)
915                s, line = _extendLine_pretty(
916                    s, line, word, elem_width, hanging_indent, legacy)
917                line += separator
918
919            if legacy <= 113:
920                # width of the separator is not considered on 1.13
921                elem_width = curr_width
922            word = recurser(index + (-1,), next_hanging_indent, next_width)
923            s, line = _extendLine_pretty(
924                s, line, word, elem_width, hanging_indent, legacy)
925
926            s += line
927
928        # other axes - insert newlines between rows
929        else:
930            s = ''
931            line_sep = separator.rstrip() + '\n' * (axes_left - 1)
932
933            for i in range(leading_items):
934                nested = recurser(
935                    index + (i,), next_hanging_indent, next_width
936                )
937                s += hanging_indent + nested + line_sep
938
939            if show_summary:
940                if legacy <= 113:
941                    # trailing space, fixed nbr of newlines,
942                    # and fixed separator
943                    s += hanging_indent + summary_insert + ", \n"
944                else:
945                    s += hanging_indent + summary_insert + line_sep
946
947            for i in range(trailing_items, 1, -1):
948                nested = recurser(index + (-i,), next_hanging_indent,
949                                  next_width)
950                s += hanging_indent + nested + line_sep
951
952            nested = recurser(index + (-1,), next_hanging_indent, next_width)
953            s += hanging_indent + nested
954
955        # remove the hanging indent, and wrap in []
956        s = '[' + s[len(hanging_indent):] + ']'
957        return s
958
959    try:
960        # invoke the recursive part with an initial index and prefix
961        return recurser(index=(),
962                        hanging_indent=next_line_prefix,
963                        curr_width=line_width)
964    finally:
965        # recursive closures have a cyclic reference to themselves, which
966        # requires gc to collect (gh-10620). To avoid this problem, for
967        # performance and PyPy friendliness, we break the cycle:
968        recurser = None
969
970def _none_or_positive_arg(x, name):
971    if x is None:
972        return -1
973    if x < 0:
974        raise ValueError(f"{name} must be >= 0")
975    return x
976
977class FloatingFormat:
978    """ Formatter for subtypes of np.floating """
979    def __init__(self, data, precision, floatmode, suppress_small, sign=False,
980                 *, legacy=None):
981        # for backcompatibility, accept bools
982        if isinstance(sign, bool):
983            sign = '+' if sign else '-'
984
985        self._legacy = legacy
986        if self._legacy <= 113:
987            # when not 0d, legacy does not support '-'
988            if data.shape != () and sign == '-':
989                sign = ' '
990
991        self.floatmode = floatmode
992        if floatmode == 'unique':
993            self.precision = None
994        else:
995            self.precision = precision
996
997        self.precision = _none_or_positive_arg(self.precision, 'precision')
998
999        self.suppress_small = suppress_small
1000        self.sign = sign
1001        self.exp_format = False
1002        self.large_exponent = False
1003        self.fillFormat(data)
1004
1005    def fillFormat(self, data):
1006        # only the finite values are used to compute the number of digits
1007        finite_vals = data[isfinite(data)]
1008
1009        # choose exponential mode based on the non-zero finite values:
1010        abs_non_zero = absolute(finite_vals[finite_vals != 0])
1011        if len(abs_non_zero) != 0:
1012            max_val = np.max(abs_non_zero)
1013            min_val = np.min(abs_non_zero)
1014            if self._legacy <= 202:
1015                exp_cutoff_max = 1.e8
1016            else:
1017                # consider data type while deciding the max cutoff for exp format
1018                exp_cutoff_max = 10.**min(8, np.finfo(data.dtype).precision)
1019            with errstate(over='ignore'):  # division can overflow
1020                if max_val >= exp_cutoff_max or (not self.suppress_small and
1021                        (min_val < 0.0001 or max_val / min_val > 1000.)):
1022                    self.exp_format = True
1023
1024        # do a first pass of printing all the numbers, to determine sizes
1025        if len(finite_vals) == 0:
1026            self.pad_left = 0
1027            self.pad_right = 0
1028            self.trim = '.'
1029            self.exp_size = -1
1030            self.unique = True
1031            self.min_digits = None
1032        elif self.exp_format:
1033            trim, unique = '.', True
1034            if self.floatmode == 'fixed' or self._legacy <= 113:
1035                trim, unique = 'k', False
1036            strs = (dragon4_scientific(x, precision=self.precision,
1037                               unique=unique, trim=trim, sign=self.sign == '+')
1038                    for x in finite_vals)
1039            frac_strs, _, exp_strs = zip(*(s.partition('e') for s in strs))
1040            int_part, frac_part = zip(*(s.split('.') for s in frac_strs))
1041            self.exp_size = max(len(s) for s in exp_strs) - 1
1042
1043            self.trim = 'k'
1044            self.precision = max(len(s) for s in frac_part)
1045            self.min_digits = self.precision
1046            self.unique = unique
1047
1048            # for back-compat with np 1.13, use 2 spaces & sign and full prec
1049            if self._legacy <= 113:
1050                self.pad_left = 3
1051            else:
1052                # this should be only 1 or 2. Can be calculated from sign.
1053                self.pad_left = max(len(s) for s in int_part)
1054            # pad_right is only needed for nan length calculation
1055            self.pad_right = self.exp_size + 2 + self.precision
1056        else:
1057            trim, unique = '.', True
1058            if self.floatmode == 'fixed':
1059                trim, unique = 'k', False
1060            strs = (dragon4_positional(x, precision=self.precision,
1061                                       fractional=True,
1062                                       unique=unique, trim=trim,
1063                                       sign=self.sign == '+')
1064                    for x in finite_vals)
1065            int_part, frac_part = zip(*(s.split('.') for s in strs))
1066            if self._legacy <= 113:
1067                self.pad_left = 1 + max(len(s.lstrip('-+')) for s in int_part)
1068            else:
1069                self.pad_left = max(len(s) for s in int_part)
1070            self.pad_right = max(len(s) for s in frac_part)
1071            self.exp_size = -1
1072            self.unique = unique
1073
1074            if self.floatmode in ['fixed', 'maxprec_equal']:
1075                self.precision = self.min_digits = self.pad_right
1076                self.trim = 'k'
1077            else:
1078                self.trim = '.'
1079                self.min_digits = 0
1080
1081        if self._legacy > 113:
1082            # account for sign = ' ' by adding one to pad_left
1083            if self.sign == ' ' and not any(np.signbit(finite_vals)):
1084                self.pad_left += 1
1085
1086        # if there are non-finite values, may need to increase pad_left
1087        if data.size != finite_vals.size:
1088            neginf = self.sign != '-' or any(data[isinf(data)] < 0)
1089            offset = self.pad_right + 1  # +1 for decimal pt
1090            current_options = format_options.get()
1091            self.pad_left = max(
1092                self.pad_left, len(current_options['nanstr']) - offset,
1093                len(current_options['infstr']) + neginf - offset
1094            )
1095
1096    def __call__(self, x):
1097        if not np.isfinite(x):
1098            with errstate(invalid='ignore'):
1099                current_options = format_options.get()
1100                if np.isnan(x):
1101                    sign = '+' if self.sign == '+' else ''
1102                    ret = sign + current_options['nanstr']
1103                else:  # isinf
1104                    sign = '-' if x < 0 else '+' if self.sign == '+' else ''
1105                    ret = sign + current_options['infstr']
1106                return ' ' * (
1107                    self.pad_left + self.pad_right + 1 - len(ret)
1108                ) + ret
1109
1110        if self.exp_format:
1111            return dragon4_scientific(x,
1112                                      precision=self.precision,
1113                                      min_digits=self.min_digits,
1114                                      unique=self.unique,
1115                                      trim=self.trim,
1116                                      sign=self.sign == '+',
1117                                      pad_left=self.pad_left,
1118                                      exp_digits=self.exp_size)
1119        else:
1120            return dragon4_positional(x,
1121                                      precision=self.precision,
1122                                      min_digits=self.min_digits,
1123                                      unique=self.unique,
1124                                      fractional=True,
1125                                      trim=self.trim,
1126                                      sign=self.sign == '+',
1127                                      pad_left=self.pad_left,
1128                                      pad_right=self.pad_right)
1129
1130
1131@set_module('numpy')
1132def format_float_scientific(x, precision=None, unique=True, trim='k',
1133                            sign=False, pad_left=None, exp_digits=None,
1134                            min_digits=None):
1135    """
1136    Format a floating-point scalar as a decimal string in scientific notation.
1137
1138    Provides control over rounding, trimming and padding. Uses and assumes
1139    IEEE unbiased rounding. Uses the "Dragon4" algorithm.
1140
1141    Parameters
1142    ----------
1143    x : python float or numpy floating scalar
1144        Value to format.
1145    precision : non-negative integer or None, optional
1146        Maximum number of digits to print. May be None if `unique` is
1147        `True`, but must be an integer if unique is `False`.
1148    unique : boolean, optional
1149        If `True`, use a digit-generation strategy which gives the shortest
1150        representation which uniquely identifies the floating-point number from
1151        other values of the same type, by judicious rounding. If `precision`
1152        is given fewer digits than necessary can be printed. If `min_digits`
1153        is given more can be printed, in which cases the last digit is rounded
1154        with unbiased rounding.
1155        If `False`, digits are generated as if printing an infinite-precision
1156        value and stopping after `precision` digits, rounding the remaining
1157        value with unbiased rounding
1158    trim : one of 'k', '.', '0', '-', optional
1159        Controls post-processing trimming of trailing digits, as follows:
1160
1161        * 'k' : keep trailing zeros, keep decimal point (no trimming)
1162        * '.' : trim all trailing zeros, leave decimal point
1163        * '0' : trim all but the zero before the decimal point. Insert the
1164          zero if it is missing.
1165        * '-' : trim trailing zeros and any trailing decimal point
1166    sign : boolean, optional
1167        Whether to show the sign for positive values.
1168    pad_left : non-negative integer, optional
1169        Pad the left side of the string with whitespace until at least that
1170        many characters are to the left of the decimal point.
1171    exp_digits : non-negative integer, optional
1172        Pad the exponent with zeros until it contains at least this
1173        many digits. If omitted, the exponent will be at least 2 digits.
1174    min_digits : non-negative integer or None, optional
1175        Minimum number of digits to print. This only has an effect for
1176        `unique=True`. In that case more digits than necessary to uniquely
1177        identify the value may be printed and rounded unbiased.
1178
1179        .. versionadded:: 1.21.0
1180
1181    Returns
1182    -------
1183    rep : string
1184        The string representation of the floating point value
1185
1186    See Also
1187    --------
1188    format_float_positional
1189
1190    Examples
1191    --------
1192    >>> import numpy as np
1193    >>> np.format_float_scientific(np.float32(np.pi))
1194    '3.1415927e+00'
1195    >>> s = np.float32(1.23e24)
1196    >>> np.format_float_scientific(s, unique=False, precision=15)
1197    '1.230000071797338e+24'
1198    >>> np.format_float_scientific(s, exp_digits=4)
1199    '1.23e+0024'
1200    """

Showing the first 1,200 of 1780 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai