32#include <fmt/format.h>
33#include <wx/wfstream.h>
34#include <wx/stdstream.h>
36#include <wx/clipbrd.h>
58#include <magic_enum.hpp>
63 int res =
static_cast<int>( aFirst ) |
static_cast<int>( aSecond);
124 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
override;
175 menu.AppendSeparator();
176 menu.Append(
MYID_FOURIER,
_(
"Perform Fourier Analysis..." ) );
179 menu.AppendSeparator();
182 menu.AppendSeparator();
185 m_grid->PopupMenu( &menu );
192 menu.AppendSeparator();
194 wxString msg =
m_grid->GetColLabelValue(
m_grid->GetNumberCols() - 1 );
196 menu.AppendSeparator();
199 m_grid->PopupMenu( &menu );
205 m_grid->PopupMenu( &menu );
212 std::vector<wxString> signals;
214 wxGridCellCoordsArray cells1 =
m_grid->GetSelectionBlockTopLeft();
215 wxGridCellCoordsArray cells2 =
m_grid->GetSelectionBlockBottomRight();
217 for(
size_t i = 0; i < cells1.Count(); i++ )
221 for(
int j = cells1[i].GetRow(); j < cells2[i].GetRow() + 1; j++ )
223 signals.push_back(
m_grid->GetCellValue( j, cells1[i].GetCol() ) );
228 wxGridCellCoordsArray cells3 =
m_grid->GetSelectedCells();
230 for(
size_t i = 0; i < cells3.Count(); i++ )
233 signals.push_back(
m_grid->GetCellValue( cells3[i].GetRow(), cells3[i].GetCol() ) );
236 if( signals.size() < 1 )
239 auto addMeasurement =
240 [
this](
const wxString& cmd, wxString signal )
242 if( signal.EndsWith(
_(
" (phase)" ) ) )
245 if( signal.EndsWith(
_(
" (gain)" ) ) || signal.EndsWith(
_(
" (amplitude)" ) ) )
247 signal = signal.Left( signal.length() - 7 );
249 if( signal.Upper().StartsWith( wxS(
"V(" ) ) )
250 signal = wxS(
"vdb" ) + signal.Mid( 1 );
253 m_parent->AddMeasurement( cmd + wxS(
" " ) + signal );
258 for(
const wxString& signal : signals )
259 addMeasurement( wxS(
"MIN" ), signal );
263 for(
const wxString& signal : signals )
264 addMeasurement( wxS(
"MAX" ), signal );
268 for(
const wxString& signal : signals )
269 addMeasurement( wxS(
"AVG" ), signal );
273 for(
const wxString& signal : signals )
274 addMeasurement( wxS(
"RMS" ), signal );
278 for(
const wxString& signal : signals )
279 addMeasurement( wxS(
"PP" ), signal );
283 for(
const wxString& signal : signals )
284 addMeasurement( wxS(
"MIN_AT" ), signal );
288 for(
const wxString& signal : signals )
289 addMeasurement( wxS(
"MAX_AT" ), signal );
293 for(
const wxString& signal : signals )
294 addMeasurement( wxS(
"INTEG" ), signal );
299 wxString fundamental = wxT(
"1K" );
301 if( signals.size() == 1 )
302 title.Printf(
_(
"Fourier Analysis of %s" ), signals[0] );
304 title =
_(
"Fourier Analyses of Multiple Signals" );
314 for(
const wxString& signal : signals )
315 m_parent->DoFourier( signal, fundamental );
322 for(
const wxString& signal : signals )
330 if( wxTheClipboard->Open() )
332 wxTheClipboard->SetData(
new wxTextDataObject( txt ) );
333 wxTheClipboard->Flush();
334 wxTheClipboard->Close();
359 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
override;
379 menu.AppendSeparator();
389 [
this](
int row ) -> wxString
393 if( signal.EndsWith(
"[2 - 1]" ) )
394 signal = signal.Left( signal.length() - 7 );
405 if( formatDialog.
ShowModal() == wxID_OK )
407 for(
int row = 0; row <
m_grid->GetNumberRows(); ++row )
409 if( getSignalName( row ) == getSignalName(
m_menuRow ) )
410 m_parent->SetCursorFormat( row, axis, format );
432 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
override;
458 menu.AppendSeparator();
471 if( formatDialog.
ShowModal() == wxID_OK )
480 std::vector<int> measurements;
482 wxGridCellCoordsArray cells1 =
m_grid->GetSelectionBlockTopLeft();
483 wxGridCellCoordsArray cells2 =
m_grid->GetSelectionBlockBottomRight();
485 for(
size_t i = 0; i < cells1.Count(); i++ )
489 for(
int j = cells1[i].GetRow(); j < cells2[i].GetRow() + 1; j++ )
490 measurements.push_back( j );
494 wxGridCellCoordsArray cells3 =
m_grid->GetSelectedCells();
496 for(
size_t i = 0; i < cells3.Count(); i++ )
499 measurements.push_back( cells3[i].GetRow() );
502 if( measurements.size() < 1 )
507 sort( measurements.begin(), measurements.end(), std::greater<>() );
509 for(
int row : measurements )
529 m_frame->m_SuppressGridEvents++;
534 m_frame->m_SuppressGridEvents--;
542#define ID_SIM_REFRESH 10207
543#define REFRESH_INTERVAL 50
568 wxGridCellAttr* attr =
new wxGridCellAttr;
572 attr =
new wxGridCellAttr;
576 attr =
new wxGridCellAttr;
580 attr =
new wxGridCellAttr;
586 attr =
new wxGridCellAttr;
596 [&]( wxTimerEvent& aEvent )
605#ifndef wxHAS_NATIVE_TABART
625 m_cursorFormat[0] = { 3, wxS(
"~s" ) };
626 m_cursorFormat[1] = { 3, wxS(
"~V" ) };
637 for(
size_t index2 = 0; index2 < std::size(
m_cursorFormats[0] ); index2++ )
651 maxCursor.Replace(
_(
"Cursor " ),
"" );
653 int tmpMax = wxAtoi( maxCursor );
655 if( nameMax < tmpMax )
665 std::vector<SPICE_VALUE_FORMAT> tmp;
677 wxGridCellAttr* attr =
new wxGridCellAttr;
697 for(
int i = 0; i < rows; i++ )
699 if(
m_signalsGrid->GetCellValue( i, col - 1 ) == wxS(
"1" ) )
702 wxGridEvent aDummy( wxID_ANY, wxEVT_GRID_CELL_CHANGED,
m_signalsGrid, i, col - 1 );
722 for(
int ii = 0; ii < static_cast<int>(
m_plotNotebook->GetPageCount() ); ++ii )
726 simTab->OnLanguageChanged();
728 wxString pageTitle(
simulator()->TypeToName( simTab->GetSimType(),
true ) );
729 pageTitle.Prepend( wxString::Format(
_(
"Analysis %u - " ), ii+1 ) );
750 tuner->ShowChangedLanguage();
790 simTab->ApplyPreferences( aPrefs );
797 if( !
simulator()->Settings()->GetWorkbookFilename().IsEmpty() )
809 if( !schTextSimCommand.IsEmpty() )
842 std::sort( signals.begin(), signals.end(),
843 [](
const wxString& lhs,
const wxString& rhs )
846 if( lhs.Upper().StartsWith(
'V' ) && !rhs.Upper().StartsWith(
'V' ) )
848 else if( !lhs.Upper().StartsWith(
'V' ) && rhs.Upper().StartsWith(
'V' ) )
851 return StrNumCmp( lhs, rhs, true ) < 0;
868 std::vector<wxString> signals;
872 wxStringTokenizer tokenizer( plotPanel->
GetSimCommand(),
" \t\r\n", wxTOKEN_STRTOK );
874 while( tokenizer.HasMoreTokens() && tokenizer.GetNextToken().Lower() != wxT(
"fft" ) )
877 while( tokenizer.HasMoreTokens() )
878 signals.emplace_back( tokenizer.GetNextToken() );
885 for(
const wxString& signal :
m_signals )
886 signals.push_back( signal );
890 if( simType ==
ST_AC )
892 signals.push_back( signal +
_(
" (gain)" ) );
893 signals.push_back( signal +
_(
" (phase)" ) );
895 else if( simType ==
ST_SP )
897 signals.push_back( signal +
_(
" (amplitude)" ) );
898 signals.push_back( signal +
_(
" (phase)" ) );
902 signals.push_back( signal );
909 if( aFilter.IsEmpty() )
910 aFilter = wxS(
"*" );
915 for(
const wxString& signal : signals )
917 if( matcher.
Find( signal.Upper() ) )
926 wxGridCellAttr* attr =
new wxGridCellAttr;
927 attr->SetRenderer(
new wxGridCellBoolRenderer() );
929 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
934 attr =
new wxGridCellAttr;
939 attr =
new wxGridCellAttr;
943 attr =
new wxGridCellAttr;
951 attr =
new wxGridCellAttr;
961 attr =
new wxGridCellAttr;
964 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
969 attr =
new wxGridCellAttr;
970 attr->SetRenderer(
new wxGridCellBoolRenderer() );
972 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
976 attr =
new wxGridCellAttr;
977 attr->SetRenderer(
new wxGridCellBoolRenderer() );
979 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
987 attr =
new wxGridCellAttr;
988 attr->SetRenderer(
new wxGridCellBoolRenderer() );
990 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
1008 wxString unconnected = wxString( wxS(
"unconnected-(" ) );
1013 unconnected.Replace(
'(',
'_' );
1016 [&](
const wxString& aSignalName )
1018 if( simType ==
ST_AC )
1020 m_signals.push_back( aSignalName +
_(
" (gain)" ) );
1021 m_signals.push_back( aSignalName +
_(
" (phase)" ) );
1023 else if( simType ==
ST_SP )
1025 m_signals.push_back( aSignalName +
_(
" (amplitude)" ) );
1026 m_signals.push_back( aSignalName +
_(
" (phase)" ) );
1043 if( netname ==
"GND" || netname ==
"0" || netname.StartsWith( unconnected ) )
1047 addSignal( wxString::Format( wxS(
"V(%s)" ), netname ) );
1057 for(
const std::string&
name : item.model->SpiceGenerator().CurrentNames( item ) )
1067 if( item.model->GetPinCount() >= 2 )
1069 wxString
name = item.model->SpiceGenerator().ItemName( item );
1070 addSignal( wxString::Format( wxS(
"P(%s)" ),
name ) );
1077 addSignal( wxS(
"inoise_spectrum" ) );
1078 addSignal( wxS(
"onoise_spectrum" ) );
1081 if( simType ==
ST_SP )
1083 std::vector<std::string> portnums;
1087 wxString
name = item.model->SpiceGenerator().ItemName( item );
1090 if( !
name.StartsWith(
"V" ) )
1093 std::string portnum =
"";
1095 if(
const SIM_MODEL::PARAM* portnum_param = item.model->FindParam(
"portnum" ) )
1099 portnums.push_back( portnum );
1102 for(
const std::string& portnum1 : portnums )
1104 for(
const std::string& portnum2 : portnums )
1105 addSignal( wxString::Format( wxS(
"S_%s_%s" ), portnum1, portnum2 ) );
1110 for(
const wxString& directive :
circuitModel()->GetDirectives() )
1112 wxStringTokenizer directivesTokenizer( directive,
"\r\n", wxTOKEN_STRTOK );
1114 while( directivesTokenizer.HasMoreTokens() )
1116 wxString line = directivesTokenizer.GetNextToken().Upper();
1117 wxString directiveParams;
1119 if( line.StartsWith( wxS(
".SAVE" ), &directiveParams )
1120 || line.StartsWith( wxS(
".PROBE" ), &directiveParams ) )
1122 wxStringTokenizer paramsTokenizer( directiveParams,
" \t", wxTOKEN_STRTOK );
1124 while( paramsTokenizer.HasMoreTokens() )
1125 addSignal( paramsTokenizer.GetNextToken() );
1148 wxString pageTitle(
simulator()->TypeToName( simType,
true ) );
1149 pageTitle.Prepend( wxString::Format(
_(
"Analysis %u - " ),
static_cast<unsigned int>( ++
m_plotNumber ) ) );
1165#if defined( __WXOSX__ )
1166 wxPoint pos = aEvent.GetPosition();
1167 wxRect ctrlRect =
m_filter->GetScreenRect();
1168 int buttonWidth = ctrlRect.GetHeight();
1170 if(
m_filter->IsSearchButtonVisible() && pos.x < buttonWidth )
1171 SetCursor( wxCURSOR_ARROW );
1172 else if(
m_filter->IsCancelButtonVisible() && pos.x > ctrlRect.GetWidth() - buttonWidth )
1173 SetCursor( wxCURSOR_ARROW );
1175 SetCursor( wxCURSOR_IBEAM );
1182 return wxString::Format( wxS(
"user%d" ), aUserDefinedSignalId );
1193 auto looksLikePower = [](
const wxString& aExpression ) ->
bool
1195 wxString exprUpper = aExpression.Upper();
1197 if( exprUpper.Contains( wxS(
":POWER" ) ) )
1200 if( exprUpper.Find(
'*' ) == wxNOT_FOUND )
1203 if( !exprUpper.Contains( wxS(
"V(" ) ) )
1206 if( !exprUpper.Contains( wxS(
"I(" ) ) )
1212 std::map<wxString, int> suffixes;
1228 wxUniChar firstChar = aSignalName.Upper()[0];
1230 if( firstChar ==
'V' )
1232 else if( firstChar ==
'I' )
1234 else if( firstChar ==
'P' )
1239 wxString
name = aSignalName;
1241 for(
const auto& [ candidate, type ] : suffixes )
1243 if(
name.EndsWith( candidate ) )
1245 name =
name.Left(
name.Length() - candidate.Length() );
1248 *aTraceType |= type;
1256 if(
name == signal )
1258 if( aTraceType && looksLikePower( signal ) )
1282 int row = aEvent.GetRow();
1283 int col = aEvent.GetCol();
1291 if(
text == wxS(
"1" ) )
1326 TRACE* activeTrace =
nullptr;
1328 if(
text == wxS(
"1" ) )
1332 activeTrace = plotTab->
GetTrace( vectorName, traceType );
1343 if( trace != activeTrace && trace->
HasCursor(
id ) )
1366 int row = aEvent.GetRow();
1367 int col = aEvent.GetCol();
1375 CURSOR* cursor1 =
nullptr;
1376 CURSOR* cursor2 =
nullptr;
1378 std::vector<CURSOR*> cursorsVec;
1400 cursorsVec.emplace_back(
cursor );
1402 if( cursorName == ( wxString(
"" ) << i ) &&
cursor )
1403 cursor->SetCoordX( value );
1410 if( cursorName == wxS(
"1" ) && cursor1 )
1412 else if( cursorName == wxS(
"2" ) && cursor2 )
1414 else if( cursorName ==
_(
"Diff" ) && cursor1 && cursor2 )
1422 wxFAIL_MSG( wxT(
"All other columns are supposed to be read-only!" ) );
1455 int row = aEvent.GetRow();
1456 int col = aEvent.GetCol();
1466 wxFAIL_MSG( wxT(
"All other columns are supposed to be read-only!" ) );
1474 for( row = rowCount - 1; row >= 0; row-- )
1484 int killRows = emptyRows - 1;
1487 else if( emptyRows == 0 )
1498 if( plotTab->GetLegendPosition() != plotTab->m_LastLegendPosition )
1500 plotTab->m_LastLegendPosition = plotTab->GetLegendPosition();
1523 static wxRegEx measureParamsRegEx( wxT(
"^"
1527 "([a-zA-Z]*)\\(([^\\)]+)\\)" ) );
1536 if(
text.IsEmpty() )
1543 wxString resultName = wxString::Format( wxS(
"meas_result_%u" ), aRow );
1544 wxString
result = wxS(
"?" );
1546 if( measureParamsRegEx.Matches(
text ) )
1548 wxString func = measureParamsRegEx.GetMatch(
text, 1 ).Upper();
1549 wxString signalType = measureParamsRegEx.GetMatch(
text, 2 ).Upper();
1550 wxString deviceName = measureParamsRegEx.GetMatch(
text, 3 );
1554 if( signalType.EndsWith( wxS(
"DB" ) ) )
1556 units = wxS(
"dB" );
1558 else if( signalType.StartsWith(
'I' ) )
1562 else if( signalType.StartsWith(
'P' ) )
1566 text = func +
" " + deviceName +
":power";
1573 if( func.EndsWith( wxS(
"_AT" ) ) )
1576 units = wxS(
"Hz" );
1580 else if( func.StartsWith( wxS(
"INTEG" ) ) )
1585 if ( signalType.StartsWith(
'P' ) )
1588 units += wxS(
".s" );
1598 units += wxS(
"·Hz" );
1606 units += wxS(
"·?" );
1619 wxString cmd = wxString::Format( wxS(
"meas %s %s %s" ), simType, resultName,
text );
1625 if( resultVec.size() > 0 )
1640 "the value of a passive R, L, C model or voltage or "
1641 "current source." ) );
1645 wxString ref = aSymbol->
GetRef( &aSheetPath );
1650 if( tuner->GetSymbolRef() == ref )
1673 const wxString& aRef,
const wxString& aValue )
1681 + wxString::Format(
_(
"%s not found" ), aRef ) );
1688 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
1689 embeddedFilesStack.push_back(
m_schematicFrame->Schematic().GetEmbeddedFiles() );
1693 embeddedFilesStack.push_back( symbolEmbeddedFiles );
1706 + wxString::Format(
_(
"%s is not tunable" ), aRef ) );
1710 model.SetParamValue( tunerParam->
info.
name, std::string( aValue.ToUTF8() ) );
1780 wxString cmd = wxString::Format( wxS(
"fourier %s %s" ),
1798 m_simConsole->AppendText(
_(
"Error: no current simulation.\n" ) );
1807 m_simConsole->AppendText(
_(
"Error: simulation type not defined.\n" ) );
1813 m_simConsole->AppendText(
_(
"Error: simulation type doesn't support plotting.\n" ) );
1820 if( simType ==
ST_AC )
1825 else if( simType ==
ST_SP )
1835 plotTab->GetPlotWin()->UpdateAll();
1857 if( aNewSignals.count(
id ) == 0 )
1862 plotTab->
DeleteTrace( vectorName, traceType | subType );
1867 plotTab->
DeleteTrace( vectorName, traceType | subType );
1880 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType | subType ) )
1881 trace->SetName( aNewSignals.at(
id ) );
1888 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType | subType ) )
1889 trace->SetName( aNewSignals.at(
id ) );
1894 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
1895 trace->SetName( aNewSignals.at(
id ) );
1915 std::vector<double>* aDataX,
bool aClearData )
1928 wxString simVectorName = aVectorName;
1931 simVectorName = simVectorName.AfterFirst(
'(' ).BeforeLast(
')' ) + wxS(
":power" );
1936 simulator()->
Command( wxString::Format( wxT(
"print %s" ), aVectorName ).ToStdString() );
1941 std::vector<double> data_x;
1942 std::vector<double> data_y;
1944 if( !aDataX || aClearData )
1948 if( aDataX->empty() && !aClearData )
1950 wxString xAxisName(
simulator()->GetXAxis( simType ) );
1952 if( xAxisName.IsEmpty() )
1958 unsigned int size = aDataX->size();
1968 wxFAIL_MSG( wxT(
"Plot type missing AC_PHASE or AC_MAG bit" ) );
1977 wxFAIL_MSG( wxT(
"Plot type missing AC_PHASE or SPT_SP_AMP bit" ) );
1992 wxFAIL_MSG( wxT(
"Unhandled plot type" ) );
1997 size_t sweepSize = std::numeric_limits<size_t>::max();
1999 if( simType ==
ST_DC
2006 sweepSize = aDataX->size() / sweepCount;
2023 size_t sweepSizeMulti = traceData.
xValues.size();
2024 size_t runCount = traceData.
yValues.size();
2026 if( sweepSizeMulti > 0 && runCount > 0 )
2028 std::vector<double> combinedX;
2029 std::vector<double> combinedY;
2031 combinedX.reserve( sweepSizeMulti * runCount );
2032 combinedY.reserve( sweepSizeMulti * runCount );
2034 for(
const std::vector<double>& runY : traceData.
yValues )
2036 if( runY.size() != sweepSizeMulti )
2039 combinedX.insert( combinedX.end(), traceData.
xValues.begin(), traceData.
xValues.end() );
2040 combinedY.insert( combinedY.end(), runY.begin(), runY.end() );
2045 if( combinedY.size() >= combinedX.size() && sweepSizeMulti > 0 )
2047 int sweepCountCombined = combinedX.empty() ? 0 :
static_cast<int>( combinedY.size() / sweepSizeMulti );
2049 if( sweepCountCombined > 0 )
2052 std::vector<wxString> labels;
2053 labels.reserve( sweepCountCombined );
2055 for(
int i = 0; i < sweepCountCombined && i < (int)
m_multiRunState.steps.size(); ++i )
2063 label += wxS(
", " );
2066 double value = it->second;
2072 labels.push_back( label );
2075 aPlotTab->
SetTraceData( trace, combinedX, combinedY, sweepCountCombined,
2076 sweepSizeMulti,
true, labels );
2089 if( data_y.size() >= size )
2090 aPlotTab->
SetTraceData( trace, *aDataX, data_y, sweepCount, sweepSize );
2100template <
typename T,
typename U,
typename R>
2108 wxGridCellAttrPtr attr =
m_signalsGrid->GetOrCreateCellAttrPtr( r,
static_cast<int>( t ) );
2110 if(
TRACE* trace = plotTab ? plotTab->
GetTrace( vectorName, traceType ) :
nullptr )
2112 attr->SetReadOnly();
2116 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
2119 if constexpr ( std::is_enum<T>::value )
2123 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxS(
"1" ) );
2127 if( !attr->HasRenderer() )
2130 if( !attr->HasEditor() )
2133 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
2134 attr->SetReadOnly(
false );
2143 if( !attr->HasRenderer() )
2144 attr->SetRenderer(
new wxGridCellBoolRenderer() );
2146 if( u > 0 && trace->HasCursor( u ) )
2147 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxS(
"1" ) );
2149 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2155 if constexpr ( std::is_enum<T>::value )
2159 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2166 attr->SetEditor(
nullptr );
2167 attr->SetRenderer(
nullptr );
2168 attr->SetReadOnly();
2169 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2178 for(
int row = 0; row <
m_signalsGrid->GetNumberRows(); ++row )
2200 auto quoteNetNames =
2201 [&]( wxString aExpression ) -> wxString
2203 std::vector<bool> mask( aExpression.length(),
false );
2205 auto isNetnameChar =
2206 []( wxUniChar aChar ) ->
bool
2208 wxUint32 value = aChar.GetValue();
2210 if( ( value >=
'0' && value <=
'9' ) || ( value >=
'A' && value <=
'Z' )
2211 || ( value >=
'a' && value <=
'z' ) )
2234 size_t pos = aExpression.find( netname );
2236 while( pos != wxString::npos )
2238 for(
size_t i = 0; i < netname.length(); ++i )
2239 mask[pos + i] =
true;
2241 pos = aExpression.find( netname, pos + 1 );
2245 for(
size_t i = 0; i < aExpression.length(); ++i )
2247 if( !mask[i] || ( i > 0 && mask[i - 1] ) )
2252 while( j < aExpression.length() )
2260 if( isNetnameChar( aExpression[j] ) )
2272 wxString quotedNetnames =
"";
2273 bool startQuote =
true;
2276 for(
size_t i = 0; i < aExpression.length(); i++ )
2278 if( mask[i] && startQuote )
2280 quotedNetnames = quotedNetnames +
"\"";
2283 else if( !mask[i] && !startQuote )
2285 quotedNetnames = quotedNetnames +
"\"";
2289 wxString ch = aExpression[i];
2290 quotedNetnames = quotedNetnames + ch;
2294 quotedNetnames = quotedNetnames +
"\"";
2296 return quotedNetnames;
2301 constexpr const char* cmd =
"let user{} = {}";
2303 simulator()->
Command(
"echo " + fmt::format( cmd,
id, signal.ToStdString() ) );
2304 simulator()->
Command( fmt::format( cmd,
id, quoteNetNames( signal ).ToStdString() ) );
2316 wxString ref = tuner->GetSymbolRef();
2317 KIID symbolId = tuner->GetSymbol( &sheetPath );
2323 reporter.
Report( wxString::Format(
_(
"%s not found" ), ref ) );
2331 reporter.
Report( wxString::Format(
_(
"%s is not tunable" ), ref ) );
2340 floatVal = overrideIt->second;
2342 floatVal = tuner->GetValue().ToDouble();
2353 wxTextFile file( aPath );
2358 wxString firstLine = file.GetFirstLine();
2360 bool legacy = firstLine.StartsWith( wxT(
"version " ) ) || firstLine.ToLong( &
dummy );
2385 wxFileName filename( aPath );
2397 wxFFileInputStream fp( aPath, wxT(
"rt" ) );
2398 wxStdInputStream fstream( fp );
2405 nlohmann::json js = nlohmann::json::parse( fstream,
nullptr,
true,
true );
2407 std::map<SIM_PLOT_TAB*, nlohmann::json> traceInfo;
2409 for(
const nlohmann::json& tab_js : js[
"tabs" ] )
2411 wxString simCommand;
2415 for(
const nlohmann::json& cmd : tab_js[
"commands" ] )
2417 if( cmd ==
".kicad adjustpaths" )
2419 else if( cmd ==
".save all" )
2421 else if( cmd ==
".probe alli" )
2423 else if( cmd ==
".probe allp" )
2425 else if( cmd ==
".kicad esavenone" )
2428 simCommand += wxString( cmd.get<wxString>() ).Trim();
2438 if( tab_js.contains(
"traces" ) )
2439 traceInfo[plotTab] = tab_js[
"traces" ];
2441 if( tab_js.contains(
"measurements" ) )
2443 for(
const nlohmann::json& m_js : tab_js[
"measurements" ] )
2444 plotTab->
Measurements().emplace_back( m_js[
"expr" ], m_js[
"format" ] );
2448 plotTab->
ShowGrid( tab_js[
"showGrid" ] );
2450 if( tab_js.contains(
"fixedY1scale" ) )
2452 const nlohmann::json& scale_js = tab_js[
"fixedY1scale" ];
2453 plotTab->
SetY1Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2457 if( tab_js.contains(
"fixedY2scale" ) )
2459 const nlohmann::json& scale_js = tab_js[
"fixedY2scale" ];
2460 plotTab->
SetY2Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2464 if( tab_js.contains(
"fixedY3scale" ) )
2467 const nlohmann::json& scale_js = tab_js[
"fixedY3scale" ];
2468 plotTab->
SetY3Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2472 if( tab_js.contains(
"legend" ) )
2474 const nlohmann::json& legend_js = tab_js[
"legend" ];
2479 if( tab_js.contains(
"margins" ) )
2481 const nlohmann::json& margins_js = tab_js[
"margins" ];
2483 margins_js[
"right" ],
2484 margins_js[
"bottom" ],
2485 margins_js[
"left" ] );
2492 if( js.contains(
"user_defined_signals" ) )
2494 for(
const nlohmann::json& signal_js : js[
"user_defined_signals" ] )
2500 m_simulatorFrame->LoadSimulator( simTab->GetSimCommand(), simTab->GetSimOptions() );
2503 firstTab->SetLastSchTextSimCommand( js[
"last_sch_text_sim_command"] );
2506 int tempCustomCursorsCnt = 0;
2508 if( js.contains(
"custom_cursors" ) )
2509 tempCustomCursorsCnt = js[
"custom_cursors"];
2511 tempCustomCursorsCnt = 2;
2521 int aCursorId,
const nlohmann::json& aCursor_js )
2523 if( aCursorId >= 1 )
2527 cursor->SetName( aSignalName );
2528 cursor->SetCoordX( aCursor_js[
"position" ] );
2530 aTrace->SetCursor( aCursorId,
cursor );
2534 if( aCursorId == -1 )
2555 for(
const auto& [ plotTab, traces_js ] : traceInfo )
2557 for(
const nlohmann::json& trace_js : traces_js )
2559 wxString signalName = trace_js[
"signal" ];
2561 TRACE* trace = plotTab->GetOrAddTrace( vectorName, trace_js[
"trace_type" ] );
2565 if( trace_js.contains(
"cursorD" ) )
2566 addCursor( plotTab, trace, signalName, -1, trace_js[
"cursorD" ] );
2568 std::vector<const char*> aVec;
2571 for(
int i = 1; i <= tempCustomCursorsCnt; i++ )
2573 wxString str =
"cursor" + std::to_string( i );
2574 aVec.emplace_back( str.c_str() );
2576 if( trace_js.contains( aVec[i - 1] ) )
2577 addCursor( plotTab, trace, signalName, i, trace_js[aVec[i - 1]] );
2580 if( trace_js.contains(
"color" ) )
2583 color.Set( wxString( trace_js[
"color"].get<wxString>() ) );
2585 plotTab->UpdateTraceStyle( trace );
2590 plotTab->UpdatePlotColors();
2593 catch( nlohmann::json::parse_error& error )
2595 wxLogTrace(
traceSettings, wxT(
"Json parse error reading %s: %s" ), aPath, error.what() );
2599 catch( nlohmann::json::type_error& error )
2601 wxLogTrace(
traceSettings, wxT(
"Json type error reading %s: %s" ), aPath, error.what() );
2605 catch( nlohmann::json::invalid_iterator& error )
2607 wxLogTrace(
traceSettings, wxT(
"Json invalid_iterator error reading %s: %s" ), aPath, error.what() );
2611 catch( nlohmann::json::out_of_range& error )
2613 wxLogTrace(
traceSettings, wxT(
"Json out_of_range error reading %s: %s" ), aPath, error.what() );
2619 wxLogTrace(
traceSettings, wxT(
"Error reading %s" ), aPath );
2628 int cursorIdAfterD = aCursorId;
2631 cursorIdAfterD = cursorIdAfterD - 1;
2636 aTraceJs[
"cursor" + wxString(
"" ) << aCursorId] =
2637 nlohmann::json( { {
"position",
cursor->GetCoords().x },
2644 aTraceJs[
"cursorD"] =
2655 wxFileName filename = aPath;
2660 file.Create( filename.GetFullPath(),
true );
2662 if( !file.IsOpened() )
2665 nlohmann::json tabs_js = nlohmann::json::array();
2676 nlohmann::json commands_js = nlohmann::json::array();
2683 commands_js.push_back(
".kicad adjustpaths" );
2686 commands_js.push_back(
".save all" );
2689 commands_js.push_back(
".probe alli" );
2692 commands_js.push_back(
".probe allp" );
2695 commands_js.push_back(
".kicad esavenone" );
2697 nlohmann::json tab_js = nlohmann::json(
2699 {
"commands", commands_js } } );
2703 nlohmann::json traces_js = nlohmann::json::array();
2705 auto findSignalName =
2706 [&](
const wxString& aVectorName ) -> wxString
2708 wxString vectorName;
2711 if( aVectorName.EndsWith(
_(
" (phase)" ) ) )
2712 suffix =
_(
" (phase)" );
2713 else if( aVectorName.EndsWith(
_(
" (gain)" ) ) )
2714 suffix =
_(
" (gain)" );
2716 vectorName = aVectorName.Left( aVectorName.Length() - suffix.Length() );
2721 return signal + suffix;
2727 for(
const auto& [
name, trace] : plotTab->GetTraces() )
2729 nlohmann::json trace_js = nlohmann::json(
2730 { {
"trace_type", (int) trace->GetType() },
2731 {
"signal", findSignalName( trace->GetDisplayName() ) },
2737 if( trace->GetCursor( 1 ) || trace->GetCursor( 2 ) )
2739 trace_js[
"cursorD"] = nlohmann::json(
2744 traces_js.push_back( trace_js );
2747 nlohmann::json measurements_js = nlohmann::json::array();
2749 for(
const auto& [
measurement, format ] : plotTab->Measurements() )
2751 measurements_js.push_back( nlohmann::json( { {
"expr",
measurement },
2752 {
"format", format } } ) );
2755 tab_js[
"traces" ] = traces_js;
2756 tab_js[
"measurements" ] = measurements_js;
2757 tab_js[
"dottedSecondary" ] = plotTab->GetDottedSecondary();
2758 tab_js[
"showGrid" ] = plotTab->IsGridShown();
2762 if( plotTab->GetY1Scale( &min, &max ) )
2763 tab_js[
"fixedY1scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2765 if( plotTab->GetY2Scale( &min, &max ) )
2766 tab_js[
"fixedY2scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2768 if( plotTab->GetY3Scale( &min, &max ) )
2769 tab_js[
"fixedY3scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2771 if( plotTab->IsLegendShown() )
2773 tab_js[
"legend" ] = nlohmann::json( { {
"x", plotTab->GetLegendPosition().x },
2774 {
"y", plotTab->GetLegendPosition().y } } );
2777 mpWindow* plotWin = plotTab->GetPlotWin();
2779 tab_js[
"margins" ] = nlohmann::json( { {
"left", plotWin->
GetMarginLeft() },
2785 tabs_js.push_back( tab_js );
2788 nlohmann::json userDefinedSignals_js = nlohmann::json::array();
2791 userDefinedSignals_js.push_back( signal );
2794 nlohmann::json js = nlohmann::json( { {
"version", 7 },
2795 {
"tabs", tabs_js },
2796 {
"user_defined_signals", userDefinedSignals_js },
2809 std::stringstream buffer;
2810 buffer << std::setw( 2 ) << js << std::endl;
2812 bool res = file.Write( buffer.str() );
2839 wxFAIL_MSG( wxString::Format( wxS(
"Unhandled simulation type: %d" ), (
int) aType ) );
2859 &source, &
scale, &pts, &fStart, &fStop, &saveAll );
2867 int& aSashPosition )
2869 bool isShown = aPanel->IsShown();
2872 aSashPosition = aSplitterWindow->GetSashPosition();
2874 aPanel->Show( !isShown );
2876 aSplitterWindow->SetSashInvisible( isShown );
2877 aSplitterWindow->SetSashPosition( isShown ? -1 : aSashPosition,
true );
2879 aSplitterWindow->UpdateSize();
2880 m_parent->Refresh();
2917 for(
size_t page = 0; page <
m_plotNotebook->GetPageCount(); page++ )
2965 std::vector<std::pair<wxString, wxString>>& measurements = plotTab->Measurements();
2967 measurements.clear();
3005 simulator()->
Command(
"setplot " + simTab->GetSpicePlotName().ToStdString() );
3022 for(
const auto& [
measurement, format ] : plotTab->Measurements() )
3030 if( plotTab->GetSimType() ==
ST_TRAN || plotTab->GetSimType() ==
ST_AC
3031 || plotTab->GetSimType() ==
ST_DC || plotTab->GetSimType() ==
ST_SP )
3068 CURSOR* cursor1 =
nullptr;
3069 wxString cursor1Name;
3070 wxString cursor1Units;
3071 CURSOR* cursor2 =
nullptr;
3072 wxString cursor2Name;
3073 wxString cursor2Units;
3076 [&](
TRACE* aTrace ) -> wxString
3097 [&](
TRACE* aTrace ) -> wxString
3118 [
this](
double aValue,
int aCursorId,
int aCol ) -> wxString
3120 if( ( !
m_simulatorFrame->SimFinished() && aCol == 1 ) || std::isnan( aValue ) )
3131 cursor1Name = getNameY( trace );
3132 cursor1Units = getUnitsY( trace );
3134 wxRealPoint coords =
cursor->GetCoords();
3154 cursor2Name = getNameY( trace );
3155 cursor2Units = getUnitsY( trace );
3157 wxRealPoint coords =
cursor->GetCoords();
3172 if( cursor1 && cursor2 && cursor1Units == cursor2Units )
3181 signal = wxString::Format( wxS(
"%s[2 - 1]" ), cursor2->
GetName() );
3183 signal = wxString::Format( wxS(
"%s - %s" ), cursor2->
GetName(), cursor1->
GetName() );
3194 wxString valColName =
_(
"Value" );
3196 if( !cursor1Name.IsEmpty() )
3198 if( cursor2Name.IsEmpty() || cursor1Name == cursor2Name )
3199 valColName = cursor1Name;
3201 else if( !cursor2Name.IsEmpty() )
3203 valColName = cursor2Name;
3217 wxString cursName = getNameY( trace );
3218 wxString cursUnits = getUnitsY( trace );
3220 wxRealPoint coords =
cursor->GetCoords();
3235 valColName =
_(
"Value" );
3238 valColName = cursName;
3259 plotTab->ResetScales(
true );
3281 std::vector<wxString> signals;
3283 for(
const std::string& vec :
simulator()->AllVectors() )
3284 signals.emplace_back( vec );
3292 std::vector<wxString> signals;
3294 for(
const wxString& signal :
m_signals )
3295 signals.emplace_back( signal );
3298 signals.emplace_back( signal );
3316 bool storeMultiRun =
false;
3322 storeMultiRun =
true;
3345 if( simType ==
ST_NOISE && aFinal )
3347 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3356 for(
const std::string& vec :
simulator()->AllVectors() )
3361 msg.Printf( wxS(
"%s: %sV\n" ), vec, value );
3372 wxCHECK_RET( plotTab, wxString::Format( wxT(
"No SIM_PLOT_TAB for: %s" ),
3373 magic_enum::enum_name( simType ) ) );
3382 std::map<TRACE*, TRACE_INFO> traceMap;
3385 traceMap[ trace ] = { wxEmptyString,
SPT_UNKNOWN,
false };
3390 for(
const wxString& signal :
m_signals )
3395 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
3396 traceMap[ trace ] = { vectorName, traceType,
false };
3404 if( simType ==
ST_AC )
3410 if(
TRACE* trace = plotTab->
GetTrace( vectorName, subType ) )
3411 traceMap[ trace ] = { vectorName, subType, !aFinal };
3414 else if( simType ==
ST_SP )
3420 if(
TRACE* trace = plotTab->
GetTrace( vectorName, subType ) )
3421 traceMap[trace] = { vectorName, subType, !aFinal };
3426 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
3427 traceMap[ trace ] = { vectorName, traceType, !aFinal };
3433 for(
const auto& [ trace, traceInfo ] : traceMap )
3435 if( traceInfo.Vector.IsEmpty() )
3439 for(
const auto& [ trace,
info ] : traceMap )
3441 std::vector<double> data_x;
3443 if( !
info.Vector.IsEmpty() )
3461 else if( simType ==
ST_OP && aFinal )
3463 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3466 for(
const std::string& vec :
simulator()->AllVectors() )
3470 if( val_list.empty() )
3477 const size_t tab = 25;
3478 size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1;
3482 case SPT_VOLTAGE: value.Append( wxS(
"V" ) );
break;
3483 case SPT_CURRENT: value.Append( wxS(
"A" ) );
break;
3484 case SPT_POWER: value.Append( wxS(
"W" ) );
break;
3485 default: value.Append( wxS(
"?" ) );
break;
3488 msg.Printf( wxT(
"%s%s\n" ),
3489 ( signal + wxT(
":" ) ).Pad( padding, wxUniChar(
' ' ) ),
3496 signal = signal.SubString( 2, signal.Length() - 2 );
3499 signal += wxS(
":power" );
3501 m_schematicFrame->Schematic().SetOperatingPoint( signal, val_list.at( 0 ) );
3504 else if( simType ==
ST_PZ && aFinal )
3506 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3567 std::vector<TUNER_SLIDER*> multiTuners;
3572 multiTuners.push_back( tuner );
3575 if( multiTuners.empty() )
3607 else if( tunersChanged )
3616 for(
const auto& entry : step.
overrides )
3623 const std::vector<TUNER_SLIDER*>& aTuners )
const
3625 std::vector<MULTI_RUN_STEP> steps;
3627 if( aTuners.empty() )
3630 std::vector<std::vector<double>> tunerValues;
3631 tunerValues.reserve( aTuners.size() );
3638 double startValue = tuner->GetMin().ToDouble();
3639 double endValue = tuner->GetMax().ToDouble();
3640 int stepCount = std::max( 2, tuner->GetStepCount() );
3645 double increment = ( endValue - startValue ) /
static_cast<double>( stepCount - 1 );
3647 std::vector<double> values;
3648 values.reserve( stepCount );
3650 for(
int ii = 0; ii < stepCount; ++ii )
3651 values.push_back( startValue + increment * ii );
3653 tunerValues.push_back( std::move( values ) );
3661 std::vector<double> currentValues( aTuners.size(), 0.0 );
3663 auto generate = [&](
auto&& self,
size_t depth ) ->
void
3665 if( steps.size() >=
static_cast<size_t>( limit ) )
3668 if( depth == aTuners.size() )
3672 for(
size_t ii = 0; ii < aTuners.size(); ++ii )
3673 step.
overrides.emplace( aTuners[ii], currentValues[ii] );
3675 steps.push_back( std::move( step ) );
3679 for(
double value : tunerValues[depth] )
3681 currentValues[depth] = value;
3682 self( self, depth + 1 );
3684 if( steps.size() >=
static_cast<size_t>( limit ) )
3689 generate( generate, 0 );
3697 return fmt::format(
"{}|{}", aVectorName.ToStdString(), aTraceType );
3702 const std::vector<double>& aX,
3703 const std::vector<double>& aY )
3705 if( aX.empty() || aY.empty() )
3716 if( trace.
xValues.size() != aX.size() )
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
void showPopupMenu(wxMenu &menu, wxGridEvent &aEvent) override
void doPopupSelection(wxCommandEvent &event) override
SIMULATOR_FRAME_UI * m_parent
CURSORS_GRID_TRICKS(SIMULATOR_FRAME_UI *aParent, WX_GRID *aGrid)
The SIMULATOR_FRAME holds the main user-interface for running simulations.
const wxRealPoint & GetCoords() const
void SetCoordX(double aValue)
bool Find(const wxString &aTerm, int &aMatchersTriggered, int &aPosition)
Look in all existing matchers, return the earliest match of any of the existing.
GRID_TRICKS(WX_GRID *aGrid)
virtual void doPopupSelection(wxCommandEvent &event)
virtual void showPopupMenu(wxMenu &menu, wxGridEvent &aEvent)
WX_GRID * m_grid
I don't own the grid, but he owns me.
A color representation with 4 components: red, green, blue, alpha.
wxString ToCSSString() const
wxColour ToColour() const
Hold a translatable error message and may be used when throwing exceptions containing a translated er...
const wxString What() const
void AppendParentEmbeddedFiles(std::vector< EMBEDDED_FILES * > &aStack) const
void doPopupSelection(wxCommandEvent &event) override
void showPopupMenu(wxMenu &menu, wxGridEvent &aEvent) override
SIMULATOR_FRAME_UI * m_parent
MEASUREMENTS_GRID_TRICKS(SIMULATOR_FRAME_UI *aParent, WX_GRID *aGrid)
static void ConvertToSpiceMarkup(wxString *aNetName)
Remove formatting wrappers and replace illegal spice net name characters with underscores.
@ OPTION_SAVE_ALL_CURRENTS
@ OPTION_SAVE_ALL_VOLTAGES
@ OPTION_SAVE_ALL_DISSIPATIONS
@ OPTION_ADJUST_INCLUDE_PATHS
@ OPTION_ADJUST_PASSIVE_VALS
const SPICE_ITEM * FindItem(const wxString &aRefName) const
Find and return the item corresponding to aRefName.
A singleton reporter that reports to nowhere.
virtual bool HasMessage() const
Returns true if any messages were reported.
Holds all the data relating to one schematic.
void ClearOperatingPoints()
Clear operating points from a .op simulation.
Schematic editor (Eeschema) main window.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
SCH_ITEM * ResolveItem(const KIID &aID) const
Fetch a SCH_ITEM by ID.
EMBEDDED_FILES * GetEmbeddedFiles() override
SCH_SYMBOLs don't currently support embedded files, but their LIB_SYMBOL counterparts do.
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
void doPopupSelection(wxCommandEvent &event) override
void showPopupMenu(wxMenu &menu, wxGridEvent &aEvent) override
SIMULATOR_FRAME_UI * m_parent
SIGNALS_GRID_TRICKS(SIMULATOR_FRAME_UI *aParent, WX_GRID *aGrid)
wxBoxSizer * m_sizerTuners
WX_GRID * m_measurementsGrid
wxSplitterWindow * m_splitterLeftRight
wxSplitterWindow * m_splitterMeasurements
wxTextCtrl * m_simConsole
wxSplitterWindow * m_splitterCursors
wxSplitterWindow * m_splitterPlotAndConsole
SIMULATOR_FRAME_UI_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
wxSplitterWindow * m_splitterSignals
wxAuiNotebook * m_plotNotebook
The SIMULATOR_FRAME_UI holds the main user-interface for running simulations.
SIM_TAB * NewSimTab(const wxString &aSimCommand)
Create a new simulation tab for a given simulation type.
std::string multiRunTraceKey(const wxString &aVectorName, int aTraceType) const
void SetUserDefinedSignals(const std::map< int, wxString > &aSignals)
void updatePlotCursors()
Update the cursor values (in the grid) and graphics (in the plot window).
void OnSimRefresh(bool aFinal)
void onPlotClose(wxAuiNotebookEvent &event) override
void CustomCursorsInit()
Init handler for custom cursors.
void recordMultiRunData(const wxString &aVectorName, int aTraceType, const std::vector< double > &aX, const std::vector< double > &aY)
std::vector< MULTI_RUN_STEP > calculateMultiRunSteps(const std::vector< TUNER_SLIDER * > &aTuners) const
int m_splitterTuneValuesSashPosition
void TogglePanel(wxPanel *aPanel, wxSplitterWindow *aSplitterWindow, int &aSashPosition)
A common toggler for the two main wxSplitterWindow s.
void onPlotChanged(wxAuiNotebookEvent &event) override
void rebuildSignalsGrid(wxString aFilter)
Rebuild the filtered list of signals in the signals grid.
std::vector< std::vector< SPICE_VALUE_FORMAT > > m_cursorFormatsDyn
void DoFourier(const wxString &aSignal, const wxString &aFundamental)
void rebuildMeasurementsGrid()
Rebuild the measurements grid for the current plot.
std::list< TUNER_SLIDER * > m_tuners
void rebuildSignalsList()
Rebuild the list of signals available from the netlist.
bool loadLegacyWorkbook(const wxString &aPath)
int m_splitterCursorsSashPosition
MULTI_RUN_STATE m_multiRunState
SPICE expressions need quoted versions of the netnames since KiCad allows '-' and '/' in netnames.
void ToggleSimSidePanel()
void UpdateMeasurement(int aRow)
Update a measurement in the measurements grid.
wxString getNoiseSource() const
std::vector< wxString > SimPlotVectors() const
unsigned int m_plotNumber
void SetSubWindowsSashSize()
Adjust the sash dimension of splitter windows after reading the config settings must be called after ...
void applyUserDefinedSignals()
Apply user-defined signals to the SPICE session.
SIM_PREFERENCES m_preferences
void DeleteMeasurement(int aRow)
Delete a row from the measurements grid.
SCH_EDIT_FRAME * m_schematicFrame
wxString vectorNameFromSignalName(SIM_PLOT_TAB *aPlotTab, const wxString &aSignalName, int *aTraceType)
Get the simulator output vector name for a given signal name and type.
void updateSignalsGrid()
Update the values in the signals grid.
int m_splitterLeftRightSashPosition
void onCursorsGridCellChanged(wxGridEvent &aEvent) override
void onPlotDragged(wxAuiNotebookEvent &event) override
std::vector< wxString > Signals() const
bool SaveWorkbook(const wxString &aPath)
Save plot, signal, cursor, measurement, etc.
bool hasMultiRunTrace(const wxString &aVectorName, int aTraceType) const
std::vector< wxString > m_signals
SIM_TAB * GetCurrentSimTab() const
Return the currently opened plot panel (or NULL if there is none).
void SaveCursorToWorkbook(nlohmann::json &aTraceJs, TRACE *aTrace, int aCursorId)
void updateMeasurementsFromGrid()
bool LoadWorkbook(const wxString &aPath)
Load plot, signal, cursor, measurement, etc.
SPICE_VALUE_FORMAT GetMeasureFormat(int aRow) const
Get/Set the format of a value in the measurements grid.
std::map< int, wxString > m_userDefinedSignals
void UpdateTunerValue(const SCH_SHEET_PATH &aSheetPath, const KIID &aSymbol, const wxString &aRef, const wxString &aValue)
Safely update a field of the associated symbol without dereferencing the symbol.
std::vector< wxString > m_netnames
void AddTrace(const wxString &aName, SIM_TRACE_TYPE aType)
Add a new trace to the current plot.
void onPlotClosed(wxAuiNotebookEvent &event) override
void RemoveTuner(TUNER_SLIDER *aTuner)
Remove an existing tuner.
void SaveSettings(EESCHEMA_SETTINGS *aCfg)
std::shared_ptr< SPICE_CIRCUIT_MODEL > circuitModel() const
void OnFilterText(wxCommandEvent &aEvent) override
void onMeasurementsGridCellChanged(wxGridEvent &aEvent) override
void DeleteCursor()
Deletes last m_signalsGrid "Cursor n" column, removes vector's m_cursorFormatsDyn last entry,...
void CreateNewCursor()
Creates a column at the end of m_signalsGrid named "Cursor n" ( n = m_customCursorsCnt ),...
void applyTuners()
Apply component values specified using tuner sliders to the current netlist.
bool loadJsonWorkbook(const wxString &aPath)
void clearMultiRunState(bool aClearTraces)
void OnFilterMouseMoved(wxMouseEvent &aEvent) override
void AddMeasurement(const wxString &aCmd)
Add a measurement to the measurements grid.
void onPlotChanging(wxAuiNotebookEvent &event) override
std::map< const TUNER_SLIDER *, double > m_tunerOverrides
std::shared_ptr< SPICE_SIMULATOR > simulator() const
void onPlotCursorUpdate(wxCommandEvent &aEvent)
void onSignalsGridCellChanged(wxGridEvent &aEvent) override
void InitWorkbook()
Load the currently active workbook stored in the project settings.
void ToggleDarkModePlots()
SIM_TRACE_TYPE getXAxisType(SIM_TYPE aType) const
Return X axis for a given simulation type.
void prepareMultiRunState()
void OnPlotSettingsChanged()
void signalsGridCursorUpdate(T t, U u, R r)
Updates m_signalsGrid cursor widget, column rendering and attributes.
void SetMeasureFormat(int aRow, const SPICE_VALUE_FORMAT &aFormat)
int m_splitterSignalsSashPosition
void OnSimReport(const wxString &aMsg)
void ApplyPreferences(const SIM_PREFERENCES &aPrefs)
Called when settings are changed via the common Preferences dialog.
const SPICE_CIRCUIT_MODEL * GetExporter() const
Return the netlist exporter object used for simulations.
int m_splitterPlotAndConsoleSashPosition
SIMULATOR_FRAME * m_simulatorFrame
void ShowChangedLanguage()
void AddTuner(const SCH_SHEET_PATH &aSheetPath, SCH_SYMBOL *aSymbol)
Add a tuner for a symbol.
bool IsSimSidePanelShown()
void OnUpdateUI(wxUpdateUIEvent &event) override
void updateTrace(const wxString &aVectorName, int aTraceType, SIM_PLOT_TAB *aPlotTab, std::vector< double > *aDataX=nullptr, bool aClearData=false)
Update a trace in a particular SIM_PLOT_TAB.
SIMULATOR_FRAME_UI(SIMULATOR_FRAME *aSimulatorFrame, SCH_EDIT_FRAME *aSchematicFrame)
SPICE_VALUE_FORMAT m_cursorFormats[3][2]
void LoadSettings(EESCHEMA_SETTINGS *aCfg)
The SIMULATOR_FRAME holds the main user-interface for running simulations.
SIM_MODEL & CreateModel(SIM_MODEL::TYPE aType, const std::vector< SCH_PIN * > &aPins, REPORTER &aReporter)
void SetFilesStack(std::vector< EMBEDDED_FILES * > aFilesStack)
virtual const PARAM * GetTunerParam() const
const SPICE_GENERATOR & SpiceGenerator() const
static void FillDefaultColorList(bool aWhiteBg)
Fills m_colorList by a default set of colors.
bool DeleteTrace(const wxString &aVectorName, int aTraceType)
wxString GetLabelY1() const
mpWindow * GetPlotWin() const
void ShowGrid(bool aEnable)
void SetTraceData(TRACE *aTrace, std::vector< double > &aX, std::vector< double > &aY, int aSweepCount, size_t aSweepSize, bool aIsMultiRun=false, const std::vector< wxString > &aMultiRunLabels={})
wxString GetUnitsY2() const
void SetY2Scale(bool aLock, double aMin, double aMax)
TRACE * GetTrace(const wxString &aVecName, int aType) const
wxString GetLabelX() const
const std::map< wxString, TRACE * > & GetTraces() const
wxString GetLabelY3() const
void SetY1Scale(bool aLock, double aMin, double aMax)
void SetY3Scale(bool aLock, double aMin, double aMax)
std::vector< std::pair< wxString, wxString > > & Measurements()
void UpdateTraceStyle(TRACE *trace)
Update plot colors.
void SetLegendPosition(const wxPoint &aPosition)
void ResetScales(bool aIncludeX)
Update trace line style.
void ShowLegend(bool aEnable)
wxString GetLabelY2() const
void EnableCursor(TRACE *aTrace, int aCursorId, const wxString &aSignalName)
wxString GetUnitsX() const
void EnsureThirdYAxisExists()
TRACE * GetOrAddTrace(const wxString &aVectorName, int aType)
void SetDottedSecondary(bool aEnable)
Draw secondary signal traces (current or phase) with dotted lines.
void ApplyPreferences(const SIM_PREFERENCES &aPrefs) override
wxString GetUnitsY1() const
void DisableCursor(TRACE *aTrace, int aCursorId)
Reset scale ranges to fit the current traces.
wxString GetUnitsY3() const
int GetSimOptions() const
SIM_TYPE GetSimType() const
const wxString & GetSimCommand() const
static bool IsPlottable(SIM_TYPE aSimType)
void SetSimOptions(int aOptions)
wxString GetLastSchTextSimCommand() const
void SetSpicePlotName(const wxString &aPlotName)
static std::string ToSpice(const std::string &aString)
Special netlist exporter flavor that allows one to override simulation commands.
static SIM_TYPE CommandToSimType(const wxString &aCmd)
Return simulation type basing on a simulation command directive.
bool ParseNoiseCommand(const wxString &aCmd, wxString *aOutput, wxString *aRef, wxString *aSource, wxString *aScale, SPICE_VALUE *aPts, SPICE_VALUE *aFStart, SPICE_VALUE *aFStop, bool *aSaveAll)
wxString GetSchTextSimCommand()
Return simulation command directives placed in schematic sheets (if any).
SIM_TRACE_TYPE VectorToSignal(const std::string &aVector, wxString &aSignal) const
Return name of Spice dataset for a specific trace.
virtual std::string TunerCommand(const SPICE_ITEM &aItem, double aValue) const
wxString GetWorkbookFilename() const
void SetWorkbookFilename(const wxString &aFilename)
virtual bool Command(const std::string &aCmd)=0
Execute a Spice command as if it was typed into console.
static wxString TypeToName(SIM_TYPE aType, bool aShortName)
Return a string with simulation name based on enum.
std::shared_ptr< SPICE_SETTINGS > & Settings()
Return the simulator configuration settings.
virtual wxString CurrentPlotName() const =0
virtual std::vector< double > GetRealVector(const std::string &aName, int aMaxLen=-1)=0
Return a requested vector with real values.
virtual std::vector< double > GetGainVector(const std::string &aName, int aMaxLen=-1)=0
Return a requested vector with magnitude values.
virtual std::vector< double > GetPhaseVector(const std::string &aName, int aMaxLen=-1)=0
Return a requested vector with phase values.
Helper class to recognize Spice formatted values.
wxString ToString() const
Return string value as when converting double to string (e.g.
wxString ToSpiceString() const
Return string value in Spice format (e.g.
~SUPPRESS_GRID_CELL_EVENTS()
SUPPRESS_GRID_CELL_EVENTS(SIMULATOR_FRAME_UI *aFrame)
SIMULATOR_FRAME_UI * m_frame
void SetTraceColour(const wxColour &aColour)
bool HasCursor(int aCursorId)
CURSOR * GetCursor(int aCursorId)
Custom widget to handle quick component values modification and simulation on the fly.
wxString GetSymbolRef() const
A wrapper for reporting to a wxString object.
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
const wxString & GetMessages() const
A KICAD version of wxTextEntryDialog which supports the various improvements/work-arounds from DIALOG...
wxString GetValue() const
const wxString & GetName() const
Get layer name.
const wxPen & GetPen() const
Get pen set for this layer.
Canvas for plotting mpLayer implementations.
int GetMarginLeft() const
void SetMargins(int top, int right, int bottom, int left)
Set window margins, creating a blank area where some kinds of layers cannot draw.
void UpdateAll()
Refresh display.
int GetMarginRight() const
int GetMarginBottom() const
bool AddLayer(mpLayer *layer, bool refreshDisplay=true)
Add a plot layer to the canvas.
void Fit() override
Set view to fit global bounding box of all plot layers and refresh display.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
Abstract pattern-matching tool and implementations.
@ GRIDTRICKS_FIRST_CLIENT_ID
int m_SimulatorMultiRunCombinationLimit
Maximum number of tuner combinations simulated when using multi-run mode.
static const std::string WorkbookFileExtension
KICOMMON_API wxFont GetStatusFont(wxWindow *aWindow)
SIM_TYPE
< Possible simulation types
void sortSignals(std::vector< wxString > &signals)
wxString vectorNameFromSignalId(int aUserDefinedSignalId)
MEASUREMENTS_GIRD_COLUMNS
@ MYID_DELETE_MEASUREMENT
SIM_TRACE_TYPE operator|(SIM_TRACE_TYPE aFirst, SIM_TRACE_TYPE aSecond)
std::vector< FAB_LAYER_COLOR > dummy
wxString UnescapeString(const wxString &aSource)
int measurements_panel_height
SIM_PREFERENCES preferences
std::map< const TUNER_SLIDER *, double > overrides
std::vector< std::vector< double > > yValues
std::vector< double > xValues
Contains preferences pertaining to the simulator.
wxString result
Test unit parsing edge cases and error handling.
Definition of file extensions used in Kicad.