oscura 0.0.1__py3-none-any.whl → 0.1.1__py3-none-any.whl
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.
- oscura/__init__.py +813 -8
- oscura/__main__.py +392 -0
- oscura/analyzers/__init__.py +37 -0
- oscura/analyzers/digital/__init__.py +177 -0
- oscura/analyzers/digital/bus.py +691 -0
- oscura/analyzers/digital/clock.py +805 -0
- oscura/analyzers/digital/correlation.py +720 -0
- oscura/analyzers/digital/edges.py +632 -0
- oscura/analyzers/digital/extraction.py +413 -0
- oscura/analyzers/digital/quality.py +878 -0
- oscura/analyzers/digital/signal_quality.py +877 -0
- oscura/analyzers/digital/thresholds.py +708 -0
- oscura/analyzers/digital/timing.py +1104 -0
- oscura/analyzers/eye/__init__.py +46 -0
- oscura/analyzers/eye/diagram.py +434 -0
- oscura/analyzers/eye/metrics.py +555 -0
- oscura/analyzers/jitter/__init__.py +83 -0
- oscura/analyzers/jitter/ber.py +333 -0
- oscura/analyzers/jitter/decomposition.py +759 -0
- oscura/analyzers/jitter/measurements.py +413 -0
- oscura/analyzers/jitter/spectrum.py +220 -0
- oscura/analyzers/measurements.py +40 -0
- oscura/analyzers/packet/__init__.py +171 -0
- oscura/analyzers/packet/daq.py +1077 -0
- oscura/analyzers/packet/metrics.py +437 -0
- oscura/analyzers/packet/parser.py +327 -0
- oscura/analyzers/packet/payload.py +2156 -0
- oscura/analyzers/packet/payload_analysis.py +1312 -0
- oscura/analyzers/packet/payload_extraction.py +236 -0
- oscura/analyzers/packet/payload_patterns.py +670 -0
- oscura/analyzers/packet/stream.py +359 -0
- oscura/analyzers/patterns/__init__.py +266 -0
- oscura/analyzers/patterns/clustering.py +1036 -0
- oscura/analyzers/patterns/discovery.py +539 -0
- oscura/analyzers/patterns/learning.py +797 -0
- oscura/analyzers/patterns/matching.py +1091 -0
- oscura/analyzers/patterns/periodic.py +650 -0
- oscura/analyzers/patterns/sequences.py +767 -0
- oscura/analyzers/power/__init__.py +116 -0
- oscura/analyzers/power/ac_power.py +391 -0
- oscura/analyzers/power/basic.py +383 -0
- oscura/analyzers/power/conduction.py +314 -0
- oscura/analyzers/power/efficiency.py +297 -0
- oscura/analyzers/power/ripple.py +356 -0
- oscura/analyzers/power/soa.py +372 -0
- oscura/analyzers/power/switching.py +479 -0
- oscura/analyzers/protocol/__init__.py +150 -0
- oscura/analyzers/protocols/__init__.py +150 -0
- oscura/analyzers/protocols/base.py +500 -0
- oscura/analyzers/protocols/can.py +620 -0
- oscura/analyzers/protocols/can_fd.py +448 -0
- oscura/analyzers/protocols/flexray.py +405 -0
- oscura/analyzers/protocols/hdlc.py +399 -0
- oscura/analyzers/protocols/i2c.py +368 -0
- oscura/analyzers/protocols/i2s.py +296 -0
- oscura/analyzers/protocols/jtag.py +393 -0
- oscura/analyzers/protocols/lin.py +445 -0
- oscura/analyzers/protocols/manchester.py +333 -0
- oscura/analyzers/protocols/onewire.py +501 -0
- oscura/analyzers/protocols/spi.py +334 -0
- oscura/analyzers/protocols/swd.py +325 -0
- oscura/analyzers/protocols/uart.py +393 -0
- oscura/analyzers/protocols/usb.py +495 -0
- oscura/analyzers/signal_integrity/__init__.py +63 -0
- oscura/analyzers/signal_integrity/embedding.py +294 -0
- oscura/analyzers/signal_integrity/equalization.py +370 -0
- oscura/analyzers/signal_integrity/sparams.py +484 -0
- oscura/analyzers/spectral/__init__.py +53 -0
- oscura/analyzers/spectral/chunked.py +273 -0
- oscura/analyzers/spectral/chunked_fft.py +571 -0
- oscura/analyzers/spectral/chunked_wavelet.py +391 -0
- oscura/analyzers/spectral/fft.py +92 -0
- oscura/analyzers/statistical/__init__.py +250 -0
- oscura/analyzers/statistical/checksum.py +923 -0
- oscura/analyzers/statistical/chunked_corr.py +228 -0
- oscura/analyzers/statistical/classification.py +778 -0
- oscura/analyzers/statistical/entropy.py +1113 -0
- oscura/analyzers/statistical/ngrams.py +614 -0
- oscura/analyzers/statistics/__init__.py +119 -0
- oscura/analyzers/statistics/advanced.py +885 -0
- oscura/analyzers/statistics/basic.py +263 -0
- oscura/analyzers/statistics/correlation.py +630 -0
- oscura/analyzers/statistics/distribution.py +298 -0
- oscura/analyzers/statistics/outliers.py +463 -0
- oscura/analyzers/statistics/streaming.py +93 -0
- oscura/analyzers/statistics/trend.py +520 -0
- oscura/analyzers/validation.py +598 -0
- oscura/analyzers/waveform/__init__.py +36 -0
- oscura/analyzers/waveform/measurements.py +943 -0
- oscura/analyzers/waveform/measurements_with_uncertainty.py +371 -0
- oscura/analyzers/waveform/spectral.py +1689 -0
- oscura/analyzers/waveform/wavelets.py +298 -0
- oscura/api/__init__.py +62 -0
- oscura/api/dsl.py +538 -0
- oscura/api/fluent.py +571 -0
- oscura/api/operators.py +498 -0
- oscura/api/optimization.py +392 -0
- oscura/api/profiling.py +396 -0
- oscura/automotive/__init__.py +73 -0
- oscura/automotive/can/__init__.py +52 -0
- oscura/automotive/can/analysis.py +356 -0
- oscura/automotive/can/checksum.py +250 -0
- oscura/automotive/can/correlation.py +212 -0
- oscura/automotive/can/discovery.py +355 -0
- oscura/automotive/can/message_wrapper.py +375 -0
- oscura/automotive/can/models.py +385 -0
- oscura/automotive/can/patterns.py +381 -0
- oscura/automotive/can/session.py +452 -0
- oscura/automotive/can/state_machine.py +300 -0
- oscura/automotive/can/stimulus_response.py +461 -0
- oscura/automotive/dbc/__init__.py +15 -0
- oscura/automotive/dbc/generator.py +156 -0
- oscura/automotive/dbc/parser.py +146 -0
- oscura/automotive/dtc/__init__.py +30 -0
- oscura/automotive/dtc/database.py +3036 -0
- oscura/automotive/j1939/__init__.py +14 -0
- oscura/automotive/j1939/decoder.py +745 -0
- oscura/automotive/loaders/__init__.py +35 -0
- oscura/automotive/loaders/asc.py +98 -0
- oscura/automotive/loaders/blf.py +77 -0
- oscura/automotive/loaders/csv_can.py +136 -0
- oscura/automotive/loaders/dispatcher.py +136 -0
- oscura/automotive/loaders/mdf.py +331 -0
- oscura/automotive/loaders/pcap.py +132 -0
- oscura/automotive/obd/__init__.py +14 -0
- oscura/automotive/obd/decoder.py +707 -0
- oscura/automotive/uds/__init__.py +48 -0
- oscura/automotive/uds/decoder.py +265 -0
- oscura/automotive/uds/models.py +64 -0
- oscura/automotive/visualization.py +369 -0
- oscura/batch/__init__.py +55 -0
- oscura/batch/advanced.py +627 -0
- oscura/batch/aggregate.py +300 -0
- oscura/batch/analyze.py +139 -0
- oscura/batch/logging.py +487 -0
- oscura/batch/metrics.py +556 -0
- oscura/builders/__init__.py +41 -0
- oscura/builders/signal_builder.py +1131 -0
- oscura/cli/__init__.py +14 -0
- oscura/cli/batch.py +339 -0
- oscura/cli/characterize.py +273 -0
- oscura/cli/compare.py +775 -0
- oscura/cli/decode.py +551 -0
- oscura/cli/main.py +247 -0
- oscura/cli/shell.py +350 -0
- oscura/comparison/__init__.py +66 -0
- oscura/comparison/compare.py +397 -0
- oscura/comparison/golden.py +487 -0
- oscura/comparison/limits.py +391 -0
- oscura/comparison/mask.py +434 -0
- oscura/comparison/trace_diff.py +30 -0
- oscura/comparison/visualization.py +481 -0
- oscura/compliance/__init__.py +70 -0
- oscura/compliance/advanced.py +756 -0
- oscura/compliance/masks.py +363 -0
- oscura/compliance/reporting.py +483 -0
- oscura/compliance/testing.py +298 -0
- oscura/component/__init__.py +38 -0
- oscura/component/impedance.py +365 -0
- oscura/component/reactive.py +598 -0
- oscura/component/transmission_line.py +312 -0
- oscura/config/__init__.py +191 -0
- oscura/config/defaults.py +254 -0
- oscura/config/loader.py +348 -0
- oscura/config/memory.py +271 -0
- oscura/config/migration.py +458 -0
- oscura/config/pipeline.py +1077 -0
- oscura/config/preferences.py +530 -0
- oscura/config/protocol.py +875 -0
- oscura/config/schema.py +713 -0
- oscura/config/settings.py +420 -0
- oscura/config/thresholds.py +599 -0
- oscura/convenience.py +457 -0
- oscura/core/__init__.py +299 -0
- oscura/core/audit.py +457 -0
- oscura/core/backend_selector.py +405 -0
- oscura/core/cache.py +590 -0
- oscura/core/cancellation.py +439 -0
- oscura/core/confidence.py +225 -0
- oscura/core/config.py +506 -0
- oscura/core/correlation.py +216 -0
- oscura/core/cross_domain.py +422 -0
- oscura/core/debug.py +301 -0
- oscura/core/edge_cases.py +541 -0
- oscura/core/exceptions.py +535 -0
- oscura/core/gpu_backend.py +523 -0
- oscura/core/lazy.py +832 -0
- oscura/core/log_query.py +540 -0
- oscura/core/logging.py +931 -0
- oscura/core/logging_advanced.py +952 -0
- oscura/core/memoize.py +171 -0
- oscura/core/memory_check.py +274 -0
- oscura/core/memory_guard.py +290 -0
- oscura/core/memory_limits.py +336 -0
- oscura/core/memory_monitor.py +453 -0
- oscura/core/memory_progress.py +465 -0
- oscura/core/memory_warnings.py +315 -0
- oscura/core/numba_backend.py +362 -0
- oscura/core/performance.py +352 -0
- oscura/core/progress.py +524 -0
- oscura/core/provenance.py +358 -0
- oscura/core/results.py +331 -0
- oscura/core/types.py +504 -0
- oscura/core/uncertainty.py +383 -0
- oscura/discovery/__init__.py +52 -0
- oscura/discovery/anomaly_detector.py +672 -0
- oscura/discovery/auto_decoder.py +415 -0
- oscura/discovery/comparison.py +497 -0
- oscura/discovery/quality_validator.py +528 -0
- oscura/discovery/signal_detector.py +769 -0
- oscura/dsl/__init__.py +73 -0
- oscura/dsl/commands.py +246 -0
- oscura/dsl/interpreter.py +455 -0
- oscura/dsl/parser.py +689 -0
- oscura/dsl/repl.py +172 -0
- oscura/exceptions.py +59 -0
- oscura/exploratory/__init__.py +111 -0
- oscura/exploratory/error_recovery.py +642 -0
- oscura/exploratory/fuzzy.py +513 -0
- oscura/exploratory/fuzzy_advanced.py +786 -0
- oscura/exploratory/legacy.py +831 -0
- oscura/exploratory/parse.py +358 -0
- oscura/exploratory/recovery.py +275 -0
- oscura/exploratory/sync.py +382 -0
- oscura/exploratory/unknown.py +707 -0
- oscura/export/__init__.py +25 -0
- oscura/export/wireshark/README.md +265 -0
- oscura/export/wireshark/__init__.py +47 -0
- oscura/export/wireshark/generator.py +312 -0
- oscura/export/wireshark/lua_builder.py +159 -0
- oscura/export/wireshark/templates/dissector.lua.j2 +92 -0
- oscura/export/wireshark/type_mapping.py +165 -0
- oscura/export/wireshark/validator.py +105 -0
- oscura/exporters/__init__.py +94 -0
- oscura/exporters/csv.py +303 -0
- oscura/exporters/exporters.py +44 -0
- oscura/exporters/hdf5.py +219 -0
- oscura/exporters/html_export.py +701 -0
- oscura/exporters/json_export.py +291 -0
- oscura/exporters/markdown_export.py +367 -0
- oscura/exporters/matlab_export.py +354 -0
- oscura/exporters/npz_export.py +219 -0
- oscura/exporters/spice_export.py +210 -0
- oscura/extensibility/__init__.py +131 -0
- oscura/extensibility/docs.py +752 -0
- oscura/extensibility/extensions.py +1125 -0
- oscura/extensibility/logging.py +259 -0
- oscura/extensibility/measurements.py +485 -0
- oscura/extensibility/plugins.py +414 -0
- oscura/extensibility/registry.py +346 -0
- oscura/extensibility/templates.py +913 -0
- oscura/extensibility/validation.py +651 -0
- oscura/filtering/__init__.py +89 -0
- oscura/filtering/base.py +563 -0
- oscura/filtering/convenience.py +564 -0
- oscura/filtering/design.py +725 -0
- oscura/filtering/filters.py +32 -0
- oscura/filtering/introspection.py +605 -0
- oscura/guidance/__init__.py +24 -0
- oscura/guidance/recommender.py +429 -0
- oscura/guidance/wizard.py +518 -0
- oscura/inference/__init__.py +251 -0
- oscura/inference/active_learning/README.md +153 -0
- oscura/inference/active_learning/__init__.py +38 -0
- oscura/inference/active_learning/lstar.py +257 -0
- oscura/inference/active_learning/observation_table.py +230 -0
- oscura/inference/active_learning/oracle.py +78 -0
- oscura/inference/active_learning/teachers/__init__.py +15 -0
- oscura/inference/active_learning/teachers/simulator.py +192 -0
- oscura/inference/adaptive_tuning.py +453 -0
- oscura/inference/alignment.py +653 -0
- oscura/inference/bayesian.py +943 -0
- oscura/inference/binary.py +1016 -0
- oscura/inference/crc_reverse.py +711 -0
- oscura/inference/logic.py +288 -0
- oscura/inference/message_format.py +1305 -0
- oscura/inference/protocol.py +417 -0
- oscura/inference/protocol_dsl.py +1084 -0
- oscura/inference/protocol_library.py +1230 -0
- oscura/inference/sequences.py +809 -0
- oscura/inference/signal_intelligence.py +1509 -0
- oscura/inference/spectral.py +215 -0
- oscura/inference/state_machine.py +634 -0
- oscura/inference/stream.py +918 -0
- oscura/integrations/__init__.py +59 -0
- oscura/integrations/llm.py +1827 -0
- oscura/jupyter/__init__.py +32 -0
- oscura/jupyter/display.py +268 -0
- oscura/jupyter/magic.py +334 -0
- oscura/loaders/__init__.py +526 -0
- oscura/loaders/binary.py +69 -0
- oscura/loaders/configurable.py +1255 -0
- oscura/loaders/csv.py +26 -0
- oscura/loaders/csv_loader.py +473 -0
- oscura/loaders/hdf5.py +9 -0
- oscura/loaders/hdf5_loader.py +510 -0
- oscura/loaders/lazy.py +370 -0
- oscura/loaders/mmap_loader.py +583 -0
- oscura/loaders/numpy_loader.py +436 -0
- oscura/loaders/pcap.py +432 -0
- oscura/loaders/preprocessing.py +368 -0
- oscura/loaders/rigol.py +287 -0
- oscura/loaders/sigrok.py +321 -0
- oscura/loaders/tdms.py +367 -0
- oscura/loaders/tektronix.py +711 -0
- oscura/loaders/validation.py +584 -0
- oscura/loaders/vcd.py +464 -0
- oscura/loaders/wav.py +233 -0
- oscura/math/__init__.py +45 -0
- oscura/math/arithmetic.py +824 -0
- oscura/math/interpolation.py +413 -0
- oscura/onboarding/__init__.py +39 -0
- oscura/onboarding/help.py +498 -0
- oscura/onboarding/tutorials.py +405 -0
- oscura/onboarding/wizard.py +466 -0
- oscura/optimization/__init__.py +19 -0
- oscura/optimization/parallel.py +440 -0
- oscura/optimization/search.py +532 -0
- oscura/pipeline/__init__.py +43 -0
- oscura/pipeline/base.py +338 -0
- oscura/pipeline/composition.py +242 -0
- oscura/pipeline/parallel.py +448 -0
- oscura/pipeline/pipeline.py +375 -0
- oscura/pipeline/reverse_engineering.py +1119 -0
- oscura/plugins/__init__.py +122 -0
- oscura/plugins/base.py +272 -0
- oscura/plugins/cli.py +497 -0
- oscura/plugins/discovery.py +411 -0
- oscura/plugins/isolation.py +418 -0
- oscura/plugins/lifecycle.py +959 -0
- oscura/plugins/manager.py +493 -0
- oscura/plugins/registry.py +421 -0
- oscura/plugins/versioning.py +372 -0
- oscura/py.typed +0 -0
- oscura/quality/__init__.py +65 -0
- oscura/quality/ensemble.py +740 -0
- oscura/quality/explainer.py +338 -0
- oscura/quality/scoring.py +616 -0
- oscura/quality/warnings.py +456 -0
- oscura/reporting/__init__.py +248 -0
- oscura/reporting/advanced.py +1234 -0
- oscura/reporting/analyze.py +448 -0
- oscura/reporting/argument_preparer.py +596 -0
- oscura/reporting/auto_report.py +507 -0
- oscura/reporting/batch.py +615 -0
- oscura/reporting/chart_selection.py +223 -0
- oscura/reporting/comparison.py +330 -0
- oscura/reporting/config.py +615 -0
- oscura/reporting/content/__init__.py +39 -0
- oscura/reporting/content/executive.py +127 -0
- oscura/reporting/content/filtering.py +191 -0
- oscura/reporting/content/minimal.py +257 -0
- oscura/reporting/content/verbosity.py +162 -0
- oscura/reporting/core.py +508 -0
- oscura/reporting/core_formats/__init__.py +17 -0
- oscura/reporting/core_formats/multi_format.py +210 -0
- oscura/reporting/engine.py +836 -0
- oscura/reporting/export.py +366 -0
- oscura/reporting/formatting/__init__.py +129 -0
- oscura/reporting/formatting/emphasis.py +81 -0
- oscura/reporting/formatting/numbers.py +403 -0
- oscura/reporting/formatting/standards.py +55 -0
- oscura/reporting/formatting.py +466 -0
- oscura/reporting/html.py +578 -0
- oscura/reporting/index.py +590 -0
- oscura/reporting/multichannel.py +296 -0
- oscura/reporting/output.py +379 -0
- oscura/reporting/pdf.py +373 -0
- oscura/reporting/plots.py +731 -0
- oscura/reporting/pptx_export.py +360 -0
- oscura/reporting/renderers/__init__.py +11 -0
- oscura/reporting/renderers/pdf.py +94 -0
- oscura/reporting/sections.py +471 -0
- oscura/reporting/standards.py +680 -0
- oscura/reporting/summary_generator.py +368 -0
- oscura/reporting/tables.py +397 -0
- oscura/reporting/template_system.py +724 -0
- oscura/reporting/templates/__init__.py +15 -0
- oscura/reporting/templates/definition.py +205 -0
- oscura/reporting/templates/index.html +649 -0
- oscura/reporting/templates/index.md +173 -0
- oscura/schemas/__init__.py +158 -0
- oscura/schemas/bus_configuration.json +322 -0
- oscura/schemas/device_mapping.json +182 -0
- oscura/schemas/packet_format.json +418 -0
- oscura/schemas/protocol_definition.json +363 -0
- oscura/search/__init__.py +16 -0
- oscura/search/anomaly.py +292 -0
- oscura/search/context.py +149 -0
- oscura/search/pattern.py +160 -0
- oscura/session/__init__.py +34 -0
- oscura/session/annotations.py +289 -0
- oscura/session/history.py +313 -0
- oscura/session/session.py +445 -0
- oscura/streaming/__init__.py +43 -0
- oscura/streaming/chunked.py +611 -0
- oscura/streaming/progressive.py +393 -0
- oscura/streaming/realtime.py +622 -0
- oscura/testing/__init__.py +54 -0
- oscura/testing/synthetic.py +808 -0
- oscura/triggering/__init__.py +68 -0
- oscura/triggering/base.py +229 -0
- oscura/triggering/edge.py +353 -0
- oscura/triggering/pattern.py +344 -0
- oscura/triggering/pulse.py +581 -0
- oscura/triggering/window.py +453 -0
- oscura/ui/__init__.py +48 -0
- oscura/ui/formatters.py +526 -0
- oscura/ui/progressive_display.py +340 -0
- oscura/utils/__init__.py +99 -0
- oscura/utils/autodetect.py +338 -0
- oscura/utils/buffer.py +389 -0
- oscura/utils/lazy.py +407 -0
- oscura/utils/lazy_imports.py +147 -0
- oscura/utils/memory.py +836 -0
- oscura/utils/memory_advanced.py +1326 -0
- oscura/utils/memory_extensions.py +465 -0
- oscura/utils/progressive.py +352 -0
- oscura/utils/windowing.py +362 -0
- oscura/visualization/__init__.py +321 -0
- oscura/visualization/accessibility.py +526 -0
- oscura/visualization/annotations.py +374 -0
- oscura/visualization/axis_scaling.py +305 -0
- oscura/visualization/colors.py +453 -0
- oscura/visualization/digital.py +337 -0
- oscura/visualization/eye.py +420 -0
- oscura/visualization/histogram.py +281 -0
- oscura/visualization/interactive.py +858 -0
- oscura/visualization/jitter.py +702 -0
- oscura/visualization/keyboard.py +394 -0
- oscura/visualization/layout.py +365 -0
- oscura/visualization/optimization.py +1028 -0
- oscura/visualization/palettes.py +446 -0
- oscura/visualization/plot.py +92 -0
- oscura/visualization/power.py +290 -0
- oscura/visualization/power_extended.py +626 -0
- oscura/visualization/presets.py +467 -0
- oscura/visualization/protocols.py +932 -0
- oscura/visualization/render.py +207 -0
- oscura/visualization/rendering.py +444 -0
- oscura/visualization/reverse_engineering.py +791 -0
- oscura/visualization/signal_integrity.py +808 -0
- oscura/visualization/specialized.py +553 -0
- oscura/visualization/spectral.py +811 -0
- oscura/visualization/styles.py +381 -0
- oscura/visualization/thumbnails.py +311 -0
- oscura/visualization/time_axis.py +351 -0
- oscura/visualization/waveform.py +367 -0
- oscura/workflow/__init__.py +13 -0
- oscura/workflow/dag.py +377 -0
- oscura/workflows/__init__.py +58 -0
- oscura/workflows/compliance.py +280 -0
- oscura/workflows/digital.py +272 -0
- oscura/workflows/multi_trace.py +502 -0
- oscura/workflows/power.py +178 -0
- oscura/workflows/protocol.py +492 -0
- oscura/workflows/reverse_engineering.py +639 -0
- oscura/workflows/signal_integrity.py +227 -0
- oscura-0.1.1.dist-info/METADATA +300 -0
- oscura-0.1.1.dist-info/RECORD +463 -0
- oscura-0.1.1.dist-info/entry_points.txt +2 -0
- {oscura-0.0.1.dist-info → oscura-0.1.1.dist-info}/licenses/LICENSE +1 -1
- oscura-0.0.1.dist-info/METADATA +0 -63
- oscura-0.0.1.dist-info/RECORD +0 -5
- {oscura-0.0.1.dist-info → oscura-0.1.1.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
"""Stream processing utilities for packet analysis.
|
|
2
|
+
|
|
3
|
+
This module provides generator-based stream processing for
|
|
4
|
+
O(1) memory usage when analyzing large packet captures.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
>>> from oscura.analyzers.packet.stream import stream_packets
|
|
9
|
+
>>> for packet in stream_packets(file_path, format="pcap"):
|
|
10
|
+
... process(packet) # Process one at a time
|
|
11
|
+
|
|
12
|
+
References:
|
|
13
|
+
Python generators and itertools patterns
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import io
|
|
19
|
+
from dataclasses import dataclass
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import TYPE_CHECKING, Any, BinaryIO, TypeVar
|
|
22
|
+
|
|
23
|
+
from oscura.analyzers.packet.parser import BinaryParser
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from collections.abc import Callable, Iterator
|
|
27
|
+
|
|
28
|
+
T = TypeVar("T")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class StreamPacket:
|
|
33
|
+
"""Packet from a stream.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
timestamp: Packet timestamp in seconds.
|
|
37
|
+
data: Raw packet data.
|
|
38
|
+
metadata: Additional packet metadata.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
timestamp: float
|
|
42
|
+
data: bytes
|
|
43
|
+
metadata: dict[str, Any]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def stream_file(
|
|
47
|
+
file_path: str | Path,
|
|
48
|
+
chunk_size: int = 65536,
|
|
49
|
+
) -> Iterator[bytes]:
|
|
50
|
+
"""Stream file in chunks.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
file_path: Path to file.
|
|
54
|
+
chunk_size: Bytes per chunk (default 64KB).
|
|
55
|
+
|
|
56
|
+
Yields:
|
|
57
|
+
Byte chunks from file.
|
|
58
|
+
|
|
59
|
+
Example:
|
|
60
|
+
>>> for chunk in stream_file("large_capture.bin"):
|
|
61
|
+
... process_chunk(chunk)
|
|
62
|
+
"""
|
|
63
|
+
path = Path(file_path)
|
|
64
|
+
|
|
65
|
+
with open(path, "rb") as f:
|
|
66
|
+
while True:
|
|
67
|
+
chunk = f.read(chunk_size)
|
|
68
|
+
if not chunk:
|
|
69
|
+
break
|
|
70
|
+
yield chunk
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def stream_records(
|
|
74
|
+
file_or_buffer: str | Path | BinaryIO | bytes,
|
|
75
|
+
record_size: int,
|
|
76
|
+
) -> Iterator[bytes]:
|
|
77
|
+
"""Stream fixed-size records.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
file_or_buffer: Source file path, file object, or bytes.
|
|
81
|
+
record_size: Size of each record in bytes.
|
|
82
|
+
|
|
83
|
+
Yields:
|
|
84
|
+
Records as bytes objects.
|
|
85
|
+
|
|
86
|
+
Example:
|
|
87
|
+
>>> for record in stream_records("data.bin", record_size=128):
|
|
88
|
+
... parse_record(record)
|
|
89
|
+
"""
|
|
90
|
+
if isinstance(file_or_buffer, bytes):
|
|
91
|
+
buffer: BinaryIO = io.BytesIO(file_or_buffer)
|
|
92
|
+
should_close = True
|
|
93
|
+
elif isinstance(file_or_buffer, str | Path):
|
|
94
|
+
buffer = open(file_or_buffer, "rb") # noqa: SIM115
|
|
95
|
+
should_close = True
|
|
96
|
+
else:
|
|
97
|
+
buffer = file_or_buffer
|
|
98
|
+
should_close = False
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
while True:
|
|
102
|
+
record = buffer.read(record_size)
|
|
103
|
+
if len(record) < record_size:
|
|
104
|
+
break
|
|
105
|
+
yield record
|
|
106
|
+
finally:
|
|
107
|
+
if should_close:
|
|
108
|
+
buffer.close()
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def stream_packets(
|
|
112
|
+
file_or_buffer: str | Path | BinaryIO | bytes,
|
|
113
|
+
*,
|
|
114
|
+
header_parser: BinaryParser | None = None,
|
|
115
|
+
length_field: int = 1,
|
|
116
|
+
header_included: bool = False,
|
|
117
|
+
) -> Iterator[StreamPacket]:
|
|
118
|
+
"""Stream variable-length packets.
|
|
119
|
+
|
|
120
|
+
Parses packets with length-prefixed format.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
file_or_buffer: Source.
|
|
124
|
+
header_parser: Parser for packet header.
|
|
125
|
+
length_field: Index of length field in header (default 1).
|
|
126
|
+
header_included: True if length includes header.
|
|
127
|
+
|
|
128
|
+
Yields:
|
|
129
|
+
StreamPacket objects.
|
|
130
|
+
|
|
131
|
+
Example:
|
|
132
|
+
>>> header = BinaryParser(">HH") # sync, length
|
|
133
|
+
>>> for pkt in stream_packets("capture.bin", header_parser=header):
|
|
134
|
+
... print(f"Packet: {len(pkt.data)} bytes")
|
|
135
|
+
"""
|
|
136
|
+
if header_parser is None:
|
|
137
|
+
# Default: 2-byte big-endian length prefix
|
|
138
|
+
header_parser = BinaryParser(">H")
|
|
139
|
+
length_field = 0
|
|
140
|
+
|
|
141
|
+
header_size = header_parser.size
|
|
142
|
+
|
|
143
|
+
if isinstance(file_or_buffer, bytes):
|
|
144
|
+
buffer: BinaryIO = io.BytesIO(file_or_buffer)
|
|
145
|
+
should_close = True
|
|
146
|
+
elif isinstance(file_or_buffer, str | Path):
|
|
147
|
+
buffer = open(file_or_buffer, "rb") # noqa: SIM115
|
|
148
|
+
should_close = True
|
|
149
|
+
else:
|
|
150
|
+
buffer = file_or_buffer
|
|
151
|
+
should_close = False
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
packet_num = 0
|
|
155
|
+
|
|
156
|
+
while True:
|
|
157
|
+
# Read header
|
|
158
|
+
header_bytes = buffer.read(header_size)
|
|
159
|
+
if len(header_bytes) < header_size:
|
|
160
|
+
break
|
|
161
|
+
|
|
162
|
+
header = header_parser.unpack(header_bytes)
|
|
163
|
+
length = header[length_field]
|
|
164
|
+
|
|
165
|
+
# Compute payload size
|
|
166
|
+
payload_size = length - header_size if header_included else length
|
|
167
|
+
|
|
168
|
+
if payload_size < 0:
|
|
169
|
+
break
|
|
170
|
+
|
|
171
|
+
# Read payload
|
|
172
|
+
payload = buffer.read(payload_size)
|
|
173
|
+
if len(payload) < payload_size:
|
|
174
|
+
break
|
|
175
|
+
|
|
176
|
+
packet_num += 1
|
|
177
|
+
|
|
178
|
+
yield StreamPacket(
|
|
179
|
+
timestamp=packet_num, # Placeholder
|
|
180
|
+
data=header_bytes + payload,
|
|
181
|
+
metadata={"header": header, "packet_num": packet_num},
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
finally:
|
|
185
|
+
if should_close:
|
|
186
|
+
buffer.close()
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def stream_delimited(
|
|
190
|
+
file_or_buffer: str | Path | BinaryIO | bytes,
|
|
191
|
+
delimiter: bytes = b"\n",
|
|
192
|
+
*,
|
|
193
|
+
max_record_size: int = 1048576,
|
|
194
|
+
) -> Iterator[bytes]:
|
|
195
|
+
"""Stream delimiter-separated records.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
file_or_buffer: Source.
|
|
199
|
+
delimiter: Record delimiter (default newline).
|
|
200
|
+
max_record_size: Maximum record size (default 1MB).
|
|
201
|
+
|
|
202
|
+
Yields:
|
|
203
|
+
Records as bytes (without delimiter).
|
|
204
|
+
|
|
205
|
+
Example:
|
|
206
|
+
>>> for line in stream_delimited("log.txt", b"\\n"):
|
|
207
|
+
... process_line(line)
|
|
208
|
+
"""
|
|
209
|
+
if isinstance(file_or_buffer, bytes):
|
|
210
|
+
buffer: BinaryIO = io.BytesIO(file_or_buffer)
|
|
211
|
+
should_close = True
|
|
212
|
+
elif isinstance(file_or_buffer, str | Path):
|
|
213
|
+
buffer = open(file_or_buffer, "rb") # noqa: SIM115
|
|
214
|
+
should_close = True
|
|
215
|
+
else:
|
|
216
|
+
buffer = file_or_buffer
|
|
217
|
+
should_close = False
|
|
218
|
+
|
|
219
|
+
try:
|
|
220
|
+
partial = b""
|
|
221
|
+
|
|
222
|
+
while True:
|
|
223
|
+
chunk = buffer.read(65536)
|
|
224
|
+
if not chunk:
|
|
225
|
+
if partial:
|
|
226
|
+
yield partial
|
|
227
|
+
break
|
|
228
|
+
|
|
229
|
+
data = partial + chunk
|
|
230
|
+
parts = data.split(delimiter)
|
|
231
|
+
|
|
232
|
+
# Yield complete records
|
|
233
|
+
for part in parts[:-1]:
|
|
234
|
+
if len(part) <= max_record_size:
|
|
235
|
+
yield part
|
|
236
|
+
|
|
237
|
+
# Keep partial record for next iteration
|
|
238
|
+
partial = parts[-1]
|
|
239
|
+
|
|
240
|
+
# Guard against memory issues
|
|
241
|
+
if len(partial) > max_record_size:
|
|
242
|
+
yield partial[:max_record_size]
|
|
243
|
+
partial = b""
|
|
244
|
+
|
|
245
|
+
finally:
|
|
246
|
+
if should_close:
|
|
247
|
+
buffer.close()
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def pipeline(
|
|
251
|
+
source: Iterator[T],
|
|
252
|
+
*transforms: Callable[[Iterator[T]], Iterator[T]],
|
|
253
|
+
) -> Iterator[T]:
|
|
254
|
+
"""Chain processing transforms.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
source: Source iterator.
|
|
258
|
+
*transforms: Transform functions.
|
|
259
|
+
|
|
260
|
+
Yields:
|
|
261
|
+
Transformed items.
|
|
262
|
+
|
|
263
|
+
Example:
|
|
264
|
+
>>> def filter_large(packets):
|
|
265
|
+
... for pkt in packets:
|
|
266
|
+
... if len(pkt.data) > 100:
|
|
267
|
+
... yield pkt
|
|
268
|
+
...
|
|
269
|
+
>>> def decode(packets):
|
|
270
|
+
... for pkt in packets:
|
|
271
|
+
... pkt.metadata["decoded"] = decode_packet(pkt.data)
|
|
272
|
+
... yield pkt
|
|
273
|
+
...
|
|
274
|
+
>>> for pkt in pipeline(stream_packets(f), filter_large, decode):
|
|
275
|
+
... print(pkt)
|
|
276
|
+
"""
|
|
277
|
+
result: Iterator = source # type: ignore[type-arg]
|
|
278
|
+
|
|
279
|
+
for transform in transforms:
|
|
280
|
+
result = transform(result)
|
|
281
|
+
|
|
282
|
+
yield from result
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def batch[T](
|
|
286
|
+
source: Iterator[T],
|
|
287
|
+
size: int,
|
|
288
|
+
) -> Iterator[list[T]]:
|
|
289
|
+
"""Batch items from iterator.
|
|
290
|
+
|
|
291
|
+
Args:
|
|
292
|
+
source: Source iterator.
|
|
293
|
+
size: Batch size.
|
|
294
|
+
|
|
295
|
+
Yields:
|
|
296
|
+
Lists of items.
|
|
297
|
+
|
|
298
|
+
Example:
|
|
299
|
+
>>> for batch_items in batch(stream_packets(f), size=100):
|
|
300
|
+
... process_batch(batch_items)
|
|
301
|
+
"""
|
|
302
|
+
current_batch: list[T] = []
|
|
303
|
+
|
|
304
|
+
for item in source:
|
|
305
|
+
current_batch.append(item)
|
|
306
|
+
if len(current_batch) >= size:
|
|
307
|
+
yield current_batch
|
|
308
|
+
current_batch = []
|
|
309
|
+
|
|
310
|
+
if current_batch:
|
|
311
|
+
yield current_batch
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def take[T](source: Iterator[T], n: int) -> Iterator[T]:
|
|
315
|
+
"""Take first n items.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
source: Source iterator.
|
|
319
|
+
n: Number of items to take.
|
|
320
|
+
|
|
321
|
+
Yields:
|
|
322
|
+
First n items.
|
|
323
|
+
"""
|
|
324
|
+
count = 0
|
|
325
|
+
for item in source:
|
|
326
|
+
if count >= n:
|
|
327
|
+
break
|
|
328
|
+
yield item
|
|
329
|
+
count += 1 # noqa: SIM113
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def skip[T](source: Iterator[T], n: int) -> Iterator[T]:
|
|
333
|
+
"""Skip first n items.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
source: Source iterator.
|
|
337
|
+
n: Number of items to skip.
|
|
338
|
+
|
|
339
|
+
Yields:
|
|
340
|
+
Items after first n.
|
|
341
|
+
"""
|
|
342
|
+
count = 0
|
|
343
|
+
for item in source:
|
|
344
|
+
if count >= n:
|
|
345
|
+
yield item
|
|
346
|
+
count += 1 # noqa: SIM113
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
__all__ = [
|
|
350
|
+
"StreamPacket",
|
|
351
|
+
"batch",
|
|
352
|
+
"pipeline",
|
|
353
|
+
"skip",
|
|
354
|
+
"stream_delimited",
|
|
355
|
+
"stream_file",
|
|
356
|
+
"stream_packets",
|
|
357
|
+
"stream_records",
|
|
358
|
+
"take",
|
|
359
|
+
]
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"""Pattern Detection & Analysis module for Oscura.
|
|
2
|
+
|
|
3
|
+
This module provides comprehensive pattern detection and analysis capabilities
|
|
4
|
+
for digital signals and binary data, including:
|
|
5
|
+
|
|
6
|
+
- Periodic pattern detection (autocorrelation, FFT, suffix array)
|
|
7
|
+
- Repeating sequence detection (n-grams, LRS, approximate matching)
|
|
8
|
+
- Automatic signature discovery (headers, delimiters, magic bytes)
|
|
9
|
+
- Pattern clustering by similarity (Hamming, edit distance, hierarchical)
|
|
10
|
+
- Binary regex pattern matching
|
|
11
|
+
- Multi-pattern search (Aho-Corasick)
|
|
12
|
+
- Fuzzy/approximate pattern matching
|
|
13
|
+
- Pattern learning and discovery
|
|
14
|
+
|
|
15
|
+
- RE-PAT-001: Binary Regex Pattern Matching
|
|
16
|
+
- RE-PAT-002: Multi-Pattern Search (Aho-Corasick)
|
|
17
|
+
- RE-PAT-003: Fuzzy Pattern Matching
|
|
18
|
+
- RE-PAT-004: Pattern Learning and Discovery
|
|
19
|
+
|
|
20
|
+
Author: Oscura Development Team
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
# Periodic pattern detection (PAT-001)
|
|
24
|
+
# Pattern clustering (PAT-004)
|
|
25
|
+
from .clustering import (
|
|
26
|
+
ClusteringResult,
|
|
27
|
+
ClusterResult,
|
|
28
|
+
analyze_cluster,
|
|
29
|
+
cluster_by_edit_distance,
|
|
30
|
+
cluster_by_hamming,
|
|
31
|
+
cluster_hierarchical,
|
|
32
|
+
compute_distance_matrix,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Signature discovery (PAT-003)
|
|
36
|
+
from .discovery import (
|
|
37
|
+
CandidateSignature,
|
|
38
|
+
SignatureDiscovery,
|
|
39
|
+
discover_signatures,
|
|
40
|
+
find_delimiter_candidates,
|
|
41
|
+
find_header_candidates,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# RE-PAT-004: Pattern Learning and Discovery
|
|
45
|
+
from .learning import (
|
|
46
|
+
LearnedPattern,
|
|
47
|
+
NgramModel,
|
|
48
|
+
PatternLearner,
|
|
49
|
+
StructureHypothesis,
|
|
50
|
+
find_recurring_structures,
|
|
51
|
+
infer_structure,
|
|
52
|
+
learn_patterns_from_data,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# RE-PAT-001, RE-PAT-002, RE-PAT-003: Advanced pattern matching
|
|
56
|
+
from .matching import (
|
|
57
|
+
AhoCorasickMatcher,
|
|
58
|
+
# Classes
|
|
59
|
+
BinaryRegex,
|
|
60
|
+
FuzzyMatcher,
|
|
61
|
+
FuzzyMatchResult,
|
|
62
|
+
# Data classes
|
|
63
|
+
PatternMatchResult,
|
|
64
|
+
# RE-PAT-001: Binary Regex
|
|
65
|
+
binary_regex_search,
|
|
66
|
+
count_pattern_occurrences,
|
|
67
|
+
# Utilities
|
|
68
|
+
find_pattern_positions,
|
|
69
|
+
find_similar_sequences,
|
|
70
|
+
# RE-PAT-003: Fuzzy Matching
|
|
71
|
+
fuzzy_search,
|
|
72
|
+
# RE-PAT-002: Multi-Pattern Search
|
|
73
|
+
multi_pattern_search,
|
|
74
|
+
)
|
|
75
|
+
from .periodic import (
|
|
76
|
+
PeriodicPatternDetector,
|
|
77
|
+
PeriodResult,
|
|
78
|
+
detect_period,
|
|
79
|
+
detect_periods_autocorr,
|
|
80
|
+
detect_periods_fft,
|
|
81
|
+
validate_period,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Alias for backward compatibility
|
|
85
|
+
detect_period_autocorr = detect_periods_autocorr
|
|
86
|
+
detect_period_fft = detect_periods_fft
|
|
87
|
+
|
|
88
|
+
# Repeating sequence detection (PAT-002)
|
|
89
|
+
# Motif detection functions (aliases for test compatibility)
|
|
90
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
91
|
+
|
|
92
|
+
from .sequences import (
|
|
93
|
+
NgramResult,
|
|
94
|
+
RepeatingSequence,
|
|
95
|
+
find_approximate_repeats,
|
|
96
|
+
find_frequent_ngrams,
|
|
97
|
+
find_longest_repeat,
|
|
98
|
+
find_repeating_sequences,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
if TYPE_CHECKING:
|
|
102
|
+
import numpy as np
|
|
103
|
+
from numpy.typing import NDArray
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def find_motifs(
|
|
107
|
+
data: Any, motif_length: int = 8, max_distance: float = 0.1
|
|
108
|
+
) -> list[RepeatingSequence]:
|
|
109
|
+
"""Find motifs (repeating patterns) in data.
|
|
110
|
+
|
|
111
|
+
This is an alias for find_repeating_sequences for test compatibility.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
data: Input data array.
|
|
115
|
+
motif_length: Length of motifs to find.
|
|
116
|
+
max_distance: Maximum distance for fuzzy matching (unused).
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
List of RepeatingSequence objects.
|
|
120
|
+
"""
|
|
121
|
+
import numpy as np
|
|
122
|
+
|
|
123
|
+
data = np.asarray(data)
|
|
124
|
+
results = find_repeating_sequences(data, min_length=motif_length, min_count=2)
|
|
125
|
+
return results
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def extract_motif(data: Any, start: int, length: int) -> "NDArray[np.generic]":
|
|
129
|
+
"""Extract a motif from data.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
data: Input data array.
|
|
133
|
+
start: Start index.
|
|
134
|
+
length: Length to extract.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Extracted motif as numpy array.
|
|
138
|
+
"""
|
|
139
|
+
import numpy as np
|
|
140
|
+
from numpy.typing import NDArray
|
|
141
|
+
|
|
142
|
+
data_arr = np.asarray(data)
|
|
143
|
+
result: NDArray[np.generic] = data_arr[start : start + length]
|
|
144
|
+
return result
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def detect_anomalies(data: Any, threshold: float = 3.0) -> list[int]:
|
|
148
|
+
"""Detect anomalies in data using z-score.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
data: Input data array.
|
|
152
|
+
threshold: Z-score threshold for anomaly detection.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
List of anomaly indices.
|
|
156
|
+
"""
|
|
157
|
+
import numpy as np
|
|
158
|
+
|
|
159
|
+
data_arr = np.asarray(data)
|
|
160
|
+
mean = np.mean(data_arr)
|
|
161
|
+
std = np.std(data_arr)
|
|
162
|
+
if std == 0:
|
|
163
|
+
return []
|
|
164
|
+
|
|
165
|
+
z_scores = np.abs((data_arr - mean) / std)
|
|
166
|
+
indices = np.where(z_scores > threshold)[0].tolist()
|
|
167
|
+
return cast("list[int]", indices)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def cluster_patterns(patterns: Any, method: str = "hamming") -> ClusteringResult:
|
|
171
|
+
"""Cluster patterns by similarity.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
patterns: List of patterns to cluster.
|
|
175
|
+
method: Clustering method ('hamming' or 'edit').
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
ClusteringResult with cluster assignments.
|
|
179
|
+
"""
|
|
180
|
+
if method == "hamming":
|
|
181
|
+
return cluster_by_hamming(patterns)
|
|
182
|
+
else:
|
|
183
|
+
return cluster_by_edit_distance(patterns)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def pattern_similarity(pattern1: Any, pattern2: Any) -> float:
|
|
187
|
+
"""Calculate similarity between two patterns.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
pattern1: First pattern.
|
|
191
|
+
pattern2: Second pattern.
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
Similarity score (0-1, 1 = identical).
|
|
195
|
+
"""
|
|
196
|
+
import numpy as np
|
|
197
|
+
|
|
198
|
+
p1 = np.asarray(pattern1)
|
|
199
|
+
p2 = np.asarray(pattern2)
|
|
200
|
+
|
|
201
|
+
if len(p1) != len(p2):
|
|
202
|
+
return 0.0
|
|
203
|
+
|
|
204
|
+
if len(p1) == 0:
|
|
205
|
+
return 1.0
|
|
206
|
+
|
|
207
|
+
matches = int(np.sum(p1 == p2))
|
|
208
|
+
return float(matches / len(p1))
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
__all__ = [
|
|
212
|
+
# RE-PAT-002: Multi-Pattern Search
|
|
213
|
+
"AhoCorasickMatcher",
|
|
214
|
+
# RE-PAT-001: Binary Regex Pattern Matching
|
|
215
|
+
"BinaryRegex",
|
|
216
|
+
"CandidateSignature",
|
|
217
|
+
"ClusterResult",
|
|
218
|
+
"ClusteringResult",
|
|
219
|
+
"FuzzyMatchResult",
|
|
220
|
+
# RE-PAT-003: Fuzzy Pattern Matching
|
|
221
|
+
"FuzzyMatcher",
|
|
222
|
+
# RE-PAT-004: Pattern Learning and Discovery
|
|
223
|
+
"LearnedPattern",
|
|
224
|
+
"NgramModel",
|
|
225
|
+
"NgramResult",
|
|
226
|
+
"PatternLearner",
|
|
227
|
+
"PatternMatchResult",
|
|
228
|
+
"PeriodResult",
|
|
229
|
+
"PeriodicPatternDetector",
|
|
230
|
+
"RepeatingSequence",
|
|
231
|
+
"SignatureDiscovery",
|
|
232
|
+
"StructureHypothesis",
|
|
233
|
+
"analyze_cluster",
|
|
234
|
+
"binary_regex_search",
|
|
235
|
+
"cluster_by_edit_distance",
|
|
236
|
+
"cluster_by_hamming",
|
|
237
|
+
"cluster_hierarchical",
|
|
238
|
+
"cluster_patterns",
|
|
239
|
+
"compute_distance_matrix",
|
|
240
|
+
"count_pattern_occurrences",
|
|
241
|
+
# Motif detection (compatibility)
|
|
242
|
+
"detect_anomalies",
|
|
243
|
+
"detect_period",
|
|
244
|
+
"detect_period_autocorr",
|
|
245
|
+
"detect_period_fft",
|
|
246
|
+
"detect_periods_autocorr",
|
|
247
|
+
"detect_periods_fft",
|
|
248
|
+
"discover_signatures",
|
|
249
|
+
"extract_motif",
|
|
250
|
+
"find_approximate_repeats",
|
|
251
|
+
"find_delimiter_candidates",
|
|
252
|
+
"find_frequent_ngrams",
|
|
253
|
+
"find_header_candidates",
|
|
254
|
+
"find_longest_repeat",
|
|
255
|
+
"find_motifs",
|
|
256
|
+
"find_pattern_positions",
|
|
257
|
+
"find_recurring_structures",
|
|
258
|
+
"find_repeating_sequences",
|
|
259
|
+
"find_similar_sequences",
|
|
260
|
+
"fuzzy_search",
|
|
261
|
+
"infer_structure",
|
|
262
|
+
"learn_patterns_from_data",
|
|
263
|
+
"multi_pattern_search",
|
|
264
|
+
"pattern_similarity",
|
|
265
|
+
"validate_period",
|
|
266
|
+
]
|