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() );
1701 embeddedFilesStack.push_back( symbolEmbeddedFiles );
1714 + wxString::Format(
_(
"%s is not tunable" ), aRef ) );
1718 model.SetParamValue( tunerParam->
info.
name, std::string( aValue.ToUTF8() ) );
1786 wxString cmd = wxString::Format( wxS(
"fourier %s %s" ),
1804 m_simConsole->AppendText(
_(
"Error: no current simulation.\n" ) );
1813 m_simConsole->AppendText(
_(
"Error: simulation type not defined.\n" ) );
1819 m_simConsole->AppendText(
_(
"Error: simulation type doesn't support plotting.\n" ) );
1826 if( simType ==
ST_AC )
1831 else if( simType ==
ST_SP )
1841 plotTab->GetPlotWin()->UpdateAll();
1863 if( aNewSignals.count(
id ) == 0 )
1868 plotTab->
DeleteTrace( vectorName, traceType | subType );
1873 plotTab->
DeleteTrace( vectorName, traceType | subType );
1886 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType | subType ) )
1887 trace->SetName( aNewSignals.at(
id ) );
1894 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType | subType ) )
1895 trace->SetName( aNewSignals.at(
id ) );
1900 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
1901 trace->SetName( aNewSignals.at(
id ) );
1935 wxString simVectorName = aVectorName;
1938 simVectorName = simVectorName.AfterFirst(
'(' ).BeforeLast(
')' ) + wxS(
":power" );
1943 simulator()->
Command( wxString::Format( wxT(
"print %s" ), aVectorName ).ToStdString() );
1948 std::vector<double> data_x;
1949 std::vector<double> data_y;
1951 if( !aDataX || aClearData )
1955 if( aDataX->empty() && !aClearData )
1957 wxString xAxisName(
simulator()->GetXAxis( simType ) );
1959 if( xAxisName.IsEmpty() )
1965 unsigned int size = aDataX->size();
1975 wxFAIL_MSG( wxT(
"Plot type missing AC_PHASE or AC_MAG bit" ) );
1984 wxFAIL_MSG( wxT(
"Plot type missing AC_PHASE or SPT_SP_AMP bit" ) );
1999 wxFAIL_MSG( wxT(
"Unhandled plot type" ) );
2004 size_t sweepSize = std::numeric_limits<size_t>::max();
2006 if( simType ==
ST_DC
2013 sweepSize = aDataX->size() / sweepCount;
2030 size_t sweepSizeMulti = traceData.
xValues.size();
2031 size_t runCount = traceData.
yValues.size();
2033 if( sweepSizeMulti > 0 && runCount > 0 )
2035 std::vector<double> combinedX;
2036 std::vector<double> combinedY;
2038 combinedX.reserve( sweepSizeMulti * runCount );
2039 combinedY.reserve( sweepSizeMulti * runCount );
2041 for(
const std::vector<double>& runY : traceData.
yValues )
2043 if( runY.size() != sweepSizeMulti )
2046 combinedX.insert( combinedX.end(), traceData.
xValues.begin(), traceData.
xValues.end() );
2047 combinedY.insert( combinedY.end(), runY.begin(), runY.end() );
2052 if( combinedY.size() >= combinedX.size() && sweepSizeMulti > 0 )
2054 int sweepCountCombined = combinedX.empty() ? 0 :
static_cast<int>( combinedY.size() / sweepSizeMulti );
2056 if( sweepCountCombined > 0 )
2059 std::vector<wxString> labels;
2060 labels.reserve( sweepCountCombined );
2062 for(
int i = 0; i < sweepCountCombined && i < (int)
m_multiRunState.steps.size(); ++i )
2070 label += wxS(
", " );
2073 double value = it->second;
2079 labels.push_back( label );
2082 aPlotTab->
SetTraceData( trace, combinedX, combinedY, sweepCountCombined,
2083 sweepSizeMulti,
true, labels );
2096 if( data_y.size() >= size )
2097 aPlotTab->
SetTraceData( trace, *aDataX, data_y, sweepCount, sweepSize );
2107template <
typename T,
typename U,
typename R>
2116 wxGridCellAttrPtr attr =
m_signalsGrid->GetOrCreateCellAttrPtr( r,
static_cast<int>( t ) );
2118 if(
TRACE* trace = plotTab ? plotTab->
GetTrace( vectorName, traceType ) :
nullptr )
2120 attr->SetReadOnly();
2124 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
2127 if constexpr ( std::is_enum<T>::value )
2131 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxS(
"1" ) );
2135 if( !attr->HasRenderer() )
2138 if( !attr->HasEditor() )
2141 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
2142 attr->SetReadOnly(
false );
2151 if( !attr->HasRenderer() )
2152 attr->SetRenderer(
new wxGridCellBoolRenderer() );
2154 if( u > 0 && trace->HasCursor( u ) )
2155 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxS(
"1" ) );
2157 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2163 if constexpr ( std::is_enum<T>::value )
2167 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2174 attr->SetEditor(
nullptr );
2175 attr->SetRenderer(
nullptr );
2176 attr->SetReadOnly();
2177 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2186 for(
int row = 0; row <
m_signalsGrid->GetNumberRows(); ++row )
2211 auto quoteNetNames = [&]( wxString aExpression ) -> wxString
2213 std::vector<bool> mask( aExpression.length(),
false );
2215 auto isNetnameChar = []( wxUniChar aChar ) ->
bool
2217 wxUint32 value = aChar.GetValue();
2219 if( ( value >=
'0' && value <=
'9' ) || ( value >=
'A' && value <=
'Z' )
2220 || ( value >=
'a' && value <=
'z' ) )
2243 size_t pos = aExpression.find( netname );
2245 while( pos != wxString::npos )
2247 for(
size_t i = 0; i < netname.length(); ++i )
2249 mask[pos + i] =
true;
2251 pos = aExpression.find( netname, pos + 1 );
2255 for(
size_t i = 0; i < aExpression.length(); ++i )
2257 if( !mask[i] || ( i > 0 && mask[i - 1] ) )
2262 while( j < aExpression.length() )
2270 if( isNetnameChar( aExpression[j] ) )
2282 wxString quotedNetnames =
"";
2283 bool startQuote =
true;
2286 for(
size_t i = 0; i < aExpression.length(); i++ )
2288 if( mask[i] && startQuote )
2290 quotedNetnames = quotedNetnames +
"\"";
2293 else if( !mask[i] && !startQuote )
2295 quotedNetnames = quotedNetnames +
"\"";
2298 wxString ch = aExpression[i];
2299 quotedNetnames = quotedNetnames + ch;
2304 quotedNetnames = quotedNetnames +
"\"";
2306 return quotedNetnames;
2311 constexpr const char* cmd =
"let user{} = {}";
2313 simulator()->
Command(
"echo " + fmt::format( cmd,
id, signal.ToStdString() ) );
2314 simulator()->
Command( fmt::format( cmd,
id, quoteNetNames( signal ).ToStdString() ) );
2326 wxString ref = tuner->GetSymbolRef();
2327 KIID symbolId = tuner->GetSymbol( &sheetPath );
2333 reporter.
Report( wxString::Format(
_(
"%s not found" ), ref ) );
2341 reporter.
Report( wxString::Format(
_(
"%s is not tunable" ), ref ) );
2350 floatVal = overrideIt->second;
2352 floatVal = tuner->GetValue().ToDouble();
2364 wxTextFile file( aPath );
2369 wxString firstLine = file.GetFirstLine();
2371 bool legacy = firstLine.StartsWith( wxT(
"version " ) ) || firstLine.ToLong( &
dummy );
2396 wxFileName filename( aPath );
2408 wxFFileInputStream fp( aPath, wxT(
"rt" ) );
2409 wxStdInputStream fstream( fp );
2416 nlohmann::json js = nlohmann::json::parse( fstream,
nullptr,
true,
true );
2418 std::map<SIM_PLOT_TAB*, nlohmann::json> traceInfo;
2420 for(
const nlohmann::json& tab_js : js[
"tabs" ] )
2422 wxString simCommand;
2426 for(
const nlohmann::json& cmd : tab_js[
"commands" ] )
2428 if( cmd ==
".kicad adjustpaths" )
2430 else if( cmd ==
".save all" )
2432 else if( cmd ==
".probe alli" )
2434 else if( cmd ==
".probe allp" )
2436 else if( cmd ==
".kicad esavenone" )
2439 simCommand += wxString( cmd.get<wxString>() ).Trim();
2449 if( tab_js.contains(
"traces" ) )
2450 traceInfo[plotTab] = tab_js[
"traces" ];
2452 if( tab_js.contains(
"measurements" ) )
2454 for(
const nlohmann::json& m_js : tab_js[
"measurements" ] )
2455 plotTab->
Measurements().emplace_back( m_js[
"expr" ], m_js[
"format" ] );
2459 plotTab->
ShowGrid( tab_js[
"showGrid" ] );
2461 if( tab_js.contains(
"fixedY1scale" ) )
2463 const nlohmann::json& scale_js = tab_js[
"fixedY1scale" ];
2464 plotTab->
SetY1Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2468 if( tab_js.contains(
"fixedY2scale" ) )
2470 const nlohmann::json& scale_js = tab_js[
"fixedY2scale" ];
2471 plotTab->
SetY2Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2475 if( tab_js.contains(
"fixedY3scale" ) )
2478 const nlohmann::json& scale_js = tab_js[
"fixedY3scale" ];
2479 plotTab->
SetY3Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2483 if( tab_js.contains(
"legend" ) )
2485 const nlohmann::json& legend_js = tab_js[
"legend" ];
2490 if( tab_js.contains(
"margins" ) )
2492 const nlohmann::json& margins_js = tab_js[
"margins" ];
2494 margins_js[
"right" ],
2495 margins_js[
"bottom" ],
2496 margins_js[
"left" ] );
2503 if( js.contains(
"user_defined_signals" ) )
2505 for(
const nlohmann::json& signal_js : js[
"user_defined_signals" ] )
2511 m_simulatorFrame->LoadSimulator( simTab->GetSimCommand(), simTab->GetSimOptions() );
2514 firstTab->SetLastSchTextSimCommand( js[
"last_sch_text_sim_command"] );
2517 int tempCustomCursorsCnt = 0;
2519 if( js.contains(
"custom_cursors" ) )
2520 tempCustomCursorsCnt = js[
"custom_cursors"];
2522 tempCustomCursorsCnt = 2;
2532 int aCursorId,
const nlohmann::json& aCursor_js )
2534 if( aCursorId >= 1 )
2538 cursor->SetName( aSignalName );
2539 cursor->SetCoordX( aCursor_js[
"position" ] );
2541 aTrace->SetCursor( aCursorId,
cursor );
2545 if( aCursorId == -1 )
2556 aCursor_js[
"x_format"] );
2558 aCursor_js[
"y_format"] );
2568 for(
const auto& [ plotTab, traces_js ] : traceInfo )
2570 for(
const nlohmann::json& trace_js : traces_js )
2572 wxString signalName = trace_js[
"signal" ];
2574 TRACE* trace = plotTab->GetOrAddTrace( vectorName, trace_js[
"trace_type" ] );
2578 if( trace_js.contains(
"cursorD" ) )
2579 addCursor( plotTab, trace, signalName, -1, trace_js[
"cursorD" ] );
2581 std::vector<const char*> aVec;
2584 for(
int i = 1; i <= tempCustomCursorsCnt; i++ )
2586 wxString str =
"cursor" + std::to_string( i );
2587 aVec.emplace_back( str.c_str() );
2589 if( trace_js.contains( aVec[i - 1] ) )
2590 addCursor( plotTab, trace, signalName, i, trace_js[aVec[i - 1]] );
2593 if( trace_js.contains(
"color" ) )
2596 color.Set( wxString( trace_js[
"color"].get<wxString>() ) );
2598 plotTab->UpdateTraceStyle( trace );
2603 plotTab->UpdatePlotColors();
2606 catch( nlohmann::json::parse_error& error )
2608 wxLogTrace(
traceSettings, wxT(
"Json parse error reading %s: %s" ), aPath, error.what() );
2612 catch( nlohmann::json::type_error& error )
2614 wxLogTrace(
traceSettings, wxT(
"Json type error reading %s: %s" ), aPath, error.what() );
2618 catch( nlohmann::json::invalid_iterator& error )
2620 wxLogTrace(
traceSettings, wxT(
"Json invalid_iterator error reading %s: %s" ), aPath, error.what() );
2624 catch( nlohmann::json::out_of_range& error )
2626 wxLogTrace(
traceSettings, wxT(
"Json out_of_range error reading %s: %s" ), aPath, error.what() );
2632 wxLogTrace(
traceSettings, wxT(
"Error reading %s" ), aPath );
2641 int cursorIdAfterD = aCursorId;
2644 cursorIdAfterD = cursorIdAfterD - 1;
2649 aTraceJs[
"cursor" + wxString(
"" ) << aCursorId] =
2650 nlohmann::json( { {
"position",
cursor->GetCoords().x },
2657 aTraceJs[
"cursorD"] =
2668 wxFileName filename = aPath;
2673 file.Create( filename.GetFullPath(),
true );
2675 if( !file.IsOpened() )
2678 nlohmann::json tabs_js = nlohmann::json::array();
2689 nlohmann::json commands_js = nlohmann::json::array();
2696 commands_js.push_back(
".kicad adjustpaths" );
2699 commands_js.push_back(
".save all" );
2702 commands_js.push_back(
".probe alli" );
2705 commands_js.push_back(
".probe allp" );
2708 commands_js.push_back(
".kicad esavenone" );
2710 nlohmann::json tab_js = nlohmann::json(
2712 {
"commands", commands_js } } );
2716 nlohmann::json traces_js = nlohmann::json::array();
2718 auto findSignalName =
2719 [&](
const wxString& aVectorName ) -> wxString
2721 wxString vectorName;
2724 if( aVectorName.EndsWith(
_(
" (phase)" ) ) )
2725 suffix =
_(
" (phase)" );
2726 else if( aVectorName.EndsWith(
_(
" (gain)" ) ) )
2727 suffix =
_(
" (gain)" );
2729 vectorName = aVectorName.Left( aVectorName.Length() - suffix.Length() );
2734 return signal + suffix;
2740 for(
const auto& [
name, trace] : plotTab->GetTraces() )
2742 nlohmann::json trace_js = nlohmann::json(
2743 { {
"trace_type", (int) trace->GetType() },
2744 {
"signal", findSignalName( trace->GetDisplayName() ) },
2750 if( trace->GetCursor( 1 ) || trace->GetCursor( 2 ) )
2752 trace_js[
"cursorD"] = nlohmann::json(
2757 traces_js.push_back( trace_js );
2760 nlohmann::json measurements_js = nlohmann::json::array();
2762 for(
const auto& [
measurement, format ] : plotTab->Measurements() )
2764 measurements_js.push_back( nlohmann::json( { {
"expr",
measurement },
2765 {
"format", format } } ) );
2768 tab_js[
"traces" ] = traces_js;
2769 tab_js[
"measurements" ] = measurements_js;
2770 tab_js[
"dottedSecondary" ] = plotTab->GetDottedSecondary();
2771 tab_js[
"showGrid" ] = plotTab->IsGridShown();
2775 if( plotTab->GetY1Scale( &min, &max ) )
2776 tab_js[
"fixedY1scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2778 if( plotTab->GetY2Scale( &min, &max ) )
2779 tab_js[
"fixedY2scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2781 if( plotTab->GetY3Scale( &min, &max ) )
2782 tab_js[
"fixedY3scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2784 if( plotTab->IsLegendShown() )
2786 tab_js[
"legend" ] = nlohmann::json( { {
"x", plotTab->GetLegendPosition().x },
2787 {
"y", plotTab->GetLegendPosition().y } } );
2790 mpWindow* plotWin = plotTab->GetPlotWin();
2792 tab_js[
"margins" ] = nlohmann::json( { {
"left", plotWin->
GetMarginLeft() },
2798 tabs_js.push_back( tab_js );
2801 nlohmann::json userDefinedSignals_js = nlohmann::json::array();
2804 userDefinedSignals_js.push_back( signal );
2807 nlohmann::json js = nlohmann::json( { {
"version", 7 },
2808 {
"tabs", tabs_js },
2809 {
"user_defined_signals", userDefinedSignals_js },
2822 std::stringstream buffer;
2823 buffer << std::setw( 2 ) << js << std::endl;
2825 bool res = file.Write( buffer.str() );
2852 wxFAIL_MSG( wxString::Format( wxS(
"Unhandled simulation type: %d" ), (
int) aType ) );
2872 &source, &
scale, &pts, &fStart, &fStop, &saveAll );
2880 int& aSashPosition )
2882 bool isShown = aPanel->IsShown();
2885 aSashPosition = aSplitterWindow->GetSashPosition();
2887 aPanel->Show( !isShown );
2889 aSplitterWindow->SetSashInvisible( isShown );
2890 aSplitterWindow->SetSashPosition( isShown ? -1 : aSashPosition,
true );
2892 aSplitterWindow->UpdateSize();
2893 m_parent->Refresh();
2930 for(
size_t page = 0; page <
m_plotNotebook->GetPageCount(); page++ )
2978 std::vector<std::pair<wxString, wxString>>& measurements = plotTab->Measurements();
2980 measurements.clear();
3018 simulator()->
Command(
"setplot " + simTab->GetSpicePlotName().ToStdString() );
3035 for(
const auto& [
measurement, format ] : plotTab->Measurements() )
3043 if( plotTab->GetSimType() ==
ST_TRAN || plotTab->GetSimType() ==
ST_AC
3044 || plotTab->GetSimType() ==
ST_DC || plotTab->GetSimType() ==
ST_SP )
3081 CURSOR* cursor1 =
nullptr;
3082 wxString cursor1Name;
3083 wxString cursor1Units;
3084 CURSOR* cursor2 =
nullptr;
3085 wxString cursor2Name;
3086 wxString cursor2Units;
3089 [&](
TRACE* aTrace ) -> wxString
3110 [&](
TRACE* aTrace ) -> wxString
3131 [
this](
double aValue,
int aCursorId,
int aCol ) -> wxString
3133 if( ( !
m_simulatorFrame->SimFinished() && aCol == 1 ) || std::isnan( aValue ) )
3144 cursor1Name = getNameY( trace );
3145 cursor1Units = getUnitsY( trace );
3147 wxRealPoint coords =
cursor->GetCoords();
3167 cursor2Name = getNameY( trace );
3168 cursor2Units = getUnitsY( trace );
3170 wxRealPoint coords =
cursor->GetCoords();
3185 if( cursor1 && cursor2 && cursor1Units == cursor2Units )
3194 signal = wxString::Format( wxS(
"%s[2 - 1]" ), cursor2->
GetName() );
3196 signal = wxString::Format( wxS(
"%s - %s" ), cursor2->
GetName(), cursor1->
GetName() );
3207 wxString valColName =
_(
"Value" );
3209 if( !cursor1Name.IsEmpty() )
3211 if( cursor2Name.IsEmpty() || cursor1Name == cursor2Name )
3212 valColName = cursor1Name;
3214 else if( !cursor2Name.IsEmpty() )
3216 valColName = cursor2Name;
3230 wxString cursName = getNameY( trace );
3231 wxString cursUnits = getUnitsY( trace );
3233 wxRealPoint coords =
cursor->GetCoords();
3248 valColName =
_(
"Value" );
3250 if( !cursName.IsEmpty()
3253 valColName = cursName;
3274 plotTab->ResetScales(
true );
3296 std::vector<wxString> signals;
3298 for(
const std::string& vec :
simulator()->AllVectors() )
3299 signals.emplace_back( vec );
3307 std::vector<wxString> signals;
3309 for(
const wxString& signal :
m_signals )
3310 signals.emplace_back( signal );
3313 signals.emplace_back( signal );
3331 bool storeMultiRun =
false;
3337 storeMultiRun =
true;
3360 if( simType ==
ST_NOISE && aFinal )
3362 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3371 for(
const std::string& vec :
simulator()->AllVectors() )
3376 msg.Printf( wxS(
"%s: %sV\n" ), vec, value );
3387 wxCHECK_RET( plotTab, wxString::Format( wxT(
"No SIM_PLOT_TAB for: %s" ),
3388 magic_enum::enum_name( simType ) ) );
3397 std::map<TRACE*, TRACE_INFO> traceMap;
3400 traceMap[ trace ] = { wxEmptyString,
SPT_UNKNOWN,
false };
3405 for(
const wxString& signal :
m_signals )
3410 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
3411 traceMap[ trace ] = { vectorName, traceType,
false };
3419 if( simType ==
ST_AC )
3425 if(
TRACE* trace = plotTab->
GetTrace( vectorName, subType ) )
3426 traceMap[ trace ] = { vectorName, subType, !aFinal };
3429 else if( simType ==
ST_SP )
3435 if(
TRACE* trace = plotTab->
GetTrace( vectorName, subType ) )
3436 traceMap[trace] = { vectorName, subType, !aFinal };
3441 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
3442 traceMap[ trace ] = { vectorName, traceType, !aFinal };
3448 for(
const auto& [ trace, traceInfo ] : traceMap )
3450 if( traceInfo.Vector.IsEmpty() )
3454 for(
const auto& [ trace,
info ] : traceMap )
3456 std::vector<double> data_x;
3458 if( !
info.Vector.IsEmpty() )
3476 else if( simType ==
ST_OP && aFinal )
3478 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3481 for(
const std::string& vec :
simulator()->AllVectors() )
3485 if( val_list.empty() )
3492 const size_t tab = 25;
3493 size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1;
3497 case SPT_VOLTAGE: value.Append( wxS(
"V" ) );
break;
3498 case SPT_CURRENT: value.Append( wxS(
"A" ) );
break;
3499 case SPT_POWER: value.Append( wxS(
"W" ) );
break;
3500 default: value.Append( wxS(
"?" ) );
break;
3503 msg.Printf( wxT(
"%s%s\n" ),
3504 ( signal + wxT(
":" ) ).Pad( padding, wxUniChar(
' ' ) ),
3511 signal = signal.SubString( 2, signal.Length() - 2 );
3514 signal += wxS(
":power" );
3516 m_schematicFrame->Schematic().SetOperatingPoint( signal, val_list.at( 0 ) );
3519 else if( simType ==
ST_PZ && aFinal )
3521 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3582 std::vector<TUNER_SLIDER*> multiTuners;
3587 multiTuners.push_back( tuner );
3590 if( multiTuners.empty() )
3624 else if( tunersChanged )
3633 for(
const auto& entry : step.
overrides )
3640 const std::vector<TUNER_SLIDER*>& aTuners )
const
3642 std::vector<MULTI_RUN_STEP> steps;
3644 if( aTuners.empty() )
3647 std::vector<std::vector<double>> tunerValues;
3648 tunerValues.reserve( aTuners.size() );
3655 double startValue = tuner->GetMin().ToDouble();
3656 double endValue = tuner->GetMax().ToDouble();
3657 int stepCount = std::max( 2, tuner->GetStepCount() );
3662 double increment = ( endValue - startValue ) /
static_cast<double>( stepCount - 1 );
3664 std::vector<double> values;
3665 values.reserve( stepCount );
3667 for(
int ii = 0; ii < stepCount; ++ii )
3668 values.push_back( startValue + increment * ii );
3670 tunerValues.push_back( std::move( values ) );
3678 std::vector<double> currentValues( aTuners.size(), 0.0 );
3680 auto generate = [&](
auto&& self,
size_t depth ) ->
void
3682 if( steps.size() >=
static_cast<size_t>( limit ) )
3685 if( depth == aTuners.size() )
3689 for(
size_t ii = 0; ii < aTuners.size(); ++ii )
3690 step.
overrides.emplace( aTuners[ii], currentValues[ii] );
3692 steps.push_back( std::move( step ) );
3696 for(
double value : tunerValues[depth] )
3698 currentValues[depth] = value;
3699 self( self, depth + 1 );
3701 if( steps.size() >=
static_cast<size_t>( limit ) )
3706 generate( generate, 0 );
3714 return fmt::format(
"{}|{}", aVectorName.ToStdString(), aTraceType );
3719 const std::vector<double>& aX,
3720 const std::vector<double>& aY )
3722 if( aX.empty() || aY.empty() )
3733 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.