File: test_networkSet.py

package info (click to toggle)
scikit-rf 1.10.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 82,128 kB
  • sloc: python: 33,328; makefile: 130; sh: 19
file content (459 lines) | stat: -rw-r--r-- 18,613 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
import glob
import os
import sys
import unittest
from pathlib import Path

import numpy as np
import pytest

import skrf as rf


class NetworkSetTestCase(unittest.TestCase):
    """
    NetworkSet class operation test case.
    """

    def setUp(self):
        """
        Initialize tests.
        """
        # Touchstone files

        rng = np.random.default_rng()
        self.test_dir = os.path.dirname(os.path.abspath(__file__))+'/'
        self.ntwk1 = rf.Network(os.path.join(self.test_dir, 'ntwk1.s2p'))
        self.ntwk2 = rf.Network(os.path.join(self.test_dir, 'ntwk2.s2p'))
        self.ntwk3 = rf.Network(os.path.join(self.test_dir, 'ntwk3.s2p'))
        self.ntwk4 = rf.Network(os.path.join(self.test_dir, 'ntwk4.s2p'))

        # dummy networks of various frequency and port shapes
        self.freq1 = rf.Frequency(75, 110, 101, 'ghz')
        self.freq2 = rf.Frequency(75, 110, 201, 'ghz')
        self.ntwk_freq1_1p = rf.Network(frequency=self.freq1)
        self.ntwk_freq1_1p.s = rng.random((len(self.freq1), 1, 1))
        self.ntwk_freq1_2p = rf.Network(frequency=self.freq1)
        self.ntwk_freq1_2p.s = rng.random((len(self.freq1), 2, 2))
        self.ntwk_freq2_1p = rf.Network(frequency=self.freq2)
        self.ntwk_freq2_1p.s = rng.random((len(self.freq2), 1, 1))
        self.ntwk_freq2_2p = rf.Network(frequency=self.freq2)
        self.ntwk_freq2_2p.s = rng.random((len(self.freq2), 2, 2))

        # dummy networks with associated parameters
        # total number of different networks
        self.params = [
                {'a':0, 'X':10, 'c':'A'},
                {'a':1, 'X':10, 'c':'A'},
                {'a':2, 'X':10, 'c':'A'},
                {'a':1, 'X':20, 'c':'A'},
                {'a':0, 'X':20, 'c':'A'},
            ]
        # for write_mdif
        self.params_datatypes = {'a': 'int', 'X': 'double', 'c': 'string'}

        # create M dummy networks
        self.ntwks_params = [rf.Network(frequency=self.freq1,
                                        s=rng.random((len(self.freq1),2,2)),
                                        name=f'ntwk_{m}',
                                        comment=f'ntwk_{m}',
                                        params=params) \
                             for (m, params) in enumerate(self.params) ]

        # Test nominal
        self.ns = rf.NetworkSet([self.ntwk1, self.ntwk2, self.ntwk3])

        # Create NetworkSet from a list of Network containing a .params dict parameters
        self.ns_params = rf.NetworkSet(self.ntwks_params)

    def test_constructor(self):
        """
        Test the `NetworkSet()` constructor.
        """
        # NetworkSet without input parameter is an empty NetworkSet
        self.assertEqual(rf.NetworkSet(), rf.NetworkSet([]))

        # the required parameter must be a list
        self.assertRaises(ValueError, rf.NetworkSet, 0)
        self.assertRaises(ValueError, rf.NetworkSet, 'wrong')
        self.assertRaises(ValueError, rf.NetworkSet, False)

        # all elements should be of Network type
        self.assertRaises(TypeError, rf.NetworkSet, [self.ntwk1, 0])
        self.assertRaises(TypeError, rf.NetworkSet, [self.ntwk1, 'wrong'])

        # all Networks should share the same Frequency
        self.assertRaises(ValueError, rf.NetworkSet, [self.ntwk_freq1_1p, self.ntwk_freq2_1p])

        # all Networks should share the same number of ports
        self.assertRaises(ValueError, rf.NetworkSet, [self.ntwk_freq1_1p, self.ntwk_freq1_2p])

        # expected situations: same number of ports and frequencies
        ntwk_set1 = rf.NetworkSet([self.ntwk_freq1_1p, self.ntwk_freq1_1p])
        ntwk_set2 = rf.NetworkSet([self.ntwk_freq2_1p, self.ntwk_freq2_1p])

    def test_from_zip(self):
        """
        Test the `NetworkSet.from_zip()` constructor class method.
        """
        # reading a zip of touchstone
        zip_filename = os.path.join(self.test_dir, 'ntwks.zip')
        ntwk_set = rf.NetworkSet.from_zip(zip_filename)
        # reading a zip of pickled networks
        zip_filename2 = os.path.join(self.test_dir, 'ntwk_pickle.zip')
        ntwk_set = rf.NetworkSet.from_zip(zip_filename2)

    def test_from_dir(self):
        """
        Test the `NetworkSet.from_dir()` constructor class method.
        """
        dir_path = os.path.join(self.test_dir, './ntwks')
        ntwk_set = rf.NetworkSet.from_dir(dir_path)

    def test_from_s_dict(self):
        """
        Test the `NetworkSet.from_s_dict()` constructor class method.
        """
        d = {'ntwk1': self.ntwk1.s,
             'ntwk2': self.ntwk2.s,
             'ntwk3': self.ntwk3.s}
        ntwk_set = rf.NetworkSet.from_s_dict(d, frequency=self.ntwk1.frequency)

    def test_to_dict(self):
        """
        Test the `to_dict()` method.
        """
        d = self.ns.to_dict()
        self.assertIsInstance(d, dict)
        self.assertEqual(len(d), len(self.ns))
        for (key, ntwk) in zip(d.keys(), self.ns):
            self.assertEqual(d[key], ntwk)

    def test_to_s_dict(self):
        """
        Test the `to_s_dict()` method.
        """
        s_d = self.ns.to_s_dict()
        self.assertIsInstance(s_d, dict)
        self.assertEqual(len(s_d), len(self.ns))
        for (key, ntwk) in zip(s_d.keys(), self.ns):
            np.testing.assert_equal(s_d[key], ntwk.s)

    def test_copy(self):
        """
        Test the `copy()`method and the equality of two NetworkSets
        """
        copy = self.ns.copy()
        self.assertEqual(copy, self.ns)

        copy_inversed = rf.NetworkSet([self.ntwk3, self.ntwk2, self.ntwk1])
        self.assertNotEqual(copy_inversed, self.ns)


    def test_sort(self):
        """
        Test the `sort` method.
        """
        ns_unsorted = rf.NetworkSet([self.ntwk2, self.ntwk1, self.ntwk3])
        # not inplace sorting
        ns_sorted = ns_unsorted.sort(inplace=False)
        for (idx, ntwk) in enumerate(ns_sorted):
            self.assertEqual(ntwk.name, f'ntwk{idx+1}')

        # inplace sorting
        ns_unsorted.sort()
        for (idx, ntwk) in enumerate(ns_unsorted):
            self.assertEqual(ntwk.name, f'ntwk{idx+1}')

        # sorting with respect to a property
        self.ntwk1.dummy = 100
        self.ntwk2.dummy = 10
        self.ntwk3.dummy = 40
        ns_unsorted = rf.NetworkSet([self.ntwk2, self.ntwk1, self.ntwk3])
        ns_unsorted.sort(key=lambda x: x.dummy)  # dummy -> 10, 40, 100
        self.assertEqual(ns_unsorted,
                         rf.NetworkSet([self.ntwk2, self.ntwk3, self.ntwk1]))

    def test_filter(self):
        """
        Test the `filter` method.
        """
        ns_unfiltered = rf.NetworkSet([self.ntwk2, self.ntwk1, self.ntwk3])
        ns_filtered = ns_unfiltered.filter('ntwk2')
        self.assertEqual(len(ns_filtered), 1)
        self.assertEqual(ns_filtered[0], self.ntwk2)

    def test_scalar_mat(self):
        """
        Test the `scalar_mat` method.
        """
        mat = self.ns.scalar_mat()
        # check the resulting shape
        self.assertEqual(mat.shape, (len(self.ns[0].f), len(self.ns), 2*self.ns[0].nports**2))

    def test_inv(self):
        """
        Test the `inv` method.
        """
        ns_inverted = self.ns.inv
        for (ntwk, ntwk_inv) in zip(self.ns, ns_inverted):
            self.assertEqual(ntwk.inv, ntwk_inv)

    def test_write(self):
        """
        Test the `write` method.
        """
        ns = self.ns.copy()
        # should fail if no name is given to the NetworkSet or not filename
        self.assertRaises(ValueError, ns.write)
        ns.write(file='testing.ns')

        # using a name
        ns.name = 'testing'
        ns.write()  # write 'testing.ns'
        os.remove('testing.ns')

    @pytest.mark.skipif("openpyxl" not in sys.modules, reason="Requires openpyxl in sys.modules.")
    def test_write_spreadsheet(self):
        """
        Test the `write_spreadsheet` method.
        """
        ns = self.ns.copy()
        # should fail if not NetworkSet.name attribute exist
        self.assertRaises(ValueError, ns.write_spreadsheet)
        # passing a name
        ns.name = 'testing'
        ns.write_spreadsheet()  # write 'testing.xlsx'
        os.remove('testing.xlsx')
        # passing a filename
        ns.write_spreadsheet(file_name='testing2.xlsx')
        # Using pathlib
        ns.write_spreadsheet(file_name=Path('testing2.xlsx'))
        os.remove('testing2.xlsx')

    def test_ntwk_attr_2_df(self):
        """
        Test the `ntwk_attr_2_df` method.
        """
        df = self.ns.ntwk_attr_2_df('s_db', m=1, n=0)

    def test_2_df(self):
        """
        Test the `to_dataframe` method.
        """

        # Raises a ValueError since the networks have no parameters
        self.assertRaises(ValueError, self.ns.to_dataframe)

        df = self.ns_params.to_dataframe()

    def test_interpolate_from_network(self):
        """
        Test the `interpolate_from_network` method.

        """
        param = [1, 2, 3]
        x0 = 1.5
        interp_ntwk = self.ns.interpolate_from_network(param, x0)

    def test_has_params(self):
        """ Test the .has_params() method """
        # all params have been set
        self.assertTrue(self.ns_params.has_params())

        # at least one params property is None (>=v0.21.0)
        self.assertFalse(self.ns.has_params())

        # at least one params property does not exist (<v0.21.0)
        ns_wo_params = self.ns.copy()
        for ntwk in ns_wo_params:
            delattr(ntwk, 'params')
        self.assertFalse(ns_wo_params.has_params())

        # some params do not have the same length
        ns_wo_all_same_params_length = self.ns_params.copy()
        ns_wo_all_same_params_length[0].params = {'a': 0, 'c': 'A'}
        self.assertFalse(ns_wo_params.has_params())
        ns_wo_all_same_params_length[0].params = {'a': 0, 'b': 10, 'c':'A', 'd':'hu ho'}
        self.assertFalse(ns_wo_params.has_params())

        # not all keys of the params are the same
        ns_params_diff_keys = self.ns_params.copy()
        ns_params_diff_keys[0].params = {'X': 0, 'Y': 10, 'Z' : 'A'}
        self.assertFalse(ns_params_diff_keys.has_params())

    def test_dims_param(self):
        """ Tests associated to the .dims parameter """
        from collections import Counter

        # unassigned params NetworkSet
        self.assertEqual(Counter(self.ns.dims), Counter(None))
        # assigned params
        expected_dims = self.params[0].keys()
        self.assertEqual(Counter(self.ns_params.dims), Counter(expected_dims))

    def test_coords_param(self):
        """ Tests associated to the .coords parameter """
        from collections import Counter

        # unassigned params NetworkSet
        self.assertEqual(Counter(self.ns.coords), Counter(None))

        # assigned params
        # get a dict of unique values for each param
        expected_coords = {p: [] for p in self.params[0]}
        for params in self.params:
            for p in expected_coords.keys():
                expected_coords[p].append(params[p])
        for p in expected_coords.keys():
            expected_coords[p] = list(set(expected_coords[p]))

        self.assertEqual(Counter(self.ns_params.coords), Counter(expected_coords))

    def test_params_param(self):
        """ Test the params property """
        self.assertEqual(self.ns_params.params, list(self.ns_params.dims))
        self.assertEqual(self.ns.params, [])

    def test_sel(self):
        """ Tests associated to the .sel method """
        # passing nothing or empty dict returns the complete NetworkSet
        self.assertEqual(self.ns_params.sel(), self.ns_params)
        self.assertEqual(self.ns_params.sel({}), self.ns_params)

        # should pass a dictionary
        self.assertRaises(TypeError, self.ns_params.sel, 'wrong')
        self.assertRaises(TypeError, self.ns_params.sel, 1)

        # searching for a parameter which do not exist returns empty networkset
        self.assertEqual(self.ns.sel({'a': 1}), rf.NetworkSet())
        self.assertEqual(self.ns_params.sel({'ho ho': 1}), rf.NetworkSet())
        self.assertEqual(self.ns_params.sel({'a': 10}), rf.NetworkSet())

        # there is two times the param key/value 'a':1
        self.assertEqual(len(self.ns_params.sel({'a': 1})), 2)
        # Iterable values
        self.assertEqual(len(self.ns_params.sel({'a': [0,1]})), 4)
        self.assertEqual(len(self.ns_params.sel({'a': range(0,2)})), 4)
        # Multiple parameters
        self.assertEqual(len(self.ns_params.sel({'a': 0, 'X': [10,20]})), 2)
        self.assertEqual(len(self.ns_params.sel({'a': [0,1], 'X': [10,20]})), 4)

    def test_interpolate_from_params(self):
        """ Tests associated to the .interpolate_from_params method """
        ## error handling
        # param does not exist
        self.assertRaises(ValueError, self.ns_params.interpolate_from_params, 'duh!', 0)
        # param values should be bounded by bounded by existing param values
        self.assertRaises(ValueError, self.ns_params.interpolate_from_params, 'a', -1, {'X': 10})
        self.assertRaises(ValueError, self.ns_params.interpolate_from_params, 'a', 100, {'X': 10})
        # cannot interpolate string-valued param
        self.assertRaises(ValueError, self.ns_params.interpolate_from_params, 'c', 'duh!', {'X': 10})
        # ambiguity: could interpolate a for X=10 or X=20...
        self.assertRaises(ValueError, self.ns_params.interpolate_from_params, 'a', 0.5)

        ## working cases
        # returns a Network ?
        self.assertIsInstance(self.ns_params.interpolate_from_params('a', 0.5, {'X':10}), rf.Network)

        # test interpolated values
        f1 = rf.Frequency(1, 1, 1, unit='GHz')
        ntwk0 = rf.Network(frequency=f1, s=[[0]], params={'s': 0})
        ntwk1 = rf.Network(frequency=f1, s=[[1]], params={'s': 1})
        ns2 = rf.NetworkSet([ntwk0, ntwk1])
        self.assertTrue(np.all(ns2.interpolate_from_params('s', 0.3).s == 0.3))

    def test_params_values(self):
        """Test the dictionary containing all parameters names and values"""
        # returns None when no parameters are defined in a NetworkSet
        self.assertEqual(self.ns.params_values, None)
        # return a dict when parameters have been defined
        self.assertIsInstance(self.ns_params.params_values, dict)

        values = self.ns_params.params_values
        for idx, ntwk in enumerate(self.ns_params):
            for key in ntwk.params:
                self.assertEqual(values[key][idx], ntwk.params[key])

    def test_from_mdif(self):
        """ Create NetworkSets from MDIF files """
        mdif_files = glob.glob(self.test_dir+'../io/tests/MDIF_CITI_MDL/test_*.mdf')
        for mdif_file in mdif_files:
            print(mdif_file)
            self.assertIsInstance(rf.NetworkSet.from_mdif(mdif_file), rf.NetworkSet)

            # With Path objects
            self.assertIsInstance(rf.NetworkSet.from_mdif(Path(mdif_file)), rf.NetworkSet)

    def test_to_mdif(self):
        """ Test is NetworkSet are equal after writing and reading to MDIF """
        test_file = '_test.mdif'

        # With and without Path objects
        for func in (str, Path):

            # without parameters
            self.ns.write_mdif(func(test_file))
            ns = rf.NetworkSet.from_mdif(func(test_file))
            self.assertEqual(ns, self.ns)

            # with parameters but without passing explicitly the values
            self.ns_params.write_mdif(func(test_file))
            ns_params = rf.NetworkSet.from_mdif(func(test_file))
            self.assertEqual(ns_params, self.ns_params)

            # with parameters and passing explicitly values but not types
            self.ns_params.write_mdif(func(test_file),
                                      values=self.ns_params.params_values)
            ns_params = rf.NetworkSet.from_mdif(func(test_file))
            self.assertEqual(ns_params, self.ns_params)

            # with parameters and passing explicitly types but not values
            self.ns_params.write_mdif(func(test_file),
                                      data_types=self.ns_params.params_types)
            ns_params = rf.NetworkSet.from_mdif(func(test_file))
            self.assertEqual(ns_params, self.ns_params)

            # with parameters and passing explicitly values and types
            self.ns_params.write_mdif(func(test_file),
                                      values=self.ns_params.params_values,
                                      data_types=self.ns_params.params_types)
            ns_params = rf.NetworkSet.from_mdif(func(test_file))
            self.assertEqual(ns_params, self.ns_params)

            # with parameters and passing explicitly values but not types and ads_compatible
            self.ns_params.write_mdif(func(test_file),
                                      values=self.ns_params.params_values,
                                      ads_compatible=True)
            ns_params = rf.NetworkSet.from_mdif(func(test_file))
            self.assertEqual(ns_params, self.ns_params)

            # with parameters and passing explicitly types but not values and ads_compatible
            self.ns_params.write_mdif(func(test_file),
                                      data_types=self.ns_params.params_types,
                                      ads_compatible=True)
            ns_params = rf.NetworkSet.from_mdif(func(test_file))
            self.assertEqual(ns_params, self.ns_params)

            # with parameters and passing explicitly values and types and ads_compatible
            self.ns_params.write_mdif(func(test_file),
                                      values=self.ns_params.params_values,
                                      data_types=self.ns_params.params_types,
                                      ads_compatible=True)
            ns_params = rf.NetworkSet.from_mdif(func(test_file))
            self.assertEqual(ns_params, self.ns_params)

        os.remove(test_file)

    def test_from_citi(self):
        """ Create NetworkSets from CITI files """
        citi_files = glob.glob(self.test_dir+'../io/tests/MDIF_CITI_MDL/test_*.cti')
        for citi_file in citi_files:
            print(citi_file)
            self.assertIsInstance(rf.NetworkSet.from_citi(citi_file), rf.NetworkSet)

            # With Path object
            self.assertIsInstance(rf.NetworkSet.from_citi(Path(citi_file)), rf.NetworkSet)

suite = unittest.TestLoader().loadTestsFromTestCase(NetworkSetTestCase)
unittest.TextTestRunner(verbosity=2).run(suite)