예제 #1
0
def spread_plot(args):
    """Draw the spreading as a function of time."""

    # Get colours and line styles from default
    colours = get_colours(args.colour, len(args.spreading))
    labels, draw_legend = get_labels(args.label, len(args.spreading))

    linestyles = {}
    linestyles['line'] = get_linestyles(args.linestyle, len(args.spreading))
    linestyles['fit'] = get_linestyles(args.fitstyle, len(args.spreading),
            'dashed')

    # Create linear fitting function
    fitfunc = lambda p, t, r: r - p[0] - p[1] * t
    pinit = [1.0, 1/7]

    # Find shift array for synchronisation
    shift_array = get_shift(args.spreading, sync=args.sync)
    impact_shift = get_shift(args.spreading, sync='impact')

    # Create dicts for lists of fit constants (r = amp * t**index)
    amp = {}
    index = {}
    ampError = {}
    indexError = {}

    ampMean = []
    ampMeanError = []
    indexMean = []
    indexMeanError = []

    for i, spread_list in enumerate(args.spreading):
        amp[i] = []
        index[i] = []
        ampError[i] = []
        indexError[i] = []

        spread, full_data = combine_spread(spread_list, shift=shift_array[i])
        spread.times = np.array(spread.times) - spread.times[0]

        for k, _file in enumerate(spread_list):
            data = Spread().read(_file)
            data.times = np.array(data.times) - impact_shift[i][k]

            # Get radius and domain
            radius = {'real': np.array(calc_radius(data))}
            domain = {'real': np.array(data.times)}

            # Cut times outside of range
            for j, time in enumerate(domain['real']):
                if time > args.tend:
                    radius['real'] = radius['real'][:j]
                    domain['real'] = domain['real'][:j]

            # Add logged values
            radius['log'] = np.log10(radius['real'][1:])
            domain['log'] = np.log10(domain['real'][1:])

            # Cut in log range
            for j, logt in enumerate(domain['log']):
                if logt > args.tendlog:
                    radius['log'] = radius['log'][:j]
                    domain['log'] = domain['log'][:j]

            # Fit constants to data
            out = optimize.leastsq(fitfunc, pinit,
                    args=(domain['log'], radius['log']), full_output=1)

            pfinal = out[0]
            covar = out[1]

            # Add unlogged constants to lists
            amp[i].append(10**pfinal[0])
            index[i].append(pfinal[1])
            ampError[i].append(np.sqrt(covar[1][1]) * amp[i][-1])
            indexError[i].append(np.sqrt(covar[0][0]))

            if args.draw == 'log' and args.nomean:
                plot_line(
                        line=radius['log'],
                        domain=domain['log'],
                        color=colours[i],
                        linestyle=linestyles['line'][i]
                    )
                if not args.nofit:
                    plot_line(
                            line=out[0][0] + out[0][1] * domain['log'],
                            domain=domain['log'],
                            color=colours[i], linestyle=linestyles['fit'][i]
                            )
            if args.draw == 'real' and args.nomean:
                plot_line(
                        line=radius['real'],
                        domain=domain['real'],
                        color=colours[i], linestyle=linestyles['line'][i]
                        )
                if not args.nofit:
                    plot_line(
                            line=amp[i][-1] * (domain['real']**index[i][-1]),
                            domain=domain['real'],
                            color=colours[i], linestyle=linestyles['fit'][i]
                            )

        ampMean.append(np.mean(amp[i]))
        ampMeanError.append(np.std(amp[i]) / np.sqrt(len(amp[i]) - 1))
        indexMean.append(np.mean(index[i]))
        indexMeanError.append(np.std(index[i]) / np.sqrt(len(index[i]) - 1))

        if not args.nomean:
            if args.draw == 'log':
                plot_line(
                        line=np.log10(calc_radius(spread)),
                        domain=np.log10(spread.times),
                        label=labels[i],
                        color=colours[i], linestyle=linestyles['line'][i]
                        )
                if not args.nofit:
                    plot_line(
                            line=(np.log10(ampMean[i])
                                    + indexMean[i] * np.log10(spread.times)),
                            domain=np.log10(spread.times),
                            label='C=%.2f, n=%.2f'%(ampMean[i], indexMean[i]),
                            color=colours[i], linestyle=linestyles['fit'][i]
                            )
            if args.draw == 'real':
                plot_line(
                        line=calc_radius(spread),
                        domain=spread.times,
                        label=labels[i],
                        color=colours[i], linestyle=linestyles['line'][i]
                        )
                if not args.nofit:
                    plot_line(
                            line=ampMean[i] * (domain['real']**indexMean[i]),
                            domain=domain['real'],
                            label='C=%.2f, n=%.2f'%(ampMean[i], indexMean[i]),
                            color=colours[i], linestyle=linestyles['fit'][i]
                            )

    plt.title(args.title, fontsize='medium')
    plt.axis('normal')

    plt.legend()

    # Default xlabel and xlims based on draw method
    if args.draw == 'real':
        if args.ylabel == None:
            args.ylabel = "Spread radius (nm)"
        if args.xlabel == None:
            args.xlabel = "Time (ps)"
        if (args.tend and args.tendlog) < np.inf:
            plt.xlim([None, min(args.tend, 10**args.tendlog)])
    elif args.draw == 'log':
        if args.ylabel == None:
            args.ylabel = "log10 of radius (in nm)"
        if args.xlabel == None:
            args.xlabel = "log10 of time (in ps)"
        if (args.tend and args.tendlog) < np.inf:
            plt.xlim([None, min(args.tend, args.tendlog)])

    plt.xlabel(args.xlabel, fontsize='medium')
    plt.ylabel(args.ylabel, fontsize='medium')

    if args.xlim:
        plt.xlim(args.xlim)

    # Print collected output
    print("Fitting spread radius 'R' of input file sets to power law functions "
            "of time 't' as 'R = C * (t ** n)' and taking means:")
    for i, _ in enumerate(amp):
        print()
        # If nomean, print individual line values
        if args.nomean:
            for values in zip(amp[i], ampError[i], index[i], indexError[i]):
                print("%f +/- %f" % (values[0], values[1]), end=', ')
                print("%f +/- %f" % (values[2], values[3]))

        # Print mean values
        if args.nomean:
            print("  -> ", end='')
        print("C = %f +/- %f" % (ampMean[i], ampMeanError[i]))
        if args.nomean:
            print("  -> ", end='')
        print("n = %f +/- %f" % (indexMean[i], indexMeanError[i]))

    # Finish by saving and / or showing
    if args.save:
        plt.savefig(args.save)

    if args.draw != 'off':
        plt.show()

    return None
예제 #2
0
def vel_plot(args):
    """Draw the spreading as a function of time."""

    def plot_data(spread, times):
        """Plot either edges or radius of specified line."""

        for _type in args.plot_type:
            velocity = spread[_type]['val']
            plot_line(
                    line=velocity,
                    domain=times,
                    color=colours[i], label=label,
                    linestyle=linestyles['line'][i]
                )

        return None

    def calc_velocity(spread, plot_type, N, N_sample):
        """
        Returns the velocity of the spreading curve, as a running average
        over N frames.

        """

        def get_velocity(spreading, times, N_sample):
            velocity = []
            for i, _ in enumerate(spreading):
                i_min = max(0, i-N_sample)
                i_max = min(i+N_sample, len(spreading)-1)
                delta_x = spreading[i_max] - spreading[i_min]
                delta_t = times[i_max] - times[i_min]
                velocity.append(delta_x/delta_t)

            return velocity

        def calc_running_avg(velocity, full_times, N):
            N0 = N
            running_avg = {'val': [], 'std': []}
            times = []

            for i, _ in enumerate(velocity):
                if args.include == 'equal':
                    N = min(i - max(0, i-N0), min(i+N0, len(velocity)-1)-i)

                i_min = max(0, i-N)
                i_max = min(i+N, len(velocity)-1)

                if N == 0 or (args.include == 'limited' and i_max - i_min != 2*N):
                    continue

                running_avg['val'].append(np.average(velocity[i_min:i_max+1]))
                times.append(full_times[i])

            return running_avg, times

        running_avg = {}
        for _type in plot_type:
            velocity = get_velocity(spread.spread[_type]['val'], spread.times, N_sample)
            running_avg[_type], times = calc_running_avg(velocity, spread.times, N)

        return running_avg, times

    def print_vel(velocity, times):
        """Output the mean spread velocity to standard output."""

        print("%9c Velocity of (nm / ps)" % ' ')
        print("%9s " % "Time (ps)", end='')
        for _key in velocity.keys():
            print("%9s " % _key.capitalize(), end='')
        print()

        for i, time in enumerate(times[1:]):
            print("%9g " % time, end='')
            for _type in velocity.keys():
                print("%9g " % velocity[_type]['val'][i+1], end='')
            print()

        return None

    # Get colours, labels and line styles from default
    colours = get_colours(args.colour, len(args.spreading))
    labels, draw_legend = get_labels(args.label, len(args.spreading))

    linestyles = {}
    linestyles['line'] = get_linestyles(args.linestyle, len(args.spreading))

    # Find shift array for synchronisation
    shift_array = get_shift(args.spreading, sync=args.sync)

    for i, spread_list in enumerate(args.spreading):
        spread, data = combine_spread(spread_list, shift=shift_array[i])

        # If --nomean, draw lines here
        label = labels[i]
        if args.nomean:
            for spread_data in data:
                vel, times = calc_velocity(spread_data, args.plot_type,
                        args.num_average, args.num_sample)
                plot_data(vel, times)
                label = '_nolegend_'

        # Else draw the mean result
        else:
            vel, times = calc_velocity(spread, args.plot_type,
                    args.num_average, args.num_sample)
            plot_data(vel, times)

    plt.title(args.title, fontsize='medium')
    plt.xlabel(args.xlabel, fontsize='medium')
    plt.ylabel(args.ylabel, fontsize='medium')

    if args.loglog:
        plt.xscale('log')
        plt.yscale('log')

    plt.axis('normal')

    plt.xlim([args.t0, args.tend])

    if draw_legend:
        plt.legend(loc=args.legend_loc)

    # Finish by saving and / or showing
    if args.save:
        plt.savefig(
                args.save, dpi=args.dpi,
                transparent=args.transparent,
                bbox_inches='tight'
                )

    if args.print:
        if args.nomean:
            vel = calc_velocity(spread, args.plot_type, args.num_average, args.num_sample)
        print_vel(vel, spread.times)

    if args.show:
        plt.show()

    return None
예제 #3
0
def sample_error_plot(args):
    """Draw the sample error for spread data."""

    def plot(spreading, _type, shift, style):
        def get_line(spread, _type):
            if _type == 'left' or _type == 'right':
                return spread.spread[_type]['std_error']
            elif _type == 'radius':
                _, radius = calc_radius(spread, error=True)
                return radius

        for i, spread_list in enumerate(spreading):
            spread, _ = combine_spread(spread_list, shift=shift[0])

            domain = spread.times
            line = get_line(spread, _type)
            plot_line(
                    line=line, domain=domain,
                    color=colours[i], label=labels[i],
                    linestyle=style[i],
                    hold=True
                    )

        return None

    colours = get_colours(args.colour, len(args.spreading))
    labels, draw_legend = get_labels(args.label, len(args.spreading))
    complabels, draw_comp = get_labels(args.complabel, len(args.spreading))
    draw_legend = draw_legend or draw_comp

    linestyles = {}
    linestyles['line'] = get_linestyles(args.linestyle, len(args.spreading))
    linestyles['compare'] = get_linestyles(args.compstyle, len(args.spreading),
            'dotted')

    for i, spread_list in enumerate(args.spreading):
        if args.sync == 'com':
            shift = get_shift([spread_list], sync='com')
            comp_shift = get_shift([spread_list], sync='impact')
        else:
            shift = get_shift([spread_list], sync='impact')
            comp_shift = get_shift([spread_list], sync='com')

    if args.radius:
        plot(args.spreading, 'radius', shift, linestyles['line'])
        if args.compare:
            plot(args.spreading, 'radius', comp_shift, linestyles['compare'])
    else:
        for _type in ('left', 'right'):
            plot(args.spreading, _type, shift, linestyles['line'])
            if args.compare:
                plot(args.spreading, _type, comp_shift, linestyles['compare'])

    plt.title(args.title)
    plt.xlabel(args.xlabel)
    plt.ylabel(args.ylabel)

    plt.axis('normal')

    plt.xlim([args.t0, args.tend])

    if draw_legend:
        plt.legend()

    if args.save:
        plt.savefig(args.save)

    if args.show:
        plt.show()

    return None
예제 #4
0
def t_test_plot(args):
    """Perform a Welch's t-test on two sets of spread data, plot probability."""

    def plot(spreading, _type, shift_array):
        def get_line(spread, _type):
            if _type == 'left' or _type == 'right':
                return spread.spread[_type]['val']
            elif _type == 'radius':
                return calc_radius(spread)

        data = {}
        n = 0
        for i, spread_list in enumerate(spreading):
            for j, _file in enumerate(spread_list):
                spread = Spread().read(_file)
                line = get_line(spread, _type)
                times = np.array(spread.times) - shift_array[i][j]
                data[n] = Series(data=line, index=times)
                n += 1

        # Create DataFrame for all values and drop nan
        df = DataFrame(data).dropna()
        domain = df.index

        n = 0
        data = [[], []]
        for i, spread_list in enumerate(spreading):
            for j, _ in enumerate(spread_list):
                data[i].append(df[n].tolist())
                n += 1
        t, p = stats.ttest_ind(data[0], data[1], equal_var=False)
        plot_line(line=p, domain=domain, label=label[0], color=colour[0],
                linestyle=linestyle['line'][0], hold=True)

        return None

    # Two sets of data must be given
    if len(args.spreading) != 2:
        parser.error("exactly two sets of spread data must be supplied with -f "
                "(%d given)" % len(args.spreading))

    # Get colours, labels and line styles from default
    colour = get_colours(args.colour, len(args.spreading))
    label, draw_legend = get_labels(args.label, len(args.spreading))

    linestyle = {}
    linestyle['line'] = get_linestyles(args.linestyle, 2)

    # Find shift array for synchronisation
    shift_array = get_shift(args.spreading, sync=args.sync)

    if args.radius:
        plot(args.spreading, 'radius', shift_array)
    else:
        plot(args.spreading, 'left', shift_array)
        plot(args.spreading, 'right', shift_array)

    plt.axis('normal')

    plt.title(args.title)
    plt.xlabel(args.xlabel)
    plt.ylabel(args.ylabel)

    plt.xlim([args.t0, args.tend])

    if draw_legend:
        plt.legend()

    # Finish by saving and / or showing
    if args.save:
        plt.savefig(args.save)

    if args.show:
        plt.show()

    return None
예제 #5
0
def com_plot(args):
    """Draw the center of mass height as a function of time."""

    # Get colours, labels and line styles from default
    colours = get_colours(args.colour, len(args.spreading))
    labels, draw_legend = get_labels(args.label, len(args.spreading))

    linestyles = {}
    linestyles['line'] = get_linestyles(args.linestyle, len(args.spreading))
    linestyles['error'] = get_linestyles(args.errorstyle, len(args.spreading),
            'dashed')

    # Find shift array for synchronisation
    shift_array = get_shift(args.spreading, sync=args.sync)

    for i, spread_list in enumerate(args.spreading):
        spread, data = combine_spread(spread_list, shift=shift_array[i])

        # Check if error bars need to be included
        error = args.error and len(spread_list) > 1

        # Create graph
        if args.nomean:
            label = labels[i]
            for spread_data in data:
                domain = spread_data.times
                line = spread_data.dist
                plot_line(line=line, domain=domain, color=colours[i],
                        label=label, linestyle=linestyles['line'][i])
                label = '_nolegend_'
        else:
            domain = spread.times
            line = spread.dist
            plot_line(line=line, domain=domain, color=colours[i],
                    label=labels[i], linestyle=linestyles['line'][i])

        if error:
            domain = spread.times
            line = list(np.array(spread.dist)
                    + np.array(spread.spread['dist']['std_error'])
                    * args.sigma)
            plot_line(line=line, domain=domain, color=colours[i],
                    linestyle=linestyles['error'][i])
            line = list(np.array(spread.dist)
                    - np.array(spread.spread['dist']['std_error'])
                    * args.sigma)
            plot_line(line=line, domain=domain, color=colours[i],
                    linestyle=linestyles['error'][i])

    plt.title(args.title)
    plt.xlabel(args.xlabel)
    plt.ylabel(args.ylabel)

    plt.axis('normal')

    plt.xlim([args.t0, args.tend])

    if draw_legend:
        plt.legend()

    # Finish by saving and / or showing
    if args.save:
        plt.savefig(args.save)

    if args.show:
        plt.show()

    return None
예제 #6
0
def spread_plot(args):
    """Draw the spreading of sets of droplets as a function of time."""

    def add_xvgdata(spread, xvg_set):
        """
        Adds data for current line to list of data to output in
        .xvg format.

        """
        add = {}
        line = []
        for _type in plot_type:
            add['legend'] = labels[i]
            add['line'] = spread.spread[_type]['val'][0:]
            add['time'] = np.array(spread.times[0:])
            line.append(add.copy())

        xvg_set.append(line)

        return None

    def save_xvgdata(xvg_data):
        """
        Saves spreading lines to .xvg files of input filenames.

        """

        def print_xvgfile(line, fnin):

            fnout = fnin.rsplit('.', 1)[0] + '.xvg'
            backup_file(fnout)
            with open(fnout, 'w') as _file:
                _file.write(
                        "@ title \"%s\"\n"
                        "@ xaxis label \"%s\"\n"
                        "@ yaxis label \"%s\"\n"
                        "@TYPE xy\n"
                        % (args.title, args.xlabel, args.ylabel)
                        )

                # Output legend information
                _file.write(
                        "@ legend on\n"
                        "@ legend box on\n"
                        "@ legend loctype view\n"
                        "@ legend 0.78 0.8\n"
                        "@ legend length 2\n"
                        "@s0 legend \"%s\"\n\n"
                        % line[0]['legend']
                        )

                for i in range(len(line[0]['time'])):
                    time = line[0]['time'][i]
                    _file.write("%f " % time)
                    for j in range(len(line)):
                        value = line[j]['line'][i]
                        _file.write("%f " % value)
                    _file.write("\n")

            return None

        def backup_file(fn):
            """If a file 'fn' exists, move to backup location."""

            fnmv = fn

            n = 0
            while (os.path.isfile(fnmv)):
                n += 1
                try:
                    _path, _file = fn.rsplit('/', 1)
                    _path += '/'
                except ValueError:
                    _path = ''
                    _file = fn

                fnmv = _path + '#' + _file.rsplit('.', 1)[0] + '.xvg.%d#' % n

            if (n > 0):
                print("File '%s' backed up to '%s'" % (fn, fnmv))
                shutil.move(fn, fnmv)

            return None

        for i, xvg_set in enumerate(xvg_data):
            # Print either all lines to separate files with extension switch
            if args.nomean:
                for j, line in enumerate(xvg_set):
                    # Replace last extension with .xvg
                    fnin = args.spreading[i][j]
                    print_xvgfile(line, fnin)

            # Or print combined lines to files with base filename as first file
            else:
                line = xvg_set[0]
                fnin = args.spreading[i][0]
                print_xvgfile(line, fnin)

        return None

    def plot_data(spread, times):
        """Plot either edges or radius of specified line."""

        for _type in plot_type:
            plot_line(
                    line=spread[_type]['val'][0:],
                    domain=np.array(times[0:]),
                    color=colours[i], label=label,
                    linestyle=linestyles['line'][i],
                    linewidth=2
                )

        return None

    def plot_error(spread):
        """Plot the error of either the edges or radius of a line."""

        def draw_error_line(spread):
            mean = np.array(get_line(spread, _type, error=False))
            std = np.array(get_line(spread, _type, error=True))

            # If not standard deviation desired, calculate std error
            if args.std:
                error = std
            else:
                error = (std / np.sqrt(spread.spread['num']))*args.sigma

            plot_line(
                    line=(mean + error),
                    domain=spread.times,
                    color=colours[i],
                    linestyle=linestyles['error'][i]
                )
            plot_line(
                    line=(mean - error),
                    domain=spread.times,
                    color=colours[i],
                    linestyle=linestyles['error'][i]
                )

            return None

        for _type in plot_type:
            draw_error_line(spread)

        return None

    def get_line(spread, _type, error=False):
        """Return a desired line to plot."""

        _value = 'val'
        if error:
            _value = 'std'

        return spread.spread[_type][_value]

    def get_scaling(input_time, input_radius,
            num_factors, default=1.0):
        """Get scaling factors for time and radii of all lines."""

        scaling = {}
        input_factors = {'time': input_time, 'radius': input_radius}

        for key in ['time', 'radius']:
            scaling[key] = []
            for i in range(0, num_factors):
                if i < len(input_factors[key]):
                    scaling[key].append(input_factors[key][i])
                else:
                    scaling[key].append(default)

        return scaling

    def apply_scaling(spread, all_data, scaling, num):
        """Apply time and radius scaling onto all spread data."""

        spread.scale_data(scaling['time'][num], scaling['radius'][num])
        for i, _ in enumerate(all_data):
            all_data[i].scale_data(scaling['time'][num], scaling['radius'][num])

        return None

    # Get colours, labels and line styles from default
    colours = get_colours(args.colour, len(args.spreading))
    labels, draw_legend = get_labels(args.label, len(args.spreading))

    linestyles = {}
    linestyles['line'] = get_linestyles(args.linestyle, len(args.spreading))
    linestyles['error'] = get_linestyles(args.errorstyle, len(args.spreading),
            'dashed')

    # Find scaling factors for lines
    scaling = get_scaling(args.time_scaling, args.radius,
        len(args.spreading))

    # Find shift array for synchronisation
    shift_array = get_shift(args.spreading, sync=args.sync,
            radius_array=scaling['radius'], radius_fraction=args.sync_radius_fraction)

    # Initiate xvg data
    xvgdata = []

    for i, spread_list in enumerate(args.spreading):
        spread, data = combine_spread(spread_list, shift=shift_array[i])
        apply_scaling(spread, data, scaling, i)

        # Either draw all or a combined line; set which set here
        xvg_set = []
        if args.nomean:
            spread_array = data
        else:
            spread_array = [spread]

        label = labels[i]
        for spread_data in spread_array:
            plot_data(spread_data.spread, spread_data.times)
            label = '_nolegend_'

            if args.xvg:
                add_xvgdata(spread_data, xvg_set)

        # If error for line is desired, calculate and plot
        if args.error:
            plot_error(spread)

        # Add set of xvg data to array
        if args.xvg:
            xvgdata.append(xvg_set)

    plt.title(args.title, fontsize='medium')
    plt.xlabel(args.xlabel, fontsize='medium')
    plt.ylabel(args.ylabel, fontsize='medium')

    if args.loglog:
        plt.xscale('log')
        plt.yscale('log')

    plt.axis('normal')

    plt.xlim([args.t0, args.tend])

    if draw_legend:
        plt.legend(loc=args.legend_loc)

    # Finish by saving and / or showing
    if args.save:
        plt.savefig(
                args.save,
                dpi=args.dpi,
                transparent=args.transparent,
                bbox_inches='tight'
                )

    if args.xvg:
        save_xvgdata(xvgdata)

    if args.show:
        plt.show()

    return None