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
569 wxGridCellAttr* attr =
new wxGridCellAttr;
573 attr =
new wxGridCellAttr;
577 attr =
new wxGridCellAttr;
581 attr =
new wxGridCellAttr;
587 attr =
new wxGridCellAttr;
597 [&]( wxTimerEvent& aEvent )
606#ifndef wxHAS_NATIVE_TABART
626 m_cursorFormat[0] = { 3, wxS(
"~s" ) };
627 m_cursorFormat[1] = { 3, wxS(
"~V" ) };
638 for(
size_t index2 = 0; index2 < std::size(
m_cursorFormats[0] ); index2++ )
654 maxCursor.Replace(
_(
"Cursor " ),
"" );
656 int tmpMax = wxAtoi( maxCursor );
658 if( nameMax < tmpMax )
668 std::vector<SPICE_VALUE_FORMAT> tmp;
680 wxGridCellAttr* attr =
new wxGridCellAttr;
700 for(
int i = 0; i < rows; i++ )
702 if(
m_signalsGrid->GetCellValue( i, col - 1 ) == wxS(
"1" ) )
705 wxGridEvent aDummy( wxID_ANY, wxEVT_GRID_CELL_CHANGED,
m_signalsGrid, i, col - 1 );
725 for(
int ii = 0; ii < static_cast<int>(
m_plotNotebook->GetPageCount() ); ++ii )
729 simTab->OnLanguageChanged();
731 wxString pageTitle(
simulator()->TypeToName( simTab->GetSimType(),
true ) );
732 pageTitle.Prepend( wxString::Format(
_(
"Analysis %u - " ), ii+1 ) );
753 tuner->ShowChangedLanguage();
793 simTab->ApplyPreferences( aPrefs );
800 if( !
simulator()->Settings()->GetWorkbookFilename().IsEmpty() )
812 if( !schTextSimCommand.IsEmpty() )
845 std::sort( signals.begin(), signals.end(),
846 [](
const wxString& lhs,
const wxString& rhs )
849 if( lhs.Upper().StartsWith(
'V' ) && !rhs.Upper().StartsWith(
'V' ) )
851 else if( !lhs.Upper().StartsWith(
'V' ) && rhs.Upper().StartsWith(
'V' ) )
854 return StrNumCmp( lhs, rhs, true ) < 0;
871 std::vector<wxString> signals;
875 wxStringTokenizer tokenizer( plotPanel->
GetSimCommand(),
" \t\r\n", wxTOKEN_STRTOK );
877 while( tokenizer.HasMoreTokens() && tokenizer.GetNextToken().Lower() != wxT(
"fft" ) )
880 while( tokenizer.HasMoreTokens() )
881 signals.emplace_back( tokenizer.GetNextToken() );
888 for(
const wxString& signal :
m_signals )
889 signals.push_back( signal );
893 if( simType ==
ST_AC )
895 signals.push_back( signal +
_(
" (gain)" ) );
896 signals.push_back( signal +
_(
" (phase)" ) );
898 else if( simType ==
ST_SP )
900 signals.push_back( signal +
_(
" (amplitude)" ) );
901 signals.push_back( signal +
_(
" (phase)" ) );
905 signals.push_back( signal );
912 if( aFilter.IsEmpty() )
913 aFilter = wxS(
"*" );
918 for(
const wxString& signal : signals )
920 if( matcher.
Find( signal.Upper() ) )
929 wxGridCellAttr* attr =
new wxGridCellAttr;
930 attr->SetRenderer(
new wxGridCellBoolRenderer() );
932 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
937 attr =
new wxGridCellAttr;
942 attr =
new wxGridCellAttr;
946 attr =
new wxGridCellAttr;
954 attr =
new wxGridCellAttr;
964 attr =
new wxGridCellAttr;
967 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
972 attr =
new wxGridCellAttr;
973 attr->SetRenderer(
new wxGridCellBoolRenderer() );
975 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
979 attr =
new wxGridCellAttr;
980 attr->SetRenderer(
new wxGridCellBoolRenderer() );
982 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
990 attr =
new wxGridCellAttr;
991 attr->SetRenderer(
new wxGridCellBoolRenderer() );
993 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
1012 wxString unconnected = wxString( wxS(
"unconnected-(" ) );
1017 unconnected.Replace(
'(',
'_' );
1020 [&](
const wxString& aSignalName )
1022 if( simType ==
ST_AC )
1024 m_signals.push_back( aSignalName +
_(
" (gain)" ) );
1025 m_signals.push_back( aSignalName +
_(
" (phase)" ) );
1027 else if( simType ==
ST_SP )
1029 m_signals.push_back( aSignalName +
_(
" (amplitude)" ) );
1030 m_signals.push_back( aSignalName +
_(
" (phase)" ) );
1047 if( netname ==
"GND" || netname ==
"0" || netname.StartsWith( unconnected ) )
1051 addSignal( wxString::Format( wxS(
"V(%s)" ), netname ) );
1061 for(
const std::string&
name : item.model->SpiceGenerator().CurrentNames( item ) )
1071 if( item.model->GetPinCount() >= 2 )
1073 wxString
name = item.model->SpiceGenerator().ItemName( item );
1074 addSignal( wxString::Format( wxS(
"P(%s)" ),
name ) );
1081 addSignal( wxS(
"inoise_spectrum" ) );
1082 addSignal( wxS(
"onoise_spectrum" ) );
1085 if( simType ==
ST_SP )
1087 std::vector<std::string> portnums;
1091 wxString
name = item.model->SpiceGenerator().ItemName( item );
1094 if( !
name.StartsWith(
"V" ) )
1097 std::string portnum =
"";
1099 if(
const SIM_MODEL::PARAM* portnum_param = item.model->FindParam(
"portnum" ) )
1103 portnums.push_back( portnum );
1106 for(
const std::string& portnum1 : portnums )
1108 for(
const std::string& portnum2 : portnums )
1110 addSignal( wxString::Format( wxS(
"S_%s_%s" ), portnum1, portnum2 ) );
1116 for(
const wxString& directive :
circuitModel()->GetDirectives() )
1118 wxStringTokenizer directivesTokenizer( directive,
"\r\n", wxTOKEN_STRTOK );
1120 while( directivesTokenizer.HasMoreTokens() )
1122 wxString line = directivesTokenizer.GetNextToken().Upper();
1123 wxString directiveParams;
1125 if( line.StartsWith( wxS(
".SAVE" ), &directiveParams )
1126 || line.StartsWith( wxS(
".PROBE" ), &directiveParams ) )
1128 wxStringTokenizer paramsTokenizer( directiveParams,
" \t", wxTOKEN_STRTOK );
1130 while( paramsTokenizer.HasMoreTokens() )
1131 addSignal( paramsTokenizer.GetNextToken() );
1154 wxString pageTitle(
simulator()->TypeToName( simType,
true ) );
1155 pageTitle.Prepend( wxString::Format(
_(
"Analysis %u - " ),
static_cast<unsigned int>( ++
m_plotNumber ) ) );
1171#if defined( __WXOSX__ ) || wxCHECK_VERSION( 3, 3, 0 )
1172 wxPoint pos = aEvent.GetPosition();
1173 wxRect ctrlRect =
m_filter->GetScreenRect();
1174 int buttonWidth = ctrlRect.GetHeight();
1176 if(
m_filter->IsSearchButtonVisible() && pos.x < buttonWidth )
1177 SetCursor( wxCURSOR_ARROW );
1178 else if(
m_filter->IsCancelButtonVisible() && pos.x > ctrlRect.GetWidth() - buttonWidth )
1179 SetCursor( wxCURSOR_ARROW );
1181 SetCursor( wxCURSOR_IBEAM );
1188 return wxString::Format( wxS(
"user%d" ), aUserDefinedSignalId );
1197 const wxString& aSignalName,
1200 auto looksLikePower = [](
const wxString& aExpression ) ->
bool
1202 wxString exprUpper = aExpression.Upper();
1204 if( exprUpper.Contains( wxS(
":POWER" ) ) )
1207 if( exprUpper.Find(
'*' ) == wxNOT_FOUND )
1210 if( !exprUpper.Contains( wxS(
"V(" ) ) )
1213 if( !exprUpper.Contains( wxS(
"I(" ) ) )
1219 std::map<wxString, int> suffixes;
1235 wxUniChar firstChar = aSignalName.Upper()[0];
1237 if( firstChar ==
'V' )
1239 else if( firstChar ==
'I' )
1241 else if( firstChar ==
'P' )
1246 wxString
name = aSignalName;
1248 for(
const auto& [ candidate, type ] : suffixes )
1250 if(
name.EndsWith( candidate ) )
1252 name =
name.Left(
name.Length() - candidate.Length() );
1255 *aTraceType |= type;
1263 if(
name == signal )
1265 if( aTraceType && looksLikePower( signal ) )
1289 int row = aEvent.GetRow();
1290 int col = aEvent.GetCol();
1298 if(
text == wxS(
"1" ) )
1334 TRACE* activeTrace =
nullptr;
1336 if(
text == wxS(
"1" ) )
1340 activeTrace = plotTab->
GetTrace( vectorName, traceType );
1351 if( trace != activeTrace && trace->
HasCursor(
id ) )
1374 int row = aEvent.GetRow();
1375 int col = aEvent.GetCol();
1383 CURSOR* cursor1 =
nullptr;
1384 CURSOR* cursor2 =
nullptr;
1386 std::vector<CURSOR*> cursorsVec;
1408 cursorsVec.emplace_back(
cursor );
1410 if( cursorName == ( wxString(
"" ) << i ) &&
cursor )
1411 cursor->SetCoordX( value );
1418 if( cursorName == wxS(
"1" ) && cursor1 )
1420 else if( cursorName == wxS(
"2" ) && cursor2 )
1422 else if( cursorName ==
_(
"Diff" ) && cursor1 && cursor2 )
1430 wxFAIL_MSG( wxT(
"All other columns are supposed to be read-only!" ) );
1463 int row = aEvent.GetRow();
1464 int col = aEvent.GetCol();
1474 wxFAIL_MSG( wxT(
"All other columns are supposed to be read-only!" ) );
1482 for( row = rowCount - 1; row >= 0; row-- )
1492 int killRows = emptyRows - 1;
1495 else if( emptyRows == 0 )
1506 if( plotTab->GetLegendPosition() != plotTab->m_LastLegendPosition )
1508 plotTab->m_LastLegendPosition = plotTab->GetLegendPosition();
1531 static wxRegEx measureParamsRegEx( wxT(
"^"
1535 "([a-zA-Z]*)\\(([^\\)]+)\\)" ) );
1544 if(
text.IsEmpty() )
1551 wxString resultName = wxString::Format( wxS(
"meas_result_%u" ), aRow );
1552 wxString
result = wxS(
"?" );
1554 if( measureParamsRegEx.Matches(
text ) )
1556 wxString func = measureParamsRegEx.GetMatch(
text, 1 ).Upper();
1557 wxString signalType = measureParamsRegEx.GetMatch(
text, 2 ).Upper();
1558 wxString deviceName = measureParamsRegEx.GetMatch(
text, 3 );
1562 if( signalType.EndsWith( wxS(
"DB" ) ) )
1564 units = wxS(
"dB" );
1566 else if( signalType.StartsWith(
'I' ) )
1570 else if( signalType.StartsWith(
'P' ) )
1574 text = func +
" " + deviceName +
":power";
1581 if( func.EndsWith( wxS(
"_AT" ) ) )
1584 units = wxS(
"Hz" );
1588 else if( func.StartsWith( wxS(
"INTEG" ) ) )
1593 if ( signalType.StartsWith(
'P' ) )
1596 units += wxS(
".s" );
1606 units += wxS(
"·Hz" );
1614 units += wxS(
"·?" );
1627 wxString cmd = wxString::Format( wxS(
"meas %s %s %s" ), simType, resultName,
text );
1633 if( resultVec.size() > 0 )
1648 "the value of a passive R, L, C model or voltage or "
1649 "current source." ) );
1653 wxString ref = aSymbol->
GetRef( &aSheetPath );
1658 if( tuner->GetSymbolRef() == ref )
1681 const wxString& aRef,
const wxString& aValue )
1689 + wxString::Format(
_(
"%s not found" ), aRef ) );
1696 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
1697 embeddedFilesStack.push_back(
m_schematicFrame->Schematic().GetEmbeddedFiles() );
1700 embeddedFilesStack.push_back( symbolEmbeddedFiles );
1711 + wxString::Format(
_(
"%s is not tunable" ), aRef ) );
1783 wxString cmd = wxString::Format( wxS(
"fourier %s %s" ),
1801 m_simConsole->AppendText(
_(
"Error: no current simulation.\n" ) );
1810 m_simConsole->AppendText(
_(
"Error: simulation type not defined.\n" ) );
1816 m_simConsole->AppendText(
_(
"Error: simulation type doesn't support plotting.\n" ) );
1823 if( simType ==
ST_AC )
1828 else if( simType ==
ST_SP )
1838 plotTab->GetPlotWin()->UpdateAll();
1860 if( aNewSignals.count(
id ) == 0 )
1865 plotTab->
DeleteTrace( vectorName, traceType | subType );
1870 plotTab->
DeleteTrace( vectorName, traceType | subType );
1883 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType | subType ) )
1884 trace->SetName( aNewSignals.at(
id ) );
1891 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType | subType ) )
1892 trace->SetName( aNewSignals.at(
id ) );
1897 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
1898 trace->SetName( aNewSignals.at(
id ) );
1932 wxString simVectorName = aVectorName;
1935 simVectorName = simVectorName.AfterFirst(
'(' ).BeforeLast(
')' ) + wxS(
":power" );
1940 simulator()->
Command( wxString::Format( wxT(
"print %s" ), aVectorName ).ToStdString() );
1945 std::vector<double> data_x;
1946 std::vector<double> data_y;
1948 if( !aDataX || aClearData )
1952 if( aDataX->empty() && !aClearData )
1954 wxString xAxisName(
simulator()->GetXAxis( simType ) );
1956 if( xAxisName.IsEmpty() )
1962 unsigned int size = aDataX->size();
1972 wxFAIL_MSG( wxT(
"Plot type missing AC_PHASE or AC_MAG bit" ) );
1981 wxFAIL_MSG( wxT(
"Plot type missing AC_PHASE or SPT_SP_AMP bit" ) );
1996 wxFAIL_MSG( wxT(
"Unhandled plot type" ) );
2001 size_t sweepSize = std::numeric_limits<size_t>::max();
2003 if( simType ==
ST_DC
2010 sweepSize = aDataX->size() / sweepCount;
2027 size_t sweepSizeMulti = traceData.
xValues.size();
2028 size_t runCount = traceData.
yValues.size();
2030 if( sweepSizeMulti > 0 && runCount > 0 )
2032 std::vector<double> combinedX;
2033 std::vector<double> combinedY;
2035 combinedX.reserve( sweepSizeMulti * runCount );
2036 combinedY.reserve( sweepSizeMulti * runCount );
2038 for(
const std::vector<double>& runY : traceData.
yValues )
2040 if( runY.size() != sweepSizeMulti )
2043 combinedX.insert( combinedX.end(), traceData.
xValues.begin(), traceData.
xValues.end() );
2044 combinedY.insert( combinedY.end(), runY.begin(), runY.end() );
2049 if( combinedY.size() >= combinedX.size() && sweepSizeMulti > 0 )
2051 int sweepCountCombined = combinedX.empty() ? 0 :
static_cast<int>( combinedY.size() / sweepSizeMulti );
2053 if( sweepCountCombined > 0 )
2056 std::vector<wxString> labels;
2057 labels.reserve( sweepCountCombined );
2059 for(
int i = 0; i < sweepCountCombined && i < (int)
m_multiRunState.steps.size(); ++i )
2067 label += wxS(
", " );
2070 double value = it->second;
2076 labels.push_back( label );
2079 aPlotTab->
SetTraceData( trace, combinedX, combinedY, sweepCountCombined,
2080 sweepSizeMulti,
true, labels );
2093 if( data_y.size() >= size )
2094 aPlotTab->
SetTraceData( trace, *aDataX, data_y, sweepCount, sweepSize );
2104template <
typename T,
typename U,
typename R>
2113 wxGridCellAttrPtr attr =
m_signalsGrid->GetOrCreateCellAttrPtr( r,
static_cast<int>( t ) );
2115 if(
TRACE* trace = plotTab ? plotTab->
GetTrace( vectorName, traceType ) :
nullptr )
2117 attr->SetReadOnly();
2121 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
2124 if constexpr ( std::is_enum<T>::value )
2128 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxS(
"1" ) );
2132 if( !attr->HasRenderer() )
2135 if( !attr->HasEditor() )
2138 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
2139 attr->SetReadOnly(
false );
2148 if( !attr->HasRenderer() )
2149 attr->SetRenderer(
new wxGridCellBoolRenderer() );
2151 if( u > 0 && trace->HasCursor( u ) )
2152 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxS(
"1" ) );
2154 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2160 if constexpr ( std::is_enum<T>::value )
2164 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2171 attr->SetEditor(
nullptr );
2172 attr->SetRenderer(
nullptr );
2173 attr->SetReadOnly();
2174 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2183 for(
int row = 0; row <
m_signalsGrid->GetNumberRows(); ++row )
2208 auto quoteNetNames = [&]( wxString aExpression ) -> wxString
2210 std::vector<bool> mask( aExpression.length(),
false );
2212 auto isNetnameChar = []( wxUniChar aChar ) ->
bool
2214 wxUint32 value = aChar.GetValue();
2216 if( ( value >=
'0' && value <=
'9' ) || ( value >=
'A' && value <=
'Z' )
2217 || ( value >=
'a' && value <=
'z' ) )
2240 size_t pos = aExpression.find( netname );
2242 while( pos != wxString::npos )
2244 for(
size_t i = 0; i < netname.length(); ++i )
2246 mask[pos + i] =
true;
2248 pos = aExpression.find( netname, pos + 1 );
2252 for(
size_t i = 0; i < aExpression.length(); ++i )
2254 if( !mask[i] || ( i > 0 && mask[i - 1] ) )
2259 while( j < aExpression.length() )
2267 if( isNetnameChar( aExpression[j] ) )
2279 wxString quotedNetnames =
"";
2280 bool startQuote =
true;
2283 for(
size_t i = 0; i < aExpression.length(); i++ )
2285 if( mask[i] && startQuote )
2287 quotedNetnames = quotedNetnames +
"\"";
2290 else if( !mask[i] && !startQuote )
2292 quotedNetnames = quotedNetnames +
"\"";
2295 wxString ch = aExpression[i];
2296 quotedNetnames = quotedNetnames + ch;
2301 quotedNetnames = quotedNetnames +
"\"";
2303 return quotedNetnames;
2308 constexpr const char* cmd =
"let user{} = {}";
2310 simulator()->
Command(
"echo " + fmt::format( cmd,
id, signal.ToStdString() ) );
2311 simulator()->
Command( fmt::format( cmd,
id, quoteNetNames( signal ).ToStdString() ) );
2323 wxString ref = tuner->GetSymbolRef();
2324 KIID symbolId = tuner->GetSymbol( &sheetPath );
2330 reporter.
Report( wxString::Format(
_(
"%s not found" ), ref ) );
2338 reporter.
Report( wxString::Format(
_(
"%s is not tunable" ), ref ) );
2347 floatVal = overrideIt->second;
2349 floatVal = tuner->GetValue().ToDouble();
2361 wxTextFile file( aPath );
2366 wxString firstLine = file.GetFirstLine();
2368 bool legacy = firstLine.StartsWith( wxT(
"version " ) ) || firstLine.ToLong( &
dummy );
2393 wxFileName filename( aPath );
2405 wxFFileInputStream fp( aPath, wxT(
"rt" ) );
2406 wxStdInputStream fstream( fp );
2413 nlohmann::json js = nlohmann::json::parse( fstream,
nullptr,
true,
true );
2415 std::map<SIM_PLOT_TAB*, nlohmann::json> traceInfo;
2417 for(
const nlohmann::json& tab_js : js[
"tabs" ] )
2419 wxString simCommand;
2423 for(
const nlohmann::json& cmd : tab_js[
"commands" ] )
2425 if( cmd ==
".kicad adjustpaths" )
2427 else if( cmd ==
".save all" )
2429 else if( cmd ==
".probe alli" )
2431 else if( cmd ==
".probe allp" )
2433 else if( cmd ==
".kicad esavenone" )
2436 simCommand += wxString( cmd.get<wxString>() ).Trim();
2446 if( tab_js.contains(
"traces" ) )
2447 traceInfo[plotTab] = tab_js[
"traces" ];
2449 if( tab_js.contains(
"measurements" ) )
2451 for(
const nlohmann::json& m_js : tab_js[
"measurements" ] )
2452 plotTab->
Measurements().emplace_back( m_js[
"expr" ], m_js[
"format" ] );
2456 plotTab->
ShowGrid( tab_js[
"showGrid" ] );
2458 if( tab_js.contains(
"fixedY1scale" ) )
2460 const nlohmann::json& scale_js = tab_js[
"fixedY1scale" ];
2461 plotTab->
SetY1Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2465 if( tab_js.contains(
"fixedY2scale" ) )
2467 const nlohmann::json& scale_js = tab_js[
"fixedY2scale" ];
2468 plotTab->
SetY2Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2472 if( tab_js.contains(
"fixedY3scale" ) )
2475 const nlohmann::json& scale_js = tab_js[
"fixedY3scale" ];
2476 plotTab->
SetY3Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2480 if( tab_js.contains(
"legend" ) )
2482 const nlohmann::json& legend_js = tab_js[
"legend" ];
2487 if( tab_js.contains(
"margins" ) )
2489 const nlohmann::json& margins_js = tab_js[
"margins" ];
2491 margins_js[
"right" ],
2492 margins_js[
"bottom" ],
2493 margins_js[
"left" ] );
2500 if( js.contains(
"user_defined_signals" ) )
2502 for(
const nlohmann::json& signal_js : js[
"user_defined_signals" ] )
2508 m_simulatorFrame->LoadSimulator( simTab->GetSimCommand(), simTab->GetSimOptions() );
2511 firstTab->SetLastSchTextSimCommand( js[
"last_sch_text_sim_command"] );
2514 int tempCustomCursorsCnt = 0;
2516 if( js.contains(
"custom_cursors" ) )
2517 tempCustomCursorsCnt = js[
"custom_cursors"];
2519 tempCustomCursorsCnt = 2;
2529 int aCursorId,
const nlohmann::json& aCursor_js )
2531 if( aCursorId >= 1 )
2535 cursor->SetName( aSignalName );
2536 cursor->SetCoordX( aCursor_js[
"position" ] );
2538 aTrace->SetCursor( aCursorId,
cursor );
2542 if( aCursorId == -1 )
2553 aCursor_js[
"x_format"] );
2555 aCursor_js[
"y_format"] );
2565 for(
const auto& [ plotTab, traces_js ] : traceInfo )
2567 for(
const nlohmann::json& trace_js : traces_js )
2569 wxString signalName = trace_js[
"signal" ];
2571 TRACE* trace = plotTab->GetOrAddTrace( vectorName, trace_js[
"trace_type" ] );
2575 if( trace_js.contains(
"cursorD" ) )
2576 addCursor( plotTab, trace, signalName, -1, trace_js[
"cursorD" ] );
2578 std::vector<const char*> aVec;
2581 for(
int i = 1; i <= tempCustomCursorsCnt; i++ )
2583 wxString str =
"cursor" + std::to_string( i );
2584 aVec.emplace_back( str.c_str() );
2586 if( trace_js.contains( aVec[i - 1] ) )
2587 addCursor( plotTab, trace, signalName, i, trace_js[aVec[i - 1]] );
2590 if( trace_js.contains(
"color" ) )
2593 color.Set( wxString( trace_js[
"color"].get<wxString>() ) );
2595 plotTab->UpdateTraceStyle( trace );
2600 plotTab->UpdatePlotColors();
2603 catch( nlohmann::json::parse_error& error )
2605 wxLogTrace(
traceSettings, wxT(
"Json parse error reading %s: %s" ), aPath, error.what() );
2609 catch( nlohmann::json::type_error& error )
2611 wxLogTrace(
traceSettings, wxT(
"Json type error reading %s: %s" ), aPath, error.what() );
2615 catch( nlohmann::json::invalid_iterator& error )
2617 wxLogTrace(
traceSettings, wxT(
"Json invalid_iterator error reading %s: %s" ), aPath, error.what() );
2621 catch( nlohmann::json::out_of_range& error )
2623 wxLogTrace(
traceSettings, wxT(
"Json out_of_range error reading %s: %s" ), aPath, error.what() );
2629 wxLogTrace(
traceSettings, wxT(
"Error reading %s" ), aPath );
2638 int cursorIdAfterD = aCursorId;
2641 cursorIdAfterD = cursorIdAfterD - 1;
2646 aTraceJs[
"cursor" + wxString(
"" ) << aCursorId] =
2647 nlohmann::json( { {
"position",
cursor->GetCoords().x },
2654 aTraceJs[
"cursorD"] =
2665 wxFileName filename = aPath;
2670 file.Create( filename.GetFullPath(),
true );
2672 if( !file.IsOpened() )
2675 nlohmann::json tabs_js = nlohmann::json::array();
2686 nlohmann::json commands_js = nlohmann::json::array();
2693 commands_js.push_back(
".kicad adjustpaths" );
2696 commands_js.push_back(
".save all" );
2699 commands_js.push_back(
".probe alli" );
2702 commands_js.push_back(
".probe allp" );
2705 commands_js.push_back(
".kicad esavenone" );
2707 nlohmann::json tab_js = nlohmann::json(
2709 {
"commands", commands_js } } );
2713 nlohmann::json traces_js = nlohmann::json::array();
2715 auto findSignalName =
2716 [&](
const wxString& aVectorName ) -> wxString
2718 wxString vectorName;
2721 if( aVectorName.EndsWith(
_(
" (phase)" ) ) )
2722 suffix =
_(
" (phase)" );
2723 else if( aVectorName.EndsWith(
_(
" (gain)" ) ) )
2724 suffix =
_(
" (gain)" );
2726 vectorName = aVectorName.Left( aVectorName.Length() - suffix.Length() );
2731 return signal + suffix;
2737 for(
const auto& [
name, trace] : plotTab->GetTraces() )
2739 nlohmann::json trace_js = nlohmann::json(
2740 { {
"trace_type", (int) trace->GetType() },
2741 {
"signal", findSignalName( trace->GetDisplayName() ) },
2747 if( trace->GetCursor( 1 ) || trace->GetCursor( 2 ) )
2749 trace_js[
"cursorD"] = nlohmann::json(
2754 traces_js.push_back( trace_js );
2757 nlohmann::json measurements_js = nlohmann::json::array();
2759 for(
const auto& [
measurement, format ] : plotTab->Measurements() )
2761 measurements_js.push_back( nlohmann::json( { {
"expr",
measurement },
2762 {
"format", format } } ) );
2765 tab_js[
"traces" ] = traces_js;
2766 tab_js[
"measurements" ] = measurements_js;
2767 tab_js[
"dottedSecondary" ] = plotTab->GetDottedSecondary();
2768 tab_js[
"showGrid" ] = plotTab->IsGridShown();
2772 if( plotTab->GetY1Scale( &min, &max ) )
2773 tab_js[
"fixedY1scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2775 if( plotTab->GetY2Scale( &min, &max ) )
2776 tab_js[
"fixedY2scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2778 if( plotTab->GetY3Scale( &min, &max ) )
2779 tab_js[
"fixedY3scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2781 if( plotTab->IsLegendShown() )
2783 tab_js[
"legend" ] = nlohmann::json( { {
"x", plotTab->GetLegendPosition().x },
2784 {
"y", plotTab->GetLegendPosition().y } } );
2787 mpWindow* plotWin = plotTab->GetPlotWin();
2789 tab_js[
"margins" ] = nlohmann::json( { {
"left", plotWin->
GetMarginLeft() },
2795 tabs_js.push_back( tab_js );
2798 nlohmann::json userDefinedSignals_js = nlohmann::json::array();
2801 userDefinedSignals_js.push_back( signal );
2804 nlohmann::json js = nlohmann::json( { {
"version", 7 },
2805 {
"tabs", tabs_js },
2806 {
"user_defined_signals", userDefinedSignals_js },
2819 std::stringstream buffer;
2820 buffer << std::setw( 2 ) << js << std::endl;
2822 bool res = file.Write( buffer.str() );
2849 wxFAIL_MSG( wxString::Format( wxS(
"Unhandled simulation type: %d" ), (
int) aType ) );
2869 &source, &
scale, &pts, &fStart, &fStop, &saveAll );
2877 int& aSashPosition )
2879 bool isShown = aPanel->IsShown();
2882 aSashPosition = aSplitterWindow->GetSashPosition();
2884 aPanel->Show( !isShown );
2886 aSplitterWindow->SetSashInvisible( isShown );
2887 aSplitterWindow->SetSashPosition( isShown ? -1 : aSashPosition,
true );
2889 aSplitterWindow->UpdateSize();
2890 m_parent->Refresh();
2927 for(
size_t page = 0; page <
m_plotNotebook->GetPageCount(); page++ )
2972 std::vector<std::pair<wxString, wxString>>& measurements = plotTab->Measurements();
2974 measurements.clear();
3012 simulator()->
Command(
"setplot " + simTab->GetSpicePlotName().ToStdString() );
3026 for(
const auto& [
measurement, format ] : plotTab->Measurements() )
3034 if( plotTab->GetSimType() ==
ST_TRAN || plotTab->GetSimType() ==
ST_AC
3035 || plotTab->GetSimType() ==
ST_DC || plotTab->GetSimType() ==
ST_SP )
3072 CURSOR* cursor1 =
nullptr;
3073 wxString cursor1Name;
3074 wxString cursor1Units;
3075 CURSOR* cursor2 =
nullptr;
3076 wxString cursor2Name;
3077 wxString cursor2Units;
3080 [&](
TRACE* aTrace ) -> wxString
3101 [&](
TRACE* aTrace ) -> wxString
3122 [
this](
double aValue,
int aCursorId,
int aCol ) -> wxString
3124 if( ( !
m_simulatorFrame->SimFinished() && aCol == 1 ) || std::isnan( aValue ) )
3135 cursor1Name = getNameY( trace );
3136 cursor1Units = getUnitsY( trace );
3138 wxRealPoint coords =
cursor->GetCoords();
3158 cursor2Name = getNameY( trace );
3159 cursor2Units = getUnitsY( trace );
3161 wxRealPoint coords =
cursor->GetCoords();
3176 if( cursor1 && cursor2 && cursor1Units == cursor2Units )
3185 signal = wxString::Format( wxS(
"%s[2 - 1]" ), cursor2->
GetName() );
3187 signal = wxString::Format( wxS(
"%s - %s" ), cursor2->
GetName(), cursor1->
GetName() );
3198 wxString valColName =
_(
"Value" );
3200 if( !cursor1Name.IsEmpty() )
3202 if( cursor2Name.IsEmpty() || cursor1Name == cursor2Name )
3203 valColName = cursor1Name;
3205 else if( !cursor2Name.IsEmpty() )
3207 valColName = cursor2Name;
3221 wxString cursName = getNameY( trace );
3222 wxString cursUnits = getUnitsY( trace );
3224 wxRealPoint coords =
cursor->GetCoords();
3239 valColName =
_(
"Value" );
3241 if( !cursName.IsEmpty()
3244 valColName = cursName;
3265 plotTab->ResetScales(
true );
3287 std::vector<wxString> signals;
3289 for(
const std::string& vec :
simulator()->AllVectors() )
3290 signals.emplace_back( vec );
3298 std::vector<wxString> signals;
3300 for(
const wxString& signal :
m_signals )
3301 signals.emplace_back( signal );
3304 signals.emplace_back( signal );
3322 bool storeMultiRun =
false;
3328 storeMultiRun =
true;
3351 if( simType ==
ST_NOISE && aFinal )
3353 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3362 for(
const std::string& vec :
simulator()->AllVectors() )
3367 msg.Printf( wxS(
"%s: %sV\n" ), vec, value );
3378 wxCHECK_RET( plotTab, wxString::Format( wxT(
"No SIM_PLOT_TAB for: %s" ),
3379 magic_enum::enum_name( simType ) ) );
3388 std::map<TRACE*, TRACE_INFO> traceMap;
3391 traceMap[ trace ] = { wxEmptyString,
SPT_UNKNOWN,
false };
3396 for(
const wxString& signal :
m_signals )
3401 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
3402 traceMap[ trace ] = { vectorName, traceType,
false };
3410 if( simType ==
ST_AC )
3416 if(
TRACE* trace = plotTab->
GetTrace( vectorName, subType ) )
3417 traceMap[ trace ] = { vectorName, subType, !aFinal };
3420 else if( simType ==
ST_SP )
3426 if(
TRACE* trace = plotTab->
GetTrace( vectorName, subType ) )
3427 traceMap[trace] = { vectorName, subType, !aFinal };
3432 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
3433 traceMap[ trace ] = { vectorName, traceType, !aFinal };
3439 for(
const auto& [ trace, traceInfo ] : traceMap )
3441 if( traceInfo.Vector.IsEmpty() )
3445 for(
const auto& [ trace,
info ] : traceMap )
3447 std::vector<double> data_x;
3449 if( !
info.Vector.IsEmpty() )
3467 else if( simType ==
ST_OP && aFinal )
3469 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3472 for(
const std::string& vec :
simulator()->AllVectors() )
3476 if( val_list.empty() )
3483 const size_t tab = 25;
3484 size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1;
3488 case SPT_VOLTAGE: value.Append( wxS(
"V" ) );
break;
3489 case SPT_CURRENT: value.Append( wxS(
"A" ) );
break;
3490 case SPT_POWER: value.Append( wxS(
"W" ) );
break;
3491 default: value.Append( wxS(
"?" ) );
break;
3494 msg.Printf( wxT(
"%s%s\n" ),
3495 ( signal + wxT(
":" ) ).Pad( padding, wxUniChar(
' ' ) ),
3502 signal = signal.SubString( 2, signal.Length() - 2 );
3505 signal += wxS(
":power" );
3507 m_schematicFrame->Schematic().SetOperatingPoint( signal, val_list.at( 0 ) );
3510 else if( simType ==
ST_PZ && aFinal )
3512 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3573 std::vector<TUNER_SLIDER*> multiTuners;
3578 multiTuners.push_back( tuner );
3581 if( multiTuners.empty() )
3615 else if( tunersChanged )
3624 for(
const auto& entry : step.
overrides )
3631 const std::vector<TUNER_SLIDER*>& aTuners )
const
3633 std::vector<MULTI_RUN_STEP> steps;
3635 if( aTuners.empty() )
3638 std::vector<std::vector<double>> tunerValues;
3639 tunerValues.reserve( aTuners.size() );
3646 double startValue = tuner->GetMin().ToDouble();
3647 double endValue = tuner->GetMax().ToDouble();
3648 int stepCount = std::max( 2, tuner->GetStepCount() );
3653 double increment = ( endValue - startValue ) /
static_cast<double>( stepCount - 1 );
3655 std::vector<double> values;
3656 values.reserve( stepCount );
3658 for(
int ii = 0; ii < stepCount; ++ii )
3659 values.push_back( startValue + increment * ii );
3661 tunerValues.push_back( std::move( values ) );
3669 std::vector<double> currentValues( aTuners.size(), 0.0 );
3671 auto generate = [&](
auto&& self,
size_t depth ) ->
void
3673 if( steps.size() >=
static_cast<size_t>( limit ) )
3676 if( depth == aTuners.size() )
3680 for(
size_t ii = 0; ii < aTuners.size(); ++ii )
3681 step.
overrides.emplace( aTuners[ii], currentValues[ii] );
3683 steps.push_back( std::move( step ) );
3687 for(
double value : tunerValues[depth] )
3689 currentValues[depth] = value;
3690 self( self, depth + 1 );
3692 if( steps.size() >=
static_cast<size_t>( limit ) )
3697 generate( generate, 0 );
3705 return fmt::format(
"{}|{}", aVectorName.ToStdString(), aTraceType );
3710 const std::vector<double>& aX,
3711 const std::vector<double>& aY )
3713 if( aX.empty() || aY.empty() )
3724 if( trace.
xValues.size() != aX.size() )
3729 if( trace.
yValues.size() <= index )
3730 trace.
yValues.resize( index + 1 );
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
Hold a translatable error message and may be used when throwing exceptions containing a translated er...
const wxString What() 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.
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
void WriteFields(std::vector< SCH_FIELD > &aFields) const
void SetParamValue(int aParamIndex, const std::string &aValue, SIM_VALUE::NOTATION aNotation=SIM_VALUE::NOTATION::SI)
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.