qplotter 1.6.1__tar.gz → 1.6.2__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.
- {qplotter-1.6.1 → qplotter-1.6.2}/CHANGELOG.md +39 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/PKG-INFO +10 -5
- {qplotter-1.6.1 → qplotter-1.6.2}/README.md +9 -4
- {qplotter-1.6.1 → qplotter-1.6.2}/docs/demo-data.md +7 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/docs/distribution.md +20 -19
- {qplotter-1.6.1 → qplotter-1.6.2}/pyproject.toml +1 -1
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/benchmark_plot_launch.py +23 -10
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/profile_trusted_reads.py +14 -4
- qplotter-1.6.2/src/qplot/_build_info.json +1 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/_metadata.py +14 -5
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/configuration/config_schema.json +7 -1
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/LoadFromDB.py +14 -1
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/_trusted_live_helper.py +9 -4
- qplotter-1.6.2/src/qplot/datahandling/parameter_data.py +345 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/qcodes_cache.py +17 -1
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/readonly.py +27 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_array_preview.py +44 -9
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_derived_rendering.py +7 -3
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_live.py +12 -1
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_live_queries.py +38 -7
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_plot.py +13 -3
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/diagnostics.py +42 -7
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/testdata.py +38 -2
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/tools/general.py +12 -5
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/tools/plot_tools.py +113 -17
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/tools/sample_statistics.py +12 -3
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/tools/worker.py +15 -1
- qplotter-1.6.2/src/qplot/windows/_csv_filenames.py +19 -0
- qplotter-1.6.2/src/qplot/windows/_dataset_statistics.py +36 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_display_precision.py +3 -2
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_mixed_plots.py +3 -2
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_native_transforms.py +52 -9
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plotWin.py +3 -3
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_actions.py +100 -6
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_drop_axes.py +12 -2
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_export.py +23 -8
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_marquee.py +31 -23
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_refresh.py +20 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_source_promotion.py +31 -3
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_preferences.py +17 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_run_controls.py +2 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_subplots/subplot2d.py +3 -1
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_widgets/preview.py +9 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_widgets/run_list_items.py +7 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_widgets/treeWidgets.py +6 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplotter.egg-info/SOURCES.txt +40 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_array_preview.py +1 -1
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_derivative_cancellation.py +1 -1
- qplotter-1.6.2/tests/test_campaign_array_expansion_budget.py +221 -0
- qplotter-1.6.2/tests/test_campaign_boolean_derivative.py +195 -0
- qplotter-1.6.2/tests/test_campaign_clipped_trace_reparenting.py +63 -0
- qplotter-1.6.2/tests/test_campaign_diagnostics.py +104 -0
- qplotter-1.6.2/tests/test_campaign_empty_incremental_records.py +157 -0
- qplotter-1.6.2/tests/test_campaign_extended_float_centering.py +109 -0
- qplotter-1.6.2/tests/test_campaign_extended_float_derivative.py +109 -0
- qplotter-1.6.2/tests/test_campaign_extended_float_display.py +135 -0
- qplotter-1.6.2/tests/test_campaign_extended_float_fft.py +159 -0
- qplotter-1.6.2/tests/test_campaign_extended_float_heatmap.py +88 -0
- qplotter-1.6.2/tests/test_campaign_extended_float_previews.py +199 -0
- qplotter-1.6.2/tests/test_campaign_generator_backend.py +178 -0
- qplotter-1.6.2/tests/test_campaign_generator_input.py +37 -0
- qplotter-1.6.2/tests/test_campaign_heatmap_csv_precision.py +76 -0
- qplotter-1.6.2/tests/test_campaign_inferred_array_missing_cells.py +524 -0
- qplotter-1.6.2/tests/test_campaign_inferred_parameter_loading.py +259 -0
- qplotter-1.6.2/tests/test_campaign_live_schema_refresh.py +121 -0
- qplotter-1.6.2/tests/test_campaign_log_symlink_loops.py +81 -0
- qplotter-1.6.2/tests/test_campaign_measurement_coordinate_gaps.py +115 -0
- qplotter-1.6.2/tests/test_campaign_measurement_longdouble_csv.py +91 -0
- qplotter-1.6.2/tests/test_campaign_metadata_omission_recovery.py +154 -0
- qplotter-1.6.2/tests/test_campaign_mixed_extended_clipping.py +124 -0
- qplotter-1.6.2/tests/test_campaign_mixed_extended_finiteness.py +119 -0
- qplotter-1.6.2/tests/test_campaign_narrow_float_clipping.py +115 -0
- qplotter-1.6.2/tests/test_campaign_profiling_scripts.py +182 -0
- qplotter-1.6.2/tests/test_campaign_safety_cancellation.py +162 -0
- qplotter-1.6.2/tests/test_campaign_singleton_array_previews.py +448 -0
- qplotter-1.6.2/tests/test_campaign_split_storage_safety.py +148 -0
- qplotter-1.6.2/tests/test_campaign_ui_cut_axis_refresh.py +43 -0
- qplotter-1.6.2/tests/test_campaign_ui_cut_ownership.py +69 -0
- qplotter-1.6.2/tests/test_campaign_ui_manual_refresh.py +280 -0
- qplotter-1.6.2/tests/test_campaign_ui_paused_promotion.py +82 -0
- qplotter-1.6.2/tests/test_campaign_ui_pending_drop.py +110 -0
- qplotter-1.6.2/tests/test_campaign_ui_promoted_cut_mapping.py +64 -0
- qplotter-1.6.2/tests/test_campaign_ui_promotion.py +93 -0
- qplotter-1.6.2/tests/test_campaign_wal_artifact_observation.py +107 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_config.py +15 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_version_info.py +60 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/widgets/test_run_details.py +3 -3
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_bounded_shutdown.py +111 -18
- qplotter-1.6.2/tests/windows/test_csv_filenames.py +42 -0
- qplotter-1.6.2/tests/windows/test_dataset_statistics.py +101 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_heatmap_layer_integration.py +18 -8
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot2d_layers.py +48 -3
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot_annotation.py +8 -3
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot_tiling.py +7 -6
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_preferences.py +4 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_refresh_lifecycle.py +1 -0
- qplotter-1.6.1/src/qplot/_build_info.json +0 -1
- qplotter-1.6.1/src/qplot/datahandling/parameter_data.py +0 -149
- {qplotter-1.6.1 → qplotter-1.6.2}/Agents.md +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/CONTRIBUTING.md +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/LICENSE +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/MANIFEST.in +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/docs/architecture.md +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/docs/assets/qplot-color-scale-dialog.png +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/docs/assets/qplot-heatmap.png +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/docs/assets/qplot-line-plot.png +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/docs/assets/qplot-main-window.png +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/docs/configuration.md +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/docs/troubleshooting.md +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/docs/trusted-live-reader.md +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/docs/user-guide.md +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/README.md +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/benchmark_heatmap_aggregation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/capture_demo_screenshots.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/liveplot.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/manual_run.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/release.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/revalidate_published_release.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/time_stress.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/validate_compiler_free_install.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/validate_distribution.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/scripts/write_build_info.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/setup.cfg +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/__init__.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/__main__.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/_auxiliary_paths.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/_repair.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/_shutdown_supervisor.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/_version.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/_windows_shutdown_job.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/configuration/__init__.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/configuration/config.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/configuration/fonts.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/configuration/scripts.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/configuration/themes/__init__.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/configuration/themes/_base.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/configuration/themes/blank.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/configuration/themes/dark.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/configuration/themes/light.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/__init__.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/_trusted_live_protocol.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/database.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/dimensions.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/file_identity.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/plot_progress.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/qcodes_compat.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/readSQL.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/source_activity.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_derived_cache.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_heatmap.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_live_service.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_live_supervisor.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_presentation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_snapshot.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_work_coordinator.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/datahandling/trusted_work_scheduler.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/resources/testdata/qplot_test_db_01_10mb.csv +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/resources/testdata/qplot_test_db_02_25mb.csv +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/resources/testdata/qplot_test_db_03_50mb.csv +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/resources/testdata/qplot_test_db_04_100mb.csv +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/resources/testdata/qplot_test_db_05_250mb.csv +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/resources/testdata/qplot_test_db_06_500mb.csv +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/resources/testdata/qplot_test_db_07_1gb.csv +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/resources/testdata/qplot_test_db_08_5gb.csv +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/resources/testdata/qplot_test_db_09_10gb.csv +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/resources/testdata/qplot_test_db_10_30gb.csv +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/tools/__init__.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/tools/finite_means.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/tools/heatmap_geometry.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/tools/operation_registry.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/__init__.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_auto_plot.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_colorbar.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_commands.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_config_persistence.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_database_actions.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_dataset_handle.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_dragdrop.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_export_paths.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_help.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_mixed_appearance.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_native_averaging.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot1d_snap.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot1d_traces.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot2d_colorbar.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot2d_colorbar_dialog.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot2d_layers.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot2d_sweeps.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_annotation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_appearance.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_axis_scaling.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_data_viewbox.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_feedback.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_state.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_status.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_tiling.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_plot_transform_labels.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_refresh_interval.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_shortcuts.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_subplots/__init__.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_subplots/subplot1d.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_svg_export.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_trusted_derived_qt.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_widgets/__init__.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_widgets/_run_formatting.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_widgets/details_tables.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_widgets/dropbox.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_widgets/operations.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_widgets/toolbar.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/_window_controls.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/main.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/plot1d.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/src/qplot/windows/plot2d.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/_artifact_audit.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/_ci_scheduling.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/_window_lifecycle.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/conftest.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/_wal_lineage_scenarios.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_array_record_metadata.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_database_worker_instance_binding.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_dimensions.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_inferred_planned_counts.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_integer_record_cache.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_live_acquired_point_counts.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_plot_progress.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_qcodes_cache.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_read_sql.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_read_sql_database_identity.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_readonly.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_snapshot_planned_setpoints.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_stage5c_real_qcodes.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_array_record_metadata.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_database_information.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_derived_cache.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_derived_cache_ownership.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_derived_live_integration.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_derived_queries.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_derived_rendering.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_heatmap.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_live.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_live_partial_frames.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_live_protocol.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_live_queries.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_live_result_limits.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_live_service.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_live_stage4_integration.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_live_supervisor.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_live_worker_integration.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_plot.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_presentation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_read_scope.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_snapshot.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_source_identifiers.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_wal_contention.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_work_coordinator.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_trusted_work_scheduler.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/datahandling/test_wal_lineage_subprocess.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_auxiliary_database_protection.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bounded_heatmap_means.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bounded_integer_precision.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_array_bin_ranges.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_auxiliary_safety.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_average_view_updates.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_bounded_mixed_means.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_config.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_constant_auto_recovery.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_database_refresh.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_duplicate_mean_cancellation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_fill_cancellation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_float_average_performance.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_generator_fifo.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_generator_safety.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_heatmap_display_ranges.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_integer_mean_cancellation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_line_display_ranges.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_longdouble_samples.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_marquee_statistics_performance.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_measurement_generator.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_measurement_lines.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_measurement_previews.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_mixed_average_performance.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_native_averaging.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_object_scan_cancellation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_shaped_coordinate_ranges.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_snapshot_fifo.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_tiny_heatmap_bins.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_ui_cuts.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_ui_display_precision.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_bug_hunt_ui_refresh.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_ci_artifacts.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_ci_scheduling.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_compiler_free_install.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_demo_database_safety.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_derivative_numeric_ranges.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_diagnostics.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_distribution_validator.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_heatmap_cancellation_residuals.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_heatmap_float_means.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_heatmap_geometry.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_independent_heatmap_extremes.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_liveplot_database_safety.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_native_fft_mixed_coordinates.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_nonuniform_cancellation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_package_import.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_packaging_split.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_release.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_sample_statistics_accuracy.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_shutdown_supervisor.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_testdata.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_time_stress_database_safety.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_tools.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_windows_ci.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_windows_shutdown_job.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_worker_array_heatmaps.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_worker_array_measurements.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_worker_boolean_heatmap_missing.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_worker_complex_heatmaps.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_worker_complex_lines.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_worker_coordinate_precision.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_worker_heatmap_limits.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_worker_nonfinite_sql_heatmaps.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_worker_shaped_coordinate_validity.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/test_worker_sidecar_identities.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/widgets/test_operations.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/widgets/test_plot_preview_reuse.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/widgets/test_preview_database_instance.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/widgets/test_preview_dragdrop.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/widgets/test_preview_extreme_range.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/widgets/test_preview_placeholders.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/widgets/test_run_list.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/widgets/test_themes.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/_trusted_derived_wal_ui.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_appearance_swap_cuts.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_auto_plot.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_axis_auto_padding_overflow.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_axis_global_auto_validation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_axis_limit_overflow.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_axis_limit_precision.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_centering_extremes.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_color_scale_locale.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_commands.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_complex_line_data.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_config_transactions.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_csv_shared_coordinates.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_cursor_precision_preference.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_cut_cursor_integration.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_database_information.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_database_worker_errors.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_derivative_scale.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_differentiation_integration.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_export_paths.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_filtered_axis_autoscale.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_font_preferences.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_free_cursor_axis_assignment.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_heatmap_appearance.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_heatmap_color_range.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_heatmap_limit_missing_samples.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_help_menu.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_independent_cancellation_mean.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_independent_native_extremes.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_limit_integer_integration.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_live_array_dtypes.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_main_window.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_marquee_statistics_accuracy.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_merged_trace_metadata.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_mixed_plot_drops.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_native_average_cancellation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_native_averaging.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_native_boolean_derivatives.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_native_fft_coordinates.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_native_fft_dynamic_range.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_native_fft_float_precision.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_native_fft_integer_precision.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_native_float_transforms.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_native_integer_transforms.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_native_transform_labels.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_native_transform_snapping.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_nonuniform_gradient_overflow.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_numeric_sample_preservation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_numerical_stability.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_offset_precision_regressions.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_pending_preview_drop.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_planned_integer_array_extent.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot1d.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot1d_snap_precision.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot2d.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot_actions.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot_csv_precision.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot_dialog_lifecycle.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot_integration.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot_overlay_integration.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot_progress_ui.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot_sidecar_binding.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_plot_window.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_preferences_lifecycle.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_preferences_value_preservation.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_preview_drop_axes.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_refresh_interval_precision.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_run_csv_export_race.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_run_csv_mixed_integer_precision.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_run_duration_wal.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_settings_decoder_limits.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_svg_export_integration.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_testdata_gui.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_tiny_tick_labels.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_trusted_derived_live_counts.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_trusted_derived_qt.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_trusted_derived_wal_grid_ui.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_trusted_derived_wal_snapshot_ui.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_trusted_derived_wal_tiers_ui.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_trusted_derived_wal_ui.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_trusted_live_ui.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_trusted_plot_launch.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_unloaded_database_export.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_variable_array_records.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_visual_smoke.py +0 -0
- {qplotter-1.6.1 → qplotter-1.6.2}/tests/windows/test_window_controls.py +0 -0
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
All notable user-facing changes are recorded here.
|
|
4
4
|
|
|
5
|
+
## 1.6.2 — Unreleased
|
|
6
|
+
|
|
7
|
+
This bugfix release improves measurement correctness, live viewing and plot
|
|
8
|
+
lifecycle reliability. The native dependency remains `qplotter-native==1.0.1`.
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Load inferred QCoDeS parameters and missing ancillary array cells, preserving
|
|
13
|
+
recorded samples across previews, plotting, incremental refresh and raw CSV.
|
|
14
|
+
- Handle singleton and empty array acquisitions consistently, including planned
|
|
15
|
+
scan shapes, and check expanded memory requirements before allocating them.
|
|
16
|
+
- Preserve extended floating-point and integer precision in derivatives, FFTs,
|
|
17
|
+
clipping, centering, statistics, heatmaps, previews and CSV exports.
|
|
18
|
+
Honor finite clipping bounds on float16/float32 measurement arrays.
|
|
19
|
+
- Preserve axis meaning and source ownership during mixed-plot promotion,
|
|
20
|
+
cut refresh and drag-and-drop; refresh retained sources while paused and
|
|
21
|
+
cancel pending work when its target window closes.
|
|
22
|
+
- Avoid Qt callback errors when reassigning axes on a clipped trace, and clear
|
|
23
|
+
obsolete omission warnings when live metadata becomes available again.
|
|
24
|
+
- Honor accepted reader cancellation and delayed helper cancellation without
|
|
25
|
+
publishing stale results or unnecessarily retiring healthy readers.
|
|
26
|
+
- Refresh live-reader schema descriptions when QCoDeS adds metadata, so newly
|
|
27
|
+
acquired runs expose their current columns without missing data or query errors.
|
|
28
|
+
- Protect measurement files from diagnostic-log reuse and synthetic generation
|
|
29
|
+
side effects; report malformed generator inputs and profiling failures cleanly.
|
|
30
|
+
Retire benchmark plot windows before Qt application teardown.
|
|
31
|
+
- Allow qPlot to start when the diagnostic log path contains a symlink loop.
|
|
32
|
+
|
|
33
|
+
### Compatibility and validation
|
|
34
|
+
|
|
35
|
+
- Standard QCoDeS main-database storage remains supported. Runs using the
|
|
36
|
+
optional separate-per-dataset storage backend are refused before opening
|
|
37
|
+
their measurement files, since safe multi-file live viewing is not implemented.
|
|
38
|
+
- Main databases, WAL files and rollback journals remain physically read-only.
|
|
39
|
+
Only the pinned native reader may modify the exact colocated SHM file.
|
|
40
|
+
- Add regression coverage and independently reviewed fixes documented in
|
|
41
|
+
`BUG_HUNT.md`. No legacy settings migrations are introduced. This draft does
|
|
42
|
+
not publish a release.
|
|
43
|
+
|
|
5
44
|
## 1.6.1
|
|
6
45
|
|
|
7
46
|
This patch release improves live acquisition viewing and release validation.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qplotter
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.2
|
|
4
4
|
Summary: PyQt-based viewer for completed and running QCoDeS database experiments
|
|
5
5
|
Author-email: Ben Wordsworth <b.wordsworth@lancaster.ac.uk>, Edward Laird <e.a.laird@lancaster.ac.uk>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -84,6 +84,11 @@ selected run's plain detail view without copying the database. Main-database,
|
|
|
84
84
|
WAL, and rollback-journal handles remain read-only; SQLite may update only the
|
|
85
85
|
exact colocated `-shm` file as transient WAL coordination state.
|
|
86
86
|
|
|
87
|
+
Measurement viewing supports QCoDeS's standard `sqlite_main_db` storage backend.
|
|
88
|
+
Runs using the optional `sqlite_per_dataset_db` backend can appear in the run
|
|
89
|
+
list, but their measurement actions are refused before opening the separate
|
|
90
|
+
raw-data files. Safe multi-file live viewing is not yet implemented.
|
|
91
|
+
|
|
87
92
|
Normal `qplot`, `python -m qplot`, and `qplot.run()` launches put the complete
|
|
88
93
|
qPlot process tree behind a shutdown boundary before Qt or reader helpers can
|
|
89
94
|
start. The command-line process is the launcher. A public `qplot.run()` call
|
|
@@ -152,7 +157,7 @@ source builds, and release validation.
|
|
|
152
157
|
## Install
|
|
153
158
|
|
|
154
159
|
Install qPlot inside a supported Python virtual environment. This checkout
|
|
155
|
-
prepares the stable application release `1.6.
|
|
160
|
+
prepares the stable application release `1.6.2`, with native `1.0.1`.
|
|
156
161
|
The installation examples below work after publication; until then, use
|
|
157
162
|
validated local artifacts as described in [Distribution](docs/distribution.md).
|
|
158
163
|
|
|
@@ -183,9 +188,9 @@ For ordinary installation after a stable PyPI release is available:
|
|
|
183
188
|
python -m pip install --only-binary=:all: qplotter
|
|
184
189
|
```
|
|
185
190
|
|
|
186
|
-
To select version 1.6.
|
|
191
|
+
To select version 1.6.2 explicitly after publication:
|
|
187
192
|
```console
|
|
188
|
-
python -m pip install --only-binary=:all: qplotter==1.6.
|
|
193
|
+
python -m pip install --only-binary=:all: qplotter==1.6.2
|
|
189
194
|
```
|
|
190
195
|
|
|
191
196
|
Both commands install the full runtime dependency set as wheels, with no C
|
|
@@ -207,7 +212,7 @@ installing the new packages:
|
|
|
207
212
|
|
|
208
213
|
```console
|
|
209
214
|
python -m pip uninstall -y qplot qcodes-plotter qcodes-plotter-native qplotter qplotter-native
|
|
210
|
-
python -m pip install --only-binary=:all: qplotter==1.6.
|
|
215
|
+
python -m pip install --only-binary=:all: qplotter==1.6.2
|
|
211
216
|
python -m pip check
|
|
212
217
|
```
|
|
213
218
|
|
|
@@ -39,6 +39,11 @@ selected run's plain detail view without copying the database. Main-database,
|
|
|
39
39
|
WAL, and rollback-journal handles remain read-only; SQLite may update only the
|
|
40
40
|
exact colocated `-shm` file as transient WAL coordination state.
|
|
41
41
|
|
|
42
|
+
Measurement viewing supports QCoDeS's standard `sqlite_main_db` storage backend.
|
|
43
|
+
Runs using the optional `sqlite_per_dataset_db` backend can appear in the run
|
|
44
|
+
list, but their measurement actions are refused before opening the separate
|
|
45
|
+
raw-data files. Safe multi-file live viewing is not yet implemented.
|
|
46
|
+
|
|
42
47
|
Normal `qplot`, `python -m qplot`, and `qplot.run()` launches put the complete
|
|
43
48
|
qPlot process tree behind a shutdown boundary before Qt or reader helpers can
|
|
44
49
|
start. The command-line process is the launcher. A public `qplot.run()` call
|
|
@@ -107,7 +112,7 @@ source builds, and release validation.
|
|
|
107
112
|
## Install
|
|
108
113
|
|
|
109
114
|
Install qPlot inside a supported Python virtual environment. This checkout
|
|
110
|
-
prepares the stable application release `1.6.
|
|
115
|
+
prepares the stable application release `1.6.2`, with native `1.0.1`.
|
|
111
116
|
The installation examples below work after publication; until then, use
|
|
112
117
|
validated local artifacts as described in [Distribution](docs/distribution.md).
|
|
113
118
|
|
|
@@ -138,9 +143,9 @@ For ordinary installation after a stable PyPI release is available:
|
|
|
138
143
|
python -m pip install --only-binary=:all: qplotter
|
|
139
144
|
```
|
|
140
145
|
|
|
141
|
-
To select version 1.6.
|
|
146
|
+
To select version 1.6.2 explicitly after publication:
|
|
142
147
|
```console
|
|
143
|
-
python -m pip install --only-binary=:all: qplotter==1.6.
|
|
148
|
+
python -m pip install --only-binary=:all: qplotter==1.6.2
|
|
144
149
|
```
|
|
145
150
|
|
|
146
151
|
Both commands install the full runtime dependency set as wheels, with no C
|
|
@@ -162,7 +167,7 @@ installing the new packages:
|
|
|
162
167
|
|
|
163
168
|
```console
|
|
164
169
|
python -m pip uninstall -y qplot qcodes-plotter qcodes-plotter-native qplotter qplotter-native
|
|
165
|
-
python -m pip install --only-binary=:all: qplotter==1.6.
|
|
170
|
+
python -m pip install --only-binary=:all: qplotter==1.6.2
|
|
166
171
|
python -m pip check
|
|
167
172
|
```
|
|
168
173
|
|
|
@@ -65,6 +65,13 @@ database and each run, including elapsed times and whether generation completed,
|
|
|
65
65
|
was cancelled, or failed. These appear alongside QCoDeS's existing
|
|
66
66
|
`Starting experimental run with id:` messages.
|
|
67
67
|
|
|
68
|
+
Generation requires QCoDeS's `dataset.raw_data_backend` to be `sqlite_main_db`,
|
|
69
|
+
`dataset.export_automatic` to be false, and
|
|
70
|
+
`subscription.default_subscribers` to be empty. Other settings are rejected
|
|
71
|
+
before creating files because they can write outside the selected output.
|
|
72
|
+
qPlot leaves these global settings unchanged and uses an empty private station
|
|
73
|
+
so synthetic measurements do not read parameters from an acquisition station.
|
|
74
|
+
|
|
68
75
|
Every nonblank CSV row creates one run, named `run_1`, `run_2`, and so on. A 1D
|
|
69
76
|
row sweeps `V_SD`; a 2D row sweeps both `V_SD` and `V_G`. Each measured signal
|
|
70
77
|
is the sum of two sinusoids with independently randomised amplitudes,
|
|
@@ -29,15 +29,15 @@ virtual environment with:
|
|
|
29
29
|
python -m pip install --only-binary=:all: qplotter
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
The current development target is the stable application release `1.6.
|
|
32
|
+
The current development target is the stable application release `1.6.2`,
|
|
33
33
|
with exact native dependency `1.0.1`. Existing candidate tags do not establish
|
|
34
34
|
that publication succeeded. Preparing a PR does not publish either package.
|
|
35
35
|
|
|
36
|
-
The prepared stable application release is `1.6.
|
|
36
|
+
The prepared stable application release is `1.6.2`, with exact native
|
|
37
37
|
dependency `1.0.1`. Once published, install that release explicitly:
|
|
38
38
|
|
|
39
39
|
```console
|
|
40
|
-
python -m pip install --only-binary=:all: qplotter==1.6.
|
|
40
|
+
python -m pip install --only-binary=:all: qplotter==1.6.2
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
The earlier `native-and-app/v1.6.0b2` candidate did not pass its complete hosted
|
|
@@ -59,7 +59,7 @@ wheel paths from this revision's validated artifacts together. For example,
|
|
|
59
59
|
on Windows x64 (replace the application version when appropriate):
|
|
60
60
|
|
|
61
61
|
```console
|
|
62
|
-
python -m pip install --only-binary=:all: dist/qplotter_native-1.0.1-cp311-abi3-win_amd64.whl dist/qplotter-1.6.
|
|
62
|
+
python -m pip install --only-binary=:all: dist/qplotter_native-1.0.1-cp311-abi3-win_amd64.whl dist/qplotter-1.6.2-py3-none-any.whl
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
Use your platform's native filename on macOS/Linux. Never mix artifacts from
|
|
@@ -91,7 +91,7 @@ application names before installing the replacement:
|
|
|
91
91
|
|
|
92
92
|
```console
|
|
93
93
|
python -m pip uninstall -y qplot qcodes-plotter qcodes-plotter-native qplotter qplotter-native
|
|
94
|
-
python -m pip install --only-binary=:all: qplotter==1.6.
|
|
94
|
+
python -m pip install --only-binary=:all: qplotter==1.6.2
|
|
95
95
|
python -m pip check
|
|
96
96
|
python -c "from importlib.metadata import packages_distributions; p = packages_distributions(); assert set(p['qplot']) == {'qplotter'}; assert set(p['qplot_native']) == {'qplotter-native'}"
|
|
97
97
|
```
|
|
@@ -399,8 +399,8 @@ application version from `pyproject.toml`:
|
|
|
399
399
|
|
|
400
400
|
| Tag | Native handling | PyPI uploads |
|
|
401
401
|
| --- | --- | --- |
|
|
402
|
-
| `native-and-app/v1.6.
|
|
403
|
-
| `v1.6.
|
|
402
|
+
| `native-and-app/v1.6.2` | Build/validate native `1.0.1` at this revision, if unpublished | Native wheels first, then application wheel/sdist |
|
|
403
|
+
| `v1.6.2` | Fetch/validate the application's exact published native pin | Application wheel/sdist only |
|
|
404
404
|
|
|
405
405
|
The workflow calls the entire CI workflow at the tagged revision. Failure of
|
|
406
406
|
any build, static check, source-distribution suite, database-protection suite,
|
|
@@ -432,7 +432,7 @@ After application publication and byte verification, `public-installations`
|
|
|
432
432
|
runs on all four platforms and every advertised CPython version (3.11–3.14).
|
|
433
433
|
Each entry creates two fresh environments outside the original checkout.
|
|
434
434
|
The ordinary path runs `python -m pip install --only-binary=:all:
|
|
435
|
-
qplotter==1.6.
|
|
435
|
+
qplotter==1.6.2` against the public PyPI index with all runtime dependencies.
|
|
436
436
|
The editable path fetches the exact tested commit into a fresh checkout and
|
|
437
437
|
installs `.[dev]` with `qplotter-native==1.0.1` resolved from public PyPI.
|
|
438
438
|
Neither path installs a local release wheel; the validated artifacts are only
|
|
@@ -491,13 +491,14 @@ and [pending-publisher instructions](https://docs.pypi.org/trusted-publishers/cr
|
|
|
491
491
|
release version before tagging; never move a published tag. If migrating
|
|
492
492
|
from token publishing, revoke/remove the old upload tokens/secrets.
|
|
493
493
|
|
|
494
|
-
###
|
|
494
|
+
### Application 1.6.2 release commands
|
|
495
495
|
|
|
496
|
-
Version 1.6.
|
|
497
|
-
the
|
|
496
|
+
Version 1.6.2 contains Python-only changes and retains the published native
|
|
497
|
+
1.0.1 dependency. Use the application-only tag below; published native files
|
|
498
|
+
remain unchanged.
|
|
498
499
|
|
|
499
500
|
Complete the account setup and merge the reviewed packaging/release changes
|
|
500
|
-
to `main`. With application `1.6.
|
|
501
|
+
to `main`. With application `1.6.2` and native `1.0.1`, use the configured
|
|
501
502
|
Git remote/credentials:
|
|
502
503
|
|
|
503
504
|
```console
|
|
@@ -505,22 +506,22 @@ git fetch origin
|
|
|
505
506
|
git switch main
|
|
506
507
|
git pull --ff-only origin main
|
|
507
508
|
python scripts/validate_distribution.py --check-clean
|
|
508
|
-
git tag -a
|
|
509
|
-
git push origin refs/tags/
|
|
509
|
+
git tag -a v1.6.2 -m "qPlot 1.6.2"
|
|
510
|
+
git push origin refs/tags/v1.6.2
|
|
510
511
|
```
|
|
511
512
|
|
|
512
513
|
Use the activated project venv for Python; on macOS set
|
|
513
514
|
`MPLCONFIGDIR=/private/tmp/qplot-matplotlib-cache` for Python commands that may
|
|
514
515
|
import Matplotlib. The tag push is the publication trigger. Review its hosted
|
|
515
|
-
CI results
|
|
516
|
-
|
|
516
|
+
CI results and confirm verification of the published native dependency
|
|
517
|
+
succeeds before approving `pypi-application`. No native publication is needed. The final PyPI
|
|
517
518
|
verification and all `public-installations` jobs must succeed before announcing the release. No GitHub Release
|
|
518
519
|
object is needed to trigger publication; use the connected GitHub app for any
|
|
519
520
|
subsequent release/PR operations if supported, never `gh`.
|
|
520
521
|
|
|
521
522
|
### Later Python-only releases
|
|
522
523
|
|
|
523
|
-
Update the application version (for example to `1.6.
|
|
524
|
+
Update the application version (for example to `1.6.3`) and changelog, keep
|
|
524
525
|
the exact native/APSW pins when still compatible, and merge the changes. Do
|
|
525
526
|
not change native sources/ABI under an existing native version. Then:
|
|
526
527
|
|
|
@@ -529,8 +530,8 @@ git fetch origin
|
|
|
529
530
|
git switch main
|
|
530
531
|
git pull --ff-only origin main
|
|
531
532
|
python scripts/validate_distribution.py --check-clean
|
|
532
|
-
git tag -a v1.6.
|
|
533
|
-
git push origin refs/tags/v1.6.
|
|
533
|
+
git tag -a v1.6.3 -m "qPlot 1.6.3"
|
|
534
|
+
git push origin refs/tags/v1.6.3
|
|
534
535
|
```
|
|
535
536
|
|
|
536
537
|
The native release must already contain all four non-yanked compatible wheels.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "qplotter"
|
|
7
|
-
version = "1.6.
|
|
7
|
+
version = "1.6.2"
|
|
8
8
|
description = "PyQt-based viewer for completed and running QCoDeS database experiments"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{name="Ben Wordsworth", email="b.wordsworth@lancaster.ac.uk"},{name="Edward Laird", email="e.a.laird@lancaster.ac.uk"}]
|
|
@@ -27,7 +27,7 @@ def main():
|
|
|
27
27
|
parser.add_argument("--preceding-stage", choices=("any", "aggregate", "large-summary"), default="any")
|
|
28
28
|
args = parser.parse_args()
|
|
29
29
|
|
|
30
|
-
from PyQt6 import QtCore, QtWidgets
|
|
30
|
+
from PyQt6 import QtCore, QtWidgets, sip
|
|
31
31
|
|
|
32
32
|
from qplot.configuration.config import config
|
|
33
33
|
from qplot.datahandling import readonly, trusted_heatmap, trusted_plot
|
|
@@ -36,6 +36,7 @@ def main():
|
|
|
36
36
|
_BrokerQueryExecutor,
|
|
37
37
|
)
|
|
38
38
|
from qplot.windows._plot_feedback import PlotWindowFeedbackMixin
|
|
39
|
+
from qplot.windows._plotWin import plotWidget
|
|
39
40
|
from qplot.windows.main import MainWindow
|
|
40
41
|
|
|
41
42
|
def source_state():
|
|
@@ -143,7 +144,7 @@ def main():
|
|
|
143
144
|
config.default_file = str(Path(directory) / config.config_file_name)
|
|
144
145
|
window = MainWindow()
|
|
145
146
|
window.show_error = lambda *items: errors.append(items)
|
|
146
|
-
observer = PaintTimes()
|
|
147
|
+
observer = PaintTimes(window)
|
|
147
148
|
try:
|
|
148
149
|
window.startupDatabaseTimer.stop()
|
|
149
150
|
window.config.config["user_preference"]["confirm_close"] = False
|
|
@@ -208,7 +209,9 @@ def main():
|
|
|
208
209
|
"iteration": iteration + 1,
|
|
209
210
|
"display_ms": (time.perf_counter() - started) * 1000,
|
|
210
211
|
"paint_ms": [(value - started) * 1000 for value in painted.values()],
|
|
211
|
-
"grids": [list(plot.dataGrid.shape) for plot in plots],
|
|
212
|
+
"grids": [list(plot.dataGrid.shape) for plot in plots if hasattr(plot, "dataGrid")],
|
|
213
|
+
"line_samples": [int(plot.axis_data["y"].size) for plot in plots
|
|
214
|
+
if not hasattr(plot, "dataGrid")],
|
|
212
215
|
"capture": list(timings),
|
|
213
216
|
"broker_queries": [{"run_id": run, "phase": phase, **record}
|
|
214
217
|
for (run, phase), record in list(phase_times.items())],
|
|
@@ -220,13 +223,23 @@ def main():
|
|
|
220
223
|
window.close_plot_windows(confirm=False, status=False)
|
|
221
224
|
wait_for(lambda: not window._plot_workers)
|
|
222
225
|
finally:
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
window.
|
|
226
|
-
window.
|
|
227
|
-
window.
|
|
228
|
-
|
|
229
|
-
|
|
226
|
+
# Use the application's bounded shutdown for every worker pool,
|
|
227
|
+
# preview and broker, including a failed measurement iteration.
|
|
228
|
+
window.close()
|
|
229
|
+
wait_for(lambda: window._shutdown_ready, timeout=20, check_errors=False)
|
|
230
|
+
if window._shutdown_background_work_active():
|
|
231
|
+
raise RuntimeError("Plot benchmark background work did not stop")
|
|
232
|
+
# Closed plots are still top-level widgets held by iteration
|
|
233
|
+
# locals and the paint records. Retire their native ownership
|
|
234
|
+
# before QApplication's unordered sweep of Python Qt wrappers.
|
|
235
|
+
# Leave child menus and embedded widgets to their Qt owners.
|
|
236
|
+
for widget in app.topLevelWidgets():
|
|
237
|
+
if isinstance(widget, plotWidget) and not sip.isdeleted(widget):
|
|
238
|
+
sip.delete(widget)
|
|
239
|
+
window.deleteLater()
|
|
240
|
+
app.sendPostedEvents(None, QtCore.QEvent.Type.DeferredDelete)
|
|
241
|
+
app.processEvents()
|
|
242
|
+
sip.delete(app)
|
|
230
243
|
after = source_state()
|
|
231
244
|
print(json.dumps({"database_bytes": args.database.stat().st_size,
|
|
232
245
|
"database_open_ms": open_ms, "run_id": args.run_id,
|
|
@@ -6,6 +6,8 @@ import json
|
|
|
6
6
|
import time
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
|
|
9
|
+
from qcodes.dataset.descriptions.versioning.serialization import from_json_to_current
|
|
10
|
+
|
|
9
11
|
from qplot.datahandling.trusted_live import TrustedLiveReader
|
|
10
12
|
from qplot.datahandling.trusted_plot import identifier
|
|
11
13
|
|
|
@@ -38,12 +40,19 @@ def main():
|
|
|
38
40
|
results = []
|
|
39
41
|
reader_type = FullPathReader if args.full_path_checks else TrustedLiveReader
|
|
40
42
|
with reader_type.open(args.database) as reader:
|
|
41
|
-
table, = reader.query(
|
|
42
|
-
|
|
43
|
+
table, description = reader.query(
|
|
44
|
+
"SELECT result_table_name, run_description FROM runs WHERE run_id=?",
|
|
45
|
+
(args.run_id,),
|
|
46
|
+
).rows[0]
|
|
43
47
|
table = identifier(table)
|
|
44
48
|
columns = reader.query(f"SELECT * FROM {table} WHERE 0").columns
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
types = {spec.name: spec.type for spec in from_json_to_current(description).interdeps.paramspecs}
|
|
50
|
+
numeric_parameters = [name for name in columns if types.get(name) == "numeric"]
|
|
51
|
+
if not numeric_parameters:
|
|
52
|
+
parser.error(f"Run {args.run_id} has no scalar numeric parameters to profile")
|
|
53
|
+
numeric = [identifier(name) for name in numeric_parameters]
|
|
54
|
+
# Array/complex/text values are outside this numeric profiler's scope.
|
|
55
|
+
# Read declared numeric fields, with only a small aggregate crossing the
|
|
47
56
|
# helper boundary. Match the plot's finite primary-key intervals.
|
|
48
57
|
expressions = ", ".join(f"MIN({name}), MAX({name})" for name in numeric)
|
|
49
58
|
for repeat in range(args.repeats):
|
|
@@ -69,6 +78,7 @@ def main():
|
|
|
69
78
|
if before != after:
|
|
70
79
|
raise AssertionError("Protected source file sizes/timestamps changed")
|
|
71
80
|
print(json.dumps({"run_id": args.run_id, "pages": args.pages, "results": results,
|
|
81
|
+
"numeric_parameters": numeric_parameters,
|
|
72
82
|
"full_path_checks": args.full_path_checks,
|
|
73
83
|
"protected_file_stats_unchanged": True}, indent=2))
|
|
74
84
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version": "1.6.2", "commit": "4a0baf68be2b005e25ba802d2fc166a4da38d418", "dirty": false, "released": true}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import re
|
|
3
3
|
import subprocess
|
|
4
|
+
import time
|
|
4
5
|
import tomllib
|
|
5
6
|
from importlib.metadata import PackageNotFoundError, distribution, version
|
|
6
7
|
from pathlib import Path
|
|
@@ -17,11 +18,14 @@ def package_version():
|
|
|
17
18
|
return "0+unknown"
|
|
18
19
|
|
|
19
20
|
|
|
20
|
-
def _git(root: Path, *arguments: str) -> str:
|
|
21
|
+
def _git(root: Path, *arguments: str, deadline: float) -> str:
|
|
21
22
|
"""Read bounded local Git metadata without refreshing the index."""
|
|
23
|
+
timeout = deadline - time.monotonic()
|
|
24
|
+
if timeout <= 0:
|
|
25
|
+
raise subprocess.TimeoutExpired("git", timeout=0)
|
|
22
26
|
return subprocess.run(
|
|
23
27
|
["git", "--no-optional-locks", "-C", str(root), *arguments],
|
|
24
|
-
capture_output=True, text=True, check=True, timeout=
|
|
28
|
+
capture_output=True, text=True, check=True, timeout=timeout,
|
|
25
29
|
).stdout.strip()
|
|
26
30
|
|
|
27
31
|
|
|
@@ -35,9 +39,14 @@ def checkout_info(root: Path) -> dict:
|
|
|
35
39
|
if project["name"] != "qplotter":
|
|
36
40
|
return {}
|
|
37
41
|
info = {"version": project["version"], "checkout": True}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
# Cold Git startup can exceed one second on Windows. Share one budget
|
|
43
|
+
# across all three reads so startup and About remain bounded.
|
|
44
|
+
deadline = time.monotonic() + 5
|
|
45
|
+
commit = _git(root, "rev-parse", "HEAD", deadline=deadline)
|
|
46
|
+
dirty = bool(_git(
|
|
47
|
+
root, "status", "--porcelain", "--untracked-files=normal", deadline=deadline,
|
|
48
|
+
))
|
|
49
|
+
tags = _git(root, "tag", "--points-at", "HEAD", deadline=deadline).splitlines()
|
|
41
50
|
release_tags = {f"v{project['version']}", f"native-and-app/v{project['version']}"}
|
|
42
51
|
info.update(commit=commit, dirty=dirty, released=bool(release_tags.intersection(tags)) and not dirty)
|
|
43
52
|
return info
|
|
@@ -106,6 +106,11 @@
|
|
|
106
106
|
"user_preference": {
|
|
107
107
|
"type": "object",
|
|
108
108
|
"properties": {
|
|
109
|
+
"csv_filename_format": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"enum": ["current", "qcodes"],
|
|
112
|
+
"default": "current"
|
|
113
|
+
},
|
|
109
114
|
"show_source_annotation": {
|
|
110
115
|
"type": "boolean",
|
|
111
116
|
"default": true
|
|
@@ -132,7 +137,7 @@
|
|
|
132
137
|
"type": "integer",
|
|
133
138
|
"minimum": 1,
|
|
134
139
|
"maximum": 10,
|
|
135
|
-
"default":
|
|
140
|
+
"default": 3
|
|
136
141
|
},
|
|
137
142
|
"theme":{
|
|
138
143
|
"type": "string",
|
|
@@ -302,6 +307,7 @@
|
|
|
302
307
|
"confirm_incompatible_axes",
|
|
303
308
|
"mouse_mode",
|
|
304
309
|
"copy_plot_image_resolution",
|
|
310
|
+
"csv_filename_format",
|
|
305
311
|
"auto_plot",
|
|
306
312
|
"default_refresh_rate"
|
|
307
313
|
],
|
|
@@ -68,6 +68,14 @@ def append_shaped_parameter_data_to_existing_arrays(
|
|
|
68
68
|
|
|
69
69
|
new_data_1_tree = new_data.get(meas_parameter, {})
|
|
70
70
|
|
|
71
|
+
if new_data_1_tree and not new_data_1_tree[meas_parameter].size:
|
|
72
|
+
# QCoDeS skips an empty column independently when merging unshaped
|
|
73
|
+
# caches. Empty array outputs can retain singleton setpoints, which
|
|
74
|
+
# would then be appended without their measurement and misalign the
|
|
75
|
+
# next refresh. Validate those records and retain zero samples in
|
|
76
|
+
# every field; the separate read status still counts acquired rows.
|
|
77
|
+
new_data_1_tree = flatten_record_columns(new_data_1_tree, check_cancelled)
|
|
78
|
+
|
|
71
79
|
shapes = rundescriber.shapes
|
|
72
80
|
if shapes is not None:
|
|
73
81
|
shape = shapes.get(meas_parameter, None)
|
|
@@ -82,7 +90,8 @@ def append_shaped_parameter_data_to_existing_arrays(
|
|
|
82
90
|
# Object cells count records; shaped cache offsets count samples.
|
|
83
91
|
# Flatten only the new records so QCoDeS' usual padding and offsets
|
|
84
92
|
# still apply, including the same missing-value handling.
|
|
85
|
-
if any(values.dtype.kind == "O" for values in new_data_1_tree.values())
|
|
93
|
+
if (any(values.dtype.kind == "O" for values in new_data_1_tree.values())
|
|
94
|
+
or len({values.shape for values in new_data_1_tree.values()}) > 1):
|
|
86
95
|
new_data_1_tree = flatten_record_columns(new_data_1_tree, check_cancelled)
|
|
87
96
|
private_data = {}
|
|
88
97
|
for name, values in existing_data_1_tree.items():
|
|
@@ -191,6 +200,7 @@ def load_param_data_from_db(
|
|
|
191
200
|
end: int | None = None,
|
|
192
201
|
*,
|
|
193
202
|
check_cancelled=_check_noop,
|
|
203
|
+
max_decode_bytes=None,
|
|
194
204
|
):
|
|
195
205
|
# Data fetch
|
|
196
206
|
updated_read_status: dict[str, int] = dict(read_status)
|
|
@@ -205,6 +215,9 @@ def load_param_data_from_db(
|
|
|
205
215
|
start=start,
|
|
206
216
|
end=end,
|
|
207
217
|
check_cancelled=check_cancelled,
|
|
218
|
+
max_decode_bytes=max_decode_bytes,
|
|
219
|
+
existing_data=existing_data.get(meas_parameter, {}),
|
|
220
|
+
written_count=write_status.get(meas_parameter),
|
|
208
221
|
)
|
|
209
222
|
new_data_dict[meas_parameter] = new_data
|
|
210
223
|
updated_read_status[meas_parameter] = start + n_rows_read - 1
|
|
@@ -193,15 +193,19 @@ def _control_loop(control_receive: Connection, state: _ChildControlState) -> Non
|
|
|
193
193
|
_interrupt_active_locked(state)
|
|
194
194
|
continue
|
|
195
195
|
if (
|
|
196
|
-
state.last_completed_generation
|
|
196
|
+
state.last_completed_generation is not None
|
|
197
|
+
and envelope.generation <= state.last_completed_generation
|
|
197
198
|
and cancellation_is_new
|
|
198
199
|
):
|
|
199
200
|
# The operation may finish after the parent decides to
|
|
200
201
|
# cancel but before this control thread receives that
|
|
201
202
|
# exact-generation frame. It may even arrive after the
|
|
202
|
-
# following
|
|
203
|
-
# use separate pipes.
|
|
204
|
-
#
|
|
203
|
+
# following operations finish because commands and control
|
|
204
|
+
# use separate pipes. Commands are contiguous, and the
|
|
205
|
+
# cancellation high watermark starts at this incarnation's
|
|
206
|
+
# first generation minus one. Thus this is a completed job
|
|
207
|
+
# owned by this helper. Accept it once as a no-op; never
|
|
208
|
+
# interrupt a newer generation.
|
|
205
209
|
state.last_cancelled_generation = envelope.generation
|
|
206
210
|
continue
|
|
207
211
|
if (
|
|
@@ -434,6 +438,7 @@ def trusted_live_helper_main(
|
|
|
434
438
|
session,
|
|
435
439
|
orphan_grace_ms / 1_000.0,
|
|
436
440
|
first_generation,
|
|
441
|
+
last_cancelled_generation=first_generation - 1,
|
|
437
442
|
)
|
|
438
443
|
reader: TrustedLiveReader | None = None
|
|
439
444
|
control_thread = threading.Thread(
|