From 0fa39dc830ac391af66a070cf2f07ea914172e1c Mon Sep 17 00:00:00 2001 From: John Garrett Date: Sun, 10 Mar 2019 12:19:50 +0000 Subject: [PATCH] Automatically identify input data type --- examples/analyze-experimental-data.ipynb | 32 +++++++++++----------- qmix/exp/exp_data.py | 34 ++++++++++++------------ qmix/exp/if_data.py | 26 +++++++----------- qmix/exp/iv_data.py | 22 +++++---------- qmix/exp/parameters.py | 4 --- tests/test_exp_data.py | 11 +++----- 6 files changed, 51 insertions(+), 78 deletions(-) diff --git a/examples/analyze-experimental-data.ipynb b/examples/analyze-experimental-data.ipynb index 6e6cec8..f7e8798 100644 --- a/examples/analyze-experimental-data.ipynb +++ b/examples/analyze-experimental-data.ipynb @@ -10,7 +10,7 @@ "\n", "For the purposes of this notebook, example data has been included in a directory called ``eg-230-data/``. This is experimental data that was taken from an SIS device illuminated by a local-oscillator at 230 GHz (see Garrett 2018).\n", "\n", - "QMix includes two classes that can be used to analyze these experimental data:\n", + "QMix includes two classes that can be used to analyze this experimental data:\n", "\n", " - [qmix.exp.RawData0](https://garrettj403.github.io/QMix/qmix.exp.html#qmix.exp.exp_data.RawData0), which is used to analyze DC data (no LO illumination), and\n", " - [qmix.exp.RawData](https://garrettj403.github.io/QMix/qmix.exp.html#qmix.exp.exp_data.RawData), which is used to analyze pumped data (with LO illumination).\n", @@ -51,7 +51,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -107,17 +107,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In order to import these files properly, we will define the properties of the CSV files, which will then be passed on to the ``RawData0`` and ``RawData`` classes." + "In order to import these files properly, we will define the properties of the CSV files, which will then be passed on to the ``RawData0`` class." ] }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ - "csv_params = dict(input_type = 'csv', # pass data as CSV data files\n", - " delimiter = ',', # delimiter used by CSV files\n", + "csv_params = dict(delimiter = ',', # delimiter used by CSV files\n", " usecols = (0,1), # columns to import\n", " skip_header = 1, # skip the first row (the header)\n", " v_fmt = 'mV', # units for voltage data\n", @@ -133,7 +132,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -150,7 +149,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -162,7 +161,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -187,7 +186,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -221,7 +220,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -245,7 +244,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -270,7 +269,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -316,7 +315,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -343,7 +342,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -370,7 +369,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -458,7 +457,6 @@ "source": [ "pump = qmix.exp.RawData(iv_data, dciv, hot_data, cold_data,\n", " freq = 230.2, # LO frequency in [GHz]\n", - " input_type = \"Numpy\", # Pass in Numpy arrays\n", " **params)" ] }, diff --git a/qmix/exp/exp_data.py b/qmix/exp/exp_data.py index 6b6c78f..f396569 100644 --- a/qmix/exp/exp_data.py +++ b/qmix/exp/exp_data.py @@ -103,17 +103,16 @@ class RawData0(object): Args: dciv: DC I-V curve. Either a CSV data file or a Numpy array. The data should have two columns: the first for voltage, and the second - for current. To pass a Numpy array, set the ``input_type`` keyword - argument to ``"numpy"``. To pass a CSV data file, set the - ``input_type`` keyword argument to ``"csv"``. The properties of - the CSV file can be set through additional keyword arguments. - (See below). + for current. If you are using CSV files, the properties of + the CSV file can be set through additional keyword arguments + (see below). dcif: DC IF data. Either a CSV data file or a Numpy array. The data should have two columns: the first for voltage, and the - second for IF power. + second for IF power. If you are using CSV files, the properties of + the CSV file can be set through additional keyword arguments + (see below). Keyword arguments: - input_type (str): Input type ('csv' or 'numpy'). delimiter (str): Delimiter for CSV files. usecols (tuple): List of columns to import (tuple of length 2). skip_header (int): Number of rows to skip, used to skip the header. @@ -176,12 +175,12 @@ def __init__(self, dciv, dcif=None, **kw): self.comment = comment self.vleak = vleak - if kw['input_type'].lower() == 'csv': + if isinstance(dciv, str): # input type: CSV file self.file_path = dciv - elif kw['input_type'].lower() == 'numpy': + elif isinstance(dciv, np.ndarray): # input type: Numpy array self.file_path = 'Numpy array' else: - raise ValueError('Input type not recognized.') + raise ValueError('Input data type not recognized.') # Get DC I-V data self.voltage, self.current, self.dc = dciv_curve(dciv, **kw) @@ -640,11 +639,12 @@ class RawData(object): Args: ivdata: I-V data. Either a CSV data file or a Numpy array. The data should have two columns: the first for voltage, and the second - for current. + for current. If you are using CSV files, the properties of + the CSV file can be set through additional keyword arguments + (see below). dciv (qmix.exp.iv_data.DCIVData): DC I-V metadata Keyword arguments: - input_type (str): Input type ('csv' or 'numpy'). delimiter (str): Delimiter for CSV files. usecols (tuple): List of columns to import (tuple of length 2). skip_header (int): Number of rows to skip, used to skip the header. @@ -719,7 +719,7 @@ def __init__(self, ivdata, dciv, if_hot=None, if_cold=None, **kw): analyze_if = analyze # Sort out file paths - if kw['input_type'].lower() == 'csv': + if isinstance(ivdata, str): # input type: CSV file self.iv_file = ivdata self.directory = os.path.dirname(ivdata) self.iv_filename = os.path.basename(ivdata) @@ -729,7 +729,7 @@ def __init__(self, ivdata, dciv, if_hot=None, if_cold=None, **kw): else: self.filename_hot = None self.filename_cold = None - elif kw['input_type'].lower() == 'numpy': + elif isinstance(ivdata, np.ndarray): # input type: Numpy array self.iv_file = 'Numpy array' self.directory = 'Numpy array' self.iv_filename = 'Numpy array' @@ -740,7 +740,7 @@ def __init__(self, ivdata, dciv, if_hot=None, if_cold=None, **kw): self.filename_hot = None self.filename_cold = None else: - raise ValueError("Input type not recognized.") + raise ValueError("Input data type not recognized.") # Unpack DC I-V metadata self.dciv = dciv @@ -755,8 +755,8 @@ def __init__(self, ivdata, dciv, if_hot=None, if_cold=None, **kw): self.current_dc = dciv.current # Get LO frequency - if kw['input_type'] == 'numpy' and freq is None: - str1 = 'If input_type is set to \'numpy\', ' + if isinstance(ivdata, np.ndarray) and freq is None: + str1 = 'If input data is in the form of Numpy arrays, ' str2 = 'you must define the frequency of the LO signal.' raise ValueError(str1 + str2) self.freq, self.freq_str = _get_freq(freq, ivdata) diff --git a/qmix/exp/if_data.py b/qmix/exp/if_data.py index eae7282..5bf759b 100644 --- a/qmix/exp/if_data.py +++ b/qmix/exp/if_data.py @@ -55,15 +55,12 @@ def dcif_data(ifdata, dc, **kwargs): Args: ifdata: IF data. Either a CSV data file or a Numpy array. The data should have two columns: the first for voltage, and the second - for IF power. To pass a Numpy array, set the ``input_type`` - keyword argument to ``"numpy"``. To pass a CSV data file, set the - ``input_type`` keyword argument to ``"csv"``. The properties of - the CSV file can be set through additional keyword arguments. - (See below). + for IF power. If you are passing a CSV file, the properties of + the CSV file can be set through additional keyword arguments + (see below). dc (qmix.exp.iv_data.DCIVData): DC I-V metadata. Keyword Args: - input_type (str): Input type ('csv' or 'numpy'). delimiter (str): Delimiter for CSV files. usecols (tuple): List of columns to import (tuple of length 2). skip_header (int): Number of rows to skip, used to skip the header. @@ -110,7 +107,6 @@ def if_data(if_hot, if_cold, dc, **kwargs): dc (qmix.exp.iv_data.DCIVData): DC I-V metadata. Keyword Args: - input_type (str): Input type ('csv' or 'numpy'). delimiter (str): Delimiter for CSV files. usecols (tuple): List of columns to import (tuple of length 2). skip_header (int): Number of rows to skip, used to skip the header. @@ -360,11 +356,9 @@ def _load_if(ifdata, dc, **kwargs): Args: ifdata: IF data. Either a CSV data file or a Numpy array. The data should have two columns: the first for voltage, and the second - for IF power. To pass a Numpy array, set the ``input_type`` - keyword argument to ``"numpy"``. To pass a CSV data file, set the - ``input_type`` keyword argument to ``"csv"``. The properties of - the CSV file can be set through additional keyword arguments. - (See below). + for IF power. If you are using a CSV file, the properties of + the CSV file can be set through additional keyword arguments + (see below). dc (qmix.exp.iv_data.DCIVData): DC I-V metadata. Keyword arguments: @@ -377,7 +371,6 @@ def _load_if(ifdata, dc, **kwargs): points rseries (float): series resistance of measurement system skip_header: number of rows to skip at the beginning of the file - input_type (str): Returns: IF data (in matrix form) @@ -386,7 +379,6 @@ def _load_if(ifdata, dc, **kwargs): # Unpack keyword arguments v_multiplier = kwargs.get('v_multiplier', PARAMS['v_multiplier']) skip_header = kwargs.get('skip_header', PARAMS['skip_header']) - input_type = kwargs.get('input_type', PARAMS['input_type']) sigma = kwargs.get('ifdata_sigma', PARAMS['ifdata_sigma']) vmax = kwargs.get('ifdata_vmax', PARAMS['ifdata_vmax']) npts = kwargs.get('ifdata_npts', PARAMS['ifdata_npts']) @@ -396,16 +388,16 @@ def _load_if(ifdata, dc, **kwargs): v_fmt = kwargs.get('v_fmt', PARAMS['v_fmt']) # Import raw IF data - if input_type.lower() == 'csv': + if isinstance(ifdata, str): # assume CSV data file ifdata = np.genfromtxt(ifdata, delimiter=delim, usecols=usecols, skip_header=skip_header) - elif input_type.lower() == 'numpy': + elif isinstance(ifdata, np.ndarray): # Numpy array assert isinstance(ifdata, np.ndarray), \ 'I-V data should be a Numpy array.' assert ifdata.ndim == 2, 'I-V data should be 2-dimensional.' assert ifdata.shape[1] == 2, 'I-V data should have 2 columns.' else: - raise ValueError("Input type not recognized.") + raise ValueError("Input data type not recognized.") # Clean ifdata = remove_nans_matrix(ifdata) diff --git a/qmix/exp/iv_data.py b/qmix/exp/iv_data.py index 99d100e..d03fca1 100644 --- a/qmix/exp/iv_data.py +++ b/qmix/exp/iv_data.py @@ -71,14 +71,11 @@ def dciv_curve(ivdata, **kwargs): Args: ivdata: DC I-V data. Either a CSV data file or a Numpy array. The data should have two columns: the first for voltage, and the second - for current. To pass a Numpy array, set the ``input_type`` keyword - argument to ``"numpy"``. To pass a CSV data file, set the - ``input_type`` keyword argument to ``"csv"``. The properties of + for current. If you are using CSV files, the properties of the CSV file can be set through additional keyword arguments. (See below). Keyword Args: - input_type (str): Input type ('csv' or 'numpy'). delimiter (str): Delimiter for CSV files. usecols (tuple): List of columns to import (tuple of length 2). skip_header (int): Number of rows to skip, used to skip the header. @@ -206,16 +203,13 @@ def iv_curve(ivdata, dc, **kwargs): Args: ivdata: I-V data. Either a CSV data file or a Numpy array. The data should have two columns: the first for voltage, and the second - for current. To pass a Numpy array, set the ``input_type`` keyword - argument to ``"numpy"``. To pass a CSV data file, set the - ``input_type`` keyword argument to ``"csv"``. The properties of - the CSV file can be set through additional keyword arguments. - (See below). + for current. If you are using a CSV file, the properties of + the CSV file can be set through additional keyword arguments + (see below). dc (qmix.exp.iv_data.DCIVData): DC I-V data metadata. Generated previously by ``dciv_curve``. Keyword Args: - input_type (str): Input type ('csv' or 'numpy'). delimiter (str): Delimiter for CSV files. usecols (tuple): List of columns to import (tuple of length 2). skip_header (int): Number of rows to skip, used to skip the header. @@ -327,7 +321,6 @@ def _load_iv(ivdata, **kw): for current. Keyword Arguments: - input_type: input type ('csv' or 'numpy') v_fmt: voltage units ('uV', 'mV', 'V') i_fmt: current units ('uA', 'mA', 'A') usecols: list of columns to use (tuple of length 2) @@ -341,24 +334,23 @@ def _load_iv(ivdata, **kw): # Unpack keyword arguments skip_header = kw.get('skip_header', PARAMS['skip_header']) - input_type = kw.get('input_type', PARAMS['input_type']) delimiter = kw.get('delimiter', PARAMS['delimiter']) usecols = kw.get('usecols', PARAMS['usecols']) v_fmt = kw.get('v_fmt', PARAMS['v_fmt']) i_fmt = kw.get('i_fmt', PARAMS['i_fmt']) # Import raw I-V data - if input_type.lower() == 'csv': + if isinstance(ivdata, str): # input: CSV file vraw, iraw = np.genfromtxt(ivdata, delimiter=delimiter, usecols=usecols, skip_header=skip_header).T - elif input_type.lower() == 'numpy': + elif isinstance(ivdata, np.ndarray): # input: Numpy array assert isinstance(ivdata, np.ndarray), \ 'I-V data should be a Numpy array.' assert ivdata.ndim == 2, 'I-V data should be 2-dimensional.' assert ivdata.shape[1] == 2, 'I-V data should have 2 columns.' vraw, iraw = ivdata.T else: - raise ValueError("Input type not recognized.") + raise ValueError("Input data type not recognized.") # Set units volt_v = vraw * _vfmt_dict[v_fmt] diff --git a/qmix/exp/parameters.py b/qmix/exp/parameters.py index 41cf19a..db61cdc 100644 --- a/qmix/exp/parameters.py +++ b/qmix/exp/parameters.py @@ -20,8 +20,6 @@ ``RawData`` either as CSV data files or as Numpy arrays. The CSV files should have two columns: one for voltage and one for current or IF power. The Numpy arrays should also have two columns. - - ``input_type == "csv"`` : Input type. Either ``"csv"`` or - ``"numpy"``. - CSV files: - **Note:** All of the experimental data is expected to be stored in CSV data files. These parameters control how the data is read in @@ -162,8 +160,6 @@ class will determine the best bias voltage automatically. """ params = dict( - # Experimental data data - input_type = 'csv', # CSV files delimiter = ',', usecols = (0, 1), diff --git a/tests/test_exp_data.py b/tests/test_exp_data.py index 710d983..a7d01ce 100644 --- a/tests/test_exp_data.py +++ b/tests/test_exp_data.py @@ -19,8 +19,7 @@ def test_importing_exp_data(directory='tests/exp-data/'): # Import DC data (no LO pumping) dciv = qe.RawData0(directory+'dciv-data.csv', - directory+'dcif-data.csv', - input_type='csv') + directory+'dcif-data.csv') # Check some of the attributes # Note: I calculated these by hand @@ -35,7 +34,7 @@ def test_importing_exp_data(directory='tests/exp-data/'): ivdata = np.genfromtxt(directory+'f230_0_iv.csv', **csv) hotdata = np.genfromtxt(directory+'f230_0_hot.csv', **csv) colddata = np.genfromtxt(directory+'f230_0_cold.csv', **csv) - pump = qe.RawData(ivdata, dciv, hotdata, colddata, freq=230.2, input_type='numpy') + pump = qe.RawData(ivdata, dciv, hotdata, colddata, freq=230.2) assert pump.freq == 230.2, "Wrong frequency." # Check some of the attributes @@ -44,9 +43,5 @@ def test_importing_exp_data(directory='tests/exp-data/'): assert -1.2 < pump.g_db < -1.0, "Wrong conversion gain." # Check automatic frequency determination - pump = qe.RawData(directory+'f230_0_iv.csv', dciv, analyze_iv=False, input_type='csv') + pump = qe.RawData(directory+'f230_0_iv.csv', dciv, analyze_iv=False) assert pump.freq == 230.0, "Wrong frequency." - - # Try importing the wrong data type - with pytest.raises(ValueError): - qe.RawData(directory+'f230_0_iv.csv', dciv, analyze_iv=False, input_type='pandas')