示例#1
0
def apodization(mzs, intensities, w_size=10):
    import scipy.signal as signal
    win = signal.hann(w_size)
    win = signal.slepian(w_size, 0.3)
    intensities = signal.fftconvolve(intensities, win, mode='same') / sum(win)
    intensities[intensities < 1e-6] = 0
    return intensities
示例#2
0
def apodization(mzs,intensities,w_size=10):
    import scipy.signal as signal
    win = signal.hann(w_size)
    win = signal.slepian(w_size,0.3)
    intensities = signal.fftconvolve(intensities, win, mode='same') / sum(win)
    intensities[intensities<1e-6]=0
    return intensities
示例#3
0
    def update_descriptors(self):
        if not self.kernel_type:
            raise ValueError("Integrator was passed kernel None")

        logger.debug(
            'Updating WindowIntegrator "%s" descriptors based on input descriptor: %s.',
            self.name, self.sink.descriptor)

        record_length = self.sink.descriptor.axes[-1].num_points()

        time_pts = self.sink.descriptor.axes[-1].points
        time_step = time_pts[1] - time_pts[0]
        kernel = np.zeros(record_length, dtype=np.complex128)
        sample_start = int(self.box_car_start.value / time_step)
        sample_stop = int(self.box_car_stop.value / time_step) + 1
        if self.kernel_type == 'boxcar':
            kernel[sample_start:sample_stop] = 1.0
        elif self.kernel_type == 'chebwin':
            # create a Dolph-Chebyshev window with 100 dB attenuation
            kernel[sample_start:sample_stop] = \
                chebwin(sample_start-sample_stop, at=100)
        elif self.kernel_type == 'blackman':
            kernel[sample_start:sample_stop] = \
                blackman(sample_start-sample_stop)
        elif self.kernel_type == 'slepian':
            # create a Slepian window with 0.2 bandwidth
            kernel[sample_start:sample_stop] = \
                slepian(sample_start-sample_stop, width=0.2)

        # add modulation
        kernel *= np.exp(2j * np.pi * self.frequency.value * time_step *
                         time_pts)

        # pad or truncate the kernel to match the record length
        if kernel.size < record_length:
            self.aligned_kernel = np.append(
                kernel,
                np.zeros(record_length - kernel.size, dtype=np.complex128))
        else:
            self.aligned_kernel = np.resize(kernel, record_length)

        # Integrator reduces and removes axis on output stream
        # update output descriptors
        output_descriptor = DataStreamDescriptor()
        # TODO: handle reduction to single point
        output_descriptor.axes = self.sink.descriptor.axes[:-1]
        output_descriptor._exp_src = self.sink.descriptor._exp_src
        output_descriptor.dtype = np.complex128
        for os in self.source.output_streams:
            os.set_descriptor(output_descriptor)
            os.end_connector.update_descriptors()
示例#4
0
def apodization(mzs, intensities, w_size=10):
    """
    apodization with slepian window
    :param mzs:  numpy array numpy array of mz values
    :param counts:  numpy array numpy array of values to smooth
    :param w_size:  int window size
    :return: mzs: numpy array
    :return: counts: numpy array
    """
    import scipy.signal as signal
    win = signal.hann(w_size)
    win = signal.slepian(w_size, 0.3)
    intensities = signal.fftconvolve(intensities, win, mode='same') / sum(win)
    intensities[intensities < 1e-6] = 0
    return mzs, intensities
def slepian(N, tau, N_MAX=1000):
    """ return the slepian window of size N with main lobe end at +/- tau

    the result is normalized by its mean.

    """
    ##  NOTES
    ##  MemoryError si N grand
    ##  signal.slepian is bugged and need a factor 2 on its second arg
    ##  the factor 4 is here to get the half band width
    ##  scipy 1.1 introduce signal.windows.dpss which is more standard


    if N <= N_MAX:
        res = signal.slepian(N, (4./N) * tau)  # factor 2 pour coller a la definition +/- tau
        res /= res.mean()
    else:
        a = float(N) / float(N_MAX)
        ref = slepian(N_MAX, tau)
        res = np.interp(np.arange(N), a * np.arange(N_MAX), ref)
    return res
示例#6
0
def show_old_vs_new(
    args: Namespace,
    name: str,
    start_date: int,
    end_date: int,
    people: List[str],
    days: Dict[int, Dict[int, DevDay]],
) -> None:
    from scipy.signal import convolve, slepian

    start_date = datetime.fromtimestamp(start_date)
    start_date = datetime(start_date.year, start_date.month, start_date.day)
    end_date = datetime.fromtimestamp(end_date)
    end_date = datetime(end_date.year, end_date.month, end_date.day)
    new_lines = numpy.zeros((end_date - start_date).days + 2)
    old_lines = numpy.zeros_like(new_lines)
    for day, devs in days.items():
        for stats in devs.values():
            new_lines[day] += stats.Added
            old_lines[day] += stats.Removed + stats.Changed
    resolution = 32
    window = slepian(max(len(new_lines) // resolution, 1), 0.5)
    new_lines = convolve(new_lines, window, "same")
    old_lines = convolve(old_lines, window, "same")
    matplotlib, pyplot = import_pyplot(args.backend, args.style)
    plot_x = [start_date + timedelta(days=i) for i in range(len(new_lines))]
    pyplot.fill_between(plot_x, new_lines, color="#8DB843", label="Changed new lines")
    pyplot.fill_between(
        plot_x, old_lines, color="#E14C35", label="Changed existing lines"
    )
    pyplot.legend(loc=2, fontsize=args.font_size)
    for tick in chain(
        pyplot.gca().xaxis.get_major_ticks(), pyplot.gca().yaxis.get_major_ticks()
    ):
        tick.label.set_fontsize(args.font_size)
    if args.mode == "all" and args.output:
        output = get_plot_path(args.output, "old_vs_new")
    else:
        output = args.output
    deploy_plot("Additions vs changes", output, args.background)
# Plot the window and its frequency response:

from scipy import signal
from scipy.fftpack import fft, fftshift
import matplotlib.pyplot as plt

window = signal.slepian(51, width=0.3)
plt.plot(window)
plt.title("Slepian (DPSS) window (BW=0.3)")
plt.ylabel("Amplitude")
plt.xlabel("Sample")

plt.figure()
A = fft(window, 2048) / (len(window)/2.0)
freq = np.linspace(-0.5, 0.5, len(A))
response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
plt.plot(freq, response)
plt.axis([-0.5, 0.5, -120, 0])
plt.title("Frequency response of the Slepian window (BW=0.3)")
plt.ylabel("Normalized magnitude [dB]")
plt.xlabel("Normalized frequency [cycles per sample]")
示例#8
0
def show_devs_efforts(
    args: Namespace,
    name: str,
    start_date: int,
    end_date: int,
    people: List[str],
    days: Dict[int, Dict[int, DevDay]],
    max_people: int,
) -> None:
    from scipy.signal import convolve, slepian

    start_date = datetime.fromtimestamp(start_date)
    start_date = datetime(start_date.year, start_date.month, start_date.day)
    end_date = datetime.fromtimestamp(end_date)
    end_date = datetime(end_date.year, end_date.month, end_date.day)

    efforts_by_dev = defaultdict(int)
    for day, devs in days.items():
        for dev, stats in devs.items():
            efforts_by_dev[dev] += stats.Added + stats.Removed + stats.Changed
    if len(efforts_by_dev) > max_people:
        chosen = {
            v
            for k, v in sorted(
                ((v, k) for k, v in efforts_by_dev.items()), reverse=True
            )[:max_people]
        }
        print("Warning: truncated people to the most active %d" % max_people)
    else:
        chosen = set(efforts_by_dev)
    chosen_efforts = sorted(((efforts_by_dev[k], k) for k in chosen), reverse=True)
    chosen_order = {k: i for i, (_, k) in enumerate(chosen_efforts)}

    efforts = numpy.zeros(
        (len(chosen) + 1, (end_date - start_date).days + 1), dtype=numpy.float32
    )
    for day, devs in days.items():
        if day < efforts.shape[1]:
            for dev, stats in devs.items():
                dev = chosen_order.get(dev, len(chosen_order))
                efforts[dev][day] += stats.Added + stats.Removed + stats.Changed
    efforts_cum = numpy.cumsum(efforts, axis=1)
    window = slepian(10, 0.5)
    window /= window.sum()
    for e in (efforts, efforts_cum):
        for i in range(e.shape[0]):
            ending = e[i][-len(window) * 2 :].copy()
            e[i] = convolve(e[i], window, "same")
            e[i][-len(ending) :] = ending
    matplotlib, pyplot = import_pyplot(args.backend, args.style)
    plot_x = [start_date + timedelta(days=i) for i in range(efforts.shape[1])]

    people = [people[k] for _, k in chosen_efforts] + ["others"]
    for i, name in enumerate(people):
        if len(name) > 40:
            people[i] = name[:37] + "..."

    polys = pyplot.stackplot(plot_x, efforts_cum, labels=people)
    if len(polys) == max_people + 1:
        polys[-1].set_hatch("/")
    polys = pyplot.stackplot(plot_x, -efforts * efforts_cum.max() / efforts.max())
    if len(polys) == max_people + 1:
        polys[-1].set_hatch("/")
    yticks = []
    for tick in pyplot.gca().yaxis.iter_ticks():
        if tick[1] >= 0:
            yticks.append(tick[1])
    pyplot.gca().yaxis.set_ticks(yticks)
    legend = pyplot.legend(loc=2, ncol=2, fontsize=args.font_size)
    apply_plot_style(
        pyplot.gcf(),
        pyplot.gca(),
        legend,
        args.background,
        args.font_size,
        args.size or "16,10",
    )
    if args.mode == "all" and args.output:
        output = get_plot_path(args.output, "efforts")
    else:
        output = args.output
    deploy_plot("Efforts through time (changed lines of code)", output, args.background)
示例#9
0
def show_devs(
    args: Namespace,
    name: str,
    start_date: int,
    end_date: int,
    people: List[str],
    days: Dict[int, Dict[int, DevDay]],
    max_people: int = 50,
) -> None:
    from scipy.signal import convolve, slepian

    if len(people) > max_people:
        print("Picking top %s developers by commit count" % max_people)
        # pick top N developers by commit count
        commits = defaultdict(int)
        for devs in days.values():
            for dev, stats in devs.items():
                commits[dev] += stats.Commits
        commits = sorted(((v, k) for k, v in commits.items()), reverse=True)
        chosen_people = {people[k] for _, k in commits[:max_people]}
    else:
        chosen_people = set(people)
    dists, devseries, devstats, route = order_commits(chosen_people, days, people)
    route_map = {v: i for i, v in enumerate(route)}
    # determine clusters
    clusters = hdbscan_cluster_routed_series(dists, route)
    keys = list(devseries.keys())
    route = [keys[node] for node in route]
    print("Plotting")
    # smooth time series
    start_date = datetime.fromtimestamp(start_date)
    start_date = datetime(start_date.year, start_date.month, start_date.day)
    end_date = datetime.fromtimestamp(end_date)
    end_date = datetime(end_date.year, end_date.month, end_date.day)
    size = (end_date - start_date).days + 1
    plot_x = [start_date + timedelta(days=i) for i in range(size)]
    resolution = 64
    window = slepian(size // resolution, 0.5)
    final = numpy.zeros((len(devseries), size), dtype=numpy.float32)
    for i, s in enumerate(devseries.values()):
        arr = numpy.array(s).transpose()
        full_history = numpy.zeros(size, dtype=numpy.float32)
        mask = arr[0] < size
        full_history[arr[0][mask]] = arr[1][mask]
        final[route_map[i]] = convolve(full_history, window, "same")

    matplotlib, pyplot = import_pyplot(args.backend, args.style)
    pyplot.rcParams["figure.figsize"] = (32, 16)
    pyplot.rcParams["font.size"] = args.font_size
    prop_cycle = pyplot.rcParams["axes.prop_cycle"]
    colors = prop_cycle.by_key()["color"]
    fig, axes = pyplot.subplots(final.shape[0], 1)
    backgrounds = (
        ("#C4FFDB", "#FFD0CD") if args.background == "white" else ("#05401C", "#40110E")
    )
    max_cluster = numpy.max(clusters)
    for ax, series, cluster, dev_i in zip(axes, final, clusters, route):
        if cluster >= 0:
            color = colors[cluster % len(colors)]
            i = 1
            while color == "#777777":
                color = colors[(max_cluster + i) % len(colors)]
                i += 1
        else:
            # outlier
            color = "#777777"
        ax.fill_between(plot_x, series, color=color)
        ax.set_axis_off()
        author = people[dev_i]
        ax.text(
            0.03,
            0.5,
            author[:36] + (author[36:] and "..."),
            horizontalalignment="right",
            verticalalignment="center",
            transform=ax.transAxes,
            fontsize=args.font_size,
            color="black" if args.background == "white" else "white",
        )
        ds = devstats[dev_i]
        stats = "%5d %8s %8s" % (
            ds[0],
            _format_number(ds[1] - ds[2]),
            _format_number(ds[3]),
        )
        ax.text(
            0.97,
            0.5,
            stats,
            horizontalalignment="left",
            verticalalignment="center",
            transform=ax.transAxes,
            fontsize=args.font_size,
            family="monospace",
            backgroundcolor=backgrounds[ds[1] <= ds[2]],
            color="black" if args.background == "white" else "white",
        )
    axes[0].text(
        0.97,
        1.75,
        " cmts    delta  changed",
        horizontalalignment="left",
        verticalalignment="center",
        transform=axes[0].transAxes,
        fontsize=args.font_size,
        family="monospace",
        color="black" if args.background == "white" else "white",
    )
    axes[-1].set_axis_on()
    target_num_labels = 12
    num_months = (
        (end_date.year - start_date.year) * 12 + end_date.month - start_date.month
    )
    interval = int(numpy.ceil(num_months / target_num_labels))
    if interval >= 8:
        interval = int(numpy.ceil(num_months / (12 * target_num_labels)))
        axes[-1].xaxis.set_major_locator(
            matplotlib.dates.YearLocator(base=max(1, interval // 12))
        )
        axes[-1].xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%Y"))
    else:
        axes[-1].xaxis.set_major_locator(
            matplotlib.dates.MonthLocator(interval=interval)
        )
        axes[-1].xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%Y-%m"))
    for tick in axes[-1].xaxis.get_major_ticks():
        tick.label.set_fontsize(args.font_size)
    axes[-1].spines["left"].set_visible(False)
    axes[-1].spines["right"].set_visible(False)
    axes[-1].spines["top"].set_visible(False)
    axes[-1].get_yaxis().set_visible(False)
    axes[-1].set_facecolor((1.0,) * 3 + (0.0,))

    title = ("%s commits" % name) if not args.output else ""
    if args.mode == "all" and args.output:
        output = get_plot_path(args.output, "time_series")
    else:
        output = args.output
    deploy_plot(title, output, args.background)
示例#10
0
from scipy import signal
from matplotlib import pyplot as plt
from matplotlib import style
import mysignals as sigs
import numpy as np
from scipy.fftpack import fft, fftshift

window = signal.slepian(51, width=3)
plt.plot(window)
plt.title("Slepian Window")
plt.ylabel("Amplitude")
plt.xlabel("Sample")
plt.show()

#frequency response

plt.figure()

A = fft(window, 2048) / (len(window) / 2.0)
freq = np.linspace(-0.5, 0.5, len(A))
response = 20 * np.log10(np.abs(fftshift(A / abs(A).max())))
plt.plot(freq, response)
plt.axis([-0.5, 0.5, -120, 0])
plt.title("Frequency Response of Slepian Window")
plt.ylabel("Normalized Magnitude(dB)")
plt.xlabel("Normalized Frequency in cycles/sample")
plt.show()
示例#11
0
def show_sentiment_stats(args, name, resample, start_date, data):
    from scipy.signal import convolve, slepian

    matplotlib, pyplot = import_pyplot(args.backend, args.style)

    start_date = datetime.fromtimestamp(start_date)
    data = sorted(data.items())
    mood = numpy.zeros(data[-1][0] + 1, dtype=numpy.float32)
    timeline = numpy.array(
        [start_date + timedelta(days=i) for i in range(mood.shape[0])]
    )
    for d, val in data:
        mood[d] = (0.5 - val.Value) * 2
    resolution = 32
    window = slepian(len(timeline) // resolution, 0.5)
    window /= window.sum()
    mood_smooth = convolve(mood, window, "same")
    pos = mood_smooth.copy()
    pos[pos < 0] = 0
    neg = mood_smooth.copy()
    neg[neg >= 0] = 0
    resolution = 4
    window = numpy.ones(len(timeline) // resolution)
    window /= window.sum()
    avg = convolve(mood, window, "same")
    pyplot.fill_between(timeline, pos, color="#8DB843", label="Positive")
    pyplot.fill_between(timeline, neg, color="#E14C35", label="Negative")
    pyplot.plot(timeline, avg, color="grey", label="Average", linewidth=5)
    legend = pyplot.legend(loc=1, fontsize=args.font_size)
    pyplot.ylabel("Comment sentiment")
    pyplot.xlabel("Time")
    apply_plot_style(
        pyplot.gcf(), pyplot.gca(), legend, args.background, args.font_size, args.size
    )
    pyplot.xlim(
        parse_date(args.start_date, timeline[0]),
        parse_date(args.end_date, timeline[-1]),
    )
    locator = pyplot.gca().xaxis.get_major_locator()
    # set the optimal xticks locator
    if "M" not in resample:
        pyplot.gca().xaxis.set_major_locator(matplotlib.dates.YearLocator())
    locs = pyplot.gca().get_xticks().tolist()
    if len(locs) >= 16:
        pyplot.gca().xaxis.set_major_locator(matplotlib.dates.YearLocator())
        locs = pyplot.gca().get_xticks().tolist()
        if len(locs) >= 16:
            pyplot.gca().xaxis.set_major_locator(locator)
    if locs[0] < pyplot.xlim()[0]:
        del locs[0]
    endindex = -1
    if len(locs) >= 2 and pyplot.xlim()[1] - locs[-1] > (locs[-1] - locs[-2]) / 2:
        locs.append(pyplot.xlim()[1])
        endindex = len(locs) - 1
    startindex = -1
    if len(locs) >= 2 and locs[0] - pyplot.xlim()[0] > (locs[1] - locs[0]) / 2:
        locs.append(pyplot.xlim()[0])
        startindex = len(locs) - 1
    pyplot.gca().set_xticks(locs)
    # hacking time!
    labels = pyplot.gca().get_xticklabels()
    if startindex >= 0:
        labels[startindex].set_text(timeline[0].date())
        labels[startindex].set_text = lambda _: None
        labels[startindex].set_rotation(30)
        labels[startindex].set_ha("right")
    if endindex >= 0:
        labels[endindex].set_text(timeline[-1].date())
        labels[endindex].set_text = lambda _: None
        labels[endindex].set_rotation(30)
        labels[endindex].set_ha("right")
    overall_pos = sum(2 * (0.5 - d[1].Value) for d in data if d[1].Value < 0.5)
    overall_neg = sum(2 * (d[1].Value - 0.5) for d in data if d[1].Value > 0.5)
    title = "%s sentiment +%.1f -%.1f δ=%.1f" % (
        name,
        overall_pos,
        overall_neg,
        overall_pos - overall_neg,
    )
    if args.mode == "all" and args.output:
        output = get_plot_path(args.output, "sentiment")
    else:
        output = args.output
    deploy_plot(title, output, args.background)
示例#12
0
文件: apo.py 项目: aurelienbl/pylib
def aposlepian(theta,sz):
  from scipy import signal
  slp = signal.slepian(1001,0.019)
  flp = nm.interp(theta,nm.linspace(0,sz/180.*nm.pi,501),slp[500:])
  return 1-nm.where(theta<sz/180.*nm.pi,flp,0)
示例#13
0
def seasons_study(file='challenge-data-v2.csv'):
    sns.set_style("whitegrid")

    # *****************************************************
    # Loading the data
    data = pd.read_csv('challenge-data-v2.csv',
                       index_col='event_date',
                       parse_dates=True)

    # *****************************************************
    # Changing the name of the colums to a more suitable (shorter) form
    data.columns = ['sups', 'moff', 'mon', 'hd']

    # *****************************************************
    # Scaling the values to work in a more suitable way (avoiding super-high values)
    for feature in data.columns:
        if data[feature].values.dtype != 'object':
            scale_factor = np.round(np.log10(np.mean(data[feature])))
            data[feature] = data[feature] / 10**scale_factor
            print Fore.BLUE + 'The feature: ' + feature + ' was rescaled by a factor of ' + str(
                10**scale_factor)

    print 'IMPORTANT: Take these rescaling in account when reading the plots'
    print(Style.RESET_ALL)

    # *****************************************************
    # Computation of the distributions per year for sign ups
    years = np.unique(data.index.year)

    # Definition of the figure.
    figid = plt.figure('Temporal Sign-ups distributions by year',
                       figsize=(20, 10))

    # Definition of the matrix of plots. In this case the situation is more complex that is why I need to define a
    # matrix. It will be a dim[2x3] matrix.
    col = len(data.columns[data.columns == 'sups'])
    gs = grds.GridSpec(3, col)

    for i in range(col):

        ax1 = plt.subplot(gs[0, i])
        ax2 = plt.subplot(gs[1, i])

        legend = []
        for y in years:
            dat = data[data.columns[i]][str(y)].values
            ax1.plot(np.arange(len(dat)), dat, '-')
            legend.append(str(y))
        ax1.set_title('Daily ' + data.columns[i])

        legend = []
        for y in years:
            dat = data[data.columns[i]][str(y)].resample('M').values
            ax2.plot(np.arange(len(dat)) + 1, dat, '-o')
            legend.append(str(y))
        ax2.set_title('Monthly ' + data.columns[i])
        plt.xlim([1, 12])

        ax3 = plt.subplot(gs[2, i])
        legend = []
        for y in years:
            dat = data[data.columns[i]][str(y)]
            dat1 = dat.groupby(dat.index.dayofweek).mean()
            dat1.index = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
            dat1.plot(style='-o')

            legend.append(str(y))
        ax3.set_title('Day week ' + data.columns[i])

        if i == 0:
            ax1.legend(years,
                       bbox_to_anchor=(1, 1),
                       loc='best',
                       borderaxespad=0.,
                       ncol=1,
                       fancybox=True,
                       frameon=True)

    # *****************************************************
    # Computation of different spectral estimators per year for sign ups
    years = np.unique(data.index.year)

    # Definition of the figure.
    figid = plt.figure('Spectral estimators per year', figsize=(20, 10))

    # Definition of the matrix of plots.
    col = 3
    rows = len(years)
    gs = grds.GridSpec(rows, col)

    # Spectral parameters
    Window_length = 32  # in days
    # This is equivalent to multitaper estimation but just one taper.
    window = sgn.slepian(Window_length, width=0.3)
    overlap = 0.85

    for r in range(rows):

        ax1 = plt.subplot(gs[r, 0])
        ax2 = plt.subplot(gs[r, 1])
        ax3 = plt.subplot(gs[r, 2])

        dat = data['sups'][str(years[r])].values

        spec = np.fft.fft(dat)
        n = dat.size
        f = np.fft.fftfreq(n)

        ax1.plot(f[1:round(len(spec) / 2)],
                 np.abs(spec[1:round(len(spec) / 2)]))

        f, t, Sxx = sgn.spectrogram(dat,
                                    nperseg=Window_length,
                                    window=window,
                                    noverlap=np.round(Window_length * overlap))

        #     print 'Spectrogram size',Sxx.shape
        #     print 't',t.shape
        #     print 'f',f.shape

        #     print 'f',f

        spec = np.abs(Sxx)

        ax2.imshow(spec,
                   vmax=np.percentile(spec, 98),
                   aspect='auto',
                   cmap='viridis',
                   interpolation='none',
                   origin='lower',
                   extent=[np.min(t),
                           np.max(t),
                           np.min(f),
                           np.max(f)])
        ax3.imshow(np.log(spec),
                   vmax=np.percentile(np.log(spec), 98),
                   aspect='auto',
                   cmap='viridis',
                   interpolation='none',
                   origin='lower',
                   extent=[np.min(t),
                           np.max(t),
                           np.min(f),
                           np.max(f)])

        ax2.set_ylabel('Year: ' + str(years[r]) + '\nf[Hz]',
                       multialignment='center')

        if r == 0:
            ax1.set_title('PSD[n.u.]')
            ax2.set_title('Spectrogram[n.u.]')
            ax3.set_title('Spectrogram[log10]')
        if r == rows - 1:
            ax1.set_xlabel('f[Hz]')
            ax2.set_xlabel('Time[days of the year]')
            ax3.set_xlabel('Time[days of the year]')

    return True
    def __init__(self,
                 ref=None,
                 nperseg=None,
                 noverlap=None,
                 freq_cutoffs=None,
                 window=None,
                 filter_func=None,
                 spect_func=None,
                 log_transform_spect=True):
        """Spectrogram.__init__ function
        
        Parameters
        ----------
        ref : str
            {'tachibana','koumura'}
            Use spectrogram parameters from a reference.
            'tachibana' uses spectrogram parameters from [1]_,
            'koumura' uses spectrogram parameters from [2]_.
        nperseg : int
            numper of samples per segment for FFT, e.g. 512
        noverlap : int
            number of overlapping samples in each segment

        Either ref or nperseg and noverlap are required for __init__

        Other Parameters
        ----------------
        freq_cutoffs : two-element list of integers
            limits of frequency band to keep, e.g. [1000,8000]
            Spectrogram.make keeps the band:
                freq_cutoffs[0] >= spectrogram > freq_cutoffs[1]
            Default is None.
        window : str
            window to apply to segments
            valid strings are 'Hann', 'dpss', None
            Hann -- Uses np.Hanning with parameter M (window width) set to value of nperseg
            dpss -- Discrete prolate spheroidal sequence AKA Slepian.
                Uses scipy.signal.slepian with M parameter equal to nperseg and
                width parameter equal to 4/nperseg, as in [2]_.
            Default is None.
        filter_func : str
            filter to apply to raw audio. valid strings are 'diff' or None
            'diff' -- differential filter, literally np.diff applied to signal as in [1]_.
            Default is None.
        spect_func : str
            which function to use for spectrogram.
            valid strings are 'scipy' or 'mpl'.
            'scipy' uses scipy.signal.spectrogram,
            'mpl' uses matplotlib.matlab.specgram.
            Default is 'scipy'.
        log_transform_spect : bool
            if True, applies np.log10 to spectrogram to increase range.
            Default is True.

        References
        ----------
        .. [1] Tachibana, Ryosuke O., Naoya Oosugi, and Kazuo Okanoya. "Semi-
        automatic classification of birdsong elements using a linear support vector
         machine." PloS one 9.3 (2014): e92584.

        .. [2] Koumura, Takuya, and Kazuo Okanoya. "Automatic recognition of element
        classes and boundaries in the birdsong with variable sequences."
        PloS one 11.7 (2016): e0159188.
        """

        # check for 'reference' parameter first since it takes precedence
        if ref is not None:
            if ref not in ('tachibana', 'koumura'):
                raise ValueError('{} is not a valid value for reference argument'.
                                 format(ref))
            # warn if called with 'ref' and with other params
            if any(param is not None
                   for param in [nperseg,
                                 noverlap,
                                 freq_cutoffs,
                                 filter_func,
                                 spect_func]):
                warnings.warn('Spectrogram class received ref '
                              'parameter but also received other parameters, '
                              'will over-write those with defaults for reference.')
            else:
                if ref == 'tachibana':
                    self.nperseg = 256
                    self.noverlap = 192
                    self.window = np.hanning(self.nperseg) #Hann window
                    self.freqCutoffs = None
                    self.filterFunc = 'diff'
                    self.spectFunc = 'mpl'
                    self.logTransformSpect = False  # see tachibana feature docs
                    self.ref = ref
                elif ref == 'koumura':
                    self.nperseg = 512
                    self.noverlap = 480
                    self.window = slepian(self.nperseg, 4 / self.nperseg) #dpss
                    self.freqCutoffs = [1000, 8000]
                    self.filterFunc = None
                    self.spectFunc = 'scipy'
                    self.logTransformSpect = True
                    self.ref = ref
                else:
                    raise ValueError('{} is not a valid value for \'ref\' argument. '
                                     'Valid values: {\'tachibana\',\'koumura\',None}'
                                     .format(ref))

        elif ref is None:
            if nperseg is None:
                raise ValueError('nperseg requires a value for Spectrogram.__init__')
            if noverlap is None:
                raise ValueError('noverlap requires a value for Spectrogram.__init__')
            if spect_func is None:
                # switch to default
                # can't have in args list because need to check above for
                # conflict with default spectrogram functions for each ref
                spect_func = 'scipy'
            if type(nperseg) != int:
                raise TypeError('type of nperseg must be int, but is {}'.
                                 format(type(nperseg)))
            else:
                self.nperseg = nperseg

            if type(noverlap) != int:
                raise TypeError('type of noverlap must be int, but is {}'.
                                 format(type(noverlap)))
            else:
                self.noverlap = noverlap

            if window is not None and type(window) != str:
                raise TypeError('type of window must be str, but is {}'.
                                 format(type(window)))
            else:
                if window not in ['Hann','dpss',None]:
                    raise ValueError('{} is not a valid specification for window'.
                                     format(window))
                else:
                    if window == 'Hann':
                        self.window = np.hanning(self.nperseg)
                    elif window == 'dpss':
                        self.window = slepian(self.nperseg, 4 / self.nperseg)
                    elif window is None:
                        self.window = None

            if type(freq_cutoffs) != list:
                raise TypeError('type of freq_cutoffs must be list, but is {}'.
                                 format(type(freq_cutoffs)))
            elif len(freq_cutoffs) != 2:
                raise ValueError('freq_cutoffs list should have length 2, but length is {}'.
                                 format(len(freq_cutoffs)))
            elif not all([type(val) == int for val in freq_cutoffs]):
                raise ValueError('all values in freq_cutoffs list must be ints')
            else:
                self.freqCutoffs = freq_cutoffs

            if filter_func is not None and type(filter_func) != str:
                raise TypeError('type of filter_func must be str, but is {}'.
                                 format(type(filter_func)))
            elif filter_func not in ['diff',None]:
                raise ValueError('string \'{}\' is not valid for filter_func. '
                                 'Valid values are: \'diff\' or None.'.
                                 format(filter_func))
            else:
                self.filterFunc = filter_func

                if type(spect_func) != str:
                    raise TypeError('type of spect_func must be str, but is {}'.
                                     format(type(spect_func)))
                elif spect_func not in ['scipy','mpl']:
                    raise ValueError('string \'{}\' is not valid for filter_func. '
                                     'Valid values are: \'scipy\' or \'mpl\'.'.
                                     format(spect_func))
                else:
                    self.spectFunc = spect_func

                if type(log_transform_spect) is not bool:
                    raise ValueError('Value for log_transform_spect is {}, but'
                                     ' it must be bool.'
                                     .format(type(log_transform_spect)))
                else:
                    self.logTransformSpect = log_transform_spect
示例#15
0
 def smooth(self, a, filter_n=51, width=0.5):
     W = signal.slepian(filter_n, width=width)
     W = W/np.sum(W)
     s = signal.convolve(a, W, mode='valid')
     return np.hstack([[s[0]]*(filter_n//2), s, [s[-1]]*(filter_n//2)])