Compute the impedance *(including resistive and capacitive load)* of
        the DMF device *(i.e., dielectric and droplet)*.

        See :func:`calibrate.compute_from_transfer_function`
        for details.

def Z_device(self, filter_order=None, window_size=None, tol=0.05):
        '''
        Compute the impedance *(including resistive and capacitive load)* of
        the DMF device *(i.e., dielectric and droplet)*.

        See :func:`calibrate.compute_from_transfer_function`
        for details.
        '''
        ind = mlab.find(self.fb_resistor >= 0)
        Z1 = np.empty(self.fb_resistor.shape)
        Z1.fill(np.nan)
        # convert to masked array
        Z1 = np.ma.masked_invalid(Z1)

        R2 = self.calibration.R_fb[self.fb_resistor[ind]]
        C2 = self.calibration.C_fb[self.fb_resistor[ind]]
        Z1[ind] = compute_from_transfer_function(self.calibration.hw_version
                                                 .major, 'Z1',
                                                 V1=self.V_total()[ind],
                                                 V2=self.V_fb[ind], R2=R2,
                                                 C2=C2, f=self.frequency)

        Z1 = np.ma.masked_invalid(pd.Series(Z1, pd.to_datetime(self.time, unit='s')
            ).interpolate(method='time').values)
        Z1.fill_value = np.nan
        Z1.data[Z1.mask] = Z1.fill_value

        # if we're filtering and we don't have a window size specified,
        # automatically determine one
        if filter_order and window_size is None:
            window_size = self._get_window_size(tol)

        # if the filter_order or window size is None or if the window size is
        # smaller than filter_order + 2, don't filter
        if (filter_order is None or window_size is None or window_size < filter_order + 2):
            pass
        else:
            # if the window size is less than half the sample length
            if window_size and window_size < len(Z1) / 2:
                # suppress polyfit warnings
                with warnings.catch_warnings():
                    warnings.simplefilter("ignore")
                    Z1 = savgol_filter(Z1, window_size, filter_order)
            else: # fit a line
                result = self.mean_velocity(tol=tol)
                if result['dt'] and \
                    result['dt'] > 0.1 * self.time[-1] and result['p'][0] > 0:
                    if self.calibration._c_drop:
                        c_drop = self.calibration.c_drop(self.frequency)
                    else:
                        c_drop = self.capacitance()[-1] / self.area
                    if self.calibration._c_filler:
                        c_filler = self.calibration.c_filler(self.frequency)
                    else:
                        c_filler = 0
                    x = result['p'][0]*self.time + result['p'][1]
                    C = self.area * (x * (c_drop - c_filler) / \
                                     np.sqrt(self.area) + c_filler)
                    Z1 = 1.0 / (2.0 * math.pi * self.frequency * C)
                    Z1[mlab.find(self.time==result['t_end'])[0]+1:] = \
                        Z1[mlab.find(self.time==result['t_end'])[0]]
                else:
                    Z1 = np.mean(Z1)*np.ones(Z1.shape)
        return Z1