Browse Source

Create a cross-product output of multi-run data

When multi multi-run data are created, the plot output should reflect
the available data combinatorics.  This also adds an advanced config
flag limiting the total number of allowed plot lines.  The advanced
config flag might be moved to a use config at some point or changed to a
time limit

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21871
master
Seth Hillbrand 2 weeks ago
parent
commit
24b3e26db6
  1. 7
      common/advanced_config.cpp
  2. 123
      eeschema/sim/simulator_frame_ui.cpp
  3. 13
      eeschema/sim/simulator_frame_ui.h
  4. 9
      include/advanced_config.h

7
common/advanced_config.cpp

@ -132,6 +132,7 @@ static const wxChar MaximumThreads[] = wxT( "MaximumThreads" );
static const wxChar NetInspectorBulkUpdateOptimisationThreshold[] =
wxT( "NetInspectorBulkUpdateOptimisationThreshold" );
static const wxChar ExcludeFromSimulationLineWidth[] = wxT( "ExcludeFromSimulationLineWidth" );
static const wxChar SimulatorMultiRunCombinationLimit[] = wxT( "SimulatorMultiRunCombinationLimit" );
static const wxChar GitIconRefreshInterval[] = wxT( "GitIconRefreshInterval" );
static const wxChar ConfigurableToolbars[] = wxT( "ConfigurableToolbars" );
static const wxChar MaxPastedTextLength[] = wxT( "MaxPastedTextLength" );
@ -323,6 +324,7 @@ ADVANCED_CFG::ADVANCED_CFG()
m_NetInspectorBulkUpdateOptimisationThreshold = 100;
m_ExcludeFromSimulationLineWidth = 25;
m_SimulatorMultiRunCombinationLimit = 12;
m_GitIconRefreshInterval = 10000;
@ -652,6 +654,11 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
&m_ExcludeFromSimulationLineWidth,
m_ExcludeFromSimulationLineWidth, 1, 100 ) );
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true,
AC_KEYS::SimulatorMultiRunCombinationLimit,
&m_SimulatorMultiRunCombinationLimit,
m_SimulatorMultiRunCombinationLimit, 1, 100 ) );
m_entries.push_back( std::make_unique<PARAM_CFG_INT>( true, AC_KEYS::GitIconRefreshInterval,
&m_GitIconRefreshInterval,
m_GitIconRefreshInterval, 0, 100000 ) );

123
eeschema/sim/simulator_frame_ui.cpp

@ -54,6 +54,7 @@
#include <dialogs/dialog_text_entry.h>
#include <dialogs/dialog_sim_format_value.h>
#include <eeschema_settings.h>
#include <advanced_config.h>
#include <magic_enum.hpp>
@ -1723,7 +1724,8 @@ void SIMULATOR_FRAME_UI::RemoveTuner( TUNER_SLIDER* aTuner )
{
m_tuners.remove( aTuner );
if( m_multiRunState.tuner == aTuner )
if( std::find( m_multiRunState.tuners.begin(), m_multiRunState.tuners.end(), aTuner )
!= m_multiRunState.tuners.end() )
clearMultiRunState( true );
m_tunerOverrides.erase( aTuner );
@ -3294,7 +3296,7 @@ void SIMULATOR_FRAME_UI::OnSimRefresh( bool aFinal )
if( aFinal && m_multiRunState.active )
{
if( m_multiRunState.currentStep < m_multiRunState.stepValues.size() )
if( m_multiRunState.currentStep < m_multiRunState.steps.size() )
{
storeMultiRun = true;
m_multiRunState.storePending = true;
@ -3493,7 +3495,7 @@ void SIMULATOR_FRAME_UI::OnSimRefresh( bool aFinal )
if( aFinal && m_multiRunState.active )
{
if( m_multiRunState.currentStep + 1 < m_multiRunState.stepValues.size() )
if( m_multiRunState.currentStep + 1 < m_multiRunState.steps.size() )
{
m_multiRunState.currentStep++;
@ -3502,7 +3504,7 @@ void SIMULATOR_FRAME_UI::OnSimRefresh( bool aFinal )
else
{
m_multiRunState.active = false;
m_multiRunState.stepValues.clear();
m_multiRunState.steps.clear();
m_multiRunState.currentStep = 0;
m_multiRunState.storePending = false;
m_tunerOverrides.clear();
@ -3522,8 +3524,8 @@ void SIMULATOR_FRAME_UI::OnSimRefresh( bool aFinal )
void SIMULATOR_FRAME_UI::clearMultiRunState( bool aClearTraces )
{
m_multiRunState.active = false;
m_multiRunState.tuner = nullptr;
m_multiRunState.stepValues.clear();
m_multiRunState.tuners.clear();
m_multiRunState.steps.clear();
m_multiRunState.currentStep = 0;
m_multiRunState.storePending = false;
@ -3541,76 +3543,131 @@ void SIMULATOR_FRAME_UI::prepareMultiRunState()
{
m_tunerOverrides.clear();
TUNER_SLIDER* multiTuner = nullptr;
std::vector<TUNER_SLIDER*> multiTuners;
for( TUNER_SLIDER* tuner : m_tuners )
{
if( tuner->GetRunMode() == TUNER_SLIDER::RUN_MODE::MULTI )
{
multiTuner = tuner;
break;
}
multiTuners.push_back( tuner );
}
if( !multiTuner )
if( multiTuners.empty() )
{
clearMultiRunState( true );
return;
}
if( m_multiRunState.active && m_multiRunState.tuner != multiTuner )
bool tunersChanged = multiTuners != m_multiRunState.tuners;
if( m_multiRunState.active && tunersChanged )
clearMultiRunState( true );
if( !m_multiRunState.active )
{
if( m_multiRunState.tuner != multiTuner || m_multiRunState.storedSteps > 0
|| !m_multiRunState.traces.empty() )
if( tunersChanged || m_multiRunState.storedSteps > 0 || !m_multiRunState.traces.empty() )
{
clearMultiRunState( true );
}
m_multiRunState.tuner = multiTuner;
m_multiRunState.stepValues = calculateMultiRunSteps( multiTuner );
m_multiRunState.tuners = multiTuners;
m_multiRunState.steps = calculateMultiRunSteps( multiTuners );
m_multiRunState.currentStep = 0;
m_multiRunState.storePending = false;
if( m_multiRunState.stepValues.size() >= 2 )
if( m_multiRunState.steps.size() >= 2 )
{
m_multiRunState.active = true;
m_multiRunState.storedSteps = 0;
}
else
{
m_multiRunState.stepValues.clear();
m_multiRunState.steps.clear();
return;
}
}
else if( tunersChanged )
{
m_multiRunState.tuners = multiTuners;
}
if( m_multiRunState.active && m_multiRunState.currentStep < m_multiRunState.steps.size() )
{
const MULTI_RUN_STEP& step = m_multiRunState.steps[m_multiRunState.currentStep];
if( m_multiRunState.active && m_multiRunState.currentStep < m_multiRunState.stepValues.size() )
m_tunerOverrides[multiTuner] = m_multiRunState.stepValues[m_multiRunState.currentStep];
for( const auto& entry : step.overrides )
m_tunerOverrides[entry.first] = entry.second;
}
}
std::vector<double> SIMULATOR_FRAME_UI::calculateMultiRunSteps( TUNER_SLIDER* aTuner ) const
std::vector<SIMULATOR_FRAME_UI::MULTI_RUN_STEP> SIMULATOR_FRAME_UI::calculateMultiRunSteps(
const std::vector<TUNER_SLIDER*>& aTuners ) const
{
std::vector<double> steps;
std::vector<MULTI_RUN_STEP> steps;
if( !aTuner )
if( aTuners.empty() )
return steps;
double startValue = aTuner->GetMin().ToDouble();
double endValue = aTuner->GetMax().ToDouble();
int stepCount = std::max( 2, aTuner->GetStepCount() );
std::vector<std::vector<double>> tunerValues;
tunerValues.reserve( aTuners.size() );
for( TUNER_SLIDER* tuner : aTuners )
{
if( !tuner )
return steps;
double startValue = tuner->GetMin().ToDouble();
double endValue = tuner->GetMax().ToDouble();
int stepCount = std::max( 2, tuner->GetStepCount() );
if( stepCount < 2 )
stepCount = 2;
double increment = ( endValue - startValue ) / static_cast<double>( stepCount - 1 );
std::vector<double> values;
values.reserve( stepCount );
for( int ii = 0; ii < stepCount; ++ii )
values.push_back( startValue + increment * ii );
if( stepCount < 2 )
stepCount = 2;
tunerValues.push_back( std::move( values ) );
}
int limit = ADVANCED_CFG::GetCfg().m_SimulatorMultiRunCombinationLimit;
if( limit < 1 )
limit = 1;
std::vector<double> currentValues( aTuners.size(), 0.0 );
auto generate = [&]( auto&& self, size_t depth ) -> void
{
if( steps.size() >= static_cast<size_t>( limit ) )
return;
if( depth == aTuners.size() )
{
MULTI_RUN_STEP step;
for( size_t ii = 0; ii < aTuners.size(); ++ii )
step.overrides.emplace( aTuners[ii], currentValues[ii] );
steps.push_back( std::move( step ) );
return;
}
double increment = ( endValue - startValue ) / static_cast<double>( stepCount - 1 );
for( double value : tunerValues[depth] )
{
currentValues[depth] = value;
self( self, depth + 1 );
steps.reserve( stepCount );
if( steps.size() >= static_cast<size_t>( limit ) )
return;
}
};
for( int ii = 0; ii < stepCount; ++ii )
steps.push_back( startValue + increment * ii );
generate( generate, 0 );
return steps;
}

13
eeschema/sim/simulator_frame_ui.h

@ -337,9 +337,11 @@ private:
*/
SIM_TRACE_TYPE getXAxisType( SIM_TYPE aType ) const;
struct MULTI_RUN_STEP;
void clearMultiRunState( bool aClearTraces );
void prepareMultiRunState();
std::vector<double> calculateMultiRunSteps( TUNER_SLIDER* aTuner ) const;
std::vector<MULTI_RUN_STEP> calculateMultiRunSteps( const std::vector<TUNER_SLIDER*>& aTuners ) const;
std::string multiRunTraceKey( const wxString& aVectorName, int aTraceType ) const;
void recordMultiRunData( const wxString& aVectorName, int aTraceType,
const std::vector<double>& aX, const std::vector<double>& aY );
@ -395,11 +397,16 @@ private:
std::vector<std::vector<double>> yValues;
};
struct MULTI_RUN_STEP
{
std::map<const TUNER_SLIDER*, double> overrides;
};
struct MULTI_RUN_STATE
{
bool active = false;
TUNER_SLIDER* tuner = nullptr;
std::vector<double> stepValues;
std::vector<TUNER_SLIDER*> tuners;
std::vector<MULTI_RUN_STEP> steps;
size_t currentStep = 0;
size_t storedSteps = 0;
bool storePending = false;

9
include/advanced_config.h

@ -813,6 +813,15 @@ public:
*/
int m_ExcludeFromSimulationLineWidth;
/**
* Maximum number of tuner combinations simulated when using multi-run mode.
*
* Setting name: "SimulatorMultiRunCombinationLimit"
* Valid values: 1 to 100
* Default value: 12
*/
int m_SimulatorMultiRunCombinationLimit;
/**
* The interval in milliseconds to refresh the git icons in the project tree.
*

Loading…
Cancel
Save