def fromCsv(cls,
                fname,
                skiprows=0,
                delimiter=',',
                wavelength_multiplier=1):
        '''A constructor that allows the loading of a csv datafile.'''

        material = cls()

        data = _np.loadtxt(fname, skiprows=skiprows, delimiter=delimiter)
        data[:, 0] *= wavelength_multiplier

        if (data < 0).any():
            raise ValueError(
                'Refractive index and extinction coefficient must \
			be positive, as well as wavelength.')

        print('Loaded', fname)
        print('Dataset range:', data[0, 0], 'um -', data[-1, 0], 'um')

        if len(data.shape) != 2:
            raise ValueError('Loaded data was misshapen.')
        if data.shape[1] > 3:
            print(
                '\33[33mWarning:\33[0m Extraneous columns detected. These were \
			skipped')
        if data.shape[1] == 2:
            print('2 columns detected. Assuming lossless material.')
            material.getEc = lambda l: 0
            material.getRealN = _interp1d(data[:, 0], data[:, 1])
        else:
            material.getRealN = _interp1d(data[:, 0], data[:, 1])
            material.getEc = _interp1d(data[:, 0], data[:, 2])
        return material
    def fromArray(cls, wavelength, realN, Ec=0):
        '''Constructor that allows the creation of a theoretical material
		with complex refractive index realN(lambda) + 1j*Ec(lambda).
		RealN and Ec are data for n and Ec at wavelength. Ec and realN can be
		a single number'''
        material = cls()

        realN = _np.array(realN, ndmin=1)
        Ec = _np.array(Ec, ndmin=1)
        wavelength = _np.array(wavelength, ndmin=1)

        if (len(wavelength) != len(realN) and len(realN) != 1):
            raise ValueError('Wavelength and real refractive index must be \
			the same size, or refractive index must be scalar.')

        if (len(wavelength) != len(Ec) and len(Ec) != 1):
            raise ValueError('Wavelength and extinction coefficient must be \
			the same size, or refractive index must be scalar.')

        if (realN < 0).any() or (Ec < 0).any():
            raise ValueError(
                'Refractive index and extinction coefficient must \
			be positive.')

        if (len(Ec) == 1):
            material.getRealN = lambda l: realN[0]
        else:
            material.getRealN = _interp1d(wavelengths, realN)
        if (len(Ec) == 1):
            material.getEc = lambda l: Ec[0]
        else:
            material.getEc = _interp1d(wavelengths, Ec)
        return material
예제 #3
0
 def _resample_with_constant_dx(x_data, y_data):
     f = _interp1d(x_data, y_data)
     x = _linspace(x_data[0], x_data[-1], len(x_data))
     y = f(x)
     return x, y
    def fromYml(cls, fname):
        '''Loads a yml file with the same structure as the ones contained in the
		refractiveindex.info database.'''
        table = cls()  #initialise an empty MaterialTable named table

        with open(fname) as file:
            table.datafile = _yml.full_load(file)
            print('Loaded yml datafile:', fname)

        dataK_found = False
        dataN_found = False
        # Find k and n data and load them
        for datatable in table.datafile['DATA']:
            if datatable['type'] == 'tabulated nk':
                # If both found in same dataset no extra data is needed
                data = _np.loadtxt(_io.StringIO(datatable['data']))
                print('Loaded tabulated nk data.')
                print('Range:', data[0, 0], 'um -', data[-1, 0], 'um')
                if not dataN_found:
                    table.getRealN = _interp1d(data[:, 0], data[:, 1])
                else:
                    print('\33[33mWarning:\33[0m Duplicate n data. Skipped')
                if not dataK_found:
                    table.getEc = _interp1d(data[:, 0], data[:, 2])
                else:
                    print('\33[33mWarning:\33[0m Duplicate k data. Skipped')

                dataN_found = True
                dataK_found = True

            elif datatable['type'] == 'tabulated n':
                if dataN_found:
                    print(
                        '\33[33mWarning:\33[0m Found duplicate n data. Skipped'
                    )
                    continue

                data = _np.loadtxt(_io.StringIO(datatable['data']))
                print('Loaded tabulated n data')
                print('Range:', data[0, 0], 'um -', data[-1, 0], 'um')

                dataN_found = True
                table.getRealN = _interp1d(data[:, 0], data[:, 1])
            elif datatable['type'] == 'tabulated k':
                if dataK_found:
                    print(
                        '\33[33mWarning:\33[0m Found duplicate k data. Skipped'
                    )
                    continue

                data = _np.loadtxt(_io.StringIO(datatable['data']))
                print('Loaded tabulated k data')
                print('Range:', data[0, 0], 'um -', data[-1, 0], 'um')

                dataK_found = True
                table.getEc = _interp1d(data[:, 0], data[:, 1])

            elif 'formula' in datatable['type']:
                if dataN_found:
                    print(
                        '\33[33mWarning:\33[0m Found duplicate n data. Skipped'
                    )
                    continue

                ID = int(
                    _re.search('(?<=formula\ )[0-9]',
                               datatable['type']).group(0)) - 1

                if (ID >= len(MaterialTable.formulae)):
                    raise KeyError('Unknown formula:', datatable['type'])

                print('Loaded', datatable['type'], 'data')
                range = _np.loadtxt(_io.StringIO(
                    datatable['wavelength_range']))
                coeffs = _np.loadtxt(_io.StringIO(datatable['coefficients']))
                print('Range:', range[0], 'um -', range[1], 'um')
                table.getRealN = MaterialTable.formulae[ID](coeffs, range)

                dataN_found = True

            else:
                raise ValueError('Unknown type of datatable:',
                                 datatable['type'])

            if dataN_found and dataK_found:
                # Check if we are at the end of the dataset
                if datatable != table.datafile['DATA'][-1]:
                    print('\33[33mWarning:\33[0m Some datatables were skipped \
					as sufficient data was found before end of file.')
                break  # End loop if all parameters are loaded

        if not dataK_found:
            print('No k data found. Assuming lossless material')
            table.getEc = lambda l: 0

        return table
    def parseDataset(self,database,lmin=None,lmax=None,allow_interpolation=True,\
         require_k=False):
        '''This method is responsible for checking and loading the dataset
		once the material database was found in findMaterial, or otherwise.
		lmin and lmax are the optional bounds of wavelength we are interested in
		the material in units of um.
		allow_interpolation decides whether interpolation is acceptable for
		the refractive index data.
		require_k is a parameter specifying, whether data for k is also
		desired. Datasets with k specified as well are always preffered,
		and if found will be used regardless of require_k. k is the extinction
		coefficient in this context.'''

        if (lmin == None and lmax != None):  # Sanitising the input
            lmin = lmax
        elif (lmin != None and lmax == None):
            lmax = lmin
        elif (lmin == None and lmax == None):
            lmin = _np.inf
            lmax = -_np.inf  # This makes the check below always return True
        elif (lmin > lmax):
            raise ValueError('lmin must be strictly smaller than lmax')

        goodDatasets = []
        for dataset in database:
            with open('./database/data/' + database[dataset]['data']) as file:
                datafile = _yml.full_load(file)
            for data in datafile['DATA']:
                # Filtering out not n data
                if not (('tabulated n' in data['type'] and allow_interpolation) \
                     or 'formula' in data['type']):
                    continue
                # If formula is in the data type, the range is specified
                if 'formula' in data['type']:
                    range = _np.loadtxt(_io.StringIO(data['wavelength_range']))
                else:
                    tabulated = _np.loadtxt(_io.StringIO(data['data']))
                    range = _np.array([tabulated[0, 0], tabulated[-1, 0]])
                if (range[0] < lmin and range[1] > lmax):
                    # Append data for the good datasets. The structure is:
                    # [dataset, N-index,range-N, datafile, K-index,range-K]
                    # as k is not tested yet, it is None as well as its range
                    goodDatasets.append([
                        dataset, datafile['DATA'].index(data), range, datafile,
                        None, None
                    ])

        # Check for k data
        contains_k = []
        for d in goodDatasets:
            datafile = d[3]
            for data in datafile['DATA']:
                if not ('tabulated k' in data['type']
                        or 'tabulated nk' in data['type']):
                    continue
                tabulated = _np.loadtxt(_io.StringIO(data['data']))
                range = _np.array([tabulated[0, 0], tabulated[-1, 0]])
                if (range[0] < lmin and range[1] > lmax):
                    contains_k.append(d)
                    contains_k[-1][4] = datafile['DATA'].index(data)
                    contains_k[-1][5] = range

        if len(goodDatasets) == 0:
            raise KeyError('No datasets satisfying requirements found')
        print('Found', len(goodDatasets),
              'datasets, which satisfied requirements')
        if len(contains_k) != 0:
            goodDatasets = contains_k
        elif require_k:
            raise KeyError('No k data was found')
        print('Out of which', len(contains_k), 'datasets contain k data')
        print('Using ' + goodDatasets[0][0])
        print('Name:', database[goodDatasets[0][0]]['name'])
        if 'division' in database[goodDatasets[0][0]].keys():
            print('Division:', database[goodDatasets[0][0]]['division'])
        print('Location: ./database/data/' +
              database[goodDatasets[0][0]]['data'])
        print('Datatable type:',
              goodDatasets[0][3]['DATA'][goodDatasets[0][1]]['type'])
        print('Datatable range:', goodDatasets[0][2][0], 'um -',
              goodDatasets[0][2][1], 'um')
        if (contains_k == goodDatasets):
            if (goodDatasets[0][1] != goodDatasets[0][4]):
                print('Datatable type:',
                      goodDatasets[0][3]['DATA'][goodDatasets[0][4]]['type'])
                print('Datatable range:', goodDatasets[0][5][0], 'um -',
                      goodDatasets[0][5][1], 'um')
        dataN = goodDatasets[0][1]
        dataK = goodDatasets[0][4]
        self.datafile = goodDatasets[0][3]

        # If k dataset is not found error is raised if getK is called
        if dataK == None:
            self.getEc = lambda l: 0
        # Check for the different types of data k and n might be contained in
        elif 'tabulated k' in self.datafile['DATA'][dataK]['type']:
            tabulated = _np.loadtxt(
                _io.StringIO(self.datafile['DATA'][dataK]['data']))
            self.getEc = _interp1d(tabulated[:, 0], tabulated[:, 1])
        if 'tabulated nk' in self.datafile['DATA'][dataN]['type']:
            tabulated = _np.loadtxt(
                _io.StringIO(self.datafile['DATA'][dataN]['data']))
            self.getRealN = _interp1d(tabulated[:, 0], tabulated[:, 1])
            self.getEc = _interp1d(tabulated[:, 0], tabulated[:, 2])
        elif 'tabulated n' in self.datafile['DATA'][dataN]['type']:
            tabulated = _np.loadtxt(
                _io.StringIO(self.datafile['DATA'][dataN]['data']))
            self.getRealN = _interp1d(tabulated[:, 0], tabulated[:, 1])
        else:
            formulaN = int(
                _re.search('(?<=formula\ )[0-9]',
                           self.datafile['DATA'][dataN]['type']).group(0))
            coefficients = _np.loadtxt(
                _io.StringIO(self.datafile['DATA'][dataN]['coefficients']))
            self.getRealN = MaterialTable.formulae[formulaN - 1](
                coefficients, goodDatasets[0][2])
예제 #6
0
 def _resample_with_constant_dx(x_data, y_data):
     f = _interp1d(x_data, y_data)
     x = _linspace(x_data[0], x_data[-1], len(x_data))
     y = f(x)
     return x, y
예제 #7
0
def grid_count(y, window_size, offset=0, size=None, fuzz=True, bounds=None):
    """
    Parameters
    ----------
    `y` is the 1-d array of signal samples.

    `window_size` is the number of samples to show horizontally in the
    eye diagram.  Typically this is twice the number of samples in a
    "symbol" (i.e. in a data bit).

    `offset` is the number of initial samples to skip before computing
    the eye diagram.  This allows the overall phase of the diagram to
    be adjusted.

    `size` must be a tuple of two integers.  It sets the size of the
    array of counts, (height, width).  The default is (800, 640).

    `fuzz`: If True, the values in `y` are reinterpolated with a
    random "fuzz factor" before plotting in the eye diagram.  This
    reduces an aliasing-like effect that arises with the use of
    Bresenham's algorithm.

    `bounds` must be a tuple of two floating point values, (ymin, ymax).
    These set the y range of the returned array.  If not given, the
    bounds are `(y.min() - 0.05*A, y.max() + 0.05*A)`, where `A` is
    `y.max() - y.min()`.

    Return Value
    ------------
    Returns a numpy array of integers.

    """
    if size is None:
        size = (800, 640)
    height, width = size
    dt = width / window_size
    counts = _np.zeros((width, height), dtype=_np.int32)

    if bounds is None:
        ymin = y.min()
        ymax = y.max()
        yamp = ymax - ymin
        ymin = ymin - 0.05*yamp
        ymax = ymax + 0.05*yamp
    else:
        ymin, ymax = bounds

    start = offset
    while start + window_size < len(y):
        end = start + window_size
        yy = y[start:end+1]
        k = _np.arange(len(yy))
        xx = dt*k
        if fuzz:
            f = _interp1d(xx, yy, kind='cubic')
            jiggle = dt*(_np.random.beta(a=3, b=3, size=len(xx)-2) - 0.5)
            xx[1:-1] += jiggle
            yd = f(xx)
        else:
            yd = yy
        iyd = (height * (yd - ymin)/(ymax - ymin)).astype(_np.int32)
        _bres_curve_count(xx.astype(_np.int32), iyd, counts)

        start = end
    return counts