|
13 | 13 |
|
14 | 14 | from ..compat import _pattern_type, int_types, str2bytes |
15 | 15 | from ..tools import all_type, format_error, isiterable, operator, make_Class |
16 | | -from ..tools.file import HDFFileManager, best_saver, file_dialog |
| 16 | +from ..tools.file import HDFFileManager, file_dialog |
17 | 17 | from ..tools.widgets import RangeSelect |
18 | 18 | from .array import DataArray |
19 | 19 |
|
@@ -673,6 +673,59 @@ def unique(datafile, col, return_index=False, return_inverse=False): |
673 | 673 | return np.unique(datafile.column(col), return_index, return_inverse) |
674 | 674 |
|
675 | 675 |
|
| 676 | +def _validate_index(datafile, index, replace): |
| 677 | + match index: |
| 678 | + case None | True: |
| 679 | + index = datafile.shape[1] |
| 680 | + replace = False |
| 681 | + case int() if index == datafile.shape[1]: |
| 682 | + replace = False |
| 683 | + case _: |
| 684 | + index = datafile.find_col(index) |
| 685 | + return index, replace |
| 686 | + |
| 687 | + |
| 688 | +def _normalise_column_data(datafile, column_data, header, func_args): |
| 689 | + """Sort out the data and get it into an array of values.""" |
| 690 | + if isinstance(column_data, list): |
| 691 | + column_data = np.array(column_data) |
| 692 | + |
| 693 | + if isinstance(column_data, DataArray) and header is None: |
| 694 | + header = column_data.column_headers |
| 695 | + |
| 696 | + match column_data: |
| 697 | + case np.ndarray(): |
| 698 | + np_data = column_data |
| 699 | + case _ if callable(column_data) and isinstance(func_args, dict): |
| 700 | + new_data = [column_data(x, **func_args) for x in datafile] |
| 701 | + np_data = np.array(new_data) |
| 702 | + case _ if callable(column_data): |
| 703 | + new_data = [column_data(x) for x in datafile] |
| 704 | + np_data = np.array(new_data) |
| 705 | + case _: |
| 706 | + raise NotImplementedError |
| 707 | + |
| 708 | + return np_data, header |
| 709 | + |
| 710 | + |
| 711 | +def _data_make_setas(setas, cw): |
| 712 | + """Make setas based on the existing setas and the one supplied.""" |
| 713 | + setas = "." * cw if setas is None else setas |
| 714 | + |
| 715 | + if isiterable(setas) and len(setas) == cw: |
| 716 | + for s in setas: |
| 717 | + if s not in ".-xyzuvwdefpqr": |
| 718 | + raise TypeError( |
| 719 | + f"setas parameter should be a string or list of letter in the set xyzdefuvw.-, not {setas}" |
| 720 | + ) |
| 721 | + else: |
| 722 | + raise TypeError( |
| 723 | + f"""setas parameter should be a string or list of letter the same length as the number of columns |
| 724 | + being added in the set xyzdefuvw.-, not {setas}""" |
| 725 | + ) |
| 726 | + return setas |
| 727 | + |
| 728 | + |
676 | 729 | def add_column(datafile, column_data, header=None, index=None, func_args=None, replace=False, setas=None): |
677 | 730 | """Append a column of data or inserts a column to a datafile instance. |
678 | 731 |
|
@@ -704,50 +757,14 @@ def add_column(datafile, column_data, header=None, index=None, func_args=None, r |
704 | 757 | Like most :py:class:`DataFile` methods, this method operates in-place in that it also modifies |
705 | 758 | the original DataFile Instance as well as returning it. |
706 | 759 | """ |
707 | | - if index is None or isinstance(index, bool) and index: # Enure index is set |
708 | | - index = datafile.shape[1] |
709 | | - replace = False |
710 | | - elif isinstance(index, int_types) and index == datafile.shape[1]: |
711 | | - replace = False |
712 | | - else: |
713 | | - index = datafile.find_col(index) |
714 | | - |
715 | | - # Sort out the data and get it into an array of values. |
716 | | - if isinstance(column_data, list): |
717 | | - column_data = np.array(column_data) |
718 | | - |
719 | | - if isinstance(column_data, DataArray) and header is None: |
720 | | - header = column_data.column_headers |
721 | 760 |
|
722 | | - if isinstance(column_data, np.ndarray): |
723 | | - np_data = column_data |
724 | | - elif callable(column_data): |
725 | | - if isinstance(func_args, dict): |
726 | | - new_data = [column_data(x, **func_args) for x in datafile] |
727 | | - else: |
728 | | - new_data = [column_data(x) for x in datafile] |
729 | | - np_data = np.array(new_data) |
730 | | - else: |
731 | | - return NotImplemented |
| 761 | + index, replace = _validate_index(datafile, index, replace) |
| 762 | + np_data, header = _normalise_column_data(datafile, column_data, header, func_args) |
732 | 763 |
|
733 | 764 | # Sort out the sizes of the arrays |
734 | 765 | np_data = np.atleast_2d(np_data).T |
735 | 766 | cl, cw = np_data.shape |
736 | | - |
737 | | - # Make setas |
738 | | - setas = "." * cw if setas is None else setas |
739 | | - |
740 | | - if isiterable(setas) and len(setas) == cw: |
741 | | - for s in setas: |
742 | | - if s not in ".-xyzuvwdefpqr": |
743 | | - raise TypeError( |
744 | | - f"setas parameter should be a string or list of letter in the set xyzdefuvw.-, not {setas}" |
745 | | - ) |
746 | | - else: |
747 | | - raise TypeError( |
748 | | - f"""setas parameter should be a string or list of letter the same length as the number of columns |
749 | | - being added in the set xyzdefuvw.-, not {setas}""" |
750 | | - ) |
| 767 | + setas = _data_make_setas(setas, cw) |
751 | 768 |
|
752 | 769 | # Make sure our current data is at least 2D and get its size |
753 | 770 | match datafile.data.shape: |
@@ -1161,52 +1178,6 @@ def rows(datafile, not_masked=False, reset=False): |
1161 | 1178 | yield row |
1162 | 1179 |
|
1163 | 1180 |
|
1164 | | -def save(datafile, filename=None, as_loaded=None, filetype=False): |
1165 | | - """Save a string representation of the current DataFile object into the file 'filename'. |
1166 | | -
|
1167 | | - Args: |
1168 | | - datafile (Data): |
1169 | | - Data object to work with if not being used as a bound method. |
1170 | | - filename (string, bool or None): |
1171 | | - Filename to save data as, if this is None then the current filename for the object is used. If this |
1172 | | - is not set, then then a file dialog is used. If filename is False then a file dialog is forced. |
1173 | | - as_loaded (bool,str): |
1174 | | - If True, then the *Loaded as* key is inspected to see what the original class of the DataFile was |
1175 | | - and then this class' save method is used to save the data. If a str then |
1176 | | - the keyword value is interpreted as the name of a subclass of the the current DataFile. |
1177 | | - filetype (bool): |
1178 | | - Fallback is as_loaded is not provided. |
1179 | | -
|
1180 | | - Returns: |
1181 | | - datafile: |
1182 | | - The current :py:class:`DataFile` object |
1183 | | - """ |
1184 | | - as_loaded = filetype if as_loaded is None else as_loaded |
1185 | | - if filename is None: |
1186 | | - filename = datafile.filename |
1187 | | - if filename is None or (isinstance(filename, bool) and not filename): |
1188 | | - # now go and ask for one |
1189 | | - filename = file_dialog("w", datafile.filename, "Data") |
1190 | | - if not filename: |
1191 | | - raise RuntimeError("Cannot get filename to save") |
1192 | | - match as_loaded: |
1193 | | - case False: |
1194 | | - saver = best_saver(filename, name=None, what="Data") |
1195 | | - ret = saver(datafile, filename) |
1196 | | - datafile.filename = ret.filename |
1197 | | - return datafile |
1198 | | - case True: |
1199 | | - as_loaded = datafile.get("Loaded as", "DataFile") |
1200 | | - case str(): |
1201 | | - pass |
1202 | | - case _: |
1203 | | - raise TypeError("Unable to use loadtype to work out best saving routine.") |
1204 | | - saver = best_saver(filename, name=as_loaded, what="Data") |
1205 | | - ret = saver(datafile, filename) |
1206 | | - datafile.filename = ret.filename |
1207 | | - return datafile |
1208 | | - |
1209 | | - |
1210 | 1181 | def swap_column(datafile, *swp, headers_too=True, **kwargs): |
1211 | 1182 | """Swap pairs of columns in the data. |
1212 | 1183 |
|
|
0 commit comments