예제 #1
0
파일: task3.py 프로젝트: gosom/img-proc-p1
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('img1', help=('Image1 - use magnitude'))
    parser.add_argument('img2', help=('Image2 - use phase'))

    args = parser.parse_args()

    images = (args.img1, args.img2)
    for img in images:
        try:
            with open(img, 'rb'):
                pass
        except IOError:
            print >> sys.stderr, "%s could not be opened" % img
            return 1

    img1, img2 = image2array(images[0]), image2array(images[1])

    if img1.shape != img2.shape:
        print >> sys.stderr, "Images should have the same dimensions"
        return 2

    G, H = fft(img1), fft(img2)

    magG = get_magnitude(G)
    phaseH = get_phase(H)

    K = image_from_mag_phase(magG, phaseH)

    img3 = fft(K, True)
    plot([img1, img2, prepare_show(img3, False)])

    return 0
예제 #2
0
    def forward(self, input_field):
        input_padded = self.pad_smaller_dims(input_field,
                                             self.image_resolution)

        if self.fraunhofer_crop_image:
            output_field = utils.fft(input_padded, normalized=True)
            return self.crop_larger_dims(output_field, self.image_resolution)
        else:
            input_padded_cropped = self.crop_larger_dims(
                input_padded, self.image_resolution)
            return utils.fft(input_padded_cropped, normalized=True)
예제 #3
0
def find_phase(signal_1=None,
               signal_2=None,
               fft_1=None,
               fft_2=None,
               return_1=False,
               return_2=False):
    """
    Finds the phase (time shift) between two signals.
    Either signalX or fftX should be set; the FFTs can be returned
    in order to cache them locally...

    :param signal_1: first input signal
    :type signal_1: numpy.ndarray or None
    :param signal_2: second input signal
    :type signal_2: numpy.ndarray or None
    :param fft_1: first input fft
    :type fft_1: numpy.ndarray or None
    :param fft_2: second input fft
    :type fft_2: numpy.ndarray or None
    :param return_1: whether fft1 should be returned
    :type return_1: bool
    :param return_2: whether fft2 should be returned
    :type return_2: bool
    :return: (shift, (fft1 if return_1), (fft2 if return_2))
    :rtype: tuple

    >>> find_phase(np.array([0, 1, 0, 0, 0]), np.array([0, 0, 0, 1, 0]))
    (2,)
    """

    if signal_1 is not None and fft_1 is None:
        fft_1 = fft(signal_1)
    if signal_2 is not None and fft_2 is None:
        fft_2 = fft(signal_2)

    corr = ifft(fft_1 * -fft_2.conjugate())

    corr = np.absolute(corr)
    the_max = np.argmax(corr)
    # if the_max > 2 and the_max < (len(corr) - 2):
    #    sur = corr[the_max-1:the_max+2]
    #    the_max += -0.5*sur[0] + 0.5*sur[2]

    the_max = -the_max if the_max < len(fft_1) / 2 else len(fft_1) - the_max

    result = (the_max, )
    if return_1:
        result += (fft_1, )
    if return_2:
        result += (fft_2, )
    return result
예제 #4
0
파일: task2.py 프로젝트: gosom/img-proc-p1
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('img', help=('Path of the image to perform the'
                        ' transform'))
    parser.add_argument('--rmin', type=int, help='rmin parameter', default=23)
    parser.add_argument('--rmax', type=int, help='rmax parameter', default=48)

    args = parser.parse_args()

    try:
        with open(args.img, 'rb'):
            pass
    except IOError:
        print >> sys.stderr, "%s could not be opened" % args.img
        return 1

    rmin_range = (0, 100)
    if not (rmin_range[0] < args.rmin < rmin_range[1]):
        print >> sys.stderr, "rmin should be between %d and %d" % rmin_range
        return 2

    if not (rmin_range[0] < args.rmax < rmin_range[1]):
        print >> sys.stderr, "rmax should be between %d and %d" % rmin_range
        return 2

    if args.rmin >= args.rmax:
        print >> sys.stderr, 'rmin should be less than rmax'
        return 3

    aimg = image2array(args.img)
    freq_ = fft(aimg)
    shift_freq = fftshift(freq_)

    center = (shift_freq.shape[0] / 2, shift_freq.shape[1] / 2)

    distance_array = euclidean_distance(shift_freq, center)

    mask = (distance_array < args.rmin) != (distance_array > args.rmax)

    shift_freq_cpy = shift_freq.copy()

    shift_freq_cpy[mask] = 0

    output = fft(fftshift(shift_freq_cpy, True), True)

    plot([aimg, prepare_show(shift_freq), prepare_show(shift_freq_cpy),
          prepare_show(output, False)])

    return 0
예제 #5
0
    def record_string(self, n=65536, z=8):
        inp = bs.BitArray()  # input bit array
        trailing_zeros = 0

        min_ = 10000

        while (len(inp) < n) and (trailing_zeros <
                                  z):  # read at most n bytes or z zeros
            self.record(1)  # record one frame

            # compute fft and signal distribution along frequencies
            _fft = fft(self.input_buffer, self.framerate)
            amps = fft_amps(_fft, ZERO_FREQ, ONE_FREQ)

            if amps[ZERO_FREQ] < 1000 and amps[ONE_FREQ] < 1000:
                break

            dist = fft_dist(amps)
            min_ = min(min_, max(dist.values()))

            if dist[ZERO_FREQ] > dist[ONE_FREQ]:
                inp.append('0b0')
                trailing_zeros += 1
            else:
                inp.append('0b1')
                trailing_zeros = 0

        print min_
        return inp
예제 #6
0
    def integrator_2b(self, l1, l2, l3, l4, func):
        """
      This integral can be decoupled and becomes 
      2^d delta(l2+l4 -l1-l3)* (1/V)\int_{L/2}^{L/2} dt f(2|t|) exp(-i (k2+k3 - k1-k4)*t)
      """

        ldiff = [l2[d] + l4[d] - l1[d] - l3[d] for d in xrange(self.dim)]
        if max(ldiff) != 0:
            return complex(0)

        cnk = [
            l2[d] + l3[d] - l1[d] - l4[d] + self.fftpoints / 2
            for d in xrange(self.dim)
        ]
        cnk = tuple(cnk)

        def fwrap(t):
            """
	 From f(x,y) wrap to f(2|t|) where t is given as a tuple
	 """
            p0 = [0] * self.dim
            targ = map(lambda i: i * 2, t)
            return func(p0, t)

        for (f, ft) in self._regft2b:
            if f == func:
                return 2**self.dim * ft[cnk]

        nfft = hu.fft(fwrap, fftpoints, self.Lbox)
        self._regft2b.append((func, nfft))
        return 2**self.dim * nnft[cnk]
예제 #7
0
    def integrator_1b(self, l1, l2, func):
        """
      
      """

        lidx = map(lambda i, j: i - j + self.fftpoints / 2, l2, l1)
        lidx = tuple(lidx)
        for (f, ft) in self._regft1b:
            if f == func:
                return ft[lidx]

        nfft = hu.fft(func, self.fftpoints, self.Lbox)
        self._regft1b.append((func, nfft))

        return nfft[lidx]
예제 #8
0
    def synchronize(self, tries=20):
        diff = 1  # amplitude ratio difference

        while diff > 0.05 and tries > 0:
            self.record(0.3)  # move window by 0.3 of frame width
            self.record(1)  # record one frame

            # compute fft and signal distribution along frequencies
            _fft = fft(self.input_buffer, self.framerate)
            amps = fft_amps(_fft, ZERO_FREQ, ONE_FREQ)
            dist = fft_dist(amps)

            # we try to minimize amplitude of the lesser signal in the window
            diff = min(dist.values())
            # limit how many windows we can test
            tries -= 1

        return (diff <= 0.05)
예제 #9
0
    def listen(self, addr):
        while True:
            self.record(1)  # record one frame
            _fft = fft(self.input_buffer, self.framerate)  # compute fft
            amps = fft_amps(_fft, ZERO_FREQ, ONE_FREQ)

            if amps[ZERO_FREQ] > 1000 or amps[ONE_FREQ] > 1000:
                if not self.synchronize():
                    continue

                string = self.record_string()
                if not string:
                    continue

                print "------BINARY INPUT START-------"
                print string.bin
                print "------BINARY INPUT END-------"

                (src_addr, dest_addr, msg) = Parser.decode(string)

                if dest_addr == self.addr and msg is not None:
                    return (src_addr, msg)
예제 #10
0
 def __init__(self, file_path, balance=True, balance_size=1000, augment=0):
     #self.sounds = []
     self.ffts = []
     self.labels = []
     heavy_files = os.listdir(file_path + 'bass/')
     high_files = os.listdir(file_path + 'high/')
     # light_files = os.listdir(file_path + 'beats_light/')
     # ----------------------------------------------------------------------------------
     # Balance: Training 및 중간 Validation용. Positive, Negative 숫자를 동일하게 밸런싱
     if balance:
         # Heavy
         for i in range(balance_size):
             index = random.randint(0, len(heavy_files) - 1)
             beat_file = file_path + '{}/{}'.format('bass/',
                                                    heavy_files[index])
             if '.wav' not in beat_file:
                 continue
             sr = librosa.get_samplerate(beat_file)
             sound, sr = librosa.load(beat_file, sr=sr)
             duration = librosa.get_duration(sound, sr)
             # print(beat_file, sr, duration, len(sound))
             #
             if sr != 48000:
                 # print('resampling:', beat_file, sr)
                 sound = signal.resample(sound,
                                         int(len(sound) * 48000 / sr))
             #
             # FFT
             freq, fft_abs, fft_beat = utils.fft(sound, len(sound),
                                                 len(sound))
             fft_padding = np.zeros(FFT_SIZE)
             fft_padding[:len(fft_beat)] = fft_beat[:np.min(
                 [FFT_SIZE, len(fft_beat)])]
             #
             # self.sounds.append(sound_padding.reshape(len(sound), 1))
             self.ffts.append(fft_padding.reshape(FFT_SIZE, 1))
             self.labels.append([1, 0])
         #
         # High
         for i in range(balance_size):
             index = random.randint(0, len(high_files) - 1)
             beat_file = file_path + '{}/{}'.format('high/',
                                                    high_files[index])
             if '.wav' not in beat_file:
                 continue
             sr = librosa.get_samplerate(beat_file)
             sound, sr = librosa.load(beat_file, sr=sr)
             duration = librosa.get_duration(sound, sr)
             # print(beat_file, sr, duration, len(sound))
             #
             if sr != 48000:
                 # print('resampling:', beat_file, sr)
                 sound = signal.resample(sound,
                                         int(len(sound) * 48000 / sr))
             #
             # FFT
             freq, fft_abs, fft_beat = utils.fft(sound, len(sound),
                                                 len(sound))
             fft_padding = np.zeros(FFT_SIZE)
             fft_padding[:len(fft_beat)] = fft_beat[:np.min(
                 [FFT_SIZE, len(fft_beat)])]
             #
             self.ffts.append(fft_padding.reshape(FFT_SIZE, 1))
             self.labels.append([0, 1])
     #
     # No-balance: 최종 Validation 또는 Test용. Dataset을 있는 그대로 적용
     else:
         # Heavy
         for index in range(0, len(heavy_files)):
             beat_file = file_path + '{}/{}'.format('bass/',
                                                    heavy_files[index])
             if '.wav' not in beat_file:
                 continue
             sr = librosa.get_samplerate(beat_file)
             sound, sr = librosa.load(beat_file, sr=sr)
             duration = librosa.get_duration(sound, sr)
             # print(beat_file, sr, duration, len(sound))
             #
             if sr != 48000:
                 # print('resampling:', beat_file, sr)
                 sound = signal.resample(sound,
                                         int(len(sound) * 48000 / sr))
             #
             # FFT
             freq, fft_abs, fft_beat = utils.fft(sound, len(sound),
                                                 len(sound))
             fft_padding = np.zeros(FFT_SIZE)
             fft_padding[:len(fft_beat)] = fft_beat[:np.min(
                 [FFT_SIZE, len(fft_beat)])]
             #
             self.ffts.append(fft_padding.reshape(FFT_SIZE, 1))
             self.labels.append([1, 0])
         #
         # High
         for index in range(0, len(high_files)):
             beat_file = file_path + '{}/{}'.format('high/',
                                                    high_files[index])
             if '.wav' not in beat_file:
                 continue
             sr = librosa.get_samplerate(beat_file)
             sound, sr = librosa.load(beat_file, sr=sr)
             duration = librosa.get_duration(sound, sr)
             # print(beat_file, sr, duration, len(sound))
             #
             if sr != 48000:
                 # print('resampling:', beat_file, sr)
                 sound = signal.resample(sound,
                                         int(len(sound) * 48000 / sr))
             #
             # FFT
             freq, fft_abs, fft_beat = utils.fft(sound, len(sound),
                                                 len(sound))
             fft_padding = np.zeros(FFT_SIZE)
             fft_padding[:len(fft_beat)] = fft_beat[:np.min(
                 [FFT_SIZE, len(fft_beat)])]
             #
             self.ffts.append(fft_padding.reshape(FFT_SIZE, 1))
             self.labels.append([0, 1])
     #
     print('data len:', np.sum(self.labels, axis=0))
     # -------------------------------------------------------------------------------------
     self.ffts = np.array(self.ffts)
     self.labels = np.array(self.labels)
예제 #11
0
 def padded_fft(self, input_field):
     input_padded = self.pad_smaller_dims(input_field, self.conv_resolution)
     return utils.fft(input_padded)
예제 #12
0
        #
        elif val == 0 and BEAT_START > 0:
            BEAT_END = UNIT_START_TIME + unit_time
            beat_type = 0
            # -------------------------------------------------------------------------------
            # FFT Analysis : too much time consumed!!!
            unit_beat_start = int(
                np.max([(BEAT_START - UNIT_START_TIME) - 0, 0]) * sr)
            unit_beat_end = int((BEAT_END - UNIT_START_TIME + 0) * sr)
            print('unit_beat:', np.round(BEAT_START, 3), '~',
                  np.round(BEAT_END, 3))
            beat_sound = unit_beats[unit_beat_start:unit_beat_end]
            #
            # -------------------------------------------------------------------------------
            # Model 적용
            freq, fft_abs, fft_beat = utils.fft(beat_sound, len(beat_sound),
                                                len(beat_sound))
            fft_padding = np.zeros(FFT_SIZE)
            fft_padding[:len(fft_beat)] = fft_beat[:np.min(
                [FFT_SIZE, len(fft_beat)])]
            # -------------------------------------------------------------------------------
            logit, pred = model.test(fft_padding.reshape(-1, FFT_SIZE, 1))
            print(logit, pred)
            if pred[0] == 0:
                beats_low_total += list(unit_sound)
            else:
                beats_high_total += list(unit_sound)
            # =============================================================================================
            BEAT_START = 0
            BEAT_MAX = 0
            BEAT_MAX_VAL = 0
예제 #13
0
def HybridInputOutput(target, source, phase, n_max=200, animation=True):
    '''

     [1] E. Osherovich, Numerical methods for phase retrieval, 2012,
        https://arxiv.org/abs/1203.4756
    [2] J. R. Fienup, Phase retrieval algorithms: a comparison, 1982,
        https://www.osapublishing.org/ao/abstract.cfm?uri=ao-21-15-2758

    :param target:
    :param source:
    :param phase: Algorithm goal, provided for visualization and metrics
    :param n_max: Maximum number of iteration
    :param animation:
    :return:
    '''

    # Add padding
    target = utils.addPadding(np.sqrt(target))
    source = utils.addPadding(source)

    # Metrics: tuple -> (time, rmse)
    metrics = []

    # Initialize animation
    if animation:
        f, axarr = initAnimation()

    # Timer
    timer = 0.0

    # Random initializer
    g_k_prime = np.exp(1j * 0.0 * np.pi * (np.random.rand(source.shape[0], source.shape[1])*2-1))


    # Previous iteration
    g_k_previous = None

    for n in range(n_max):
        t0 = time()

        g_k = source * np.exp(1j * np.angle(g_k_prime))
        G_k= utils.fft(g_k)
        G_k_prime = np.absolute(target) * np.exp(1j * np.angle(G_k))
        g_k_prime = utils.ifft(G_k_prime)


        if g_k_previous is None:
            g_k_previous = g_k_prime
        else:
            g_k_previous = g_k

        indices = np.logical_or(np.logical_and(g_k < 0, source),  np.logical_not(source))

        g_k[indices] = g_k_previous[indices] - 0.9 * np.real(g_k_prime[indices])

        t1 = time()
        timer += t1-t0

        phaseEst = source * np.angle(g_k)
        #phaseEst = np.rot90(np.rot90(-phaseEst))
        error = utils.rootMeanSquaredError(phase, utils.removePadding(phaseEst), mask=True)
        #error = utils.rootMeanSquaredError(G_k, G_k_prime, mask=True)

        metrics.append((timer, error))

        if animation:
            H = utils.addPadding(mask) * np.exp(1j * (phaseEst-utils.addPadding(phase)))
            h = utils.fft(H)
            psf = utils.removePadding(np.abs(h) ** 2)
            updateAnimation(f, axarr, metrics, phase, utils.removePadding(phaseEst), psf, timer)

    return metrics
예제 #14
0
            h = utils.fft(H)
            psf = utils.removePadding(np.abs(h) ** 2)
            updateAnimation(f, axarr, metrics, phase, utils.removePadding(phaseEst), psf, timer)

    return metrics

if __name__ == '__main__':

    # Files
    reference_file = 'references.fits'
    psf_file = 'psf_1.fits'

    # Data
    wavelength = 2200 * (10**(-9))  #[m]
    n=20
    z_basis = aotools.zernikeArray(n+1, 128, norm='rms') #[rad]

    rv_HDU = fits.open(reference_file)
    mask = rv_HDU[0].data # [0-1] function defining entrance pupil
    psf_reference = rv_HDU[1].data # diffraction limited point spread function

    HDU = fits.open(psf_file)
    phase = utils.meterToRadian(HDU[1].data, wavelength* (10**(9)))

    H = utils.addPadding(mask) * np.exp(1j * utils.addPadding(phase))
    h = utils.fft(H)
    psf_test = utils.removePadding(np.abs(h)**2)

    metrics = HybridInputOutput(psf_test, mask, phase, n_max=300, animation=True)
    metrics = np.array(metrics)
예제 #15
0
    def on_action_generate_triggered(self):

        from utils import WaveFile, fft, find_local_maxima

        from math import sqrt

        from matplotlib import animation

        if self.wave_file is None:
            return

        # sample_window_size = self.settings.spin_resolution.value() * 2
        sample_window_size = 2**14
        bin_width = self.wave_file.sample_rate / sample_window_size
        # desired_freq = 440
        # xlim_pad = 60
        # xlim = ((desired_freq / bin_width) - xlim_pad, (desired_freq / bin_width) + xlim_pad)
        # print(f"Bin width: {bin_width}hz")
        # print(f"Bin number @ {desired_freq}hz: {desired_freq / bin_width}")

        axis = self.figure.add_subplot(111, frameon=False)
        self.figure.tight_layout(rect=[0, 0.1, 1, 1])
        axis.get_yaxis().set_visible(False)
        axis.clear()
        #
        #         def update(data):
        #             line = axis.get_line()
        #             line.set_ydata(data)
        #             return line
        #
        #         def data_gen():
        #             channel = WaveFile.Channel.Left
        #             for window in self.wave_file.iter_samples(channel=channel, sample_window_size=sample_window_size):
        #                 bins = fft(window)
        #                 # magnitudes_x = [bin_width * _ for _ in range(sample_window_size)]
        #                 magnitudes_y = [sqrt(c.imag ** 2 + c.real ** 2) for c in bins]
        #                 yield magnitudes_y
        #
        #         ani = animation.FuncAnimation(self.figure, update, data_gen, interval=500)
        #         self.canvas.draw()

        for window in self.wave_file.iter_samples(
                channel=WaveFile.Channel.Left,
                sample_window_size=sample_window_size):
            bins = fft(window)
            magnitudes_x = [bin_width * _ for _ in range(sample_window_size)]
            magnitudes_y = [
                sqrt(c.imag * c.imag + c.real * c.real) for c in bins
            ]
            # imags = [c.imag for c in bins]

            # maxima_x = find_local_maxima(magnitudes)
            # maxima_y = [magnitudes[i] for i in maxima_x]
            # print(maxima_y[0:4])

            axis = self.figure.add_subplot(111, frameon=False)
            self.figure.tight_layout(rect=[0, 0.1, 1, 1])
            axis.get_yaxis().set_visible(False)
            axis.clear()
            axis.plot(magnitudes_x, magnitudes_y, "-", linewidth=1)
            # axis.plot(imags, "-", linewidth=1)
            # axis.plot(maxima_x, maxima_y, "go")
            # axis.set_xlim(*xlim)
            axis.set_xlim(0, sample_window_size)
            self.canvas.draw()
            break
예제 #16
0
def GerchbergSaxton(target, source, phase, n_max=200, animation=True):
    '''
        Phase retrieval, Gerchberg-Saxton algorithm.

        [1] R. W. Gerchberg and W. O. Saxton, “A practical algorithm
            for the determination of the phase from image and diffraction
            plane pictures,” Optik 35, 237 (1972)

        [2] J. R. Fienup, "Phase retrieval algorithms: a comparison,"
            Appl. Opt. 21, 2758-2769 (1982)

    :param target:
    :param source:
    :param phase: Algorithm goal, provided for visualization and metrics
    :param n_max: Maximum number of iteration
    :param animation:
    :return:
    '''

    # Add padding
    target = utils.addPadding(np.sqrt(target))
    source = utils.addPadding(source)

    # Metrics: tuple -> (time, error)
    metrics = []

    # Initialize animation
    if animation:
        f, axarr = initAnimation()

    # Timer
    timer = 0.0

    # Random initializer
    A = source * np.exp(
        1j * 0.0 * np.pi *
        (np.random.rand(source.shape[0], source.shape[1]) * 2 - 1))

    for n in range(n_max):
        t0 = time()
        B = np.absolute(source) * np.exp(1j * np.angle(A))
        C = utils.fft(B)
        D = np.absolute(target) * np.exp(1j * np.angle(C))
        A = utils.ifft(D)

        t1 = time()
        timer += t1 - t0

        phaseEst = source * np.angle(A)
        #phaseEst = np.rot90(np.rot90(-phaseEst))
        error = utils.rootMeanSquaredError(phase,
                                           utils.removePadding(phaseEst),
                                           mask=True)
        #error = utils.rootMeanSquaredError(C, D, mask=True)

        metrics.append((timer, error))

        if animation:
            H = utils.addPadding(mask) * np.exp(
                1j * (phaseEst - utils.addPadding(phase)))
            h = utils.fft(H)
            psf = utils.removePadding(np.abs(h)**2)
            updateAnimation(f, axarr, metrics, phase,
                            utils.removePadding(phaseEst), psf, timer)

    return metrics
예제 #17
0
def test_fft():
    x = [1, 2, 3, 4]
    assert np.allclose(fft(x), np.fft.fft(x))
예제 #18
0
파일: hypopt.py 프로젝트: PCJohn/dip-mem
            res['pred_best_err'] = float(best_err_pred)
            res['pred_best_psnr'] = float(best_psnr_pred)
            res['pred_best_hyp'] = hyp_str
            res['pred_best_iter'] = int((best_iter_pred + 1) * traj_iter)
            final_best_pred = best_rec_pred.copy()
            final_err_true_pred = err_true.copy()
            final_err_traj_pred = err_traj.copy()
            final_err_true_added = err_true_added.copy()

        # Save in separate folder for each hyp setting
        hyp_dir = os.path.join(output_dir, hyp_str)
        if not os.path.exists(hyp_dir):
            os.system('mkdir ' + hyp_dir)
        # save variation of |FFT|
        x = [(i + 1) * traj_iter for i in range(len(final_err_traj_pred))]
        fft_traj = [np.log(utils.fft(t)) for t in noisy_T]
        #fft_clean = utils.fft(im)
        #fft_err = [(ft-fft_clean)**2 for ft in fft_traj]  # squared error in fft components across channels
        fft_noisy = np.log(utils.fft(noisy_im))
        fft_err = [(ft - fft_noisy)**2 for ft in fft_traj
                   ]  # squared error in fft components across channels
        fft_iters = np.hstack([
            utils.power_variation(ft, bandpass_filt_set)[::2, np.newaxis]
            for ft in fft_err[:50]
        ])
        plt.imshow(fft_iters, cmap='hot')
        #plt.locator_params(axis='y', nbins=3)
        #plt.locator_params(axis='x', nbins=3)
        #plt.imshow(fft_iters,cmap='hot',extent=[x[0],x[50],0,50])
        plt.gca().set_yticklabels(['', 0] + ['' for _ in range(6)] + [1])
        plt.gca().set_xticklabels(['', 0] + ['' for _ in range(3)] + [500])