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

1"""Validation and conversion utilities for numpy.""" 

2 

3import csv 

4from pathlib import Path 

5 

6import numpy as np 

7 

8 

9def as_ndarray(arr, copy=False, dtype=None, order="K"): 

10 """Convert to numpy.ndarray starting with an arbitrary array. 

11 

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). 

14 

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. 

19 

20 If not specified, input array order is preserved, in all cases, even when 

21 a copy is requested. 

22 

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. 

25 

26 Parameters 

27 ---------- 

28 arr : array-like 

29 input array. Any value accepted by numpy.asarray is valid. 

30 

31 copy : bool 

32 if True, force a copy of the array. Always True when arr is a memmap. 

33 

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. 

37 

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. 

42 

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. 

48 

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) 

59 

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}") 

66 

67 if not isinstance(arr, (np.memmap, np.ndarray, list, tuple)): 

68 raise ValueError(f"Type not handled: {arr.__class__}") 

69 

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) 

90 

91 

92def csv_to_array(csv_path, delimiters=" \t,;", **kwargs): 

93 """Read a CSV file by trying to guess its delimiter. 

94 

95 Parameters 

96 ---------- 

97 csv_path : string or pathlib.Path 

98 Path of the CSV file to load. 

99 

100 delimiters : string 

101 Each character of the delimiters string is a potential delimiters for 

102 the CSV file. 

103 

104 kwargs : keyword arguments 

105 The additional keyword arguments are passed to numpy.genfromtxt when 

106 loading the CSV. 

107 

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 ) 

127 

128 array = np.genfromtxt( 

129 csv_path, delimiter=dialect.delimiter, encoding=None, **kwargs 

130 ) 

131 

132 return array