PyIBIS-AMI 6.1.1__tar.gz → 6.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyibis_ami-6.1.1/src/PyIBIS_AMI.egg-info → pyibis_ami-6.2.0}/PKG-INFO +2 -3
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/README.md +1 -2
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/pyproject.toml +1 -1
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0/src/PyIBIS_AMI.egg-info}/PKG-INFO +2 -3
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/ami/config.py +3 -3
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/ami/model.py +83 -60
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/ami/parser.py +18 -15
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/common.py +5 -6
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/ibis/model.py +0 -4
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/ibis/parser.py +1 -1
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/tools/run_tests.py +1 -2
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/LICENSE +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/MANIFEST.in +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/docs/source/ami.rst +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/docs/source/conf.py +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/docs/source/ibis.rst +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/docs/source/index.rst +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/docs/source/install.rst +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/docs/source/modules.rst +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/docs/source/tools.rst +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/examples/all_taps.run +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/examples/bandwidth.run +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/examples/dummy.em +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/examples/examples.md +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/examples/freq_resp.em +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/examples/impulse.em +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/examples/impulse_response_8ma.txt +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/examples/mode.run +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/examples/stratix4_ami_tx_runs/all_taps.run +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/examples/stratix4_ami_tx_runs/test_results.xml +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/examples/test_results/test_results.xsl +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/setup.cfg +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/PyIBIS_AMI.egg-info/SOURCES.txt +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/PyIBIS_AMI.egg-info/dependency_links.txt +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/PyIBIS_AMI.egg-info/entry_points.txt +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/PyIBIS_AMI.egg-info/requires.txt +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/PyIBIS_AMI.egg-info/top_level.txt +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/__init__.py +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/__main__.py +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/ami/__init__.py +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/ami/generic.ami.em +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/ami/generic.ibs.em +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/ami/parameter.py +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/ibis/__init__.py +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/ibis/file.py +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/tools/__init__.py +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/src/pyibisami/tools/test_results.xsl +0 -0
- {pyibis_ami-6.1.1 → pyibis_ami-6.2.0}/tests/test_run_tests.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyIBIS-AMI
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.2.0
|
|
4
4
|
Summary: Facilitates working directly with IBIS-AMI DLLs from the Python command prompt.
|
|
5
5
|
Author: David Patterson
|
|
6
6
|
Author-email: David Banas <capn.freako@gmail.com>
|
|
@@ -43,8 +43,7 @@ PyIBIS-AMI is a Python package of tools useful in the development and testing of
|
|
|
43
43
|
This library is used in [PyBERT](https://github.com/capn-freako/PyBERT) and also provides two
|
|
44
44
|
command line applications.
|
|
45
45
|
|
|
46
|
-
It can be installed via `
|
|
47
|
-
`pip install PyIBIS-AMI`.
|
|
46
|
+
It can be installed via: `pip install PyIBIS-AMI`.
|
|
48
47
|
|
|
49
48
|
[View API/Developer's Documentation.](https://pyibis-ami.readthedocs.io/en/latest/)
|
|
50
49
|
|
|
@@ -6,8 +6,7 @@ PyIBIS-AMI is a Python package of tools useful in the development and testing of
|
|
|
6
6
|
This library is used in [PyBERT](https://github.com/capn-freako/PyBERT) and also provides two
|
|
7
7
|
command line applications.
|
|
8
8
|
|
|
9
|
-
It can be installed via `
|
|
10
|
-
`pip install PyIBIS-AMI`.
|
|
9
|
+
It can be installed via: `pip install PyIBIS-AMI`.
|
|
11
10
|
|
|
12
11
|
[View API/Developer's Documentation.](https://pyibis-ami.readthedocs.io/en/latest/)
|
|
13
12
|
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "PyIBIS-AMI"
|
|
7
7
|
description = "Facilitates working directly with IBIS-AMI DLLs from the Python command prompt."
|
|
8
|
-
version = "6.
|
|
8
|
+
version = "6.2.0"
|
|
9
9
|
authors = [ {name = "David Banas", email = "capn.freako@gmail.com"}
|
|
10
10
|
, {name = "David Patterson"}
|
|
11
11
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PyIBIS-AMI
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.2.0
|
|
4
4
|
Summary: Facilitates working directly with IBIS-AMI DLLs from the Python command prompt.
|
|
5
5
|
Author: David Patterson
|
|
6
6
|
Author-email: David Banas <capn.freako@gmail.com>
|
|
@@ -43,8 +43,7 @@ PyIBIS-AMI is a Python package of tools useful in the development and testing of
|
|
|
43
43
|
This library is used in [PyBERT](https://github.com/capn-freako/PyBERT) and also provides two
|
|
44
44
|
command line applications.
|
|
45
45
|
|
|
46
|
-
It can be installed via `
|
|
47
|
-
`pip install PyIBIS-AMI`.
|
|
46
|
+
It can be installed via: `pip install PyIBIS-AMI`.
|
|
48
47
|
|
|
49
48
|
[View API/Developer's Documentation.](https://pyibis-ami.readthedocs.io/en/latest/)
|
|
50
49
|
|
|
@@ -237,9 +237,9 @@ def mk_tests(test_defs, file_base_name, test_dir="test_runs"): # pylint: disabl
|
|
|
237
237
|
# and import what you need from this module. This is much cleaner.
|
|
238
238
|
@click.command(context_settings={"help_option_names": ["-h", "--help"]})
|
|
239
239
|
@click.argument("py_file", type=click.Path(exists=True, resolve_path=True))
|
|
240
|
-
@click.option(
|
|
241
|
-
|
|
242
|
-
)
|
|
240
|
+
# @click.option(
|
|
241
|
+
# "-d", "--test_dir", show_default=True, default="test_runs", help="Output directory for test run generation."
|
|
242
|
+
# )
|
|
243
243
|
@click.version_option()
|
|
244
244
|
def main(py_file):
|
|
245
245
|
"""Configure IBIS-AMI model C++ source code, IBIS model, and AMI file.
|
|
@@ -10,10 +10,10 @@ Copyright (c) 2019 David Banas; All rights reserved World wide.
|
|
|
10
10
|
import copy as cp
|
|
11
11
|
from ctypes import CDLL, byref, c_char_p, c_double # pylint: disable=no-name-in-module
|
|
12
12
|
from pathlib import Path
|
|
13
|
-
from typing import
|
|
13
|
+
from typing import Any, Optional
|
|
14
14
|
|
|
15
15
|
import numpy as np
|
|
16
|
-
from numpy.random import randint
|
|
16
|
+
# from numpy.random import randint
|
|
17
17
|
|
|
18
18
|
from pyibisami.common import * # pylint: disable=wildcard-import,unused-wildcard-import # noqa: F403
|
|
19
19
|
|
|
@@ -214,7 +214,7 @@ class AMIModelInitializer:
|
|
|
214
214
|
|
|
215
215
|
class AMIModel: # pylint: disable=too-many-instance-attributes
|
|
216
216
|
"""
|
|
217
|
-
Class defining the structure and behavior of an AMI Model.
|
|
217
|
+
Class defining the structure and behavior of an IBIS-AMI Model.
|
|
218
218
|
|
|
219
219
|
Notes:
|
|
220
220
|
1. Makes the calling of ``AMI_Close()`` automagic,
|
|
@@ -272,14 +272,26 @@ class AMIModel: # pylint: disable=too-many-instance-attributes
|
|
|
272
272
|
self._amiClose(self._ami_mem_handle)
|
|
273
273
|
|
|
274
274
|
# Set up the AMI_Init() arguments.
|
|
275
|
-
self._channel_response = init_object._init_data[
|
|
275
|
+
self._channel_response = init_object._init_data[ # pylint: disable=protected-access,attribute-defined-outside-init
|
|
276
|
+
"channel_response"
|
|
277
|
+
]
|
|
276
278
|
self._initOut = cp.copy(self._channel_response) # type: ignore # pylint: disable=attribute-defined-outside-init
|
|
277
|
-
self._row_size = init_object._init_data[
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
self.
|
|
279
|
+
self._row_size = init_object._init_data[ # pylint: disable=protected-access,attribute-defined-outside-init
|
|
280
|
+
"row_size"
|
|
281
|
+
]
|
|
282
|
+
self._num_aggressors = init_object._init_data[ # pylint: disable=protected-access,attribute-defined-outside-init
|
|
283
|
+
"num_aggressors"
|
|
284
|
+
]
|
|
285
|
+
self._sample_interval = init_object._init_data[ # pylint: disable=protected-access,attribute-defined-outside-init
|
|
286
|
+
"sample_interval"
|
|
287
|
+
]
|
|
288
|
+
self._bit_time = init_object._init_data[ # pylint: disable=protected-access,attribute-defined-outside-init
|
|
289
|
+
"bit_time"
|
|
290
|
+
]
|
|
281
291
|
self._info_params = init_object.info_params # pylint: disable=attribute-defined-outside-init
|
|
282
|
-
assert self._info_params, RuntimeError(
|
|
292
|
+
assert self._info_params, RuntimeError(
|
|
293
|
+
f"`info_params` is None!\n`init_object: {init_object}"
|
|
294
|
+
) # pylint: disable=attribute-defined-outside-init
|
|
283
295
|
|
|
284
296
|
# Check GetWave() consistency if possible.
|
|
285
297
|
if init_object.info_params and init_object.info_params["GetWave_Exists"]:
|
|
@@ -342,15 +354,18 @@ class AMIModel: # pylint: disable=too-many-instance-attributes
|
|
|
342
354
|
# Initialize attributes used by getWave().
|
|
343
355
|
bit_time = init_object.bit_time
|
|
344
356
|
sample_interval = init_object.sample_interval
|
|
345
|
-
# ToDo: Fix this.
|
|
357
|
+
# ToDo: Fix this. There isn't actually a requirement that `bit_time` be an integral multiple of `sample_interval`.
|
|
358
|
+
# And there may be an advantage to having it not be!
|
|
346
359
|
if (bit_time % sample_interval) > (sample_interval / 100):
|
|
347
360
|
raise ValueError(
|
|
348
|
-
f"Bit time ({bit_time * 1e9
|
|
361
|
+
f"Bit time ({bit_time * 1e9: 6.3G} ns) must be an integral multiple of sample interval ({sample_interval * 1e9: 6.3G} ns)."
|
|
349
362
|
)
|
|
350
363
|
self._samps_per_bit = int(bit_time / sample_interval) # pylint: disable=attribute-defined-outside-init
|
|
351
|
-
self._bits_per_call =
|
|
364
|
+
self._bits_per_call = ( # pylint: disable=attribute-defined-outside-init
|
|
365
|
+
init_object.row_size / self._samps_per_bit
|
|
366
|
+
)
|
|
352
367
|
|
|
353
|
-
def getWave(self, wave: Rvec, bits_per_call: int = 0) -> tuple[Rvec, Rvec]: # noqa: F405
|
|
368
|
+
def getWave(self, wave: Rvec, bits_per_call: int = 0) -> tuple[Rvec, Rvec, list[str]]: # noqa: F405
|
|
354
369
|
"""
|
|
355
370
|
Performs time domain processing of input waveform, using the
|
|
356
371
|
``AMI_GetWave()`` function.
|
|
@@ -363,9 +378,10 @@ class AMIModel: # pylint: disable=too-many-instance-attributes
|
|
|
363
378
|
Default: 0 (Means "Use existing value.")
|
|
364
379
|
|
|
365
380
|
Returns:
|
|
366
|
-
(wave_out, clock_times): A
|
|
367
|
-
- the processed waveform,
|
|
368
|
-
- the recovered slicer sampling instants
|
|
381
|
+
(wave_out, clock_times, params_out): A tuple containing:
|
|
382
|
+
- the processed waveform,
|
|
383
|
+
- the recovered slicer sampling instants, and
|
|
384
|
+
- the list of output parameter strings received from each call to ``AMI_GetWave()``.
|
|
369
385
|
|
|
370
386
|
Notes:
|
|
371
387
|
1. The returned clock times are given in "pre-edge-aligned" fashion,
|
|
@@ -379,12 +395,13 @@ class AMIModel: # pylint: disable=too-many-instance-attributes
|
|
|
379
395
|
|
|
380
396
|
# Create the required C types.
|
|
381
397
|
Signal = c_double * samps_per_call
|
|
382
|
-
Clocks = c_double * bits_per_call
|
|
398
|
+
Clocks = c_double * (bits_per_call + 1) # The "+1" is critical, to prevent access violations by the model.
|
|
383
399
|
|
|
384
400
|
idx = 0 # Holds the starting index of the next processing chunk.
|
|
385
401
|
_clock_times = Clocks(0.0)
|
|
386
402
|
wave_out: list[float] = []
|
|
387
403
|
clock_times: list[float] = []
|
|
404
|
+
params_out: list[str] = []
|
|
388
405
|
input_len = len(wave)
|
|
389
406
|
while idx < input_len:
|
|
390
407
|
remaining_samps = input_len - idx
|
|
@@ -394,18 +411,24 @@ class AMIModel: # pylint: disable=too-many-instance-attributes
|
|
|
394
411
|
else:
|
|
395
412
|
tmp_wave = wave[idx: idx + samps_per_call]
|
|
396
413
|
_wave = Signal(*tmp_wave)
|
|
397
|
-
self._amiGetWave(
|
|
398
|
-
|
|
414
|
+
self._amiGetWave(
|
|
415
|
+
byref(_wave), len(_wave), byref(_clock_times), byref(self._ami_params_out), self._ami_mem_handle
|
|
416
|
+
) # type: ignore
|
|
399
417
|
wave_out.extend(_wave)
|
|
400
418
|
clock_times.extend(_clock_times)
|
|
419
|
+
params_out.append(self.ami_params_out)
|
|
401
420
|
idx += len(_wave)
|
|
402
421
|
|
|
403
|
-
return np.array(wave_out), np.array(clock_times[: len(wave_out) // self._samps_per_bit])
|
|
422
|
+
return np.array(wave_out), np.array(clock_times[: len(wave_out) // self._samps_per_bit]), params_out
|
|
404
423
|
|
|
405
|
-
def get_responses(
|
|
406
|
-
|
|
424
|
+
def get_responses( # pylint: disable=too-many-locals
|
|
425
|
+
self,
|
|
426
|
+
bits_per_call: int = 0,
|
|
427
|
+
# bit_gen: Optional[Iterator[int]] = None,
|
|
428
|
+
pad_bits: int = 10,
|
|
429
|
+
) -> dict[str, Any]:
|
|
407
430
|
"""
|
|
408
|
-
Get the impulse
|
|
431
|
+
Get the impulse response of an initialized IBIS-AMI model, alone and convolved with the channel.
|
|
409
432
|
|
|
410
433
|
Keyword Args:
|
|
411
434
|
bits_per_call: Number of bits to include in the input to `GetWave()`.
|
|
@@ -413,17 +436,16 @@ class AMIModel: # pylint: disable=too-many-instance-attributes
|
|
|
413
436
|
bit_gen: The bit generator to use for `GetWave()` input data generation.
|
|
414
437
|
Should produce integers from the set: {0,1}.
|
|
415
438
|
Default: None (Means "use randint(2)".)
|
|
439
|
+
pad_bits: Number of bits to pad leading edge with when calling `GetWave()`,
|
|
440
|
+
to protect from initial garbage in `GetWave()` output.
|
|
441
|
+
Default: 10
|
|
416
442
|
|
|
417
443
|
Returns:
|
|
418
|
-
Dictionary containing the responses under the following keys:
|
|
444
|
+
rslt: Dictionary containing the responses under the following keys:
|
|
419
445
|
"imp_resp_init": The model's impulse response, from its `AMI_Init()` function (V/sample).
|
|
420
|
-
"
|
|
421
|
-
"pulse_resp_init": The model's pulse response, from its `AMI_Init()` function.
|
|
422
|
-
"freq_resp_init": The model's frequency response, from its `AMI_Init()` function.
|
|
446
|
+
"out_resp_init": `imp_resp_init` convolved with the channel.
|
|
423
447
|
"imp_resp_getw": The model's impulse response, from its `AMI_GetWave()` function (V/sample).
|
|
424
|
-
"
|
|
425
|
-
"pulse_resp_getw": The model's pulse response, from its `AMI_GetWave()` function.
|
|
426
|
-
"freq_resp_getw": The model's frequency response, from its `AMI_GetWave()` function.
|
|
448
|
+
"out_resp_getw": `imp_resp_getw` convolved with the channel.
|
|
427
449
|
|
|
428
450
|
Notes:
|
|
429
451
|
1. If either set of keys (i.e. - "..._init" or "..._getw")
|
|
@@ -432,12 +454,11 @@ class AMIModel: # pylint: disable=too-many-instance-attributes
|
|
|
432
454
|
was not available in the given model.
|
|
433
455
|
2. An empty dictionary implies that neither the `Init_Returns_Impulse`
|
|
434
456
|
nor the `GetWave_Exists` AMI reserved parameter was True.
|
|
435
|
-
3.
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
f0 = 1 / (ts * impulse_length)
|
|
457
|
+
3. Note that impulse responses are returned with units: (V/sample), not (V/s).
|
|
458
|
+
|
|
459
|
+
ToDo:
|
|
460
|
+
1. Implement `bit_gen`.
|
|
461
|
+
2. Implement `ignore_bits`.
|
|
441
462
|
"""
|
|
442
463
|
|
|
443
464
|
rslt = {}
|
|
@@ -446,51 +467,51 @@ class AMIModel: # pylint: disable=too-many-instance-attributes
|
|
|
446
467
|
impulse_length = self.row_size
|
|
447
468
|
ui = self.bit_time
|
|
448
469
|
ts = self.sample_interval
|
|
449
|
-
|
|
450
|
-
ignore_bits =
|
|
470
|
+
# info_params = self.info_params
|
|
471
|
+
# ignore_bits = info_params["Ignore_Bits"] if "Ignore_Bits" in info_params else 0
|
|
451
472
|
|
|
452
473
|
# Capture/convert instance variables.
|
|
453
474
|
chnl_imp = np.array(self.channel_response) * ts # input (a.k.a. - "channel") impulse response (V/sample)
|
|
454
475
|
out_imp = np.array(self.initOut) * ts # output impulse response (V/sample)
|
|
455
476
|
|
|
477
|
+
# Calculate some needed intermediate values.
|
|
478
|
+
nspui = int(ui / ts) # samps per UI
|
|
479
|
+
pad_samps = pad_bits * nspui # leading edge padding samples for GetWave() calls
|
|
480
|
+
|
|
456
481
|
# Extract and return the model responses.
|
|
457
482
|
if self.info_params["Init_Returns_Impulse"]:
|
|
458
483
|
h_model = deconv_same(out_imp, chnl_imp) # noqa: F405
|
|
459
484
|
# h_model = irfft(rfft(out_imp) / rfft(chnl_imp)) # Seems to produce results just as noisy as above.
|
|
460
485
|
h_model = np.where(abs(h_model) > 1, np.zeros(len(h_model)), h_model)
|
|
461
486
|
rslt["imp_resp_init"] = np.roll(h_model, -len(h_model) // 2 + 3 * nspui)
|
|
462
|
-
rslt["step_resp_init"] = np.cumsum(rslt["imp_resp_init"])
|
|
463
|
-
rslt["pulse_resp_init"] = rslt["step_resp_init"] - np.pad(
|
|
464
|
-
rslt["step_resp_init"][:-nspui], (nspui, 0), mode="constant", constant_values=0
|
|
465
|
-
)
|
|
466
|
-
rslt["freq_resp_init"] = np.fft.rfft(rslt["imp_resp_init"])
|
|
467
487
|
rslt["out_resp_init"] = out_imp
|
|
468
488
|
if self.info_params["GetWave_Exists"]:
|
|
469
489
|
# Run `ignore_bits` bits of data through the model first.
|
|
470
|
-
if bit_gen:
|
|
471
|
-
|
|
472
|
-
else:
|
|
473
|
-
|
|
474
|
-
_, _ = self.getWave(np.array(wave_in) - 0.5, bits_per_call=bits_per_call)
|
|
490
|
+
# if bit_gen:
|
|
491
|
+
# wave_in = [next(bit_gen) for _ in range(ignore_bits)]
|
|
492
|
+
# else:
|
|
493
|
+
# wave_in = [randint(2) for _ in range(ignore_bits)]
|
|
494
|
+
# _, _, _ = self.getWave(np.array(wave_in) - 0.5, bits_per_call=bits_per_call)
|
|
495
|
+
|
|
475
496
|
# Then, run a perfect step, to extract model's step response.
|
|
476
|
-
wave_out, _ = self.getWave(
|
|
477
|
-
np.array([0] *
|
|
497
|
+
wave_out, _, _ = self.getWave(
|
|
498
|
+
np.array([0] * pad_samps + [1] * impulse_length) - 0.5,
|
|
499
|
+
bits_per_call=bits_per_call,
|
|
478
500
|
)
|
|
479
|
-
|
|
480
|
-
rslt["step_resp_getw"] = wave_out[impulse_length:] - wave_out[impulse_length - 1]
|
|
501
|
+
|
|
481
502
|
# Calculate other responses from step response.
|
|
482
|
-
rslt["imp_resp_getw"] = np.
|
|
483
|
-
|
|
484
|
-
rslt["step_resp_getw"][:-nspui], (nspui, 0), mode="constant", constant_values=0
|
|
485
|
-
)
|
|
486
|
-
rslt["freq_resp_getw"] = np.fft.rfft(rslt["imp_resp_getw"])
|
|
503
|
+
rslt["imp_resp_getw"] = np.diff(wave_out[pad_samps:])
|
|
504
|
+
|
|
487
505
|
# Calculate effective cumulative impulse response (i.e. - channel + Tx).
|
|
488
506
|
# - Form the step response equivalent to the given channel impulse response.
|
|
489
507
|
chnl_step = np.cumsum(chnl_imp)
|
|
490
508
|
# - And run it through `GetWave()`, after d.c. balancing.
|
|
491
|
-
|
|
509
|
+
chnl_step_bal = chnl_step - chnl_step[-1] / 2
|
|
510
|
+
out_step, _, _ = self.getWave(
|
|
511
|
+
np.pad(chnl_step_bal, (pad_samps, 0), mode="edge"), bits_per_call=bits_per_call
|
|
512
|
+
)
|
|
492
513
|
# - Convert result back to an impulse response.
|
|
493
|
-
rslt["out_resp_getw"] = np.
|
|
514
|
+
rslt["out_resp_getw"] = np.diff(out_step[pad_samps:])
|
|
494
515
|
return rslt
|
|
495
516
|
|
|
496
517
|
def _getInitOut(self):
|
|
@@ -533,7 +554,9 @@ class AMIModel: # pylint: disable=too-many-instance-attributes
|
|
|
533
554
|
def _getAmiParamsOut(self):
|
|
534
555
|
return self._ami_params_out.value
|
|
535
556
|
|
|
536
|
-
ami_params_out = property(
|
|
557
|
+
ami_params_out = property(
|
|
558
|
+
_getAmiParamsOut, doc="The AMI parameter string returned by either `AMI_Init()` or `AMI_GetWave()`."
|
|
559
|
+
)
|
|
537
560
|
|
|
538
561
|
def _getMsg(self):
|
|
539
562
|
return self._msg.value
|
|
@@ -9,7 +9,7 @@ Copyright (c) 2019 David Banas; all rights reserved World wide.
|
|
|
9
9
|
|
|
10
10
|
import re
|
|
11
11
|
|
|
12
|
-
from parsec import ParseError, generate, many,
|
|
12
|
+
from parsec import ParseError, generate, many, regex, string
|
|
13
13
|
from traits.api import Bool, Enum, HasTraits, Range, Trait
|
|
14
14
|
from traitsui.api import Group, Item, View
|
|
15
15
|
from traitsui.menu import ModalButtons
|
|
@@ -210,7 +210,9 @@ class AMIParamConfigurator(HasTraits):
|
|
|
210
210
|
# See the docs on the *HasTraits* class, if this is confusing.
|
|
211
211
|
try: # Querry for a mapped trait, first, by trying to get '<trait_name>_'. (Note the underscore.)
|
|
212
212
|
res[pname] = self.get(pname + "_")[pname + "_"]
|
|
213
|
-
except
|
|
213
|
+
except (
|
|
214
|
+
Exception # pylint: disable=broad-exception-caught
|
|
215
|
+
): # If we get an exception, we have an ordinary (i.e. - not mapped) trait.
|
|
214
216
|
res[pname] = self.get(pname)[pname]
|
|
215
217
|
elif isinstance(param, dict): # We received a dictionary of subparameters, in 'param'.
|
|
216
218
|
subs = {}
|
|
@@ -270,7 +272,7 @@ def node():
|
|
|
270
272
|
"Parse AMI node."
|
|
271
273
|
yield lparen
|
|
272
274
|
label = yield node_name
|
|
273
|
-
values = yield
|
|
275
|
+
values = yield many(expr)
|
|
274
276
|
yield rparen
|
|
275
277
|
return (label, values)
|
|
276
278
|
|
|
@@ -300,12 +302,9 @@ def proc_branch(branch):
|
|
|
300
302
|
|
|
301
303
|
Returns:
|
|
302
304
|
(str, dict): A pair containing:
|
|
303
|
-
|
|
304
|
-
err_str:
|
|
305
|
-
String containing any errors or warnings encountered,
|
|
305
|
+
err_str: String containing any errors or warnings encountered,
|
|
306
306
|
while building the parameter dictionary.
|
|
307
|
-
param_dict:
|
|
308
|
-
Resultant parameter dictionary.
|
|
307
|
+
param_dict: Resultant parameter dictionary.
|
|
309
308
|
"""
|
|
310
309
|
results = ("", {}) # Empty Results
|
|
311
310
|
if len(branch) != 2:
|
|
@@ -324,9 +323,13 @@ def proc_branch(branch):
|
|
|
324
323
|
|
|
325
324
|
try:
|
|
326
325
|
if (
|
|
327
|
-
(len(param_tags) > 1)
|
|
328
|
-
and (
|
|
329
|
-
|
|
326
|
+
(len(param_tags) > 1)
|
|
327
|
+
and ( # noqa: W503
|
|
328
|
+
param_tags[0][0] in AMIParameter._param_def_tag_procs # pylint: disable=protected-access # noqa: W503
|
|
329
|
+
)
|
|
330
|
+
and ( # noqa: W503
|
|
331
|
+
param_tags[1][0] in AMIParameter._param_def_tag_procs # pylint: disable=protected-access # noqa: W503
|
|
332
|
+
)
|
|
330
333
|
):
|
|
331
334
|
try:
|
|
332
335
|
results = ("", {param_name: AMIParameter(param_name, param_tags)})
|
|
@@ -368,12 +371,10 @@ def parse_ami_param_defs(param_str): # pylint: disable=too-many-branches
|
|
|
368
371
|
|
|
369
372
|
Returns:
|
|
370
373
|
(str, dict): A pair containing:
|
|
371
|
-
|
|
372
374
|
err_str:
|
|
373
375
|
- None, if parser succeeds.
|
|
374
376
|
- Helpful message, if it fails.
|
|
375
|
-
param_dict:
|
|
376
|
-
Dictionary containing parameter definitions.
|
|
377
|
+
param_dict: Dictionary containing parameter definitions.
|
|
377
378
|
(Empty, on failure.)
|
|
378
379
|
It has a single key, at the top level, which is the
|
|
379
380
|
model root name. This key indexes the actual
|
|
@@ -450,7 +451,9 @@ def parse_ami_param_defs(param_str): # pylint: disable=too-many-branches
|
|
|
450
451
|
return (err_str, param_dict)
|
|
451
452
|
|
|
452
453
|
|
|
453
|
-
def make_gui_items(
|
|
454
|
+
def make_gui_items(
|
|
455
|
+
pname, param, first_call=False
|
|
456
|
+
): # pylint: disable=too-many-locals,too-many-branches,too-many-statements
|
|
454
457
|
"""Builds list of GUI items from AMI parameter dictionary."""
|
|
455
458
|
|
|
456
459
|
gui_items = []
|
|
@@ -8,18 +8,17 @@ Original date: May 15, 2024
|
|
|
8
8
|
Copyright (c) 2024 David Banas; all rights reserved World wide.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
from typing import TypeVar
|
|
11
|
+
from typing_extensions import TypeAlias, TypeVar
|
|
13
12
|
|
|
14
13
|
import numpy.typing as npt # type: ignore
|
|
15
14
|
from scipy.linalg import convolution_matrix, lstsq
|
|
16
15
|
|
|
17
16
|
Real = TypeVar("Real", float, float)
|
|
18
17
|
Comp = TypeVar("Comp", complex, complex)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Rvec = npt.NDArray[Real]
|
|
22
|
-
Cvec = npt.NDArray[Comp]
|
|
18
|
+
Rvec: TypeAlias = npt.NDArray[Real]
|
|
19
|
+
Cvec: TypeAlias = npt.NDArray[Comp]
|
|
20
|
+
# Rvec = npt.NDArray[Real]
|
|
21
|
+
# Cvec = npt.NDArray[Comp]
|
|
23
22
|
|
|
24
23
|
# PI: float = np.pi # Causes a failed import of `pyibisami.ami.model` during `tox -e docs`, due to:
|
|
25
24
|
# File "C:\Users\davibana\prj\PyBERT\PyAMI\src\pyibisami\common.py", line 23, in <module>
|
|
@@ -258,10 +258,6 @@ class Model(HasTraits): # pylint: disable=too-many-instance-attributes
|
|
|
258
258
|
((os, _), _) = x
|
|
259
259
|
return os.lower() == "windows"
|
|
260
260
|
|
|
261
|
-
# def showExec(x):
|
|
262
|
-
# ((os, b), fs) = x
|
|
263
|
-
# return os + str(b) + ": " + str(fs)
|
|
264
|
-
|
|
265
261
|
def partition(p, xs):
|
|
266
262
|
ts, fs = [], []
|
|
267
263
|
for x in xs:
|
|
@@ -59,7 +59,7 @@ def logf(p, preStr=""):
|
|
|
59
59
|
res = p(txt, ix)
|
|
60
60
|
if not res.status:
|
|
61
61
|
print(
|
|
62
|
-
f"{preStr}: Expected {res.expected} in '{txt[res.index
|
|
62
|
+
f"{preStr}: Expected {res.expected} in '{txt[res.index: res.index + 5]}' at {ParseError.loc_info(txt, res.index)}."
|
|
63
63
|
)
|
|
64
64
|
return res
|
|
65
65
|
|
|
@@ -199,8 +199,7 @@ def run_tests(**kwargs): # pylint: disable=too-many-locals
|
|
|
199
199
|
print(f"Please, open file, `{xml_filename}` in a Web browser, in order to view the test results.")
|
|
200
200
|
|
|
201
201
|
|
|
202
|
-
@click.command(context_settings={"ignore_unknown_options": True,
|
|
203
|
-
"help_option_names": ["-h", "--help"]})
|
|
202
|
+
@click.command(context_settings={"ignore_unknown_options": True, "help_option_names": ["-h", "--help"]})
|
|
204
203
|
@click.option(
|
|
205
204
|
"--model", "-m", default="libami.so", type=click.Path(exists=True), help="Sets the AMI model DLL file name."
|
|
206
205
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|