Showing the changes to python (10 of 28 files). Show all
Unified · Split
| @@ -22,7 +22,7 @@ def get_file_bpm(path, params=None): · 21 unmodified lines | ||
| 22 | 22 | elif params.mode in ['default']: |
| 23 | 23 | pass |
| 24 | 24 | else: |
| 25 | − print("unknown mode {:s}".format(params.mode)) | |
| 25 | + raise ValueError("unknown mode {:s}".format(params.mode)) | |
| 26 | 26 | # manual settings |
| 27 | 27 | if 'samplerate' in params: |
| 28 | 28 | samplerate = params.samplerate |
| @@ -69,9 +69,9 @@ if __name__ == '__main__': · 40 unmodified lines | ||
| 69 | 69 | parser = argparse.ArgumentParser() |
| 70 | 70 | parser.add_argument('-m', '--mode', |
| 71 | 71 | help="mode [default|fast|super-fast]", |
| 72 | − dest="mode") | |
| 72 | + dest="mode", default='default') | |
| 73 | 73 | parser.add_argument('sources', |
| 74 | − nargs='*', | |
| 74 | + nargs='+', | |
| 75 | 75 | help="input_files") |
| 76 | 76 | args = parser.parse_args() |
| 77 | 77 | for f in args.sources: |
| @@ -117,7 +117,9 @@ Py_bintomidi (PyObject * self, PyObject * args) · 116 unmodified lines | ||
| 117 | 117 | smpl_t input, samplerate, fftsize; |
| 118 | 118 | smpl_t output; |
| 119 | 119 | |
| 120 | − if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR , &input, &samplerate, &fftsize)) { | |
| 120 | + if (!PyArg_ParseTuple (args, | |
| 121 | + "" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR, | |
| 122 | + &input, &samplerate, &fftsize)) { | |
| 121 | 123 | return NULL; |
| 122 | 124 | } |
| 123 | 125 | |
| @@ -132,7 +134,9 @@ Py_miditobin (PyObject * self, PyObject * args) · 8 unmodified lines | ||
| 132 | 134 | smpl_t input, samplerate, fftsize; |
| 133 | 135 | smpl_t output; |
| 134 | 136 | |
| 135 | − if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR , &input, &samplerate, &fftsize)) { | |
| 137 | + if (!PyArg_ParseTuple (args, | |
| 138 | + "" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR, | |
| 139 | + &input, &samplerate, &fftsize)) { | |
| 136 | 140 | return NULL; |
| 137 | 141 | } |
| 138 | 142 | |
| @@ -147,7 +151,9 @@ Py_bintofreq (PyObject * self, PyObject * args) · 8 unmodified lines | ||
| 147 | 151 | smpl_t input, samplerate, fftsize; |
| 148 | 152 | smpl_t output; |
| 149 | 153 | |
| 150 | − if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR, &input, &samplerate, &fftsize)) { | |
| 154 | + if (!PyArg_ParseTuple (args, | |
| 155 | + "" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR, | |
| 156 | + &input, &samplerate, &fftsize)) { | |
| 151 | 157 | return NULL; |
| 152 | 158 | } |
| 153 | 159 | |
| @@ -162,7 +168,9 @@ Py_freqtobin (PyObject * self, PyObject * args) · 8 unmodified lines | ||
| 162 | 168 | smpl_t input, samplerate, fftsize; |
| 163 | 169 | smpl_t output; |
| 164 | 170 | |
| 165 | − if (!PyArg_ParseTuple (args, "|" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR, &input, &samplerate, &fftsize)) { | |
| 171 | + if (!PyArg_ParseTuple (args, | |
| 172 | + "" AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR AUBIO_NPY_SMPL_CHR, | |
| 173 | + &input, &samplerate, &fftsize)) { | |
| 166 | 174 | return NULL; |
| 167 | 175 | } |
| 168 | 176 | |
| @@ -94,7 +94,7 @@ Py_filterbank_do(Py_filterbank * self, PyObject * args) · 93 unmodified lines | ||
| 94 | 94 | |
| 95 | 95 | if (self->vec.length != self->win_s / 2 + 1) { |
| 96 | 96 | PyErr_Format(PyExc_ValueError, |
| 97 | − "input cvec has length %d, but fft expects length %d", | |
| 97 | + "input cvec has length %d, but filterbank expects length %d", | |
| 98 | 98 | self->vec.length, self->win_s / 2 + 1); |
| 99 | 99 | return NULL; |
| 100 | 100 | } |
| @@ -139,7 +139,7 @@ Py_filterbank_set_triangle_bands (Py_filterbank * self, PyObject *args) · 38 unmodified lines | ||
| 139 | 139 | &(self->freqs), samplerate); |
| 140 | 140 | if (err > 0) { |
| 141 | 141 | PyErr_SetString (PyExc_ValueError, |
| 142 | − "error when setting filter to A-weighting"); | |
| 142 | + "error when running set_triangle_bands"); | |
| 143 | 143 | return NULL; |
| 144 | 144 | } |
| 145 | 145 | Py_RETURN_NONE; |
| @@ -158,7 +158,7 @@ Py_filterbank_set_mel_coeffs_slaney (Py_filterbank * self, PyObject *args) · 12 unmodified lines | ||
| 158 | 158 | err = aubio_filterbank_set_mel_coeffs_slaney (self->o, samplerate); |
| 159 | 159 | if (err > 0) { |
| 160 | 160 | PyErr_SetString (PyExc_ValueError, |
| 161 | − "error when setting filter to A-weighting"); | |
| 161 | + "error when running set_mel_coeffs_slaney"); | |
| 162 | 162 | return NULL; |
| 163 | 163 | } |
| 164 | 164 | Py_RETURN_NONE; |
| @@ -255,6 +255,9 @@ class AubioArgumentParser(argparse.ArgumentParser): · 254 unmodified lines | ||
| 255 | 255 | metavar = "<slices>", |
| 256 | 256 | action = "store", dest = "cut_until_nslices", default = None, |
| 257 | 257 | help="how many extra slices should be added at the end of each slice") |
| 258 | + self.add_argument("--create-first", | |
| 259 | + action = "store_true", dest = "create_first", default = False, | |
| 260 | + help="always include first slice") | |
| 258 | 261 | |
| 259 | 262 | # some utilities |
| 260 | 263 | |
| @@ -511,7 +514,24 @@ class process_cut(process_onset): · 250 unmodified lines | ||
| 511 | 514 | |
| 512 | 515 | def main(): |
| 513 | 516 | parser = aubio_parser() |
| 514 | − args = parser.parse_args() | |
| 517 | + if sys.version_info[0] != 3: | |
| 518 | + # on py2, create a dummy ArgumentParser to workaround the | |
| 519 | + # optional subcommand issue. See https://bugs.python.org/issue9253 | |
| 520 | + # This ensures that: | |
| 521 | + # - version string is shown when only '-V' is passed | |
| 522 | + # - help is printed if '-V' is passed with any other argument | |
| 523 | + # - any other argument get forwarded to the real parser | |
| 524 | + parser_root = argparse.ArgumentParser(add_help=False) | |
| 525 | + parser_root.add_argument('-V', '--version', help="show version", | |
| 526 | + action="store_true", dest="show_version") | |
| 527 | + args, extras = parser_root.parse_known_args() | |
| 528 | + if args.show_version == False: # no -V, forward to parser | |
| 529 | + args = parser.parse_args(extras, namespace=args) | |
| 530 | + elif len(extras) != 0: # -V with other arguments, print help | |
| 531 | + parser.print_help() | |
| 532 | + sys.exit(1) | |
| 533 | + else: # in py3, we can simply use parser directly | |
| 534 | + args = parser.parse_args() | |
| 515 | 535 | if 'show_version' in args and args.show_version: |
| 516 | 536 | sys.stdout.write('aubio version ' + aubio.version + '\n') |
| 517 | 537 | sys.exit(0) |
| @@ -101,7 +101,7 @@ def _cut_analyze(options): · 100 unmodified lines | ||
| 101 | 101 | |
| 102 | 102 | s = source(source_uri, samplerate, hopsize) |
| 103 | 103 | if samplerate == 0: |
| 104 | − samplerate = s.get_samplerate() | |
| 104 | + samplerate = s.samplerate | |
| 105 | 105 | options.samplerate = samplerate |
| 106 | 106 | |
| 107 | 107 | if options.beat: |
| @@ -150,7 +150,8 @@ def _cut_slice(options, timestamps): · 42 unmodified lines | ||
| 150 | 150 | slice_source_at_stamps(options.source_uri, |
| 151 | 151 | timestamps, timestamps_end = timestamps_end, |
| 152 | 152 | output_dir = options.output_directory, |
| 153 | − samplerate = options.samplerate) | |
| 153 | + samplerate = options.samplerate, | |
| 154 | + create_first = options.create_first) | |
| 154 | 155 | |
| 155 | 156 | def main(): |
| 156 | 157 | parser = aubio_cut_parser() |
| @@ -1,9 +1,11 @@ | ||
| 1 | 1 | # -*- coding: utf-8 -*- |
| 2 | 2 | """ utilities to convert midi note number to and from note names """ |
| 3 | 3 | |
| 4 | −__all__ = ['note2midi', 'midi2note', 'freq2note'] | |
| 4 | +__all__ = ['note2midi', 'midi2note', 'freq2note', 'note2freq'] | |
| 5 | 5 | |
| 6 | 6 | import sys |
| 7 | +from ._aubio import freqtomidi, miditofreq | |
| 8 | + | |
| 7 | 9 | py3 = sys.version_info[0] == 3 |
| 8 | 10 | if py3: |
| 9 | 11 | str_instances = str |
| @@ -24,10 +26,11 @@ def note2midi(note): · 14 unmodified lines | ||
| 24 | 26 | } |
| 25 | 27 | _valid_octaves = range(-1, 10) |
| 26 | 28 | if not isinstance(note, str_instances): |
| 27 | − raise TypeError("a string is required, got %s (%s)" % (note, str(type(note)))) | |
| 29 | + msg = "a string is required, got {:s} ({:s})" | |
| 30 | + raise TypeError(msg.format(str(type(note)), repr(note))) | |
| 28 | 31 | if len(note) not in range(2, 5): |
| 29 | − raise ValueError("string of 2 to 4 characters expected, got %d (%s)" \ | |
| 30 | − % (len(note), note)) | |
| 32 | + msg = "string of 2 to 4 characters expected, got {:d} ({:s})" | |
| 33 | + raise ValueError(msg.format(len(note), note)) | |
| 31 | 34 | notename, modifier, octave = [None]*3 |
| 32 | 35 | |
| 33 | 36 | if len(note) == 4: |
| @@ -51,7 +54,8 @@ def note2midi(note): · 17 unmodified lines | ||
| 51 | 54 | if octave not in _valid_octaves: |
| 52 | 55 | raise ValueError("%s is not a valid octave" % octave) |
| 53 | 56 | |
| 54 | − midi = 12 + octave * 12 + _valid_notenames[notename] + _valid_modifiers[modifier] | |
| 57 | + midi = 12 + octave * 12 + _valid_notenames[notename] \ | |
| 58 | + + _valid_modifiers[modifier] | |
| 55 | 59 | if midi > 127: |
| 56 | 60 | raise ValueError("%s is outside of the range C-2 to G8" % note) |
| 57 | 61 | return midi |
| @@ -61,11 +65,36 @@ def midi2note(midi): · 3 unmodified lines | ||
| 61 | 65 | if not isinstance(midi, int_instances): |
| 62 | 66 | raise TypeError("an integer is required, got %s" % midi) |
| 63 | 67 | if midi not in range(0, 128): |
| 64 | − raise ValueError("an integer between 0 and 127 is excepted, got %d" % midi) | |
| 65 | − _valid_notenames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'] | |
| 68 | + msg = "an integer between 0 and 127 is excepted, got {:d}" | |
| 69 | + raise ValueError(msg.format(midi)) | |
| 70 | + _valid_notenames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', | |
| 71 | + 'A', 'A#', 'B'] | |
| 66 | 72 | return _valid_notenames[midi % 12] + str(int(midi / 12) - 1) |
| 67 | 73 | |
| 68 | 74 | def freq2note(freq): |
| 69 | 75 | " convert frequency in Hz to nearest note name, e.g. [0, 22050.] -> [C-1, G9] " |
| 70 | − from aubio import freqtomidi | |
| 71 | − return midi2note(int(freqtomidi(freq))) | |
| 76 | + nearest_note = int(freqtomidi(freq) + .5) | |
| 77 | + return midi2note(nearest_note) | |
| 78 | + | |
| 79 | +def note2freq(note): | |
| 80 | + """Convert note name to corresponding frequency, in Hz. | |
| 81 | + | |
| 82 | + Parameters | |
| 83 | + ---------- | |
| 84 | + note : str | |
| 85 | + input note name | |
| 86 | + | |
| 87 | + Returns | |
| 88 | + ------- | |
| 89 | + freq : float [0, 23000[ | |
| 90 | + frequency, in Hz | |
| 91 | + | |
| 92 | + Example | |
| 93 | + ------- | |
| 94 | + >>> aubio.note2freq('A4') | |
| 95 | + 440 | |
| 96 | + >>> aubio.note2freq('A3') | |
| 97 | + 220.1 | |
| 98 | + """ | |
| 99 | + midi = note2midi(note) | |
| 100 | + return miditofreq(midi) | |
| @@ -6,19 +6,22 @@ from aubio import source, sink · 5 unmodified lines | ||
| 6 | 6 | _max_timestamp = 1e120 |
| 7 | 7 | |
| 8 | 8 | def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, |
| 9 | − output_dir=None, samplerate=0, hopsize=256): | |
| 9 | + output_dir=None, samplerate=0, hopsize=256, | |
| 10 | + create_first=False): | |
| 10 | 11 | """ slice a sound file at given timestamps """ |
| 11 | 12 | |
| 12 | 13 | if timestamps is None or len(timestamps) == 0: |
| 13 | 14 | raise ValueError("no timestamps given") |
| 14 | 15 | |
| 15 | − if timestamps[0] != 0: | |
| 16 | + if timestamps[0] != 0 and create_first: | |
| 16 | 17 | timestamps = [0] + timestamps |
| 17 | 18 | if timestamps_end is not None: |
| 18 | 19 | timestamps_end = [timestamps[1] - 1] + timestamps_end |
| 19 | 20 | |
| 20 | 21 | if timestamps_end is not None: |
| 21 | − if len(timestamps_end) != len(timestamps): | |
| 22 | + if len(timestamps_end) == len(timestamps) - 1: | |
| 23 | + timestamps_end = timestamps_end + [_max_timestamp] | |
| 24 | + elif len(timestamps_end) != len(timestamps): | |
| 22 | 25 | raise ValueError("len(timestamps_end) != len(timestamps)") |
| 23 | 26 | else: |
| 24 | 27 | timestamps_end = [t - 1 for t in timestamps[1:]] + [_max_timestamp] |
| @@ -48,7 +51,7 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 23 unmodified lines | ||
| 48 | 51 | # get hopsize new samples from source |
| 49 | 52 | vec, read = _source.do_multi() |
| 50 | 53 | # if the total number of frames read will exceed the next region start |
| 51 | − if len(regions) and total_frames + read >= regions[0][0]: | |
| 54 | + while len(regions) and total_frames + read >= regions[0][0]: | |
| 52 | 55 | #print "getting", regions[0], "at", total_frames |
| 53 | 56 | # get next region |
| 54 | 57 | start_stamp, end_stamp = regions.pop(0) |
| @@ -75,12 +78,15 @@ def slice_source_at_stamps(source_file, timestamps, timestamps_end=None, · 20 unmodified lines | ||
| 75 | 78 | if remaining > start: |
| 76 | 79 | # write remaining samples from current region |
| 77 | 80 | _sink.do_multi(vec[:, start:remaining], remaining - start) |
| 78 | − #print "closing region", "remaining", remaining | |
| 81 | + #print("closing region", "remaining", remaining) | |
| 79 | 82 | # close this file |
| 80 | 83 | _sink.close() |
| 81 | 84 | elif read > start: |
| 82 | 85 | # write all the samples |
| 83 | 86 | _sink.do_multi(vec[:, start:read], read - start) |
| 84 | 87 | total_frames += read |
| 88 | + # remove old slices | |
| 89 | + slices = list(filter(lambda s: s['end_stamp'] > total_frames, | |
| 90 | + slices)) | |
| 85 | 91 | if read < hopsize: |
| 86 | 92 | break |
| @@ -19,13 +19,16 @@ class aubio_cmd(TestCase): · 18 unmodified lines | ||
| 19 | 19 | class aubio_cmd_utils(TestCase): |
| 20 | 20 | |
| 21 | 21 | def test_samples2seconds(self): |
| 22 | − self.assertEqual(aubio.cmd.samples2seconds(3200, 32000), "0.100000\t") | |
| 22 | + self.assertEqual(aubio.cmd.samples2seconds(3200, 32000), | |
| 23 | + "0.100000\t") | |
| 23 | 24 | |
| 24 | 25 | def test_samples2milliseconds(self): |
| 25 | − self.assertEqual(aubio.cmd.samples2milliseconds(3200, 32000), "100.000000\t") | |
| 26 | + self.assertEqual(aubio.cmd.samples2milliseconds(3200, 32000), | |
| 27 | + "100.000000\t") | |
| 26 | 28 | |
| 27 | 29 | def test_samples2samples(self): |
| 28 | − self.assertEqual(aubio.cmd.samples2samples(3200, 32000), "3200\t") | |
| 30 | + self.assertEqual(aubio.cmd.samples2samples(3200, 32000), | |
| 31 | + "3200\t") | |
| 29 | 32 | |
| 30 | 33 | if __name__ == '__main__': |
| 31 | 34 | main() |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | |
| 4 | 4 | from __future__ import unicode_literals |
| 5 | 5 | |
| 6 | −from aubio import note2midi, freq2note | |
| 6 | +from aubio import note2midi, freq2note, note2freq, float_type | |
| 7 | 7 | from nose2.tools import params |
| 8 | 8 | import unittest |
| 9 | 9 | |
| @@ -111,10 +111,27 @@ class note2midi_wrong_values(unittest.TestCase): · 101 unmodified lines | ||
| 111 | 111 | |
| 112 | 112 | class freq2note_simple_test(unittest.TestCase): |
| 113 | 113 | |
| 114 | − def test_freq2note(self): | |
| 114 | + def test_freq2note_above(self): | |
| 115 | 115 | " make sure freq2note(441) == A4 " |
| 116 | 116 | self.assertEqual("A4", freq2note(441)) |
| 117 | 117 | |
| 118 | + def test_freq2note_under(self): | |
| 119 | + " make sure freq2note(439) == A4 " | |
| 120 | + self.assertEqual("A4", freq2note(439)) | |
| 121 | + | |
| 122 | +class note2freq_simple_test(unittest.TestCase): | |
| 123 | + | |
| 124 | + def test_note2freq(self): | |
| 125 | + " make sure note2freq('A3') == 220" | |
| 126 | + self.assertEqual(220, note2freq("A3")) | |
| 127 | + | |
| 128 | + def test_note2freq_under(self): | |
| 129 | + " make sure note2freq(A4) == 440" | |
| 130 | + if float_type == 'float32': | |
| 131 | + self.assertEqual(440, note2freq("A4")) | |
| 132 | + else: | |
| 133 | + self.assertLess(abs(note2freq("A4")-440), 1.e-12) | |
| 134 | + | |
| 118 | 135 | if __name__ == '__main__': |
| 119 | 136 | import nose2 |
| 120 | 137 | nose2.main() |
| @@ -23,19 +23,27 @@ class aubio_slicing_test_case(TestCase): · 22 unmodified lines | ||
| 23 | 23 | |
| 24 | 24 | def test_slice_start_only_no_zero(self): |
| 25 | 25 | regions_start = [i*1000 for i in range(1, n_slices)] |
| 26 | − slice_source_at_stamps(self.source_file, regions_start, output_dir = self.output_dir) | |
| 26 | + slice_source_at_stamps(self.source_file, regions_start, | |
| 27 | + output_dir = self.output_dir, create_first=True) | |
| 27 | 28 | |
| 28 | 29 | def test_slice_start_beyond_end(self): |
| 29 | 30 | regions_start = [i*1000 for i in range(1, n_slices)] |
| 30 | 31 | regions_start += [count_samples_in_file(self.source_file) + 1000] |
| 31 | − slice_source_at_stamps(self.source_file, regions_start, output_dir = self.output_dir) | |
| 32 | + slice_source_at_stamps(self.source_file, regions_start, | |
| 33 | + output_dir = self.output_dir, create_first=True) | |
| 32 | 34 | |
| 33 | 35 | def test_slice_start_every_blocksize(self): |
| 34 | 36 | hopsize = 200 |
| 35 | − regions_start = [i*hopsize for i in range(1, n_slices)] | |
| 37 | + regions_start = [i*hopsize for i in range(0, n_slices)] | |
| 36 | 38 | slice_source_at_stamps(self.source_file, regions_start, output_dir = self.output_dir, |
| 37 | 39 | hopsize = 200) |
| 38 | 40 | |
| 41 | + def test_slice_start_every_half_blocksize(self): | |
| 42 | + hopsize = 200 | |
| 43 | + regions_start = [i*hopsize//2 for i in range(0, n_slices)] | |
| 44 | + slice_source_at_stamps(self.source_file, regions_start, | |
| 45 | + output_dir = self.output_dir, hopsize = 200) | |
| 46 | + | |
| 39 | 47 | def tearDown(self): |
| 40 | 48 | original_samples = count_samples_in_file(self.source_file) |
| 41 | 49 | written_samples = count_samples_in_directory(self.output_dir) |
| @@ -91,6 +99,19 @@ class aubio_slicing_with_ends_test_case(TestCase): · 49 unmodified lines | ||
| 91 | 99 | assert_equal(written_samples, expected_samples, |
| 92 | 100 | "number of samples written different from number of original samples") |
| 93 | 101 | |
| 102 | + def test_slice_start_and_ends_with_missing_end(self): | |
| 103 | + regions_start = [i*1000 for i in range(n_slices)] | |
| 104 | + regions_ends = [r-1 for r in regions_start[1:]] | |
| 105 | + slice_source_at_stamps(self.source_file, regions_start, regions_ends, | |
| 106 | + output_dir = self.output_dir) | |
| 107 | + written_samples = count_samples_in_directory(self.output_dir) | |
| 108 | + original_samples = count_samples_in_file(self.source_file) | |
| 109 | + total_files = count_files_in_directory(self.output_dir) | |
| 110 | + assert_equal(n_slices, total_files, | |
| 111 | + "number of slices created different from expected") | |
| 112 | + assert_equal(written_samples, original_samples, | |
| 113 | + "number of samples written different from number of original samples") | |
| 114 | + | |
| 94 | 115 | def tearDown(self): |
| 95 | 116 | shutil.rmtree(self.output_dir) |
| 96 | 117 | |
| @@ -133,7 +154,7 @@ class aubio_slicing_wrong_ends_test_case(TestCase): · 36 unmodified lines | ||
| 133 | 154 | regions_start = [i*1000 for i in range(1, n_slices)] |
| 134 | 155 | regions_end = None |
| 135 | 156 | slice_source_at_stamps (self.source_file, regions_start, regions_end, |
| 136 | − output_dir = self.output_dir) | |
| 157 | + output_dir = self.output_dir, create_first=True) | |
| 137 | 158 | total_files = count_files_in_directory(self.output_dir) |
| 138 | 159 | assert_equal(n_slices, total_files, |
| 139 | 160 | "number of slices created different from expected") |