32#include <fmt/format.h>
33#include <wx/wfstream.h>
34#include <wx/stdstream.h>
36#include <wx/clipbrd.h>
38#include <wx/tokenzr.h>
59#include <magic_enum.hpp>
65 int res =
static_cast<int>( aFirst ) |
static_cast<int>( aSecond);
126 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
override;
177 menu.AppendSeparator();
178 menu.Append(
MYID_FOURIER,
_(
"Perform Fourier Analysis..." ) );
181 menu.AppendSeparator();
184 menu.AppendSeparator();
187 m_grid->PopupMenu( &menu );
194 menu.AppendSeparator();
196 wxString msg =
m_grid->GetColLabelValue(
m_grid->GetNumberCols() - 1 );
198 menu.AppendSeparator();
201 m_grid->PopupMenu( &menu );
207 m_grid->PopupMenu( &menu );
214 std::vector<wxString> signals;
216 wxGridCellCoordsArray cells1 =
m_grid->GetSelectionBlockTopLeft();
217 wxGridCellCoordsArray cells2 =
m_grid->GetSelectionBlockBottomRight();
219 for(
size_t i = 0; i < cells1.Count(); i++ )
223 for(
int j = cells1[i].GetRow(); j < cells2[i].GetRow() + 1; j++ )
225 signals.push_back(
m_grid->GetCellValue( j, cells1[i].GetCol() ) );
230 wxGridCellCoordsArray cells3 =
m_grid->GetSelectedCells();
232 for(
size_t i = 0; i < cells3.Count(); i++ )
235 signals.push_back(
m_grid->GetCellValue( cells3[i].GetRow(), cells3[i].GetCol() ) );
238 if( signals.size() < 1 )
241 auto addMeasurement =
242 [
this](
const wxString& cmd, wxString signal )
244 if( signal.EndsWith(
_(
" (phase)" ) ) )
247 if( signal.EndsWith(
_(
" (gain)" ) ) || signal.EndsWith(
_(
" (amplitude)" ) ) )
249 signal = signal.Left( signal.length() - 7 );
251 if( signal.Upper().StartsWith( wxS(
"V(" ) ) )
252 signal = wxS(
"vdb" ) + signal.Mid( 1 );
255 m_parent->AddMeasurement( cmd + wxS(
" " ) + signal );
260 for(
const wxString& signal : signals )
261 addMeasurement( wxS(
"MIN" ), signal );
265 for(
const wxString& signal : signals )
266 addMeasurement( wxS(
"MAX" ), signal );
270 for(
const wxString& signal : signals )
271 addMeasurement( wxS(
"AVG" ), signal );
275 for(
const wxString& signal : signals )
276 addMeasurement( wxS(
"RMS" ), signal );
280 for(
const wxString& signal : signals )
281 addMeasurement( wxS(
"PP" ), signal );
285 for(
const wxString& signal : signals )
286 addMeasurement( wxS(
"MIN_AT" ), signal );
290 for(
const wxString& signal : signals )
291 addMeasurement( wxS(
"MAX_AT" ), signal );
295 for(
const wxString& signal : signals )
296 addMeasurement( wxS(
"INTEG" ), signal );
301 wxString fundamental = wxT(
"1K" );
303 if( signals.size() == 1 )
304 title.Printf(
_(
"Fourier Analysis of %s" ), signals[0] );
306 title =
_(
"Fourier Analyses of Multiple Signals" );
316 for(
const wxString& signal : signals )
317 m_parent->DoFourier( signal, fundamental );
324 for(
const wxString& signal : signals )
332 if( wxTheClipboard->Open() )
334 wxTheClipboard->SetData(
new wxTextDataObject( txt ) );
335 wxTheClipboard->Flush();
336 wxTheClipboard->Close();
361 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
override;
381 menu.AppendSeparator();
391 [
this](
int row ) -> wxString
395 if( signal.EndsWith(
"[2 - 1]" ) )
396 signal = signal.Left( signal.length() - 7 );
407 if( formatDialog.
ShowModal() == wxID_OK )
409 for(
int row = 0; row <
m_grid->GetNumberRows(); ++row )
411 if( getSignalName( row ) == getSignalName(
m_menuRow ) )
412 m_parent->SetCursorFormat( row, axis, format );
434 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
override;
460 menu.AppendSeparator();
473 if( formatDialog.
ShowModal() == wxID_OK )
482 std::vector<int> measurements;
484 wxGridCellCoordsArray cells1 =
m_grid->GetSelectionBlockTopLeft();
485 wxGridCellCoordsArray cells2 =
m_grid->GetSelectionBlockBottomRight();
487 for(
size_t i = 0; i < cells1.Count(); i++ )
491 for(
int j = cells1[i].GetRow(); j < cells2[i].GetRow() + 1; j++ )
492 measurements.push_back( j );
496 wxGridCellCoordsArray cells3 =
m_grid->GetSelectedCells();
498 for(
size_t i = 0; i < cells3.Count(); i++ )
501 measurements.push_back( cells3[i].GetRow() );
504 if( measurements.size() < 1 )
509 sort( measurements.begin(), measurements.end(), std::greater<>() );
511 for(
int row : measurements )
531 m_frame->m_SuppressGridEvents++;
536 m_frame->m_SuppressGridEvents--;
544#define ID_SIM_REFRESH 10207
545#define REFRESH_INTERVAL 50
570 wxGridCellAttr* attr =
new wxGridCellAttr;
574 attr =
new wxGridCellAttr;
578 attr =
new wxGridCellAttr;
582 attr =
new wxGridCellAttr;
588 attr =
new wxGridCellAttr;
598 [&]( wxTimerEvent& aEvent )
607#ifndef wxHAS_NATIVE_TABART
627 m_cursorFormat[0] = { 3, wxS(
"~s" ) };
628 m_cursorFormat[1] = { 3, wxS(
"~V" ) };
639 for(
size_t index2 = 0; index2 < std::size(
m_cursorFormats[0] ); index2++ )
653 maxCursor.Replace(
_(
"Cursor " ),
"" );
655 int tmpMax = wxAtoi( maxCursor );
657 if( nameMax < tmpMax )
667 std::vector<SPICE_VALUE_FORMAT> tmp;
679 wxGridCellAttr* attr =
new wxGridCellAttr;
699 for(
int i = 0; i < rows; i++ )
701 if(
m_signalsGrid->GetCellValue( i, col - 1 ) == wxS(
"1" ) )
704 wxGridEvent aDummy( wxID_ANY, wxEVT_GRID_CELL_CHANGED,
m_signalsGrid, i, col - 1 );
724 for(
int ii = 0; ii < static_cast<int>(
m_plotNotebook->GetPageCount() ); ++ii )
728 simTab->OnLanguageChanged();
730 wxString pageTitle(
simulator()->TypeToName( simTab->GetSimType(),
true ) );
731 pageTitle.Prepend( wxString::Format(
_(
"Analysis %u - " ), ii+1 ) );
752 tuner->ShowChangedLanguage();
792 simTab->ApplyPreferences( aPrefs );
800 bool loadFromSchematic =
false;
802 if( !workbookFilename.IsEmpty() )
804 wxFileName filename = workbookFilename;
807 if( !filename.FileExists() )
810 wxString::Format(
_(
"Workbook file '%s' not found. "
811 "Loading simulation settings from schematic." ),
812 filename.GetFullPath() ),
813 8000, wxICON_WARNING );
816 loadFromSchematic =
true;
825 loadFromSchematic =
true;
828 if( loadFromSchematic &&
m_simulatorFrame->LoadSimulator( wxEmptyString, 0 ) )
832 if( !schTextSimCommand.IsEmpty() )
865 std::sort( signals.begin(), signals.end(),
866 [](
const wxString& lhs,
const wxString& rhs )
869 if( lhs.Upper().StartsWith(
'V' ) && !rhs.Upper().StartsWith(
'V' ) )
871 else if( !lhs.Upper().StartsWith(
'V' ) && rhs.Upper().StartsWith(
'V' ) )
874 return StrNumCmp( lhs, rhs, true ) < 0;
891 std::vector<wxString> signals;
895 wxStringTokenizer tokenizer( plotPanel->
GetSimCommand(),
" \t\r\n", wxTOKEN_STRTOK );
897 while( tokenizer.HasMoreTokens() && tokenizer.GetNextToken().Lower() != wxT(
"fft" ) )
900 while( tokenizer.HasMoreTokens() )
901 signals.emplace_back( tokenizer.GetNextToken() );
908 for(
const wxString& signal :
m_signals )
909 signals.push_back( signal );
913 if( simType ==
ST_AC )
915 signals.push_back( signal +
_(
" (gain)" ) );
916 signals.push_back( signal +
_(
" (phase)" ) );
918 else if( simType ==
ST_SP )
920 signals.push_back( signal +
_(
" (amplitude)" ) );
921 signals.push_back( signal +
_(
" (phase)" ) );
925 signals.push_back( signal );
932 if( aFilter.IsEmpty() )
933 aFilter = wxS(
"*" );
938 for(
const wxString& signal : signals )
940 if( matcher.
Find( signal.Upper() ) )
949 wxGridCellAttr* attr =
new wxGridCellAttr;
950 attr->SetRenderer(
new wxGridCellBoolRenderer() );
952 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
957 attr =
new wxGridCellAttr;
962 attr =
new wxGridCellAttr;
966 attr =
new wxGridCellAttr;
974 attr =
new wxGridCellAttr;
984 attr =
new wxGridCellAttr;
987 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
992 attr =
new wxGridCellAttr;
993 attr->SetRenderer(
new wxGridCellBoolRenderer() );
995 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
999 attr =
new wxGridCellAttr;
1000 attr->SetRenderer(
new wxGridCellBoolRenderer() );
1001 attr->SetReadOnly();
1002 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
1010 attr =
new wxGridCellAttr;
1011 attr->SetRenderer(
new wxGridCellBoolRenderer() );
1012 attr->SetReadOnly();
1013 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
1031 wxString unconnected = wxString( wxS(
"unconnected-(" ) );
1036 unconnected.Replace(
'(',
'_' );
1039 [&](
const wxString& aSignalName )
1041 if( simType ==
ST_AC )
1043 m_signals.push_back( aSignalName +
_(
" (gain)" ) );
1044 m_signals.push_back( aSignalName +
_(
" (phase)" ) );
1046 else if( simType ==
ST_SP )
1048 m_signals.push_back( aSignalName +
_(
" (amplitude)" ) );
1049 m_signals.push_back( aSignalName +
_(
" (phase)" ) );
1066 if( netname ==
"GND" || netname ==
"0" || netname.StartsWith( unconnected ) )
1070 addSignal( wxString::Format( wxS(
"V(%s)" ), netname ) );
1080 for(
const std::string&
name : item.model->SpiceGenerator().CurrentNames( item ) )
1090 if( item.model->GetPinCount() >= 2 )
1092 wxString
name = item.model->SpiceGenerator().ItemName( item );
1093 addSignal( wxString::Format( wxS(
"P(%s)" ),
name ) );
1100 addSignal( wxS(
"inoise_spectrum" ) );
1101 addSignal( wxS(
"onoise_spectrum" ) );
1104 if( simType ==
ST_SP )
1106 std::vector<std::string> portnums;
1110 wxString
name = item.model->SpiceGenerator().ItemName( item );
1113 if( !
name.StartsWith(
"V" ) )
1116 std::string portnum =
"";
1118 if(
const SIM_MODEL::PARAM* portnum_param = item.model->FindParam(
"portnum" ) )
1122 portnums.push_back( portnum );
1125 for(
const std::string& portnum1 : portnums )
1127 for(
const std::string& portnum2 : portnums )
1128 addSignal( wxString::Format( wxS(
"S_%s_%s" ), portnum1, portnum2 ) );
1133 for(
const wxString& directive :
circuitModel()->GetDirectives() )
1135 wxStringTokenizer directivesTokenizer( directive,
"\r\n", wxTOKEN_STRTOK );
1137 while( directivesTokenizer.HasMoreTokens() )
1139 wxString line = directivesTokenizer.GetNextToken().Upper();
1140 wxString directiveParams;
1142 if( line.StartsWith( wxS(
".SAVE" ), &directiveParams )
1143 || line.StartsWith( wxS(
".PROBE" ), &directiveParams ) )
1145 wxStringTokenizer paramsTokenizer( directiveParams,
" \t", wxTOKEN_STRTOK );
1147 while( paramsTokenizer.HasMoreTokens() )
1148 addSignal( paramsTokenizer.GetNextToken() );
1171 wxString pageTitle(
simulator()->TypeToName( simType,
true ) );
1172 pageTitle.Prepend( wxString::Format(
_(
"Analysis %u - " ),
static_cast<unsigned int>( ++
m_plotNumber ) ) );
1188#if defined( __WXOSX__ )
1189 wxPoint pos = aEvent.GetPosition();
1190 wxRect ctrlRect =
m_filter->GetScreenRect();
1191 int buttonWidth = ctrlRect.GetHeight();
1193 if(
m_filter->IsSearchButtonVisible() && pos.x < buttonWidth )
1194 SetCursor( wxCURSOR_ARROW );
1195 else if(
m_filter->IsCancelButtonVisible() && pos.x > ctrlRect.GetWidth() - buttonWidth )
1196 SetCursor( wxCURSOR_ARROW );
1198 SetCursor( wxCURSOR_IBEAM );
1205 return wxString::Format( wxS(
"user%d" ), aUserDefinedSignalId );
1216 auto looksLikePower = [](
const wxString& aExpression ) ->
bool
1218 wxString exprUpper = aExpression.Upper();
1220 if( exprUpper.Contains( wxS(
":POWER" ) ) )
1223 if( exprUpper.Find(
'*' ) == wxNOT_FOUND )
1226 if( !exprUpper.Contains( wxS(
"V(" ) ) )
1229 if( !exprUpper.Contains( wxS(
"I(" ) ) )
1235 std::map<wxString, int> suffixes;
1251 wxUniChar firstChar = aSignalName.Upper()[0];
1253 if( firstChar ==
'V' )
1255 else if( firstChar ==
'I' )
1257 else if( firstChar ==
'P' )
1262 wxString
name = aSignalName;
1264 for(
const auto& [ candidate, type ] : suffixes )
1266 if(
name.EndsWith( candidate ) )
1268 name =
name.Left(
name.Length() - candidate.Length() );
1271 *aTraceType |= type;
1279 if(
name == signal )
1281 if( aTraceType && looksLikePower( signal ) )
1305 int row = aEvent.GetRow();
1306 int col = aEvent.GetCol();
1314 if(
text == wxS(
"1" ) )
1349 TRACE* activeTrace =
nullptr;
1351 if(
text == wxS(
"1" ) )
1355 activeTrace = plotTab->
GetTrace( vectorName, traceType );
1366 if( trace != activeTrace && trace->
HasCursor(
id ) )
1389 int row = aEvent.GetRow();
1390 int col = aEvent.GetCol();
1398 CURSOR* cursor1 =
nullptr;
1399 CURSOR* cursor2 =
nullptr;
1401 std::vector<CURSOR*> cursorsVec;
1423 cursorsVec.emplace_back(
cursor );
1425 if( cursorName == ( wxString(
"" ) << i ) &&
cursor )
1426 cursor->SetCoordX( value );
1433 if( cursorName == wxS(
"1" ) && cursor1 )
1435 else if( cursorName == wxS(
"2" ) && cursor2 )
1437 else if( cursorName ==
_(
"Diff" ) && cursor1 && cursor2 )
1445 wxFAIL_MSG( wxT(
"All other columns are supposed to be read-only!" ) );
1478 int row = aEvent.GetRow();
1479 int col = aEvent.GetCol();
1489 wxFAIL_MSG( wxT(
"All other columns are supposed to be read-only!" ) );
1497 for( row = rowCount - 1; row >= 0; row-- )
1507 int killRows = emptyRows - 1;
1510 else if( emptyRows == 0 )
1521 if( plotTab->GetLegendPosition() != plotTab->m_LastLegendPosition )
1523 plotTab->m_LastLegendPosition = plotTab->GetLegendPosition();
1546 static wxRegEx measureParamsRegEx( wxT(
"^"
1550 "([a-zA-Z]*)\\(([^\\)]+)\\)" ) );
1559 if(
text.IsEmpty() )
1566 wxString resultName = wxString::Format( wxS(
"meas_result_%u" ), aRow );
1567 wxString
result = wxS(
"?" );
1569 if( measureParamsRegEx.Matches(
text ) )
1571 wxString func = measureParamsRegEx.GetMatch(
text, 1 ).Upper();
1572 wxString signalType = measureParamsRegEx.GetMatch(
text, 2 ).Upper();
1573 wxString deviceName = measureParamsRegEx.GetMatch(
text, 3 );
1577 if( signalType.EndsWith( wxS(
"DB" ) ) )
1579 units = wxS(
"dB" );
1581 else if( signalType.StartsWith(
'I' ) )
1585 else if( signalType.StartsWith(
'P' ) )
1589 text = func +
" " + deviceName +
":power";
1596 if( func.EndsWith( wxS(
"_AT" ) ) )
1599 units = wxS(
"Hz" );
1603 else if( func.StartsWith( wxS(
"INTEG" ) ) )
1608 if ( signalType.StartsWith(
'P' ) )
1611 units += wxS(
".s" );
1621 units += wxS(
"·Hz" );
1629 units += wxS(
"·?" );
1642 wxString cmd = wxString::Format( wxS(
"meas %s %s %s" ), simType, resultName,
text );
1648 if( resultVec.size() > 0 )
1663 "the value of a passive R, L, C model or voltage or "
1664 "current source." ) );
1668 wxString ref = aSymbol->
GetRef( &aSheetPath );
1673 if( tuner->GetSymbolRef() == ref )
1696 const wxString& aRef,
const wxString& aValue )
1706 + wxString::Format(
_(
"%s not found" ), aRef ) );
1713 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
1714 embeddedFilesStack.push_back(
m_schematicFrame->Schematic().GetEmbeddedFiles() );
1718 embeddedFilesStack.push_back( symbolEmbeddedFiles );
1731 + wxString::Format(
_(
"%s is not tunable" ), aRef ) );
1735 model.SetParamValue( tunerParam->
info.
name, std::string( aValue.ToUTF8() ) );
1805 wxString cmd = wxString::Format( wxS(
"fourier %s %s" ),
1823 m_simConsole->AppendText(
_(
"Error: no current simulation.\n" ) );
1832 m_simConsole->AppendText(
_(
"Error: simulation type not defined.\n" ) );
1838 m_simConsole->AppendText(
_(
"Error: simulation type doesn't support plotting.\n" ) );
1845 if( simType ==
ST_AC )
1850 else if( simType ==
ST_SP )
1860 plotTab->GetPlotWin()->UpdateAll();
1882 if( aNewSignals.count(
id ) == 0 )
1887 plotTab->
DeleteTrace( vectorName, traceType | subType );
1892 plotTab->
DeleteTrace( vectorName, traceType | subType );
1905 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType | subType ) )
1906 trace->SetName( aNewSignals.at(
id ) );
1913 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType | subType ) )
1914 trace->SetName( aNewSignals.at(
id ) );
1919 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
1920 trace->SetName( aNewSignals.at(
id ) );
1940 std::vector<double>* aDataX,
bool aClearData )
1953 wxString simVectorName = aVectorName;
1956 simVectorName = simVectorName.AfterFirst(
'(' ).BeforeLast(
')' ) + wxS(
":power" );
1961 simulator()->
Command( wxString::Format( wxT(
"print %s" ), aVectorName ).ToStdString() );
1966 std::vector<double> data_x;
1967 std::vector<double> data_y;
1969 if( !aDataX || aClearData )
1973 if( aDataX->empty() && !aClearData )
1975 wxString xAxisName(
simulator()->GetXAxis( simType ) );
1977 if( xAxisName.IsEmpty() )
1983 unsigned int size = aDataX->size();
1993 wxFAIL_MSG( wxT(
"Plot type missing AC_PHASE or AC_MAG bit" ) );
2002 wxFAIL_MSG( wxT(
"Plot type missing AC_PHASE or SPT_SP_AMP bit" ) );
2017 wxFAIL_MSG( wxT(
"Unhandled plot type" ) );
2022 size_t sweepSize = std::numeric_limits<size_t>::max();
2024 if( simType ==
ST_DC
2031 sweepSize = aDataX->size() / sweepCount;
2048 size_t sweepSizeMulti = traceData.
xValues.size();
2049 size_t runCount = traceData.
yValues.size();
2051 if( sweepSizeMulti > 0 && runCount > 0 )
2053 std::vector<double> combinedX;
2054 std::vector<double> combinedY;
2056 combinedX.reserve( sweepSizeMulti * runCount );
2057 combinedY.reserve( sweepSizeMulti * runCount );
2059 for(
const std::vector<double>& runY : traceData.
yValues )
2061 if( runY.size() != sweepSizeMulti )
2064 combinedX.insert( combinedX.end(), traceData.
xValues.begin(), traceData.
xValues.end() );
2065 combinedY.insert( combinedY.end(), runY.begin(), runY.end() );
2070 if( combinedY.size() >= combinedX.size() && sweepSizeMulti > 0 )
2072 int sweepCountCombined = combinedX.empty() ? 0 :
static_cast<int>( combinedY.size() / sweepSizeMulti );
2074 if( sweepCountCombined > 0 )
2077 std::vector<wxString> labels;
2078 labels.reserve( sweepCountCombined );
2080 for(
int i = 0; i < sweepCountCombined && i < (int)
m_multiRunState.steps.size(); ++i )
2088 label += wxS(
", " );
2091 double value = it->second;
2097 labels.push_back( label );
2100 aPlotTab->
SetTraceData( trace, combinedX, combinedY, sweepCountCombined,
2101 sweepSizeMulti,
true, labels );
2114 if( data_y.size() >= size )
2115 aPlotTab->
SetTraceData( trace, *aDataX, data_y, sweepCount, sweepSize );
2125template <
typename T,
typename U,
typename R>
2133 wxGridCellAttrPtr attr =
m_signalsGrid->GetOrCreateCellAttrPtr( r,
static_cast<int>( t ) );
2135 if(
TRACE* trace = plotTab ? plotTab->
GetTrace( vectorName, traceType ) :
nullptr )
2137 attr->SetReadOnly();
2141 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
2144 if constexpr ( std::is_enum<T>::value )
2148 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxS(
"1" ) );
2152 if( !attr->HasRenderer() )
2155 if( !attr->HasEditor() )
2158 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
2159 attr->SetReadOnly(
false );
2168 if( !attr->HasRenderer() )
2169 attr->SetRenderer(
new wxGridCellBoolRenderer() );
2171 if( u > 0 && trace->HasCursor( u ) )
2172 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxS(
"1" ) );
2174 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2180 if constexpr ( std::is_enum<T>::value )
2184 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2191 attr->SetEditor(
nullptr );
2192 attr->SetRenderer(
nullptr );
2193 attr->SetReadOnly();
2194 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2203 for(
int row = 0; row <
m_signalsGrid->GetNumberRows(); ++row )
2225 auto quoteNetNames =
2226 [&]( wxString aExpression ) -> wxString
2228 std::vector<bool> mask( aExpression.length(),
false );
2230 auto isNetnameChar =
2231 []( wxUniChar aChar ) ->
bool
2233 wxUint32 value = aChar.GetValue();
2235 if( ( value >=
'0' && value <=
'9' ) || ( value >=
'A' && value <=
'Z' )
2236 || ( value >=
'a' && value <=
'z' ) )
2259 size_t pos = aExpression.find( netname );
2261 while( pos != wxString::npos )
2263 for(
size_t i = 0; i < netname.length(); ++i )
2264 mask[pos + i] =
true;
2266 pos = aExpression.find( netname, pos + 1 );
2270 for(
size_t i = 0; i < aExpression.length(); ++i )
2272 if( !mask[i] || ( i > 0 && mask[i - 1] ) )
2277 while( j < aExpression.length() )
2285 if( isNetnameChar( aExpression[j] ) )
2297 wxString quotedNetnames =
"";
2298 bool startQuote =
true;
2301 for(
size_t i = 0; i < aExpression.length(); i++ )
2303 if( mask[i] && startQuote )
2305 quotedNetnames = quotedNetnames +
"\"";
2308 else if( !mask[i] && !startQuote )
2310 quotedNetnames = quotedNetnames +
"\"";
2314 wxString ch = aExpression[i];
2315 quotedNetnames = quotedNetnames + ch;
2319 quotedNetnames = quotedNetnames +
"\"";
2321 return quotedNetnames;
2326 constexpr const char* cmd =
"let user{} = {}";
2328 simulator()->
Command(
"echo " + fmt::format( cmd,
id, signal.ToStdString() ) );
2329 simulator()->
Command( fmt::format( cmd,
id, quoteNetNames( signal ).ToStdString() ) );
2341 wxString ref = tuner->GetSymbolRef();
2342 KIID symbolId = tuner->GetSymbol( &sheetPath );
2348 reporter.
Report( wxString::Format(
_(
"%s not found" ), ref ) );
2356 reporter.
Report( wxString::Format(
_(
"%s is not tunable" ), ref ) );
2365 floatVal = overrideIt->second;
2367 floatVal = tuner->GetValue().ToDouble();
2378 wxTextFile file( aPath );
2383 wxString firstLine = file.GetFirstLine();
2385 bool legacy = firstLine.StartsWith( wxT(
"version " ) ) || firstLine.ToLong( &
dummy );
2410 wxFileName filename( aPath );
2422 wxFFileInputStream fp( aPath, wxT(
"rt" ) );
2423 wxStdInputStream fstream( fp );
2430 nlohmann::json js = nlohmann::json::parse( fstream,
nullptr,
true,
true );
2432 std::map<SIM_PLOT_TAB*, nlohmann::json> traceInfo;
2434 for(
const nlohmann::json& tab_js : js[
"tabs" ] )
2436 wxString simCommand;
2440 for(
const nlohmann::json& cmd : tab_js[
"commands" ] )
2442 if( cmd ==
".kicad adjustpaths" )
2444 else if( cmd ==
".save all" )
2446 else if( cmd ==
".probe alli" )
2448 else if( cmd ==
".probe allp" )
2450 else if( cmd ==
".kicad esavenone" )
2453 simCommand += wxString( cmd.get<wxString>() ).Trim();
2463 if( tab_js.contains(
"traces" ) )
2464 traceInfo[plotTab] = tab_js[
"traces" ];
2466 if( tab_js.contains(
"measurements" ) )
2468 for(
const nlohmann::json& m_js : tab_js[
"measurements" ] )
2469 plotTab->
Measurements().emplace_back( m_js[
"expr" ], m_js[
"format" ] );
2473 plotTab->
ShowGrid( tab_js[
"showGrid" ] );
2475 if( tab_js.contains(
"fixedY1scale" ) )
2477 const nlohmann::json& scale_js = tab_js[
"fixedY1scale" ];
2478 plotTab->
SetY1Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2482 if( tab_js.contains(
"fixedY2scale" ) )
2484 const nlohmann::json& scale_js = tab_js[
"fixedY2scale" ];
2485 plotTab->
SetY2Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2489 if( tab_js.contains(
"fixedY3scale" ) )
2492 const nlohmann::json& scale_js = tab_js[
"fixedY3scale" ];
2493 plotTab->
SetY3Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2497 if( tab_js.contains(
"legend" ) )
2499 const nlohmann::json& legend_js = tab_js[
"legend" ];
2504 if( tab_js.contains(
"margins" ) )
2506 const nlohmann::json& margins_js = tab_js[
"margins" ];
2508 margins_js[
"right" ],
2509 margins_js[
"bottom" ],
2510 margins_js[
"left" ] );
2517 if( js.contains(
"user_defined_signals" ) )
2519 for(
const nlohmann::json& signal_js : js[
"user_defined_signals" ] )
2525 m_simulatorFrame->LoadSimulator( simTab->GetSimCommand(), simTab->GetSimOptions() );
2528 firstTab->SetLastSchTextSimCommand( js[
"last_sch_text_sim_command"] );
2531 int tempCustomCursorsCnt = 0;
2533 if( js.contains(
"custom_cursors" ) )
2534 tempCustomCursorsCnt = js[
"custom_cursors"];
2536 tempCustomCursorsCnt = 2;
2546 int aCursorId,
const nlohmann::json& aCursor_js )
2548 if( aCursorId >= 1 )
2552 cursor->SetName( aSignalName );
2553 cursor->SetCoordX( aCursor_js[
"position" ] );
2555 aTrace->SetCursor( aCursorId,
cursor );
2559 if( aCursorId == -1 )
2580 for(
const auto& [ plotTab, traces_js ] : traceInfo )
2582 for(
const nlohmann::json& trace_js : traces_js )
2584 wxString signalName = trace_js[
"signal" ];
2586 TRACE* trace = plotTab->GetOrAddTrace( vectorName, trace_js[
"trace_type" ] );
2590 if( trace_js.contains(
"cursorD" ) )
2591 addCursor( plotTab, trace, signalName, -1, trace_js[
"cursorD" ] );
2593 std::vector<const char*> aVec;
2596 for(
int i = 1; i <= tempCustomCursorsCnt; i++ )
2598 wxString str =
"cursor" + std::to_string( i );
2599 aVec.emplace_back( str.c_str() );
2601 if( trace_js.contains( aVec[i - 1] ) )
2602 addCursor( plotTab, trace, signalName, i, trace_js[aVec[i - 1]] );
2605 if( trace_js.contains(
"color" ) )
2608 color.Set( wxString( trace_js[
"color"].get<wxString>() ) );
2610 plotTab->UpdateTraceStyle( trace );
2615 plotTab->UpdatePlotColors();
2618 catch( nlohmann::json::parse_error& error )
2620 wxLogTrace(
traceSettings, wxT(
"Json parse error reading %s: %s" ), aPath, error.what() );
2624 catch( nlohmann::json::type_error& error )
2626 wxLogTrace(
traceSettings, wxT(
"Json type error reading %s: %s" ), aPath, error.what() );
2630 catch( nlohmann::json::invalid_iterator& error )
2632 wxLogTrace(
traceSettings, wxT(
"Json invalid_iterator error reading %s: %s" ), aPath, error.what() );
2636 catch( nlohmann::json::out_of_range& error )
2638 wxLogTrace(
traceSettings, wxT(
"Json out_of_range error reading %s: %s" ), aPath, error.what() );
2644 wxLogTrace(
traceSettings, wxT(
"Error reading %s" ), aPath );
2653 int cursorIdAfterD = aCursorId;
2656 cursorIdAfterD = cursorIdAfterD - 1;
2661 aTraceJs[
"cursor" + wxString(
"" ) << aCursorId] =
2662 nlohmann::json( { {
"position",
cursor->GetCoords().x },
2669 aTraceJs[
"cursorD"] =
2680 wxFileName filename = aPath;
2685 file.Create( filename.GetFullPath(),
true );
2687 if( !file.IsOpened() )
2690 nlohmann::json tabs_js = nlohmann::json::array();
2701 nlohmann::json commands_js = nlohmann::json::array();
2708 commands_js.push_back(
".kicad adjustpaths" );
2711 commands_js.push_back(
".save all" );
2714 commands_js.push_back(
".probe alli" );
2717 commands_js.push_back(
".probe allp" );
2720 commands_js.push_back(
".kicad esavenone" );
2722 nlohmann::json tab_js = nlohmann::json(
2724 {
"commands", commands_js } } );
2728 nlohmann::json traces_js = nlohmann::json::array();
2730 auto findSignalName =
2731 [&](
const wxString& aVectorName ) -> wxString
2733 wxString vectorName;
2736 if( aVectorName.EndsWith(
_(
" (phase)" ) ) )
2737 suffix =
_(
" (phase)" );
2738 else if( aVectorName.EndsWith(
_(
" (gain)" ) ) )
2739 suffix =
_(
" (gain)" );
2741 vectorName = aVectorName.Left( aVectorName.Length() - suffix.Length() );
2746 return signal + suffix;
2752 for(
const auto& [
name, trace] : plotTab->GetTraces() )
2754 nlohmann::json trace_js = nlohmann::json(
2755 { {
"trace_type", (int) trace->GetType() },
2756 {
"signal", findSignalName( trace->GetDisplayName() ) },
2762 if( trace->GetCursor( 1 ) || trace->GetCursor( 2 ) )
2764 trace_js[
"cursorD"] = nlohmann::json(
2769 traces_js.push_back( trace_js );
2772 nlohmann::json measurements_js = nlohmann::json::array();
2774 for(
const auto& [
measurement, format ] : plotTab->Measurements() )
2776 measurements_js.push_back( nlohmann::json( { {
"expr",
measurement },
2777 {
"format", format } } ) );
2780 tab_js[
"traces" ] = traces_js;
2781 tab_js[
"measurements" ] = measurements_js;
2782 tab_js[
"dottedSecondary" ] = plotTab->GetDottedSecondary();
2783 tab_js[
"showGrid" ] = plotTab->IsGridShown();
2787 if( plotTab->GetY1Scale( &min, &max ) )
2788 tab_js[
"fixedY1scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2790 if( plotTab->GetY2Scale( &min, &max ) )
2791 tab_js[
"fixedY2scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2793 if( plotTab->GetY3Scale( &min, &max ) )
2794 tab_js[
"fixedY3scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2796 if( plotTab->IsLegendShown() )
2798 tab_js[
"legend" ] = nlohmann::json( { {
"x", plotTab->GetLegendPosition().x },
2799 {
"y", plotTab->GetLegendPosition().y } } );
2802 mpWindow* plotWin = plotTab->GetPlotWin();
2804 tab_js[
"margins" ] = nlohmann::json( { {
"left", plotWin->
GetMarginLeft() },
2810 tabs_js.push_back( tab_js );
2813 nlohmann::json userDefinedSignals_js = nlohmann::json::array();
2816 userDefinedSignals_js.push_back( signal );
2819 nlohmann::json js = nlohmann::json( { {
"version", 7 },
2820 {
"tabs", tabs_js },
2821 {
"user_defined_signals", userDefinedSignals_js },
2834 std::stringstream buffer;
2835 buffer << std::setw( 2 ) << js << std::endl;
2837 bool res = file.Write( buffer.str() );
2864 wxFAIL_MSG( wxString::Format( wxS(
"Unhandled simulation type: %d" ), (
int) aType ) );
2884 &source, &
scale, &pts, &fStart, &fStop, &saveAll );
2892 int& aSashPosition )
2894 bool isShown = aPanel->IsShown();
2897 aSashPosition = aSplitterWindow->GetSashPosition();
2899 aPanel->Show( !isShown );
2901 aSplitterWindow->SetSashInvisible( isShown );
2902 aSplitterWindow->SetSashPosition( isShown ? -1 : aSashPosition,
true );
2904 aSplitterWindow->UpdateSize();
2905 m_parent->Refresh();
2942 for(
size_t page = 0; page <
m_plotNotebook->GetPageCount(); page++ )
2990 std::vector<std::pair<wxString, wxString>>& measurements = plotTab->Measurements();
2992 measurements.clear();
3030 simulator()->
Command(
"setplot " + simTab->GetSpicePlotName().ToStdString() );
3047 for(
const auto& [
measurement, format ] : plotTab->Measurements() )
3055 if( plotTab->GetSimType() ==
ST_TRAN || plotTab->GetSimType() ==
ST_AC
3056 || plotTab->GetSimType() ==
ST_DC || plotTab->GetSimType() ==
ST_SP )
3093 CURSOR* cursor1 =
nullptr;
3094 wxString cursor1Name;
3095 wxString cursor1Units;
3096 CURSOR* cursor2 =
nullptr;
3097 wxString cursor2Name;
3098 wxString cursor2Units;
3101 [&](
TRACE* aTrace ) -> wxString
3122 [&](
TRACE* aTrace ) -> wxString
3143 [
this](
double aValue,
int aCursorId,
int aCol ) -> wxString
3145 if( ( !
m_simulatorFrame->SimFinished() && aCol == 1 ) || std::isnan( aValue ) )
3156 cursor1Name = getNameY( trace );
3157 cursor1Units = getUnitsY( trace );
3159 wxRealPoint coords =
cursor->GetCoords();
3179 cursor2Name = getNameY( trace );
3180 cursor2Units = getUnitsY( trace );
3182 wxRealPoint coords =
cursor->GetCoords();
3197 if( cursor1 && cursor2 && cursor1Units == cursor2Units )
3206 signal = wxString::Format( wxS(
"%s[2 - 1]" ), cursor2->
GetName() );
3208 signal = wxString::Format( wxS(
"%s - %s" ), cursor2->
GetName(), cursor1->
GetName() );
3219 wxString valColName =
_(
"Value" );
3221 if( !cursor1Name.IsEmpty() )
3223 if( cursor2Name.IsEmpty() || cursor1Name == cursor2Name )
3224 valColName = cursor1Name;
3226 else if( !cursor2Name.IsEmpty() )
3228 valColName = cursor2Name;
3242 wxString cursName = getNameY( trace );
3243 wxString cursUnits = getUnitsY( trace );
3245 wxRealPoint coords =
cursor->GetCoords();
3260 valColName =
_(
"Value" );
3263 valColName = cursName;
3284 plotTab->ResetScales(
true );
3306 std::vector<wxString> signals;
3308 for(
const std::string& vec :
simulator()->AllVectors() )
3309 signals.emplace_back( vec );
3317 std::vector<wxString> signals;
3319 for(
const wxString& signal :
m_signals )
3320 signals.emplace_back( signal );
3323 signals.emplace_back( signal );
3341 bool storeMultiRun =
false;
3347 storeMultiRun =
true;
3370 if( simType ==
ST_NOISE && aFinal )
3372 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3381 for(
const std::string& vec :
simulator()->AllVectors() )
3386 msg.Printf( wxS(
"%s: %sV\n" ), vec, value );
3397 wxCHECK_RET( plotTab, wxString::Format( wxT(
"No SIM_PLOT_TAB for: %s" ),
3398 magic_enum::enum_name( simType ) ) );
3407 std::map<TRACE*, TRACE_INFO> traceMap;
3410 traceMap[ trace ] = { wxEmptyString,
SPT_UNKNOWN,
false };
3415 for(
const wxString& signal :
m_signals )
3420 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
3421 traceMap[ trace ] = { vectorName, traceType,
false };
3429 if( simType ==
ST_AC )
3435 if(
TRACE* trace = plotTab->
GetTrace( vectorName, subType ) )
3436 traceMap[ trace ] = { vectorName, subType, !aFinal };
3439 else if( simType ==
ST_SP )
3445 if(
TRACE* trace = plotTab->
GetTrace( vectorName, subType ) )
3446 traceMap[trace] = { vectorName, subType, !aFinal };
3451 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
3452 traceMap[ trace ] = { vectorName, traceType, !aFinal };
3458 for(
const auto& [ trace, traceInfo ] : traceMap )
3460 if( traceInfo.Vector.IsEmpty() )
3464 for(
const auto& [ trace,
info ] : traceMap )
3466 std::vector<double> data_x;
3468 if( !
info.Vector.IsEmpty() )
3486 else if( simType ==
ST_OP && aFinal )
3488 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3491 for(
const std::string& vec :
simulator()->AllVectors() )
3495 if( val_list.empty() )
3502 const size_t tab = 25;
3503 size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1;
3507 case SPT_VOLTAGE: value.Append( wxS(
"V" ) );
break;
3508 case SPT_CURRENT: value.Append( wxS(
"A" ) );
break;
3509 case SPT_POWER: value.Append( wxS(
"W" ) );
break;
3510 default: value.Append( wxS(
"?" ) );
break;
3513 msg.Printf( wxT(
"%s%s\n" ),
3514 ( signal + wxT(
":" ) ).Pad( padding, wxUniChar(
' ' ) ),
3521 signal = signal.SubString( 2, signal.Length() - 2 );
3524 signal += wxS(
":power" );
3526 m_schematicFrame->Schematic().SetOperatingPoint( signal, val_list.at( 0 ) );
3529 else if( simType ==
ST_PZ && aFinal )
3531 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3592 std::vector<TUNER_SLIDER*> multiTuners;
3597 multiTuners.push_back( tuner );
3600 if( multiTuners.empty() )
3632 else if( tunersChanged )
3641 for(
const auto& entry : step.
overrides )
3648 const std::vector<TUNER_SLIDER*>& aTuners )
const
3650 std::vector<MULTI_RUN_STEP> steps;
3652 if( aTuners.empty() )
3655 std::vector<std::vector<double>> tunerValues;
3656 tunerValues.reserve( aTuners.size() );
3663 double startValue = tuner->GetMin().ToDouble();
3664 double endValue = tuner->GetMax().ToDouble();
3665 int stepCount = std::max( 2, tuner->GetStepCount() );
3670 double increment = ( endValue - startValue ) /
static_cast<double>( stepCount - 1 );
3672 std::vector<double> values;
3673 values.reserve( stepCount );
3675 for(
int ii = 0; ii < stepCount; ++ii )
3676 values.push_back( startValue + increment * ii );
3678 tunerValues.push_back( std::move( values ) );
3686 std::vector<double> currentValues( aTuners.size(), 0.0 );
3688 auto generate = [&](
auto&& self,
size_t depth ) ->
void
3690 if( steps.size() >=
static_cast<size_t>( limit ) )
3693 if( depth == aTuners.size() )
3697 for(
size_t ii = 0; ii < aTuners.size(); ++ii )
3698 step.
overrides.emplace( aTuners[ii], currentValues[ii] );
3700 steps.push_back( std::move( step ) );
3704 for(
double value : tunerValues[depth] )
3706 currentValues[depth] = value;
3707 self( self, depth + 1 );
3709 if( steps.size() >=
static_cast<size_t>( limit ) )
3714 generate( generate, 0 );
3722 return fmt::format(
"{}|{}", aVectorName.ToStdString(), aTraceType );
3727 const std::vector<double>& aX,
3728 const std::vector<double>& aY )
3730 if( aX.empty() || aY.empty() )
3741 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.
wxString GetCurrentVariant() const
Return the current variant being edited.
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.