Coverage for nilearn/_utils/numpy_conversions.py: 16%
24 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-20 10:58 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-20 10:58 +0200
1"""Validation and conversion utilities for numpy."""
3import csv
4from pathlib import Path
6import numpy as np
9def as_ndarray(arr, copy=False, dtype=None, order="K"):
10 """Convert to numpy.ndarray starting with an arbitrary array.
12 In the case of a memmap array, a copy is automatically made to break the
13 link with the underlying file (whatever the value of the "copy" keyword).
15 The purpose of this function is mainly to get rid of memmap objects, but
16 it can be used for other purposes. In particular, combining copying and
17 casting can lead to performance improvements in some cases, by avoiding
18 unnecessary copies.
20 If not specified, input array order is preserved, in all cases, even when
21 a copy is requested.
23 Caveat: this function does not copy during bool to/from 1-byte dtype
24 conversions. This can lead to some surprising results in some rare cases.
26 Parameters
27 ----------
28 arr : array-like
29 input array. Any value accepted by numpy.asarray is valid.
31 copy : bool
32 if True, force a copy of the array. Always True when arr is a memmap.
34 dtype : any numpy dtype
35 dtype of the returned array. Performing copy and type conversion at the
36 same time can in some cases avoid an additional copy.
38 order : :obj:`str`, default='K'
39 gives the order of the returned array.
40 Valid values are: "C", "F", "A", "K", None.
41 See ndarray.copy() for more information.
43 Returns
44 -------
45 ret : numpy.ndarray
46 Numpy array containing the same data as arr, always of class
47 numpy.ndarray, and with no link to any underlying file.
49 Examples
50 --------
51 >>> import numpy
52 >>> a = numpy.asarray([0, 1, 2], dtype=numpy.int8)
53 >>> b = as_ndarray(a, dtype=bool)
54 >>> b
55 array([False, True, True])
56 >>> c = as_ndarray(b, dtype=numpy.int8)
57 >>> c
58 array([0, 1, 2], dtype=int8)
60 The usually expected result for the last line would be array([0, 1, 1])
61 because True evaluates to 1. Since there is no copy made here, the original
62 array is recovered.
63 """
64 if order not in ("C", "F", "A", "K", None):
65 raise ValueError(f"Invalid value for 'order': {order!s}")
67 if not isinstance(arr, (np.memmap, np.ndarray, list, tuple)):
68 raise ValueError(f"Type not handled: {arr.__class__}")
70 # the cases where we have to create a copy of the underlying array
71 if isinstance(arr, (np.memmap, list, tuple)) or (
72 isinstance(arr, np.ndarray) and copy
73 ):
74 return np.array(arr, copy=True, dtype=dtype, order=order)
75 # if the order does not change and dtype does not change or
76 # bool to/from 1-byte dtype,
77 # no need to create a copy
78 elif (
79 (arr.itemsize == 1 and dtype in (bool, np.bool_))
80 or (arr.dtype in (bool, np.bool_) and np.dtype(dtype).itemsize == 1)
81 or arr.dtype == dtype
82 ) and (
83 (order == "F" and arr.flags["F_CONTIGUOUS"])
84 or (order == "C" and arr.flags["C_CONTIGUOUS"])
85 or order in ("K", "A", None)
86 ):
87 return arr.view(dtype=dtype)
88 else:
89 return np.asarray(arr, dtype=dtype, order=order)
92def csv_to_array(csv_path, delimiters=" \t,;", **kwargs):
93 """Read a CSV file by trying to guess its delimiter.
95 Parameters
96 ----------
97 csv_path : string or pathlib.Path
98 Path of the CSV file to load.
100 delimiters : string
101 Each character of the delimiters string is a potential delimiters for
102 the CSV file.
104 kwargs : keyword arguments
105 The additional keyword arguments are passed to numpy.genfromtxt when
106 loading the CSV.
108 Returns
109 -------
110 array : numpy.ndarray
111 An array containing the data loaded from the CSV file.
112 """
113 try:
114 # First, we try genfromtxt which works in most cases.
115 array = np.genfromtxt(csv_path, loose=False, encoding=None, **kwargs)
116 except ValueError:
117 # There was an error during the conversion to numpy array, probably
118 # because the delimiter is wrong.
119 # In that case, we try to guess the delimiter.
120 try:
121 with Path(csv_path).open() as csv_file:
122 dialect = csv.Sniffer().sniff(csv_file.readline(), delimiters)
123 except csv.Error as e:
124 raise TypeError(
125 f"Could not read CSV file [{csv_path}]: {e.args[0]}"
126 )
128 array = np.genfromtxt(
129 csv_path, delimiter=dialect.delimiter, encoding=None, **kwargs
130 )
132 return array