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>
64 int res =
static_cast<int>( aFirst ) |
static_cast<int>( aSecond);
125 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
override;
176 menu.AppendSeparator();
177 menu.Append(
MYID_FOURIER,
_(
"Perform Fourier Analysis..." ) );
180 menu.AppendSeparator();
183 menu.AppendSeparator();
186 m_grid->PopupMenu( &menu );
193 menu.AppendSeparator();
195 wxString msg =
m_grid->GetColLabelValue(
m_grid->GetNumberCols() - 1 );
197 menu.AppendSeparator();
200 m_grid->PopupMenu( &menu );
206 m_grid->PopupMenu( &menu );
213 std::vector<wxString> signals;
215 wxGridCellCoordsArray cells1 =
m_grid->GetSelectionBlockTopLeft();
216 wxGridCellCoordsArray cells2 =
m_grid->GetSelectionBlockBottomRight();
218 for(
size_t i = 0; i < cells1.Count(); i++ )
222 for(
int j = cells1[i].GetRow(); j < cells2[i].GetRow() + 1; j++ )
224 signals.push_back(
m_grid->GetCellValue( j, cells1[i].GetCol() ) );
229 wxGridCellCoordsArray cells3 =
m_grid->GetSelectedCells();
231 for(
size_t i = 0; i < cells3.Count(); i++ )
234 signals.push_back(
m_grid->GetCellValue( cells3[i].GetRow(), cells3[i].GetCol() ) );
237 if( signals.size() < 1 )
240 auto addMeasurement =
241 [
this](
const wxString& cmd, wxString signal )
243 if( signal.EndsWith(
_(
" (phase)" ) ) )
246 if( signal.EndsWith(
_(
" (gain)" ) ) || signal.EndsWith(
_(
" (amplitude)" ) ) )
248 signal = signal.Left( signal.length() - 7 );
250 if( signal.Upper().StartsWith( wxS(
"V(" ) ) )
251 signal = wxS(
"vdb" ) + signal.Mid( 1 );
254 m_parent->AddMeasurement( cmd + wxS(
" " ) + signal );
259 for(
const wxString& signal : signals )
260 addMeasurement( wxS(
"MIN" ), signal );
264 for(
const wxString& signal : signals )
265 addMeasurement( wxS(
"MAX" ), signal );
269 for(
const wxString& signal : signals )
270 addMeasurement( wxS(
"AVG" ), signal );
274 for(
const wxString& signal : signals )
275 addMeasurement( wxS(
"RMS" ), signal );
279 for(
const wxString& signal : signals )
280 addMeasurement( wxS(
"PP" ), signal );
284 for(
const wxString& signal : signals )
285 addMeasurement( wxS(
"MIN_AT" ), signal );
289 for(
const wxString& signal : signals )
290 addMeasurement( wxS(
"MAX_AT" ), signal );
294 for(
const wxString& signal : signals )
295 addMeasurement( wxS(
"INTEG" ), signal );
300 wxString fundamental = wxT(
"1K" );
302 if( signals.size() == 1 )
303 title.Printf(
_(
"Fourier Analysis of %s" ), signals[0] );
305 title =
_(
"Fourier Analyses of Multiple Signals" );
315 for(
const wxString& signal : signals )
316 m_parent->DoFourier( signal, fundamental );
323 for(
const wxString& signal : signals )
331 if( wxTheClipboard->Open() )
333 wxTheClipboard->SetData(
new wxTextDataObject( txt ) );
334 wxTheClipboard->Flush();
335 wxTheClipboard->Close();
360 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
override;
380 menu.AppendSeparator();
390 [
this](
int row ) -> wxString
394 if( signal.EndsWith(
"[2 - 1]" ) )
395 signal = signal.Left( signal.length() - 7 );
406 if( formatDialog.
ShowModal() == wxID_OK )
408 for(
int row = 0; row <
m_grid->GetNumberRows(); ++row )
410 if( getSignalName( row ) == getSignalName(
m_menuRow ) )
411 m_parent->SetCursorFormat( row, axis, format );
433 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
override;
459 menu.AppendSeparator();
472 if( formatDialog.
ShowModal() == wxID_OK )
481 std::vector<int> measurements;
483 wxGridCellCoordsArray cells1 =
m_grid->GetSelectionBlockTopLeft();
484 wxGridCellCoordsArray cells2 =
m_grid->GetSelectionBlockBottomRight();
486 for(
size_t i = 0; i < cells1.Count(); i++ )
490 for(
int j = cells1[i].GetRow(); j < cells2[i].GetRow() + 1; j++ )
491 measurements.push_back( j );
495 wxGridCellCoordsArray cells3 =
m_grid->GetSelectedCells();
497 for(
size_t i = 0; i < cells3.Count(); i++ )
500 measurements.push_back( cells3[i].GetRow() );
503 if( measurements.size() < 1 )
508 sort( measurements.begin(), measurements.end(), std::greater<>() );
510 for(
int row : measurements )
530 m_frame->m_SuppressGridEvents++;
535 m_frame->m_SuppressGridEvents--;
543#define ID_SIM_REFRESH 10207
544#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++ )
652 maxCursor.Replace(
_(
"Cursor " ),
"" );
654 int tmpMax = wxAtoi( maxCursor );
656 if( nameMax < tmpMax )
666 std::vector<SPICE_VALUE_FORMAT> tmp;
678 wxGridCellAttr* attr =
new wxGridCellAttr;
698 for(
int i = 0; i < rows; i++ )
700 if(
m_signalsGrid->GetCellValue( i, col - 1 ) == wxS(
"1" ) )
703 wxGridEvent aDummy( wxID_ANY, wxEVT_GRID_CELL_CHANGED,
m_signalsGrid, i, col - 1 );
723 for(
int ii = 0; ii < static_cast<int>(
m_plotNotebook->GetPageCount() ); ++ii )
727 simTab->OnLanguageChanged();
729 wxString pageTitle(
simulator()->TypeToName( simTab->GetSimType(),
true ) );
730 pageTitle.Prepend( wxString::Format(
_(
"Analysis %u - " ), ii+1 ) );
751 tuner->ShowChangedLanguage();
791 simTab->ApplyPreferences( aPrefs );
799 bool loadFromSchematic =
false;
801 if( !workbookFilename.IsEmpty() )
803 wxFileName filename = workbookFilename;
806 if( !filename.FileExists() )
809 wxString::Format(
_(
"Workbook file '%s' not found. "
810 "Loading simulation settings from schematic." ),
811 filename.GetFullPath() ),
812 8000, wxICON_WARNING );
815 loadFromSchematic =
true;
824 loadFromSchematic =
true;
827 if( loadFromSchematic &&
m_simulatorFrame->LoadSimulator( wxEmptyString, 0 ) )
831 if( !schTextSimCommand.IsEmpty() )
864 std::sort( signals.begin(), signals.end(),
865 [](
const wxString& lhs,
const wxString& rhs )
868 if( lhs.Upper().StartsWith(
'V' ) && !rhs.Upper().StartsWith(
'V' ) )
870 else if( !lhs.Upper().StartsWith(
'V' ) && rhs.Upper().StartsWith(
'V' ) )
873 return StrNumCmp( lhs, rhs, true ) < 0;
890 std::vector<wxString> signals;
894 wxStringTokenizer tokenizer( plotPanel->
GetSimCommand(),
" \t\r\n", wxTOKEN_STRTOK );
896 while( tokenizer.HasMoreTokens() && tokenizer.GetNextToken().Lower() != wxT(
"fft" ) )
899 while( tokenizer.HasMoreTokens() )
900 signals.emplace_back( tokenizer.GetNextToken() );
907 for(
const wxString& signal :
m_signals )
908 signals.push_back( signal );
912 if( simType ==
ST_AC )
914 signals.push_back( signal +
_(
" (gain)" ) );
915 signals.push_back( signal +
_(
" (phase)" ) );
917 else if( simType ==
ST_SP )
919 signals.push_back( signal +
_(
" (amplitude)" ) );
920 signals.push_back( signal +
_(
" (phase)" ) );
924 signals.push_back( signal );
931 if( aFilter.IsEmpty() )
932 aFilter = wxS(
"*" );
937 for(
const wxString& signal : signals )
939 if( matcher.
Find( signal.Upper() ) )
948 wxGridCellAttr* attr =
new wxGridCellAttr;
949 attr->SetRenderer(
new wxGridCellBoolRenderer() );
951 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
956 attr =
new wxGridCellAttr;
961 attr =
new wxGridCellAttr;
965 attr =
new wxGridCellAttr;
973 attr =
new wxGridCellAttr;
983 attr =
new wxGridCellAttr;
986 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
991 attr =
new wxGridCellAttr;
992 attr->SetRenderer(
new wxGridCellBoolRenderer() );
994 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
998 attr =
new wxGridCellAttr;
999 attr->SetRenderer(
new wxGridCellBoolRenderer() );
1000 attr->SetReadOnly();
1001 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
1009 attr =
new wxGridCellAttr;
1010 attr->SetRenderer(
new wxGridCellBoolRenderer() );
1011 attr->SetReadOnly();
1012 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
1030 wxString unconnected = wxString( wxS(
"unconnected-(" ) );
1035 unconnected.Replace(
'(',
'_' );
1038 [&](
const wxString& aSignalName )
1040 if( simType ==
ST_AC )
1042 m_signals.push_back( aSignalName +
_(
" (gain)" ) );
1043 m_signals.push_back( aSignalName +
_(
" (phase)" ) );
1045 else if( simType ==
ST_SP )
1047 m_signals.push_back( aSignalName +
_(
" (amplitude)" ) );
1048 m_signals.push_back( aSignalName +
_(
" (phase)" ) );
1065 if( netname ==
"GND" || netname ==
"0" || netname.StartsWith( unconnected ) )
1069 addSignal( wxString::Format( wxS(
"V(%s)" ), netname ) );
1079 for(
const std::string&
name : item.model->SpiceGenerator().CurrentNames( item ) )
1089 if( item.model->GetPinCount() >= 2 )
1091 wxString
name = item.model->SpiceGenerator().ItemName( item );
1092 addSignal( wxString::Format( wxS(
"P(%s)" ),
name ) );
1099 addSignal( wxS(
"inoise_spectrum" ) );
1100 addSignal( wxS(
"onoise_spectrum" ) );
1103 if( simType ==
ST_SP )
1105 std::vector<std::string> portnums;
1109 wxString
name = item.model->SpiceGenerator().ItemName( item );
1112 if( !
name.StartsWith(
"V" ) )
1115 std::string portnum =
"";
1117 if(
const SIM_MODEL::PARAM* portnum_param = item.model->FindParam(
"portnum" ) )
1121 portnums.push_back( portnum );
1124 for(
const std::string& portnum1 : portnums )
1126 for(
const std::string& portnum2 : portnums )
1127 addSignal( wxString::Format( wxS(
"S_%s_%s" ), portnum1, portnum2 ) );
1132 for(
const wxString& directive :
circuitModel()->GetDirectives() )
1134 wxStringTokenizer directivesTokenizer( directive,
"\r\n", wxTOKEN_STRTOK );
1136 while( directivesTokenizer.HasMoreTokens() )
1138 wxString line = directivesTokenizer.GetNextToken().Upper();
1139 wxString directiveParams;
1141 if( line.StartsWith( wxS(
".SAVE" ), &directiveParams )
1142 || line.StartsWith( wxS(
".PROBE" ), &directiveParams ) )
1144 wxStringTokenizer paramsTokenizer( directiveParams,
" \t", wxTOKEN_STRTOK );
1146 while( paramsTokenizer.HasMoreTokens() )
1147 addSignal( paramsTokenizer.GetNextToken() );
1170 wxString pageTitle(
simulator()->TypeToName( simType,
true ) );
1171 pageTitle.Prepend( wxString::Format(
_(
"Analysis %u - " ),
static_cast<unsigned int>( ++
m_plotNumber ) ) );
1187#if defined( __WXOSX__ )
1188 wxPoint pos = aEvent.GetPosition();
1189 wxRect ctrlRect =
m_filter->GetScreenRect();
1190 int buttonWidth = ctrlRect.GetHeight();
1192 if(
m_filter->IsSearchButtonVisible() && pos.x < buttonWidth )
1193 SetCursor( wxCURSOR_ARROW );
1194 else if(
m_filter->IsCancelButtonVisible() && pos.x > ctrlRect.GetWidth() - buttonWidth )
1195 SetCursor( wxCURSOR_ARROW );
1197 SetCursor( wxCURSOR_IBEAM );
1204 return wxString::Format( wxS(
"user%d" ), aUserDefinedSignalId );
1215 auto looksLikePower = [](
const wxString& aExpression ) ->
bool
1217 wxString exprUpper = aExpression.Upper();
1219 if( exprUpper.Contains( wxS(
":POWER" ) ) )
1222 if( exprUpper.Find(
'*' ) == wxNOT_FOUND )
1225 if( !exprUpper.Contains( wxS(
"V(" ) ) )
1228 if( !exprUpper.Contains( wxS(
"I(" ) ) )
1234 std::map<wxString, int> suffixes;
1250 wxUniChar firstChar = aSignalName.Upper()[0];
1252 if( firstChar ==
'V' )
1254 else if( firstChar ==
'I' )
1256 else if( firstChar ==
'P' )
1261 wxString
name = aSignalName;
1263 for(
const auto& [ candidate, type ] : suffixes )
1265 if(
name.EndsWith( candidate ) )
1267 name =
name.Left(
name.Length() - candidate.Length() );
1270 *aTraceType |= type;
1278 if(
name == signal )
1280 if( aTraceType && looksLikePower( signal ) )
1304 int row = aEvent.GetRow();
1305 int col = aEvent.GetCol();
1313 if(
text == wxS(
"1" ) )
1348 TRACE* activeTrace =
nullptr;
1350 if(
text == wxS(
"1" ) )
1354 activeTrace = plotTab->
GetTrace( vectorName, traceType );
1365 if( trace != activeTrace && trace->
HasCursor(
id ) )
1388 int row = aEvent.GetRow();
1389 int col = aEvent.GetCol();
1397 CURSOR* cursor1 =
nullptr;
1398 CURSOR* cursor2 =
nullptr;
1400 std::vector<CURSOR*> cursorsVec;
1422 cursorsVec.emplace_back(
cursor );
1424 if( cursorName == ( wxString(
"" ) << i ) &&
cursor )
1425 cursor->SetCoordX( value );
1432 if( cursorName == wxS(
"1" ) && cursor1 )
1434 else if( cursorName == wxS(
"2" ) && cursor2 )
1436 else if( cursorName ==
_(
"Diff" ) && cursor1 && cursor2 )
1444 wxFAIL_MSG( wxT(
"All other columns are supposed to be read-only!" ) );
1477 int row = aEvent.GetRow();
1478 int col = aEvent.GetCol();
1488 wxFAIL_MSG( wxT(
"All other columns are supposed to be read-only!" ) );
1496 for( row = rowCount - 1; row >= 0; row-- )
1506 int killRows = emptyRows - 1;
1509 else if( emptyRows == 0 )
1520 if( plotTab->GetLegendPosition() != plotTab->m_LastLegendPosition )
1522 plotTab->m_LastLegendPosition = plotTab->GetLegendPosition();
1545 static wxRegEx measureParamsRegEx( wxT(
"^"
1549 "([a-zA-Z]*)\\(([^\\)]+)\\)" ) );
1558 if(
text.IsEmpty() )
1565 wxString resultName = wxString::Format( wxS(
"meas_result_%u" ), aRow );
1566 wxString
result = wxS(
"?" );
1568 if( measureParamsRegEx.Matches(
text ) )
1570 wxString func = measureParamsRegEx.GetMatch(
text, 1 ).Upper();
1571 wxString signalType = measureParamsRegEx.GetMatch(
text, 2 ).Upper();
1572 wxString deviceName = measureParamsRegEx.GetMatch(
text, 3 );
1576 if( signalType.EndsWith( wxS(
"DB" ) ) )
1578 units = wxS(
"dB" );
1580 else if( signalType.StartsWith(
'I' ) )
1584 else if( signalType.StartsWith(
'P' ) )
1588 text = func +
" " + deviceName +
":power";
1595 if( func.EndsWith( wxS(
"_AT" ) ) )
1598 units = wxS(
"Hz" );
1602 else if( func.StartsWith( wxS(
"INTEG" ) ) )
1607 if ( signalType.StartsWith(
'P' ) )
1610 units += wxS(
".s" );
1620 units += wxS(
"·Hz" );
1628 units += wxS(
"·?" );
1641 wxString cmd = wxString::Format( wxS(
"meas %s %s %s" ), simType, resultName,
text );
1647 if( resultVec.size() > 0 )
1662 "the value of a passive R, L, C model or voltage or "
1663 "current source." ) );
1667 wxString ref = aSymbol->
GetRef( &aSheetPath );
1672 if( tuner->GetSymbolRef() == ref )
1695 const wxString& aRef,
const wxString& aValue )
1705 + wxString::Format(
_(
"%s not found" ), aRef ) );
1712 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
1713 embeddedFilesStack.push_back(
m_schematicFrame->Schematic().GetEmbeddedFiles() );
1717 embeddedFilesStack.push_back( symbolEmbeddedFiles );
1730 + wxString::Format(
_(
"%s is not tunable" ), aRef ) );
1734 model.SetParamValue( tunerParam->
info.
name, std::string( aValue.ToUTF8() ) );
1804 wxString cmd = wxString::Format( wxS(
"fourier %s %s" ),
1822 m_simConsole->AppendText(
_(
"Error: no current simulation.\n" ) );
1831 m_simConsole->AppendText(
_(
"Error: simulation type not defined.\n" ) );
1837 m_simConsole->AppendText(
_(
"Error: simulation type doesn't support plotting.\n" ) );
1844 if( simType ==
ST_AC )
1849 else if( simType ==
ST_SP )
1859 plotTab->GetPlotWin()->UpdateAll();
1881 if( aNewSignals.count(
id ) == 0 )
1886 plotTab->
DeleteTrace( vectorName, traceType | subType );
1891 plotTab->
DeleteTrace( vectorName, traceType | subType );
1904 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType | subType ) )
1905 trace->SetName( aNewSignals.at(
id ) );
1912 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType | subType ) )
1913 trace->SetName( aNewSignals.at(
id ) );
1918 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
1919 trace->SetName( aNewSignals.at(
id ) );
1939 std::vector<double>* aDataX,
bool aClearData )
1952 wxString simVectorName = aVectorName;
1955 simVectorName = simVectorName.AfterFirst(
'(' ).BeforeLast(
')' ) + wxS(
":power" );
1960 simulator()->
Command( wxString::Format( wxT(
"print %s" ), aVectorName ).ToStdString() );
1965 std::vector<double> data_x;
1966 std::vector<double> data_y;
1968 if( !aDataX || aClearData )
1972 if( aDataX->empty() && !aClearData )
1974 wxString xAxisName(
simulator()->GetXAxis( simType ) );
1976 if( xAxisName.IsEmpty() )
1982 unsigned int size = aDataX->size();
1992 wxFAIL_MSG( wxT(
"Plot type missing AC_PHASE or AC_MAG bit" ) );
2001 wxFAIL_MSG( wxT(
"Plot type missing AC_PHASE or SPT_SP_AMP bit" ) );
2016 wxFAIL_MSG( wxT(
"Unhandled plot type" ) );
2021 size_t sweepSize = std::numeric_limits<size_t>::max();
2023 if( simType ==
ST_DC
2030 sweepSize = aDataX->size() / sweepCount;
2047 size_t sweepSizeMulti = traceData.
xValues.size();
2048 size_t runCount = traceData.
yValues.size();
2050 if( sweepSizeMulti > 0 && runCount > 0 )
2052 std::vector<double> combinedX;
2053 std::vector<double> combinedY;
2055 combinedX.reserve( sweepSizeMulti * runCount );
2056 combinedY.reserve( sweepSizeMulti * runCount );
2058 for(
const std::vector<double>& runY : traceData.
yValues )
2060 if( runY.size() != sweepSizeMulti )
2063 combinedX.insert( combinedX.end(), traceData.
xValues.begin(), traceData.
xValues.end() );
2064 combinedY.insert( combinedY.end(), runY.begin(), runY.end() );
2069 if( combinedY.size() >= combinedX.size() && sweepSizeMulti > 0 )
2071 int sweepCountCombined = combinedX.empty() ? 0 :
static_cast<int>( combinedY.size() / sweepSizeMulti );
2073 if( sweepCountCombined > 0 )
2076 std::vector<wxString> labels;
2077 labels.reserve( sweepCountCombined );
2079 for(
int i = 0; i < sweepCountCombined && i < (int)
m_multiRunState.steps.size(); ++i )
2087 label += wxS(
", " );
2090 double value = it->second;
2096 labels.push_back( label );
2099 aPlotTab->
SetTraceData( trace, combinedX, combinedY, sweepCountCombined,
2100 sweepSizeMulti,
true, labels );
2113 if( data_y.size() >= size )
2114 aPlotTab->
SetTraceData( trace, *aDataX, data_y, sweepCount, sweepSize );
2124template <
typename T,
typename U,
typename R>
2132 wxGridCellAttrPtr attr =
m_signalsGrid->GetOrCreateCellAttrPtr( r,
static_cast<int>( t ) );
2134 if(
TRACE* trace = plotTab ? plotTab->
GetTrace( vectorName, traceType ) :
nullptr )
2136 attr->SetReadOnly();
2140 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
2143 if constexpr ( std::is_enum<T>::value )
2147 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxS(
"1" ) );
2151 if( !attr->HasRenderer() )
2154 if( !attr->HasEditor() )
2157 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
2158 attr->SetReadOnly(
false );
2167 if( !attr->HasRenderer() )
2168 attr->SetRenderer(
new wxGridCellBoolRenderer() );
2170 if( u > 0 && trace->HasCursor( u ) )
2171 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxS(
"1" ) );
2173 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2179 if constexpr ( std::is_enum<T>::value )
2183 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2190 attr->SetEditor(
nullptr );
2191 attr->SetRenderer(
nullptr );
2192 attr->SetReadOnly();
2193 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2202 for(
int row = 0; row <
m_signalsGrid->GetNumberRows(); ++row )
2224 auto quoteNetNames =
2225 [&]( wxString aExpression ) -> wxString
2227 std::vector<bool> mask( aExpression.length(),
false );
2229 auto isNetnameChar =
2230 []( wxUniChar aChar ) ->
bool
2232 wxUint32 value = aChar.GetValue();
2234 if( ( value >=
'0' && value <=
'9' ) || ( value >=
'A' && value <=
'Z' )
2235 || ( value >=
'a' && value <=
'z' ) )
2258 size_t pos = aExpression.find( netname );
2260 while( pos != wxString::npos )
2262 for(
size_t i = 0; i < netname.length(); ++i )
2263 mask[pos + i] =
true;
2265 pos = aExpression.find( netname, pos + 1 );
2269 for(
size_t i = 0; i < aExpression.length(); ++i )
2271 if( !mask[i] || ( i > 0 && mask[i - 1] ) )
2276 while( j < aExpression.length() )
2284 if( isNetnameChar( aExpression[j] ) )
2296 wxString quotedNetnames =
"";
2297 bool startQuote =
true;
2300 for(
size_t i = 0; i < aExpression.length(); i++ )
2302 if( mask[i] && startQuote )
2304 quotedNetnames = quotedNetnames +
"\"";
2307 else if( !mask[i] && !startQuote )
2309 quotedNetnames = quotedNetnames +
"\"";
2313 wxString ch = aExpression[i];
2314 quotedNetnames = quotedNetnames + ch;
2318 quotedNetnames = quotedNetnames +
"\"";
2320 return quotedNetnames;
2325 constexpr const char* cmd =
"let user{} = {}";
2327 simulator()->
Command(
"echo " + fmt::format( cmd,
id, signal.ToStdString() ) );
2328 simulator()->
Command( fmt::format( cmd,
id, quoteNetNames( signal ).ToStdString() ) );
2340 wxString ref = tuner->GetSymbolRef();
2341 KIID symbolId = tuner->GetSymbol( &sheetPath );
2347 reporter.
Report( wxString::Format(
_(
"%s not found" ), ref ) );
2355 reporter.
Report( wxString::Format(
_(
"%s is not tunable" ), ref ) );
2364 floatVal = overrideIt->second;
2366 floatVal = tuner->GetValue().ToDouble();
2377 wxTextFile file( aPath );
2382 wxString firstLine = file.GetFirstLine();
2384 bool legacy = firstLine.StartsWith( wxT(
"version " ) ) || firstLine.ToLong( &
dummy );
2409 wxFileName filename( aPath );
2421 wxFFileInputStream fp( aPath, wxT(
"rt" ) );
2422 wxStdInputStream fstream( fp );
2429 nlohmann::json js = nlohmann::json::parse( fstream,
nullptr,
true,
true );
2431 std::map<SIM_PLOT_TAB*, nlohmann::json> traceInfo;
2433 for(
const nlohmann::json& tab_js : js[
"tabs" ] )
2435 wxString simCommand;
2439 for(
const nlohmann::json& cmd : tab_js[
"commands" ] )
2441 if( cmd ==
".kicad adjustpaths" )
2443 else if( cmd ==
".save all" )
2445 else if( cmd ==
".probe alli" )
2447 else if( cmd ==
".probe allp" )
2449 else if( cmd ==
".kicad esavenone" )
2452 simCommand += wxString( cmd.get<wxString>() ).Trim();
2462 if( tab_js.contains(
"traces" ) )
2463 traceInfo[plotTab] = tab_js[
"traces" ];
2465 if( tab_js.contains(
"measurements" ) )
2467 for(
const nlohmann::json& m_js : tab_js[
"measurements" ] )
2468 plotTab->
Measurements().emplace_back( m_js[
"expr" ], m_js[
"format" ] );
2472 plotTab->
ShowGrid( tab_js[
"showGrid" ] );
2474 if( tab_js.contains(
"fixedY1scale" ) )
2476 const nlohmann::json& scale_js = tab_js[
"fixedY1scale" ];
2477 plotTab->
SetY1Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2481 if( tab_js.contains(
"fixedY2scale" ) )
2483 const nlohmann::json& scale_js = tab_js[
"fixedY2scale" ];
2484 plotTab->
SetY2Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2488 if( tab_js.contains(
"fixedY3scale" ) )
2491 const nlohmann::json& scale_js = tab_js[
"fixedY3scale" ];
2492 plotTab->
SetY3Scale(
true, scale_js[
"min" ], scale_js[
"max" ] );
2496 if( tab_js.contains(
"legend" ) )
2498 const nlohmann::json& legend_js = tab_js[
"legend" ];
2503 if( tab_js.contains(
"margins" ) )
2505 const nlohmann::json& margins_js = tab_js[
"margins" ];
2507 margins_js[
"right" ],
2508 margins_js[
"bottom" ],
2509 margins_js[
"left" ] );
2516 if( js.contains(
"user_defined_signals" ) )
2518 for(
const nlohmann::json& signal_js : js[
"user_defined_signals" ] )
2524 m_simulatorFrame->LoadSimulator( simTab->GetSimCommand(), simTab->GetSimOptions() );
2527 firstTab->SetLastSchTextSimCommand( js[
"last_sch_text_sim_command"] );
2530 int tempCustomCursorsCnt = 0;
2532 if( js.contains(
"custom_cursors" ) )
2533 tempCustomCursorsCnt = js[
"custom_cursors"];
2535 tempCustomCursorsCnt = 2;
2545 int aCursorId,
const nlohmann::json& aCursor_js )
2547 if( aCursorId >= 1 )
2551 cursor->SetName( aSignalName );
2552 cursor->SetCoordX( aCursor_js[
"position" ] );
2554 aTrace->SetCursor( aCursorId,
cursor );
2558 if( aCursorId == -1 )
2579 for(
const auto& [ plotTab, traces_js ] : traceInfo )
2581 for(
const nlohmann::json& trace_js : traces_js )
2583 wxString signalName = trace_js[
"signal" ];
2585 TRACE* trace = plotTab->GetOrAddTrace( vectorName, trace_js[
"trace_type" ] );
2589 if( trace_js.contains(
"cursorD" ) )
2590 addCursor( plotTab, trace, signalName, -1, trace_js[
"cursorD" ] );
2592 std::vector<const char*> aVec;
2595 for(
int i = 1; i <= tempCustomCursorsCnt; i++ )
2597 wxString str =
"cursor" + std::to_string( i );
2598 aVec.emplace_back( str.c_str() );
2600 if( trace_js.contains( aVec[i - 1] ) )
2601 addCursor( plotTab, trace, signalName, i, trace_js[aVec[i - 1]] );
2604 if( trace_js.contains(
"color" ) )
2607 color.Set( wxString( trace_js[
"color"].get<wxString>() ) );
2609 plotTab->UpdateTraceStyle( trace );
2614 plotTab->UpdatePlotColors();
2617 catch( nlohmann::json::parse_error& error )
2619 wxLogTrace(
traceSettings, wxT(
"Json parse error reading %s: %s" ), aPath, error.what() );
2623 catch( nlohmann::json::type_error& error )
2625 wxLogTrace(
traceSettings, wxT(
"Json type error reading %s: %s" ), aPath, error.what() );
2629 catch( nlohmann::json::invalid_iterator& error )
2631 wxLogTrace(
traceSettings, wxT(
"Json invalid_iterator error reading %s: %s" ), aPath, error.what() );
2635 catch( nlohmann::json::out_of_range& error )
2637 wxLogTrace(
traceSettings, wxT(
"Json out_of_range error reading %s: %s" ), aPath, error.what() );
2643 wxLogTrace(
traceSettings, wxT(
"Error reading %s" ), aPath );
2652 int cursorIdAfterD = aCursorId;
2655 cursorIdAfterD = cursorIdAfterD - 1;
2660 aTraceJs[
"cursor" + wxString(
"" ) << aCursorId] =
2661 nlohmann::json( { {
"position",
cursor->GetCoords().x },
2668 aTraceJs[
"cursorD"] =
2679 wxFileName filename = aPath;
2684 file.Create( filename.GetFullPath(),
true );
2686 if( !file.IsOpened() )
2689 nlohmann::json tabs_js = nlohmann::json::array();
2700 nlohmann::json commands_js = nlohmann::json::array();
2707 commands_js.push_back(
".kicad adjustpaths" );
2710 commands_js.push_back(
".save all" );
2713 commands_js.push_back(
".probe alli" );
2716 commands_js.push_back(
".probe allp" );
2719 commands_js.push_back(
".kicad esavenone" );
2721 nlohmann::json tab_js = nlohmann::json(
2723 {
"commands", commands_js } } );
2727 nlohmann::json traces_js = nlohmann::json::array();
2729 auto findSignalName =
2730 [&](
const wxString& aVectorName ) -> wxString
2732 wxString vectorName;
2735 if( aVectorName.EndsWith(
_(
" (phase)" ) ) )
2736 suffix =
_(
" (phase)" );
2737 else if( aVectorName.EndsWith(
_(
" (gain)" ) ) )
2738 suffix =
_(
" (gain)" );
2740 vectorName = aVectorName.Left( aVectorName.Length() - suffix.Length() );
2745 return signal + suffix;
2751 for(
const auto& [
name, trace] : plotTab->GetTraces() )
2753 nlohmann::json trace_js = nlohmann::json(
2754 { {
"trace_type", (int) trace->GetType() },
2755 {
"signal", findSignalName( trace->GetDisplayName() ) },
2761 if( trace->GetCursor( 1 ) || trace->GetCursor( 2 ) )
2763 trace_js[
"cursorD"] = nlohmann::json(
2768 traces_js.push_back( trace_js );
2771 nlohmann::json measurements_js = nlohmann::json::array();
2773 for(
const auto& [
measurement, format ] : plotTab->Measurements() )
2775 measurements_js.push_back( nlohmann::json( { {
"expr",
measurement },
2776 {
"format", format } } ) );
2779 tab_js[
"traces" ] = traces_js;
2780 tab_js[
"measurements" ] = measurements_js;
2781 tab_js[
"dottedSecondary" ] = plotTab->GetDottedSecondary();
2782 tab_js[
"showGrid" ] = plotTab->IsGridShown();
2786 if( plotTab->GetY1Scale( &min, &max ) )
2787 tab_js[
"fixedY1scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2789 if( plotTab->GetY2Scale( &min, &max ) )
2790 tab_js[
"fixedY2scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2792 if( plotTab->GetY3Scale( &min, &max ) )
2793 tab_js[
"fixedY3scale" ] = nlohmann::json( { {
"min", min }, {
"max", max } } );
2795 if( plotTab->IsLegendShown() )
2797 tab_js[
"legend" ] = nlohmann::json( { {
"x", plotTab->GetLegendPosition().x },
2798 {
"y", plotTab->GetLegendPosition().y } } );
2801 mpWindow* plotWin = plotTab->GetPlotWin();
2803 tab_js[
"margins" ] = nlohmann::json( { {
"left", plotWin->
GetMarginLeft() },
2809 tabs_js.push_back( tab_js );
2812 nlohmann::json userDefinedSignals_js = nlohmann::json::array();
2815 userDefinedSignals_js.push_back( signal );
2818 nlohmann::json js = nlohmann::json( { {
"version", 7 },
2819 {
"tabs", tabs_js },
2820 {
"user_defined_signals", userDefinedSignals_js },
2833 std::stringstream buffer;
2834 buffer << std::setw( 2 ) << js << std::endl;
2836 bool res = file.Write( buffer.str() );
2863 wxFAIL_MSG( wxString::Format( wxS(
"Unhandled simulation type: %d" ), (
int) aType ) );
2883 &source, &
scale, &pts, &fStart, &fStop, &saveAll );
2891 int& aSashPosition )
2893 bool isShown = aPanel->IsShown();
2896 aSashPosition = aSplitterWindow->GetSashPosition();
2898 aPanel->Show( !isShown );
2900 aSplitterWindow->SetSashInvisible( isShown );
2901 aSplitterWindow->SetSashPosition( isShown ? -1 : aSashPosition,
true );
2903 aSplitterWindow->UpdateSize();
2904 m_parent->Refresh();
2941 for(
size_t page = 0; page <
m_plotNotebook->GetPageCount(); page++ )
2989 std::vector<std::pair<wxString, wxString>>& measurements = plotTab->Measurements();
2991 measurements.clear();
3029 simulator()->
Command(
"setplot " + simTab->GetSpicePlotName().ToStdString() );
3046 for(
const auto& [
measurement, format ] : plotTab->Measurements() )
3054 if( plotTab->GetSimType() ==
ST_TRAN || plotTab->GetSimType() ==
ST_AC
3055 || plotTab->GetSimType() ==
ST_DC || plotTab->GetSimType() ==
ST_SP )
3092 CURSOR* cursor1 =
nullptr;
3093 wxString cursor1Name;
3094 wxString cursor1Units;
3095 CURSOR* cursor2 =
nullptr;
3096 wxString cursor2Name;
3097 wxString cursor2Units;
3100 [&](
TRACE* aTrace ) -> wxString
3121 [&](
TRACE* aTrace ) -> wxString
3142 [
this](
double aValue,
int aCursorId,
int aCol ) -> wxString
3144 if( ( !
m_simulatorFrame->SimFinished() && aCol == 1 ) || std::isnan( aValue ) )
3155 cursor1Name = getNameY( trace );
3156 cursor1Units = getUnitsY( trace );
3158 wxRealPoint coords =
cursor->GetCoords();
3178 cursor2Name = getNameY( trace );
3179 cursor2Units = getUnitsY( trace );
3181 wxRealPoint coords =
cursor->GetCoords();
3196 if( cursor1 && cursor2 && cursor1Units == cursor2Units )
3205 signal = wxString::Format( wxS(
"%s[2 - 1]" ), cursor2->
GetName() );
3207 signal = wxString::Format( wxS(
"%s - %s" ), cursor2->
GetName(), cursor1->
GetName() );
3218 wxString valColName =
_(
"Value" );
3220 if( !cursor1Name.IsEmpty() )
3222 if( cursor2Name.IsEmpty() || cursor1Name == cursor2Name )
3223 valColName = cursor1Name;
3225 else if( !cursor2Name.IsEmpty() )
3227 valColName = cursor2Name;
3241 wxString cursName = getNameY( trace );
3242 wxString cursUnits = getUnitsY( trace );
3244 wxRealPoint coords =
cursor->GetCoords();
3259 valColName =
_(
"Value" );
3262 valColName = cursName;
3283 plotTab->ResetScales(
true );
3305 std::vector<wxString> signals;
3307 for(
const std::string& vec :
simulator()->AllVectors() )
3308 signals.emplace_back( vec );
3316 std::vector<wxString> signals;
3318 for(
const wxString& signal :
m_signals )
3319 signals.emplace_back( signal );
3322 signals.emplace_back( signal );
3340 bool storeMultiRun =
false;
3346 storeMultiRun =
true;
3369 if( simType ==
ST_NOISE && aFinal )
3371 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3380 for(
const std::string& vec :
simulator()->AllVectors() )
3385 msg.Printf( wxS(
"%s: %sV\n" ), vec, value );
3396 wxCHECK_RET( plotTab, wxString::Format( wxT(
"No SIM_PLOT_TAB for: %s" ),
3397 magic_enum::enum_name( simType ) ) );
3406 std::map<TRACE*, TRACE_INFO> traceMap;
3409 traceMap[ trace ] = { wxEmptyString,
SPT_UNKNOWN,
false };
3414 for(
const wxString& signal :
m_signals )
3419 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
3420 traceMap[ trace ] = { vectorName, traceType,
false };
3428 if( simType ==
ST_AC )
3434 if(
TRACE* trace = plotTab->
GetTrace( vectorName, subType ) )
3435 traceMap[ trace ] = { vectorName, subType, !aFinal };
3438 else if( simType ==
ST_SP )
3444 if(
TRACE* trace = plotTab->
GetTrace( vectorName, subType ) )
3445 traceMap[trace] = { vectorName, subType, !aFinal };
3450 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
3451 traceMap[ trace ] = { vectorName, traceType, !aFinal };
3457 for(
const auto& [ trace, traceInfo ] : traceMap )
3459 if( traceInfo.Vector.IsEmpty() )
3463 for(
const auto& [ trace,
info ] : traceMap )
3465 std::vector<double> data_x;
3467 if( !
info.Vector.IsEmpty() )
3485 else if( simType ==
ST_OP && aFinal )
3487 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3490 for(
const std::string& vec :
simulator()->AllVectors() )
3494 if( val_list.empty() )
3501 const size_t tab = 25;
3502 size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1;
3506 case SPT_VOLTAGE: value.Append( wxS(
"V" ) );
break;
3507 case SPT_CURRENT: value.Append( wxS(
"A" ) );
break;
3508 case SPT_POWER: value.Append( wxS(
"W" ) );
break;
3509 default: value.Append( wxS(
"?" ) );
break;
3512 msg.Printf( wxT(
"%s%s\n" ),
3513 ( signal + wxT(
":" ) ).Pad( padding, wxUniChar(
' ' ) ),
3520 signal = signal.SubString( 2, signal.Length() - 2 );
3523 signal += wxS(
":power" );
3525 m_schematicFrame->Schematic().SetOperatingPoint( signal, val_list.at( 0 ) );
3528 else if( simType ==
ST_PZ && aFinal )
3530 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
3591 std::vector<TUNER_SLIDER*> multiTuners;
3596 multiTuners.push_back( tuner );
3599 if( multiTuners.empty() )
3631 else if( tunersChanged )
3640 for(
const auto& entry : step.
overrides )
3647 const std::vector<TUNER_SLIDER*>& aTuners )
const
3649 std::vector<MULTI_RUN_STEP> steps;
3651 if( aTuners.empty() )
3654 std::vector<std::vector<double>> tunerValues;
3655 tunerValues.reserve( aTuners.size() );
3662 double startValue = tuner->GetMin().ToDouble();
3663 double endValue = tuner->GetMax().ToDouble();
3664 int stepCount = std::max( 2, tuner->GetStepCount() );
3669 double increment = ( endValue - startValue ) /
static_cast<double>( stepCount - 1 );
3671 std::vector<double> values;
3672 values.reserve( stepCount );
3674 for(
int ii = 0; ii < stepCount; ++ii )
3675 values.push_back( startValue + increment * ii );
3677 tunerValues.push_back( std::move( values ) );
3685 std::vector<double> currentValues( aTuners.size(), 0.0 );
3687 auto generate = [&](
auto&& self,
size_t depth ) ->
void
3689 if( steps.size() >=
static_cast<size_t>( limit ) )
3692 if( depth == aTuners.size() )
3696 for(
size_t ii = 0; ii < aTuners.size(); ++ii )
3697 step.
overrides.emplace( aTuners[ii], currentValues[ii] );
3699 steps.push_back( std::move( step ) );
3703 for(
double value : tunerValues[depth] )
3705 currentValues[depth] = value;
3706 self( self, depth + 1 );
3708 if( steps.size() >=
static_cast<size_t>( limit ) )
3713 generate( generate, 0 );
3721 return fmt::format(
"{}|{}", aVectorName.ToStdString(), aTraceType );
3726 const std::vector<double>& aX,
3727 const std::vector<double>& aY )
3729 if( aX.empty() || aY.empty() )
3740 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.