@@ -37,13 +37,10 @@ def test_deterministic_tone_generation(self):
3737 .generate ()
3838 )
3939
40- # verify object type
41- self .assertIsInstance (signal , SigMFFile )
42-
4340 # verify metadata
4441 self .assertEqual (signal .sample_rate , self .test_sample_rate )
45- self .assertEqual (signal .get_global_info ()[ SigMFFile . DATATYPE_KEY ] , "cf32_le" )
46- self .assertIn ("-1000.0 hz tone" , signal .get_global_info ()[ SigMFFile . DESCRIPTION_KEY ] )
42+ self .assertEqual (signal .datatype , "cf32_le" )
43+ self .assertIn ("-1000.0 hz tone" , signal .description )
4744
4845 # verify signal characteristics
4946 samples = signal .read_samples ()
@@ -60,20 +57,10 @@ def test_deterministic_tone_generation(self):
6057 dominant_freq = fft_freqs [dominant_freq_idx ]
6158 self .assertAlmostEqual (dominant_freq , self .test_freq , delta = 10 ) # within 10 hz, signed
6259
63- def test_random_tone_generation (self ):
64- """test random tone generation"""
65- signal = SigMFGenerator (self .seed ).tone ().generate ()
66-
67- # should have reasonable defaults
68- samples = signal .read_samples ()
69- self .assertGreater (len (samples ), 1000 ) # at least 0.1s at min sample rate
70- self .assertIsInstance (signal , SigMFFile )
71- self .assertIn ("hz tone" , signal .get_global_info ()[SigMFFile .DESCRIPTION_KEY ])
72-
7360 def test_reproducible_generation (self ):
7461 """test that same seed produces identical results"""
7562 # generate signal 3 times with same seed
76- # only difference will be catpure datetime
63+ # only difference will be datetime when capure is created
7764 signal0 = SigMFGenerator (self .seed ).generate ()
7865 signal1 = SigMFGenerator (self .seed ).generate ()
7966 signal2 = SigMFGenerator (self .seed ).generate ()
@@ -88,25 +75,17 @@ def test_reproducible_generation(self):
8875
8976 def test_sweep_generation (self ):
9077 """test linear frequency sweep generation"""
91- start_freq = - 500.0
92- end_freq = 2000.0
93-
9478 signal = (
9579 SigMFGenerator ()
96- .sweep (start_freq , end_freq )
80+ .sweep (- 500.0 , 2000.0 )
9781 .sample_rate (self .test_sample_rate )
9882 .duration (self .test_duration )
9983 .generate ()
10084 )
85+ self .assertIn ("-500.0-2000.0 hz sweep" , signal .description )
10186
102- # verify metadata
103- self .assertIn ("-500.0-2000.0 hz sweep" , signal .get_global_info ()[SigMFFile .DESCRIPTION_KEY ])
104-
105- # verify signal properties
106- samples = signal .read_samples ()
107- expected_samples = int (self .test_sample_rate * self .test_duration )
108- self .assertEqual (len (samples ), expected_samples )
109- self .assertTrue (np .iscomplexobj (samples ))
87+ # random sweep (no args) also works
88+ self .assertIn ("sweep" , SigMFGenerator ().sweep ().generate ().description )
11089
11190 def test_nominal_chaining (self ):
11291 """test builder pattern method chaining"""
@@ -127,7 +106,7 @@ def test_nominal_chaining(self):
127106
128107 # verify chaining worked
129108 self .assertEqual (signal .get_global_info ()[SigMFFile .AUTHOR_KEY ], "test@example.com" )
130- self .assertEqual (signal .get_global_info ()[ SigMFFile . DESCRIPTION_KEY ] , "test signal" )
109+ self .assertEqual (signal .description , "test signal" )
131110
132111 # should have multiple annotations: main signal + noise + freq offset + phase offset
133112 annotations = signal .get_annotations ()
@@ -165,8 +144,8 @@ def test_snr_noise_addition(self):
165144 )
166145
167146 # noisy signal should have higher variance due to added noise
168- clean_power = np .mean (np .abs (clean_signal . read_samples () ) ** 2 )
169- noisy_power = np .mean (np .abs (noisy_signal . read_samples () ) ** 2 )
147+ clean_power = np .mean (np .abs (clean_signal [:] ) ** 2 )
148+ noisy_power = np .mean (np .abs (noisy_signal [:] ) ** 2 )
170149
171150 # noisy signal should have more power due to added noise
172151 self .assertGreater (noisy_power , clean_power )
@@ -189,52 +168,6 @@ def test_frequency_offset(self):
189168 captures = signal .get_captures ()
190169 self .assertEqual (captures [0 ][SigMFFile .FREQUENCY_KEY ], base_freq + offset_freq )
191170
192- def test_parameter_validation (self ):
193- """test parameter validation and error handling"""
194- # bare generate() should now work (auto-generates components)
195- signal = SigMFGenerator ().generate ()
196- self .assertIsInstance (signal , SigMFFile )
197-
198- # should raise error for tone frequency exceeding nyquist (positive and negative)
199- with self .assertRaises (SigMFGeneratorError ):
200- SigMFGenerator ().tone (30000 ).sample_rate (48000 ).duration (1.0 ).generate ()
201- with self .assertRaises (SigMFGeneratorError ):
202- SigMFGenerator ().tone (- 30000 ).sample_rate (48000 ).duration (1.0 ).generate ()
203-
204- # should raise error for negative duration
205- with self .assertRaises (SigMFGeneratorError ):
206- SigMFGenerator ().tone (1000 ).sample_rate (48000 ).duration (- 1.0 ).generate ()
207-
208- # should raise error for negative sample rate
209- with self .assertRaises (SigMFGeneratorError ):
210- SigMFGenerator ().tone (1000 ).sample_rate (- 48000 ).duration (1.0 ).generate ()
211-
212- def test_sweep_parameter_validation (self ):
213- """test sweep-specific parameter validation"""
214- # sweep frequencies exceeding nyquist should raise error (positive and negative)
215- with self .assertRaises (SigMFGeneratorError ):
216- SigMFGenerator ().sweep (1000 , 30000 ).sample_rate (48000 ).generate ()
217- with self .assertRaises (SigMFGeneratorError ):
218- SigMFGenerator ().sweep (30000 , 1000 ).sample_rate (48000 ).generate ()
219- with self .assertRaises (SigMFGeneratorError ):
220- SigMFGenerator ().sweep (1000 , - 30000 ).sample_rate (48000 ).generate ()
221- with self .assertRaises (SigMFGeneratorError ):
222- SigMFGenerator ().sweep (- 30000 , 1000 ).sample_rate (48000 ).generate ()
223-
224- def test_random_sweep_parameters (self ):
225- """test random sweep parameter generation"""
226- signal = SigMFGenerator ().sweep ().generate ()
227-
228- # should successfully generate
229- self .assertIsInstance (signal , SigMFFile )
230-
231- # description should indicate it's a sweep
232- desc = signal .get_global_info ()[SigMFFile .DESCRIPTION_KEY ]
233- self .assertIn ("sweep" , desc )
234-
235- # should have start and end frequencies in description
236- self .assertIn ("-" , desc ) # should have start-end format
237-
238171 def test_metadata_completeness (self ):
239172 """test that generated metadata is complete and valid"""
240173 signal = SigMFGenerator ().tone (1000 ).generate ()
@@ -422,9 +355,6 @@ def test_phase_offset(self):
422355 .generate ()
423356 )
424357
425- samples_0 = signal_0 .read_samples ()
426- samples_1 = signal_1 .read_samples ()
427-
428358 # find where the actual signal starts by looking at annotations
429359 start_idx_0 = signal_0 .get_annotations ()[0 ][SigMFFile .START_INDEX_KEY ]
430360 start_idx_1 = signal_1 .get_annotations ()[0 ][SigMFFile .START_INDEX_KEY ]
@@ -434,62 +364,56 @@ def test_phase_offset(self):
434364
435365 # compare samples from the actual signal start + some offset to avoid edge effects
436366 sample_offset = 100
437- if start_idx_0 + sample_offset < len (samples_0 ) and start_idx_1 + sample_offset < len (samples_1 ):
438- phase_diff = np .angle (samples_1 [start_idx_0 + sample_offset ]) - np .angle (samples_0 [start_idx_0 + sample_offset ])
367+ if start_idx_0 + sample_offset < len (signal_0 ) and start_idx_1 + sample_offset < len (signal_1 ):
368+ phase_diff = np .angle (signal_1 [start_idx_0 + sample_offset ]) - np .angle (signal_0 [start_idx_0 + sample_offset ])
439369
440- # handle phase wrapping - normalize to [-pi, pi]
441- while phase_diff > np .pi :
442- phase_diff -= 2 * np .pi
443- while phase_diff < - np .pi :
444- phase_diff += 2 * np .pi
370+ # normalize to [-pi, pi]
371+ phase_diff = (phase_diff + np .pi ) % (2 * np .pi ) - np .pi
445372
446373 self .assertAlmostEqual (phase_diff , phase_offset , places = 1 )
447374
448375
449- class TestSigGenEdgeCases (unittest .TestCase ):
376+ class TestEdgeCases (unittest .TestCase ):
450377 """Test edge cases and error conditions."""
451378
452379 def test_zero_duration (self ):
453380 """test zero duration raises error"""
454381 with self .assertRaises (SigMFGeneratorError ):
455- SigMFGenerator ().tone ( 1000 ). sample_rate ( 48000 ). duration (0 ).generate ()
382+ SigMFGenerator ().duration (0 ).generate ()
456383
457- def test_very_short_duration (self ):
458- """test very short durations work"""
459- signal = SigMFGenerator ().tone (1000 ).sample_rate (48000 ).duration (0.001 ).generate () # 1ms
384+ def test_negative_duration (self ):
385+ """test negative duration raises error"""
386+ with self .assertRaises (SigMFGeneratorError ):
387+ SigMFGenerator ().duration (- 1.0 ).generate ()
460388
461- samples = signal .read_samples ()
462- expected_samples = int (48000 * 0.001 )
463- self .assertEqual (len (samples ), expected_samples )
389+ def test_negative_sample_rate (self ):
390+ """test negative sample rate raises error"""
391+ with self .assertRaises (SigMFGeneratorError ):
392+ SigMFGenerator ().sample_rate (- 8000 ).generate ()
464393
465- def test_large_frequency_offset (self ):
466- """test large frequency offsets"""
467- # large offset that doesn't violate nyquist when combined with base freq
468- signal = (
469- SigMFGenerator ()
470- .tone (1000 )
471- .frequency_offset (10000 )
472- .sample_rate (48000 )
473- .duration (0.1 )
474- .generate ()
475- )
394+ def test_tone_nyquist_validation (self ):
395+ """test tone frequency exceeding nyquist raises error"""
396+ with self .assertRaises (SigMFGeneratorError ):
397+ SigMFGenerator ().tone (5000 ).sample_rate (8000 ).generate ()
398+ with self .assertRaises (SigMFGeneratorError ):
399+ SigMFGenerator ().tone (- 5000 ).sample_rate (8000 ).generate ()
476400
477- captures = signal .get_captures ()
478- self .assertEqual (captures [0 ][SigMFFile .FREQUENCY_KEY ], 11000.0 )
401+ def test_sweep_nyquist_validation (self ):
402+ """test sweep frequencies exceeding nyquist raise error"""
403+ with self .assertRaises (SigMFGeneratorError ):
404+ SigMFGenerator ().sweep (1000 , 5000 ).sample_rate (8000 ).generate ()
405+ with self .assertRaises (SigMFGeneratorError ):
406+ SigMFGenerator ().sweep (5000 , 1000 ).sample_rate (8000 ).generate ()
407+ with self .assertRaises (SigMFGeneratorError ):
408+ SigMFGenerator ().sweep (1000 , - 5000 ).sample_rate (8000 ).generate ()
409+ with self .assertRaises (SigMFGeneratorError ):
410+ SigMFGenerator ().sweep (- 5000 , 1000 ).sample_rate (8000 ).generate ()
479411
480412 def test_sweep_same_start_end_frequency (self ):
481413 """test sweep with same start and end frequency"""
482- signal = SigMFGenerator ().sweep (1000 , 1000 ).sample_rate (48000 ).duration (0.1 ).generate ()
483-
484414 # should generate successfully (effectively a tone)
485- self .assertIsInstance (signal , SigMFFile )
486-
487- def test_sweep_reverse_frequency (self ):
488- """test sweep with higher start than end frequency"""
489- signal = SigMFGenerator ().sweep (2000 , 500 ).sample_rate (48000 ).duration (0.5 ).generate ()
415+ SigMFGenerator ().sweep (333 , 333 ).sample_rate (8000 ).duration (0.1 ).generate ()
490416
491- # should work - frequency decreasing sweep
492- self .assertIn ("2000.0-500.0 hz sweep" , signal .get_global_info ()[SigMFFile .DESCRIPTION_KEY ])
493417
494418
495419if __name__ == "__main__" :
0 commit comments