def Function(self, t, param):
        Ktrans, ve = param
        duration   = self.duration
        delay      = self.delay
        cp0        = self.cp0


        # If step imput is assumed, the respons can be described as
        #
        #   y = (Ktrans * cp0 / kep) * (1-exp(-kep*t))         (t < duration)   ... (1)
        #   y = (Ktrans * cp0 / kep) * exp(-kep*(t-duration))  (t >= duration)  ... (2)

        #sys.stderr.write('t     : %s\n' % t )


        # Calculate shifted time
        t2 = scipy.greater_equal(t, delay) * (t - delay);

        # To describe C(t) in one equasion, we introduce t_dush, which is
        # defined by t_dash = t (t < duration) and t_dash = duration (t >= duration):
        t_dash = scipy.less(t2, duration)*t2 + scipy.greater_equal(t2, duration)*duration

        # Eq. (1) and (2) can be rewritten by:
        kep = Ktrans / ve
        y = (Ktrans*cp0/kep)*(scipy.exp(kep*t_dash) - 1) * scipy.exp(-kep*t2)

        return y
    def Function(self, x, param):
        #Ktrans, ve, D, delay = param
        #Ktrans, ve, delay = param
        Ktrans, ve  = param
        #Ktrans, kep = param
        
        a1 = self.a1
        a2 = self.a2
        m1 = self.m1
        m2 = self.m2
        vp = self.vp
        delay = self.delay
        kep = Ktrans / ve
        D  = self.Dose
        
        # Calculate shifted time and convert to minutes
        # if x < delay:  x_min = 0
        # else x_min = (x - delay) / 60.0
        x_min = (scipy.greater_equal(x, delay) * (x - delay)) / 60.0

        term1  = a1*( scipy.exp(-((kep)*x_min)) - scipy.exp(-(m1*x_min))) / (m1-(kep))
        term2  = a2*( scipy.exp(-((kep)*x_min)) - scipy.exp(-(m2*x_min))) / (m2-(kep))
        y = 0.0

        if vp > 0.0:
            term3  = a1*scipy.exp(-(m1*x_min))
            term4  = a2*scipy.exp(-(m2*x_min))
            y  = (D*Ktrans)*(term1+term2)+(vp*D)*(term3+term4)
        else:
            y  = (D*Ktrans)*(term1+term2)

        
        return y * scipy.greater_equal(x, delay)
    def Function(self, x, param):
        Ktrans, ve, D, delay = param
        #Ktrans, ve, delay = param
        #Ktrans, ve  = param
        #Ktrans, kep = param
        #Ktrans, ve, D = param
        
        a1 = self.a1
        a2 = self.a2
        m1 = self.m1
        m2 = self.m2
        vp = self.vp
        #delay = self.delay
        kep = Ktrans / ve
        #D  = self.Dose
        
        # Calculate shifted time and convert to minutes
        # if x < delay:  x_min = 0
        # else x_min = (x - delay) / 60.0
        x_min = (scipy.greater_equal(x, delay) * (x - delay)) / 60.0

        term1  = a1*( scipy.exp(-((kep)*x_min)) - scipy.exp(-(m1*x_min))) / (m1-(kep))
        term2  = a2*( scipy.exp(-((kep)*x_min)) - scipy.exp(-(m2*x_min))) / (m2-(kep))
        y = 0.0

        if vp > 0.0:
            term3  = a1*scipy.exp(-(m1*x_min))
            term4  = a2*scipy.exp(-(m2*x_min))
            y  = (D*Ktrans)*(term1+term2)+(vp*D)*(term3+term4)
        else:
            y  = (D*Ktrans)*(term1+term2)

        
        #return y * scipy.greater_equal(x, delay)
        return y 
 def Function(self, x, param):
     Sp, alpha, beta, Ta  = param
     S0 = self.CalcS0(Ta)
     x2 = (scipy.greater_equal(x, Ta) * (x - Ta))
     #y  = Sp * numpy.abs(scipy.power((scipy.e / (alpha*beta)), alpha)) * numpy.abs(scipy.power(x2, alpha)) * scipy.exp(-x2/beta) + S0
     y  = Sp * numpy.abs(scipy.power((scipy.e / (alpha*beta)), alpha) * scipy.power(x2, alpha) * scipy.exp(-x2/beta)) + S0
     return y
Example #5
0
 def Function(self, x, param):
     Sp, alpha, beta, Ta = param
     S0 = self.CalcS0(Ta)
     x2 = (scipy.greater_equal(x, Ta) * (x - Ta))
     #y  = Sp * numpy.abs(scipy.power((scipy.e / (alpha*beta)), alpha)) * numpy.abs(scipy.power(x2, alpha)) * scipy.exp(-x2/beta) + S0
     y = Sp * numpy.abs(
         scipy.power((scipy.e / (alpha * beta)), alpha) *
         scipy.power(x2, alpha) * scipy.exp(-x2 / beta)) + S0
     return y
def test_efficiency_range():
    
    def eff_fun():
        v = normalise([random(),random(),10])
        rays_in = [Ray([0,0,0],v,wavelen,1)]
        rays_out = [Ray([0,0,0],v,wavelen,1)]
        wavevecs_in_mag = [r.wavevector_vac_mag for r in rays_in]
        wavevecs_in_unit = [r.wavevector_unit for r in rays_in]   
        wavevecs_out_mag = [r.wavevector_vac_mag for r in rays_out]
        wavevecs_out_unit = [r.wavevector_unit for r in rays_out]   
        return get_efficiency(aod, random(), wavevecs_in_mag, wavevecs_in_unit, wavevecs_out_mag, wavevecs_out_unit, [acoustics], (0,1))
        
    effs = [ eff_fun() for _ in range(100) ]
    assert all(less_equal(effs,1)) and all(greater_equal(effs,0))  
Example #7
0
def ght_alternative (img, template, indices):
    """
    Alternative implementation of the general hough transform, which uses iteration over
    indices rather than broadcasting rules like @see ght().
    
    It is therefore considerably slower, especially for large, multi-dimensional arrays.
    The only application are cases, where the hough transform should only be computed for
    a small number of points (=template centers) in the image. In this case the indices
    of interest can be provided as a list.
    
    @param img the original image on which to search for the structure
    @type img numpy.ndarray
    @param template a boolean array containing the structure to search for
    @type template nump.ndarray
    @param indices a sequence of image indices
    @type indices sequence
    
    @return the general hough transformation
    @rtype numpy.ndarray
    """
    # cast template to bool and img to scipy array
    img = scipy.asarray(img)
    template = scipy.asarray(template).astype(scipy.bool_)
    
    # check supplied parameters
    if img.ndim != template.ndim:
        raise AttributeError('The supplied image and template must be of the same dimensionality.')
    if not scipy.all(scipy.greater_equal(img.shape, template.shape)):
        raise AttributeError('The supplied template is bigger than the image. This setting makes no sense for a hough transform.')
    
    # pad the original image
    img_padded = pad(img, footprint=template, mode='constant')
    
    # prepare the hough image
    if scipy.bool_ == img.dtype:
        img_hough = scipy.zeros(img.shape, scipy.int32)
    else:
        img_hough = scipy.zeros(img.shape, img.dtype)
        
    # iterate over the pixels, apply the template center to each of these and save the sum into the hough image
    for idx_hough in indices:
        idx_hough = tuple(idx_hough)
        slices_img_padded = [slice(idx_hough[i], None) for i in range(img_hough.ndim)]
        img_hough[idx_hough] = sum(img_padded[slices_img_padded][template])     
        
    return img_hough
changing_pixels = []
time_plan0 = 0  # beginning time of a shot
time_plan1 = 0  # ending time of a shot

# We stream the video in the while loop
while cap.grab():
    n_frame += 1
    time_plan1 += 1 / float(fps)
    ret, frame = cap.retrieve()
    frame1 = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    temp = cv2.cvtColor(temp, cv2.COLOR_BGR2GRAY)
    shape = frame1.shape

    # We compute the percentage of changing pixels between two consecutive frames
    diff = np.absolute(frame1 - temp)
    pix_diff = 255. * sc.greater_equal(diff, ten)
    n_pix_diff = float(np.count_nonzero(pix_diff))
    changing_pixels.append(n_pix_diff / n_pix)

    # If the percentage is higher than our threshold we say that we have a new shot
    if n_pix_diff / n_pix > 0.8:
        # Saving the images in a folder
        if n_f_faces != 0 and n_faces != 0:
            save_faces(path_visages, n_shot, shots, abs_plan, n_faces,
                       int(time_plan0), int(time_plan1), w_video)
        time_plan0 = time_plan1
        n_shot += 1
        shots = {}
        abs_plan = []
        n_faces = 0
        n_f_faces = 0
    def plot_rc(self,
                save=False,
                hand=True,
                usgs=True,
                xs=True,
                xsapprox=True,
                sprnt=True,
                ci=True,
                dist=5000,
                raw=False,
                kind='power',
                alpha=0.05,
                div=5):
        """Plot HAND and xs rating curves with confidence intervals
		'hand' - plot hand rating curve [T/F]
		'xs' - plot xs rating curves [T/F]
		'xsapprox' - plot xs rating curve approximation from n-value averages [T/F]
		'ci' - plot confidence intervals [T/F]
		'alpha' - alpha for confidence intervals [float(0.0,1.0)]
		'div' - number of intervals for confidence interval [R]"""

        with open('results/output_{0}.csv'.format(self.comid), 'w') as f:
            writer = csv.writer(f)
            writer.writerow(['COMID:', self.comid])
            writer.writerow(['LENGTH:', self.handlen])

            if xs:  # Plot all linearly-interpolated XS rating curves
                intervals = scipy.arange(dist, self.handlen + dist, dist)
                # print 'Intervals:',intervals

                cutoffub = [i / self.handlen * 100 for i in intervals]
                cutofflb = scipy.copy(cutoffub)
                cutofflb = scipy.insert(cutofflb, 0, 0)[:-1]
                cutoffs = zip(cutofflb, cutoffub)
                for l, u in cutoffs:
                    idx = scipy.where(
                        scipy.logical_and(
                            scipy.greater_equal(self.xs_profs, l),
                            scipy.less(self.xs_profs, u)))
                    if u > 100: u = 100.00

                    if len(self.xs_disch[idx]) == 0:
                        continue

                    fig, ax = plt.subplots(
                    )  # get figure and axes for plotting
                    fname = 'results/sprntcompare/rc_comid_{0}_sprnt_compare.png'.format(
                        self.comid, ('%.2f' % l), ('%.2f' % u))

                    for prof, disch, stage in zip(self.xs_profs[idx],
                                                  self.xs_disch[idx],
                                                  self.xs_stage[idx]):
                        # Get interpolation function
                        # print (('%.2f' % prof) + str(disch))
                        # print (('%.2f' % prof) + str(stage))

                        f = self.interp(x=disch, y=stage, kind=kind)

                        if raw == True:  # Plot raw data (ie. only HEC-RAS points)
                            # interp over discharge
                            writer.writerow(['PROFILE:', prof])
                            writer.writerow(['DISCHARGE:'])
                            writer.writerow(disch)
                            writer.writerow(['STAGE:'])
                            writer.writerow(f(disch))
                            ax.plot(disch, f(disch), c='grey', linewidth=2)

                            # interp over stage (switched axes) for testing
                            # f = self.interp(x=stage,y=disch,kind=kind)
                            # ax.plot(f(stage),stage,c='purple',linewidth=1)

                        if raw == False:  # Plot interpolated data (ie. 'div' many interpolated points)
                            interval = disch[-1] / div
                            qvals = scipy.arange(0, (disch[-1] + interval),
                                                 interval)  # [1:]
                            writer.writerow(['PROFILE:', prof])
                            writer.writerow(['DISCHARGE:'])
                            writer.writerow(qvals)
                            writer.writerow(['STAGE:'])
                            writer.writerow(f(qvals))
                            ax.plot(qvals, f(qvals), c='grey', linewidth=2)

                    # print '\n------------------------\n'

            if ci:  # Plot confidence interval bounds
                self.get_ci(alpha=alpha,
                            div=div)  # get upper- and lower-bound variables
                # upper bounds
                f = self.interp(x=self.ci_vals, y=self.ubounds, kind=kind)
                writer.writerow(['UPPER CI:'])
                writer.writerow(['DISCHARGE:'])
                writer.writerow(self.ci_vals)
                writer.writerow(['STAGE:'])
                writer.writerow(f(self.ci_vals))
                ax.plot(self.ci_vals,
                        f(self.ci_vals),
                        label='{0}%CI'.format(int((1 - alpha) * 100)),
                        c='orange',
                        linewidth=5)
                # lower bounds
                f = self.interp(x=self.ci_vals, y=self.lbounds, kind=kind)
                writer.writerow(['LOWER CI:'])
                writer.writerow(['DISCHARGE:'])
                writer.writerow(self.ci_vals)
                writer.writerow(['STAGE:'])
                writer.writerow(f(self.ci_vals))
                ax.plot(self.ci_vals, f(self.ci_vals), c='orange', linewidth=5)

            if xsapprox:
                # Add approximate rating curve from average n-values
                qvals, hvals = self.get_xs_q(upto=83)
                f = self.interp(x=qvals, y=hvals, kind=kind)
                writer.writerow(['XSAPPROX:'])
                writer.writerow(['DISCHARGE:'])
                writer.writerow(qvals)
                writer.writerow(['STAGE:'])
                writer.writerow(f(qvals))
                ax.plot(qvals,
                        f(qvals),
                        label='Resistance Function',
                        c='red',
                        linewidth=5)

            if usgs:  # Plot interpolated USGS rating curve
                # Get data
                try:
                    self.get_usgsrc()  # Fetch usgs stage and disch values
                    # Plot curves
                    for q, h in zip(self.usgsq, self.usgsh):
                        if kind == 'cubic':
                            print 'USGS interpolation plotted as power-law fit'
                            f = self.interp(x=q, y=h, kind='power')
                        else:
                            f = self.interp(x=q, y=h, kind=kind)
                        writer.writerow(['USGS:'])
                        writer.writerow(['DISCHARGE:'])
                        writer.writerow(q)
                        writer.writerow(['STAGE:'])
                        writer.writerow(f(q))
                        ax.plot(q, f(q), label='usgs', c='g', linewidth=5)
                except IndexError:
                    print 'No USGS rating curve for comid {0}'.format(
                        self.comid)

            if hand:  # Plot interpolated HAND rating curve
                # Plot curves
                f = self.interp(x=self.handq, y=self.handh, kind=kind)
                writer.writerow(['HAND:'])
                writer.writerow(['DISCHARGE:'])
                writer.writerow(list(self.handq))
                writer.writerow(['STAGE:'])
                writer.writerow(list(f(self.handq)))
                ax.plot(self.handq,
                        f(self.handq),
                        label='hand',
                        c='b',
                        linewidth=5)

            if sprnt:
                f = self.interp(x=self.sprntq, y=self.sprnth, kind=kind)
                writer.writerow(['SPRNT:'])
                writer.writerow(['DISCHARGE:'])
                writer.writerow(list(self.sprntq))
                writer.writerow(['STAGE:'])
                writer.writerow(list(f(self.sprntq)))
                ax.plot(self.sprntq,
                        f(self.sprntq),
                        label='sprnt',
                        c='y',
                        linewidth=5)

            # Add one label for all cross-section curves
            ax.plot([], [], label='HEC-RAS', c='grey', linewidth=2)
            # Plot graph
            fig.set_size_inches(20, 16, forward=True)
            plt.gca().set_xlim(left=0, right=self.max_disch)
            plt.gca().set_ylim(bottom=0, top=self.max_stage)
            ax.set_xticks(ax.get_xticks()[::2])
            ax.set_yticks(ax.get_yticks()[::2])
            title = 'COMID {0}, ({1},{2})'.format(self.comid, ('%.2f' % l),
                                                  ('%.2f' % u))
            ax.set_title(title, y=1.04, fontsize=56)
            plt.xlabel('Q (cfs)', fontsize=56)
            plt.ylabel('H (ft)', fontsize=56)
            ax.ticklabel_format(style='sci', axis='x', scilimits=(0, 0))
            plt.rc('font', size=56)
            plt.legend(loc='upper left', fontsize=40)
            plt.tick_params(axis='both', labelsize=56)
            plt.grid()

            if save:
                fig.savefig(fname)
                plt.clf()

            if not save:
                mng = plt.get_current_fig_manager()
                mng.resize(*mng.window.maxsize())
                plt.show()
                plt.clf()
            writer.writerow('')
time_plan0 = 0  # beginning time of a shot
time_plan1 = 0  # ending time of a shot


# We stream the video in the while loop
while cap.grab():
    n_frame += 1
    time_plan1 += 1/float(fps)
    ret, frame = cap.retrieve()
    frame1 = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    temp = cv2.cvtColor(temp, cv2.COLOR_BGR2GRAY)
    shape = frame1.shape

    # We compute the percentage of changing pixels between two consecutive frames
    diff = np.absolute(frame1-temp)
    pix_diff = 255.*sc.greater_equal(diff, ten)
    n_pix_diff = float(np.count_nonzero(pix_diff))
    changing_pixels.append(n_pix_diff/n_pix)

    # If the percentage is higher than our threshold we say that we have a new shot
    if n_pix_diff/n_pix > 0.8:
        # Saving the images in a folder
        if n_f_faces != 0 and n_faces != 0:
            save_faces(path_visages, n_shot, shots, abs_plan, n_faces, int(time_plan0), int(time_plan1),
                       w_video)
        time_plan0 = time_plan1
        n_shot += 1
        shots = {}
        abs_plan = []
        n_faces = 0
        n_f_faces = 0
    def plot_rc(self,
                save=False,
                xs=True,
                xsapprox=True,
                kind='power',
                dist=5000,
                raw=False,
                alpha=0.05,
                div=5,
                box=False):
        """Plot HAND and xs rating curves with confidence intervals
		'hand' - plot hand rating curve [T/F]
		'xs' - plot xs rating curves [T/F]
		'xsapprox' - plot xs rating curve approximation from n-value averages [T/F]
		'ci' - plot confidence intervals [T/F]
		'alpha' - alpha for confidence intervals [float(0.0,1.0)]
		'div' - number of intervals for confidence interval [R]"""

        if xs:  # Plot all linearly-interpolated XS rating curves
            intervals = scipy.arange(dist, self.handlen + dist, dist)
            # print 'Intervals:',intervals

            cutoffub = [i / self.handlen * 100 for i in intervals]
            cutofflb = scipy.copy(cutoffub)
            cutofflb = scipy.insert(cutofflb, 0, 0)[:-1]
            cutoffs = zip(cutofflb, cutoffub)
            for l, u in cutoffs:
                idx = scipy.where(
                    scipy.logical_and(scipy.greater_equal(self.xs_profs, l),
                                      scipy.less(self.xs_profs, u)))[0]
                if u > 100: u = 100.00

                fig, ax = plt.subplots()  # get figure and axes for plotting
                fname = 'results/by5000/{0}/rc__comid_{0}_from_{1}_to_{2}.png'.format(
                    self.comid, ('%.2f' % l), ('%.2f' % u))

                for prof, disch, stage in zip(self.xs_profs[idx],
                                              self.xs_disch[idx],
                                              self.xs_stage[idx]):
                    # Get interpolation function
                    # print (('%.2f' % prof) + str(disch))
                    # print (('%.2f' % prof) + str(stage))

                    f = self.interp(x=disch, y=stage, kind=kind)

                    if raw == True:  # Plot raw data (ie. only HEC-RAS points)
                        # interp over discharge
                        ax.plot(disch, f(disch), c='grey', linewidth=2)

                        # interp over stage (switched axes) for testing
                        # f = self.interp(x=stage,y=disch,kind=kind)
                        # ax.plot(f(stage),stage,c='purple',linewidth=1)

                    if raw == False:  # Plot interpolated data (ie. 'div' many interpolated points)
                        interval = disch[-1] / div
                        qvals = scipy.arange(0, (disch[-1] + interval),
                                             interval)  # [1:]
                        ax.plot(qvals, f(qvals), c='grey', linewidth=2)

                # Add one label for all cross-section curves
                ax.plot([], [], label='HEC-RAS', c='grey', linewidth=2)
                # Plot graph
                fig.set_size_inches(20, 16, forward=True)
                plt.gca().set_xlim(left=0, right=self.max_disch)
                plt.gca().set_ylim(bottom=0, top=self.max_stage)
                ax.set_xticks(ax.get_xticks()[::2])
                ax.set_yticks(ax.get_yticks()[::2])
                title = 'COMID {0}, ({1},{2})'.format(self.comid, ('%.2f' % l),
                                                      ('%.2f' % u))
                ax.set_title(title, y=1.04, fontsize=56)
                plt.xlabel('Q (cfs)', fontsize=56)
                plt.ylabel('H (ft)', fontsize=56)
                ax.ticklabel_format(style='sci', axis='x', scilimits=(0, 0))
                plt.rc('font', size=56)
                plt.legend(loc='upper left', fontsize=40)
                plt.tick_params(axis='both', labelsize=56)
                plt.grid()

                # print '\n------------------------\n'
                if xsapprox:
                    # Add approximate rating curve from average n-values
                    qvals, hvals = self.get_xs_q(low=0, upto=83)
                    f = self.interp(x=qvals, y=hvals, kind=kind)
                    ax.plot(qvals,
                            f(qvals),
                            label='Resistance Function',
                            c='red',
                            linewidth=5)

                    # Add approximate rating curve for these indices
                    idxqvals, idxhvals = self.get_xs_q(low=idx[0],
                                                       upto=idx[-1])

                    if len(idxqvals) == 0:
                        print 'No data found for profiles {0} to {1}'.format(
                            ('%.2f' % l), ('%.2f' % u))
                        break

                    # f = self.interp(x=idxqvals,y=idxhvals,kind=kind)
                    # ax.plot(idxqvals,f(idxqvals),label='Resistance Function Local Average',c='orange',linewidth=5)

        else:
            fig, ax = plt.subplots()

        if save: fig.savefig(fname)
        else:
            # mng = plt.get_current_fig_manager()
            # mng.resize(*mng.window.maxsize())
            plt.show()
Example #12
0
def ght(img, template):
    """
    Implementation of the general hough transform for all dimensions.
    
    Providing a template, this method searches in the image for structures similar to the
    one depicted by the template. The returned hough image denotes how well the structure
    fit in each index.
    
    The indices of the returned image correspond with the centers of the template. At the
    corresponding locations of the original image the template is applied (like a stamp)
    and the underlying voxel values summed up to form the hough images value. It is
    suggested to normalize the input image before for speaking results.
    
    This function behaves as the general hough transform if a binary image has been
    supplied. In the case of a gray-scale image, the values of the pixels under the
    templates structure are summed up, thus weighting becomes possible.
    
    @note:
    The center of a structure with odd side-length is simple the arrays middle. When an
    even-sided array has been supplied as template, the middle rounded down is taken as
    the structures center. This means that in the second case the hough image is shifted
    by half a voxel (ndim * [-0.5]).
    
    @param img the original image on which to search for the structure
    @type img numpy.ndarray
    @param template a boolean array containing the structure to search for
    @type template nump.ndarray
    
    @return the general hough transformation
    @rtype numpy.ndarray
    """    
    # cast template to bool and img to scipy array
    img = scipy.asarray(img)
    template = scipy.asarray(template).astype(scipy.bool_)
    
    # check supplied parameters
    if img.ndim != template.ndim:
        raise AttributeError('The supplied image and template must be of the same dimensionality.')
    if not scipy.all(scipy.greater_equal(img.shape, template.shape)):
        raise AttributeError('The supplied template is bigger than the image. This setting makes no sense for a hough transform.')    
    
    # compute center of template array
    center = (scipy.asarray(template.shape) - 1) / 2 # integer division intended
    
    # prepare the hough image
    if scipy.bool_ == img.dtype:
        img_hough = scipy.zeros(img.shape, scipy.int32)
    else:
        img_hough = scipy.zeros(img.shape, img.dtype)
    
    # iterate over the templates non-zero positions and sum up the images accordingly shifted 
    for idx in scipy.transpose(template.nonzero()):
        slicers_hough = []
        slicers_orig = []
        for i in range(img.ndim):
            pos = -1 * (idx[i] - center[i])
            if 0 == pos: # no shift
                slicers_hough.append(slice(None, None))
                slicers_orig.append(slice(None, None))
            elif pos > 0: # right shifted hough
                slicers_hough.append(slice(pos, None))
                slicers_orig.append(slice(None, -1 * pos))
            else: # left shifted hough
                slicers_hough.append(slice(None, pos))
                slicers_orig.append(slice(-1 * pos, None))
        img_hough[slicers_hough] += img[slicers_orig]
        
    return img_hough
Example #13
0
def run_simulation_fast(vol, lam, sprd_client, sprd_dealer, delta_lim,
                        hedge_style, dt, nsteps, nruns, seed):
    '''Runs a Monte Carlo simulation and returns statics on PNL, client trades, and hedge trades.
    "_fast" because it uses vectorized operations.

    vol:         lognormal volatility of the spot process
    lam:         Poisson process frequency
    sprd_client: fractional bid/ask spread for client trades. eg 1e-4 means 1bp.
    sprd_dealer: fractional bid/ask spread for inter-dealer hedge trades. eg 1e-4 means 1bp.
    delta_lim:   the delta limit at or beyond which the machine will hedge in the inter-dealer market
    hedge_style: 'Zero' or 'Edge', defining the hedging style. 'Zero' means hedge to zero position,
                 'Edge' means hedge to the nearer delta limit.
    dt:          length of a time step
    nsteps:      number of time steps for each run of the simulation
    nruns:       number of Monte Carlo runs
    seed:        RNG seed
    '''

    scipy.random.seed(seed)

    trade_prob = 1 - exp(-lam * dt)
    sqrtdt = sqrt(dt)

    spots = scipy.zeros(nruns) + 1  # initial spot == 1
    posns = scipy.zeros(nruns)
    trades = scipy.zeros(nruns)
    hedges = scipy.zeros(nruns)
    pnls = scipy.zeros(nruns)

    for step in range(nsteps):
        dzs = scipy.random.normal(0, sqrtdt, nruns)
        qs = scipy.random.uniform(0, 1, nruns)
        ps = scipy.random.binomial(
            1, 0.5,
            nruns) * 2 - 1  # +1 or -1 - trade quantities if a trade happens

        # check if there are client trades for each path

        indics = scipy.less(qs, trade_prob)
        posns += indics * ps
        trades += scipy.ones(nruns) * indics
        pnls += scipy.ones(nruns) * indics * sprd_client * spots / 2.

        # check if there are hedges to do for each path

        if hedge_style == 'Zero':
            indics = scipy.logical_or(scipy.less_equal(posns, -delta_lim),
                                      scipy.greater_equal(posns, delta_lim))
            pnls -= scipy.absolute(posns) * indics * sprd_dealer * spots / 2.
            posns -= posns * indics
            hedges += scipy.ones(nruns) * indics
        elif hedge_style == 'Edge':
            # first deal with cases where pos>delta_lim

            indics = scipy.greater(posns, delta_lim)
            pnls -= (posns - delta_lim) * indics * sprd_dealer * spots / 2.
            posns = posns * scipy.logical_not(indics) + scipy.ones(
                nruns) * indics * delta_lim
            hedges += scipy.ones(nruns) * indics

            # then the cases where pos<-delta_lim

            indics = scipy.less(posns, -delta_lim)
            pnls -= (-delta_lim - posns) * indics * sprd_dealer * spots / 2.
            posns = posns * scipy.logical_not(indics) + scipy.ones(
                nruns) * indics * (-delta_lim)
            hedges += scipy.ones(nruns) * indics
        else:
            raise ValueError('hedge_style must be "Edge" or "Zero"')

        # advance the spots and calculate period PNL

        dspots = vol * spots * dzs
        pnls += posns * dspots
        spots += dspots

    return {
        'PNL': (pnls.mean(), pnls.std()),
        'Trades': (trades.mean(), trades.std()),
        'Hedges': (hedges.mean(), hedges.std())
    }