28#include <wx/settings.h>
29#include <fmt/format.h>
30#include <wx/wfstream.h>
31#include <wx/stdstream.h>
33#include <wx/clipbrd.h>
35#include <wx/tokenzr.h>
59#include <magic_enum.hpp>
65 int res =
static_cast<int>( aFirst ) |
static_cast<int>( aSecond );
147 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
override;
198 menu.AppendSeparator();
199 menu.Append(
MYID_FOURIER,
_(
"Perform Fourier Analysis..." ) );
202 menu.AppendSeparator();
205 menu.AppendSeparator();
208 m_grid->PopupMenu( &menu );
215 menu.AppendSeparator();
217 wxString msg =
m_grid->GetColLabelValue(
m_grid->GetNumberCols() - 1 );
219 menu.AppendSeparator();
222 m_grid->PopupMenu( &menu );
228 m_grid->PopupMenu( &menu );
235 std::vector<wxString> signals;
237 wxGridCellCoordsArray cells1 =
m_grid->GetSelectionBlockTopLeft();
238 wxGridCellCoordsArray cells2 =
m_grid->GetSelectionBlockBottomRight();
240 for(
size_t i = 0; i < cells1.Count(); i++ )
244 for(
int j = cells1[i].GetRow(); j < cells2[i].GetRow() + 1; j++ )
246 signals.push_back(
m_grid->GetCellValue( j, cells1[i].GetCol() ) );
251 wxGridCellCoordsArray cells3 =
m_grid->GetSelectedCells();
253 for(
size_t i = 0; i < cells3.Count(); i++ )
256 signals.push_back(
m_grid->GetCellValue( cells3[i].GetRow(), cells3[i].GetCol() ) );
259 if( signals.size() < 1 )
262 auto addMeasurement =
263 [
this](
const wxString& cmd, wxString signal )
265 if( signal.EndsWith(
_(
" (phase)" ) ) )
268 if( signal.EndsWith(
_(
" (gain)" ) ) || signal.EndsWith(
_(
" (amplitude)" ) ) )
270 signal = signal.Left( signal.length() - 7 );
272 if( signal.Upper().StartsWith( wxS(
"V(" ) ) )
273 signal = wxS(
"vdb" ) + signal.Mid( 1 );
276 m_parent->AddMeasurement( cmd + wxS(
" " ) + signal );
281 for(
const wxString& signal : signals )
282 addMeasurement( wxS(
"MIN" ), signal );
286 for(
const wxString& signal : signals )
287 addMeasurement( wxS(
"MAX" ), signal );
291 for(
const wxString& signal : signals )
292 addMeasurement( wxS(
"AVG" ), signal );
296 for(
const wxString& signal : signals )
297 addMeasurement( wxS(
"RMS" ), signal );
301 for(
const wxString& signal : signals )
302 addMeasurement( wxS(
"PP" ), signal );
306 for(
const wxString& signal : signals )
307 addMeasurement( wxS(
"MIN_AT" ), signal );
311 for(
const wxString& signal : signals )
312 addMeasurement( wxS(
"MAX_AT" ), signal );
316 for(
const wxString& signal : signals )
317 addMeasurement( wxS(
"INTEG" ), signal );
322 wxString fundamental = wxT(
"1K" );
324 if( signals.size() == 1 )
325 title.Printf(
_(
"Fourier Analysis of %s" ), signals[0] );
327 title =
_(
"Fourier Analyses of Multiple Signals" );
337 for(
const wxString& signal : signals )
338 m_parent->DoFourier( signal, fundamental );
345 for(
const wxString& signal : signals )
353 if( wxTheClipboard->Open() )
355 wxTheClipboard->SetData(
new wxTextDataObject( txt ) );
356 wxTheClipboard->Flush();
357 wxTheClipboard->Close();
383 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
override;
403 menu.AppendSeparator();
413 [
this](
int row ) -> wxString
417 if( signal.EndsWith(
"[2 - 1]" ) )
418 signal = signal.Left( signal.length() - 7 );
429 if( formatDialog.
ShowModal() == wxID_OK )
431 for(
int row = 0; row <
m_grid->GetNumberRows(); ++row )
433 if( getSignalName( row ) == getSignalName(
m_menuRow ) )
434 m_parent->SetCursorFormat( row, axis, format );
457 void showPopupMenu( wxMenu& menu, wxGridEvent& aEvent )
override;
483 menu.AppendSeparator();
496 if( formatDialog.
ShowModal() == wxID_OK )
505 std::vector<int> measurements;
507 wxGridCellCoordsArray cells1 =
m_grid->GetSelectionBlockTopLeft();
508 wxGridCellCoordsArray cells2 =
m_grid->GetSelectionBlockBottomRight();
510 for(
size_t i = 0; i < cells1.Count(); i++ )
514 for(
int j = cells1[i].GetRow(); j < cells2[i].GetRow() + 1; j++ )
515 measurements.push_back( j );
519 wxGridCellCoordsArray cells3 =
m_grid->GetSelectedCells();
521 for(
size_t i = 0; i < cells3.Count(); i++ )
524 measurements.push_back( cells3[i].GetRow() );
527 if( measurements.size() < 1 )
532 sort( measurements.begin(), measurements.end(), std::greater<>() );
534 for(
int row : measurements )
554 m_frame->m_SuppressGridEvents++;
559 m_frame->m_SuppressGridEvents--;
567#define ID_SIM_REFRESH 10207
568#define REFRESH_INTERVAL 50
585 Bind( EVT_SIM_VIEWS_CHANGED,
586 [&]( wxCommandEvent& aEvent )
601 wxGridCellAttr* attr =
new wxGridCellAttr;
605 attr =
new wxGridCellAttr;
609 attr =
new wxGridCellAttr;
613 attr =
new wxGridCellAttr;
619 attr =
new wxGridCellAttr;
629 [&]( wxTimerEvent& aEvent )
638#ifndef wxHAS_NATIVE_TABART
658 m_cursorFormat[0] = { 3, wxS(
"~s" ) };
659 m_cursorFormat[1] = { 3, wxS(
"~V" ) };
670 for(
size_t index2 = 0; index2 < std::size(
m_cursorFormats[0] ); index2++ )
684 maxCursor.Replace(
_(
"Cursor " ),
"" );
686 int tmpMax = wxAtoi( maxCursor );
688 if( nameMax < tmpMax )
698 std::vector<SPICE_VALUE_FORMAT> tmp;
710 wxGridCellAttr* attr =
new wxGridCellAttr;
730 for(
int i = 0; i < rows; i++ )
732 if(
m_signalsGrid->GetCellValue( i, col - 1 ) == wxS(
"1" ) )
735 wxGridEvent aDummy( wxID_ANY, wxEVT_GRID_CELL_CHANGED,
m_signalsGrid, i, col - 1 );
754 for(
int ii = 0; ii < static_cast<int>(
m_plotNotebook->GetPageCount() ); ++ii )
758 simTab->OnLanguageChanged();
760 wxString pageTitle(
simulator()->TypeToName( simTab->GetSimType(),
true ) );
761 pageTitle.Prepend( wxString::Format(
_(
"Analysis %u - " ), ii + 1 ) );
784 tuner->ShowChangedLanguage();
830 simTab->ApplyPreferences( aPrefs );
838 bool loadFromSchematic =
false;
840 if( !workbookFilename.IsEmpty() )
842 wxFileName filename = workbookFilename;
845 if( !filename.FileExists() )
848 wxString msg = wxString::Format(
_(
"Workbook file '%s' not found. Loading simulation settings from "
850 filename.GetFullPath() );
854 loadFromSchematic =
true;
863 loadFromSchematic =
true;
866 if( loadFromSchematic &&
m_simulatorFrame->LoadSimulator( wxEmptyString, 0 ) )
870 if( !schTextSimCommand.IsEmpty() )
903 std::sort( signals.begin(), signals.end(),
904 [](
const wxString& lhs,
const wxString& rhs )
907 if( lhs.Upper().StartsWith(
'V' ) && !rhs.Upper().StartsWith(
'V' ) )
909 else if( !lhs.Upper().StartsWith(
'V' ) && rhs.Upper().StartsWith(
'V' ) )
912 return StrNumCmp( lhs, rhs, true ) < 0;
929 std::vector<wxString> signals;
933 wxStringTokenizer tokenizer( plotPanel->
GetSimCommand(),
" \t\r\n", wxTOKEN_STRTOK );
935 while( tokenizer.HasMoreTokens() && tokenizer.GetNextToken().Lower() != wxT(
"fft" ) )
939 while( tokenizer.HasMoreTokens() )
940 signals.emplace_back( tokenizer.GetNextToken() );
947 for(
const wxString& signal :
m_signals )
948 signals.push_back( signal );
952 if( simType ==
ST_AC )
954 signals.push_back( signal +
_(
" (gain)" ) );
955 signals.push_back( signal +
_(
" (phase)" ) );
957 else if( simType ==
ST_SP )
961 signals.push_back( signal );
965 signals.push_back( signal +
_(
" (amplitude)" ) );
966 signals.push_back( signal +
_(
" (phase)" ) );
971 signals.push_back( signal );
978 if( aFilter.IsEmpty() )
979 aFilter = wxS(
"*" );
984 for(
const wxString& signal : signals )
986 if( matcher.
Find( signal.Upper() ) )
994 bool plotted = trace && trace->
GetView();
999 wxGridCellAttr* attr =
new wxGridCellAttr;
1002 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
1005 attr->SetTextColour( *wxLIGHT_GREY );
1013 attr =
new wxGridCellAttr;
1014 attr->SetReadOnly();
1018 attr =
new wxGridCellAttr;
1019 attr->SetReadOnly();
1023 attr =
new wxGridCellAttr;
1024 attr->SetReadOnly();
1027 attr =
new wxGridCellAttr;
1028 attr->SetReadOnly();
1035 attr =
new wxGridCellAttr;
1036 attr->SetReadOnly();
1043 attr =
new wxGridCellAttr;
1046 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
1050 attr =
new wxGridCellAttr;
1053 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
1058 attr =
new wxGridCellAttr;
1059 attr->SetRenderer(
new wxGridCellBoolRenderer() );
1060 attr->SetReadOnly();
1061 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
1065 attr =
new wxGridCellAttr;
1066 attr->SetRenderer(
new wxGridCellBoolRenderer() );
1067 attr->SetReadOnly();
1068 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
1076 attr =
new wxGridCellAttr;
1077 attr->SetRenderer(
new wxGridCellBoolRenderer() );
1078 attr->SetReadOnly();
1079 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
1101 wxGridUpdateLocker deferRepaintsTillLeavingScope( aGrid );
1103 aGrid->AutoSizeColumn( aCol );
1104 aGrid->AutoSizeColLabelSize( aCol );
1106 if( aExtraPadding > 0 )
1107 aGrid->SetColSize( aCol, aGrid->GetColSize( aCol ) + aExtraPadding );
1109 if( aGrid->GetColSize( aCol ) < aMinWidth )
1110 aGrid->SetColSize( aCol, aMinWidth );
1114#define UNPLOTTED _( "none" )
1118 wxArrayString choices;
1124 choices.Add( wxString::Format(
_(
"View %d" ), ii + 1 ) );
1133 if( !aView || !aPlotTab )
1144 std::vector<SIM_VIEW*> views;
1150 if( view != aOwnView )
1151 views.push_back( view );
1161 wxArrayString choices;
1162 choices.Add(
_(
"Default" ) );
1174 return _(
"Default" );
1186 wxString unconnected = wxString( wxS(
"unconnected-(" ) );
1191 unconnected.Replace(
'(',
'_' );
1197 [&](
const wxString& aSignalName )
1199 if( simType ==
ST_AC )
1201 m_signals.push_back( aSignalName +
_(
" (gain)" ) );
1202 m_signals.push_back( aSignalName +
_(
" (phase)" ) );
1204 else if( simType ==
ST_SP )
1212 m_signals.push_back( aSignalName +
_(
" (amplitude)" ) );
1213 m_signals.push_back( aSignalName +
_(
" (phase)" ) );
1225 for(
const wxString& netname :
circuitModel()->GetNets() )
1227 if( netname.IsSameAs( wxS(
"GND" ),
false ) || netname ==
"0" || netname.StartsWith( unconnected ) )
1231 addSignal( wxString::Format( wxS(
"V(%s)" ), netname ) );
1241 for(
const std::string&
name : item.model->SpiceGenerator().CurrentNames( item ) )
1251 if( item.model->GetPinCount() >= 2 )
1253 wxString
name = item.model->SpiceGenerator().ItemName( item );
1254 addSignal( wxString::Format( wxS(
"P(%s)" ),
name ) );
1261 addSignal( wxS(
"inoise_spectrum" ) );
1262 addSignal( wxS(
"onoise_spectrum" ) );
1265 if( simType ==
ST_SP )
1267 std::vector<std::string> portnums;
1271 wxString
name = item.model->SpiceGenerator().ItemName( item );
1274 if( !
name.StartsWith(
"V" ) )
1277 std::string portnum =
"";
1279 if(
const SIM_MODEL::PARAM* portnum_param = item.model->FindParam(
"portnum" ) )
1283 portnums.push_back( portnum );
1286 for(
const std::string& portnum1 : portnums )
1288 for(
const std::string& portnum2 : portnums )
1292 if( smithMode && portnum1 != portnum2 )
1295 addSignal( wxString::Format( wxS(
"S_%s_%s" ), portnum1, portnum2 ) );
1301 for(
const wxString& directive :
circuitModel()->GetDirectives() )
1303 wxStringTokenizer directivesTokenizer( directive,
"\r\n", wxTOKEN_STRTOK );
1305 while( directivesTokenizer.HasMoreTokens() )
1307 wxString line = directivesTokenizer.GetNextToken().Upper();
1308 wxString directiveParams;
1310 if( line.StartsWith( wxS(
".SAVE" ), &directiveParams )
1311 || line.StartsWith( wxS(
".PROBE" ), &directiveParams ) )
1313 wxStringTokenizer paramsTokenizer( directiveParams,
" \t", wxTOKEN_STRTOK );
1315 while( paramsTokenizer.HasMoreTokens() )
1316 addSignal( paramsTokenizer.GetNextToken() );
1339 wxString pageTitle(
simulator()->TypeToName( simType,
true ) );
1340 pageTitle.Prepend( wxString::Format(
_(
"Analysis %u - " ),
static_cast<unsigned int>( ++
m_plotNumber ) ) );
1356#if defined( __WXOSX__ )
1357 wxPoint pos = aEvent.GetPosition();
1358 wxRect ctrlRect =
m_filter->GetScreenRect();
1359 int buttonWidth = ctrlRect.GetHeight();
1361 if(
m_filter->IsSearchButtonVisible() && pos.x < buttonWidth )
1362 SetCursor( wxCURSOR_ARROW );
1363 else if(
m_filter->IsCancelButtonVisible() && pos.x > ctrlRect.GetWidth() - buttonWidth )
1364 SetCursor( wxCURSOR_ARROW );
1366 SetCursor( wxCURSOR_IBEAM );
1373 return wxString::Format( wxS(
"user%d" ), aUserDefinedSignalId );
1384 auto looksLikePower = [](
const wxString& aExpression ) ->
bool
1386 wxString exprUpper = aExpression.Upper();
1388 if( exprUpper.Contains( wxS(
":POWER" ) ) )
1391 if( exprUpper.Find(
'*' ) == wxNOT_FOUND )
1394 if( !exprUpper.Contains( wxS(
"V(" ) ) )
1397 if( !exprUpper.Contains( wxS(
"I(" ) ) )
1403 std::map<wxString, int> suffixes;
1419 wxUniChar firstChar = aSignalName.Upper()[0];
1421 if( firstChar ==
'V' )
1423 else if( firstChar ==
'I' )
1425 else if( firstChar ==
'P' )
1430 wxString
name = aSignalName;
1432 for(
const auto& [candidate, type] : suffixes )
1434 if(
name.EndsWith( candidate ) )
1436 name =
name.Left(
name.Length() - candidate.Length() );
1439 *aTraceType |= type;
1454 if(
name == signal )
1456 if( aTraceType && looksLikePower( signal ) )
1480 int row = aEvent.GetRow();
1481 int col = aEvent.GetCol();
1490 int choiceIndex = choices.Index(
text );
1492 if( choiceIndex <= 0 )
1498 TRACE* existing = plotTab->
GetTrace( vectorName, traceType );
1500 if( existing && existing->
GetView() != targetView )
1503 updateTrace( vectorName, traceType, plotTab,
nullptr,
false, targetView );
1522 int choiceIndex = choices.Index(
text );
1524 if( choiceIndex == 0 )
1528 else if( choiceIndex > 0 && choiceIndex - 1 < (
int) targetViews.size() )
1564 TRACE* activeTrace =
nullptr;
1566 if(
text == wxS(
"1" ) )
1570 activeTrace = plotTab->
GetTrace( vectorName, traceType );
1581 if( trace != activeTrace && trace->
HasCursor(
id ) )
1604 int row = aEvent.GetRow();
1605 int col = aEvent.GetCol();
1613 CURSOR* cursor1 =
nullptr;
1614 CURSOR* cursor2 =
nullptr;
1616 std::vector<CURSOR*> cursorsVec;
1638 cursorsVec.emplace_back(
cursor );
1640 if( cursorName == ( wxString(
"" ) << i ) &&
cursor )
1641 cursor->SetCoordX( value );
1648 if( cursorName == wxS(
"1" ) && cursor1 )
1650 else if( cursorName == wxS(
"2" ) && cursor2 )
1652 else if( cursorName ==
_(
"Diff" ) && cursor1 && cursor2 )
1660 wxFAIL_MSG( wxT(
"All other columns are supposed to be read-only!" ) );
1693 int row = aEvent.GetRow();
1694 int col = aEvent.GetCol();
1704 wxFAIL_MSG( wxT(
"All other columns are supposed to be read-only!" ) );
1712 for( row = rowCount - 1; row >= 0; row-- )
1722 int killRows = emptyRows - 1;
1725 else if( emptyRows == 0 )
1736 if( plotTab->GetLegendPosition() != plotTab->m_LastLegendPosition )
1738 plotTab->m_LastLegendPosition = plotTab->GetLegendPosition();
1761 static wxRegEx measureParamsRegEx( wxT(
"^"
1765 "([a-zA-Z]*)\\(([^\\)]+)\\)" ) );
1774 if(
text.IsEmpty() )
1781 wxString resultName = wxString::Format( wxS(
"meas_result_%u" ), aRow );
1782 wxString
result = wxS(
"?" );
1784 if( measureParamsRegEx.Matches(
text ) )
1786 wxString func = measureParamsRegEx.GetMatch(
text, 1 ).Upper();
1787 wxString signalType = measureParamsRegEx.GetMatch(
text, 2 ).Upper();
1788 wxString deviceName = measureParamsRegEx.GetMatch(
text, 3 );
1792 if( signalType.EndsWith( wxS(
"DB" ) ) )
1794 units = wxS(
"dB" );
1796 else if( signalType.StartsWith(
'I' ) )
1800 else if( signalType.StartsWith(
'P' ) )
1804 text = func +
" " + deviceName +
":power";
1811 if( func.EndsWith( wxS(
"_AT" ) ) )
1814 units = wxS(
"Hz" );
1818 else if( func.StartsWith( wxS(
"INTEG" ) ) )
1823 if ( signalType.StartsWith(
'P' ) )
1826 units += wxS(
".s" );
1836 units += wxS(
"·Hz" );
1844 units += wxS(
"·?" );
1857 wxString cmd = wxString::Format( wxS(
"meas %s %s %s" ), simType, resultName,
text );
1863 if( resultVec.size() > 0 )
1878 "the value of a passive R, L, C model or voltage or "
1879 "current source." ) );
1883 wxString ref = aSymbol->
GetRef( &aSheetPath );
1888 if( tuner->GetSymbolRef() == ref )
1911 const wxString& aValue )
1921 + wxString::Format(
_(
"%s not found" ), aRef ) );
1928 std::vector<EMBEDDED_FILES*> embeddedFilesStack;
1929 embeddedFilesStack.push_back(
m_schematicFrame->Schematic().GetEmbeddedFiles() );
1933 embeddedFilesStack.push_back( symbolEmbeddedFiles );
1946 + wxString::Format(
_(
"%s is not tunable" ), aRef ) );
1950 model.SetParamValue( tunerParam->
info.
name, std::string( aValue.ToUTF8() ) );
2020 wxString cmd = wxString::Format( wxS(
"fourier %s %s" ),
2038 m_simConsole->AppendText(
_(
"Error: no current simulation.\n" ) );
2047 m_simConsole->AppendText(
_(
"Error: simulation type not defined.\n" ) );
2053 m_simConsole->AppendText(
_(
"Error: simulation type doesn't support plotting.\n" ) );
2060 if( simType ==
ST_AC )
2065 else if( simType ==
ST_SP )
2067 if( plotTab->IsSmithMode() )
2082 for(
SIM_VIEW* view : plotTab->GetViews() )
2105 if( aNewSignals.count(
id ) == 0 )
2110 plotTab->
DeleteTrace( vectorName, traceType | subType );
2115 plotTab->
DeleteTrace( vectorName, traceType | subType );
2128 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType | subType ) )
2129 trace->SetName( aNewSignals.at(
id ) );
2136 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType | subType ) )
2137 trace->SetName( aNewSignals.at(
id ) );
2142 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
2143 trace->SetName( aNewSignals.at(
id ) );
2164 long responsePort, drivePort;
2180 || portnum != responsePort )
2201 std::vector<double>* aDataX,
bool aClearData,
SIM_VIEW* aView )
2205 TRACE* existing = aPlotTab->
GetTrace( aVectorName, aTraceType );
2220 wxString simVectorName = aVectorName;
2223 simVectorName = simVectorName.AfterFirst(
'(' ).BeforeLast(
')' ) + wxS(
":power" );
2233 std::vector<double> data_x;
2234 std::vector<double> data_y;
2235 std::vector<double> frequencies;
2237 if( !aDataX || aClearData )
2241 if( aDataX->empty() && !aClearData )
2243 wxString xAxisName(
simulator()->GetXAxis( simType ) );
2245 if( xAxisName.IsEmpty() )
2251 unsigned int size = aDataX->size();
2261 wxFAIL_MSG( wxT(
"Plot type missing AC_PHASE or AC_MAG bit" ) );
2268 frequencies = *aDataX;
2282 wxFAIL_MSG( wxT(
"Plot type missing AC_PHASE, SPT_SP_AMP or SPT_SP_SMITH bit" ) );
2298 wxFAIL_MSG( wxT(
"Unhandled plot type" ) );
2303 size_t sweepSize = std::numeric_limits<size_t>::max();
2305 if( simType ==
ST_DC
2312 sweepSize = aDataX->size() / sweepCount;
2331 size_t sweepSizeMulti = traceData.
xValues.size();
2332 size_t runCount = traceData.
yValues.size();
2334 if( sweepSizeMulti > 0 && runCount > 0 )
2336 std::vector<double> combinedX;
2337 std::vector<double> combinedY;
2338 std::vector<double> combinedFreq;
2340 combinedX.reserve( sweepSizeMulti * runCount );
2341 combinedY.reserve( sweepSizeMulti * runCount );
2343 for(
size_t run = 0; run < traceData.
yValues.size(); run++ )
2345 const std::vector<double>& runY = traceData.
yValues[run];
2347 if( runY.size() != sweepSizeMulti )
2353 if( run >= traceData.
xRuns.size() || traceData.
xRuns[run].size() != sweepSizeMulti )
2356 combinedX.insert( combinedX.end(), traceData.
xRuns[run].begin(),
2357 traceData.
xRuns[run].end() );
2361 combinedX.insert( combinedX.end(), traceData.
xValues.begin(), traceData.
xValues.end() );
2364 combinedY.insert( combinedY.end(), runY.begin(), runY.end() );
2367 if( frequencies.size() == sweepSizeMulti )
2368 combinedFreq.insert( combinedFreq.end(), frequencies.begin(), frequencies.end() );
2378 if( combinedFreq.size() == combinedX.size() )
2379 smith->SetFrequencies( combinedFreq );
2382 if( combinedY.size() >= combinedX.size() && sweepSizeMulti > 0 )
2384 int sweepCountCombined =
2385 combinedX.empty() ? 0 :
static_cast<int>( combinedY.size() / sweepSizeMulti );
2387 if( sweepCountCombined > 0 )
2390 std::vector<wxString> labels;
2391 labels.reserve( sweepCountCombined );
2393 for(
int i = 0; i < sweepCountCombined && i < (int)
m_multiRunState.steps.size(); ++i )
2401 label += wxS(
", " );
2404 double value = it->second;
2410 labels.push_back( label );
2413 aPlotTab->
SetTraceData( trace, combinedX, combinedY, sweepCountCombined, sweepSizeMulti,
2427 if( data_y.size() >= size )
2431 smith->SetFrequencies( frequencies );
2436 aPlotTab->
SetTraceData( trace, *aDataX, data_y, sweepCount, sweepSize );
2447template <
typename T,
typename U,
typename R>
2456 wxGridCellAttrPtr attr =
m_signalsGrid->GetOrCreateCellAttrPtr( r,
static_cast<int>( t ) );
2458 TRACE* trace = plotTab ? plotTab->
GetTrace( vectorName, traceType ) :
nullptr;
2462 bool plotted = trace && trace->
GetView();
2466 attr->SetReadOnly();
2470 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
2473 if constexpr( std::is_enum<T>::value )
2477 if( !attr->HasEditor() )
2480 if( !attr->HasRenderer() )
2483 attr->SetReadOnly(
false );
2484 attr->SetTextColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ) );
2489 if( !attr->HasEditor() )
2492 if( !attr->HasRenderer() )
2495 attr->SetReadOnly(
false );
2500 if( !attr->HasRenderer() )
2503 if( !attr->HasEditor() )
2506 attr->SetAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
2507 attr->SetReadOnly(
false );
2516 if( !attr->HasRenderer() )
2517 attr->SetRenderer(
new wxGridCellBoolRenderer() );
2520 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxS(
"1" ) );
2522 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2528 if constexpr( std::is_enum<T>::value )
2532 if( !attr->HasEditor() )
2535 if( !attr->HasRenderer() )
2538 attr->SetReadOnly(
false );
2539 attr->SetTextColour( *wxLIGHT_GREY );
2548 attr->SetEditor(
nullptr );
2549 attr->SetRenderer(
nullptr );
2550 attr->SetReadOnly();
2551 m_signalsGrid->SetCellValue( r,
static_cast<int>( t ), wxEmptyString );
2560 for(
int row = 0; row <
m_signalsGrid->GetNumberRows(); ++row )
2583 auto quoteNetNames =
2584 [&]( wxString aExpression ) -> wxString
2586 std::vector<bool> mask( aExpression.length(),
false );
2588 auto isNetnameChar =
2589 []( wxUniChar aChar ) ->
bool
2591 wxUint32 value = aChar.GetValue();
2593 if( ( value >=
'0' && value <=
'9' ) || ( value >=
'A' && value <=
'Z' )
2594 || ( value >=
'a' && value <=
'z' ) )
2617 size_t pos = aExpression.find( netname );
2619 while( pos != wxString::npos )
2621 for(
size_t i = 0; i < netname.length(); ++i )
2622 mask[pos + i] =
true;
2624 pos = aExpression.find( netname, pos + 1 );
2628 for(
size_t i = 0; i < aExpression.length(); ++i )
2630 if( !mask[i] || ( i > 0 && mask[i - 1] ) )
2635 while( j < aExpression.length() )
2643 if( isNetnameChar( aExpression[j] ) )
2655 wxString quotedNetnames =
"";
2656 bool startQuote =
true;
2659 for(
size_t i = 0; i < aExpression.length(); i++ )
2661 if( mask[i] && startQuote )
2663 quotedNetnames = quotedNetnames +
"\"";
2666 else if( !mask[i] && !startQuote )
2668 quotedNetnames = quotedNetnames +
"\"";
2672 wxString ch = aExpression[i];
2673 quotedNetnames = quotedNetnames + ch;
2677 quotedNetnames = quotedNetnames +
"\"";
2679 return quotedNetnames;
2684 constexpr const char* cmd =
"let user{} = {}";
2686 simulator()->
Command(
"echo " + fmt::format( cmd,
id, signal.ToStdString() ) );
2699 wxString ref = tuner->GetSymbolRef();
2700 KIID symbolId = tuner->GetSymbol( &sheetPath );
2706 reporter.Report( wxString::Format(
_(
"%s not found" ), ref ) );
2714 reporter.Report( wxString::Format(
_(
"%s is not tunable" ), ref ) );
2723 floatVal = overrideIt->second;
2725 floatVal = tuner->GetValue().ToDouble();
2736 wxTextFile file( aPath );
2741 wxString firstLine = file.GetFirstLine();
2743 bool legacy = firstLine.StartsWith( wxT(
"version " ) ) || firstLine.ToLong( &
dummy );
2768 wxFileName filename( aPath );
2780 wxFFileInputStream fp( aPath, wxT(
"rt" ) );
2781 wxStdInputStream fstream( fp );
2788 nlohmann::json js = nlohmann::json::parse( fstream,
nullptr,
true,
true );
2790 std::map<SIM_PLOT_TAB*, nlohmann::json> traceInfo;
2792 for(
const nlohmann::json& tab_js : js[
"tabs"] )
2794 wxString simCommand;
2798 if( !tab_js.contains(
"commands" ) || !tab_js[
"commands"].is_array() )
2801 for(
const nlohmann::json& cmd : tab_js[
"commands" ] )
2803 if( cmd ==
".kicad adjustpaths" )
2805 else if( cmd ==
".save all" )
2807 else if( cmd ==
".probe alli" )
2809 else if( cmd ==
".probe allp" )
2811 else if( cmd ==
".kicad esavenone" )
2814 simCommand += wxString( cmd.get<wxString>() ).Trim();
2824 int viewCount = tab_js.contains(
"viewCount" ) ? (int) tab_js[
"viewCount"] : 1;
2826 for(
int ii = 1; ii < viewCount; ++ii )
2829 if( tab_js.contains(
"traces" ) )
2830 traceInfo[plotTab] = tab_js[
"traces"];
2832 if( tab_js.contains(
"measurements" ) && tab_js[
"measurements"].is_array() )
2834 for(
const nlohmann::json& m_js : tab_js[
"measurements" ] )
2836 plotTab->
Measurements().emplace_back( wxString( m_js.value(
"expr",
"" ) ),
2837 wxString( m_js.value(
"format",
"" ) ) );
2842 plotTab->
ShowGrid( tab_js.value(
"showGrid",
true ) );
2844 if( tab_js.value(
"smithMode",
false ) )
2847 plotTab->
SetSmithView( tab_js.value(
"smithZoom", 1.0 ),
2848 tab_js.value(
"smithPanX", 0.0 ),
2849 tab_js.value(
"smithPanY", 0.0 ) );
2851 if( tab_js.contains(
"smithStashedTraces" ) && tab_js[
"smithStashedTraces"].is_array() )
2853 for(
const nlohmann::json& stash_js : tab_js[
"smithStashedTraces"] )
2855 wxString vector( stash_js.value(
"vector",
"" ) );
2856 wxString
name( stash_js.value(
"name",
"" ) );
2858 if( vector.IsEmpty() )
2863 stash_js.value(
"base_type", 0 ) } );
2867 if( tab_js.contains(
"smithStashedCursors" ) && tab_js[
"smithStashedCursors"].is_array() )
2869 for(
const nlohmann::json& stash_js : tab_js[
"smithStashedCursors"] )
2871 wxString vector( stash_js.value(
"vector",
"" ) );
2872 int id = stash_js.value(
"id", 0 );
2874 if( vector.IsEmpty() || (
id < 1 &&
id != -1 ) )
2879 stash_js.value(
"base_type", 0 ),
2880 stash_js.value(
"sub_type", 0 ),
2881 stash_js.value(
"frequency",
2882 std::nan(
"" ) ) } );
2888 [&](
const char* aKey,
auto&& aSetter )
2890 if( !tab_js.contains( aKey ) )
2894 nlohmann::json min_js = tab_js[aKey].value(
"min", nlohmann::json() );
2895 nlohmann::json max_js = tab_js[aKey].value(
"max", nlohmann::json() );
2897 if( !min_js.is_number() || !max_js.is_number() )
2900 double min = min_js.get<
double>();
2901 double max = max_js.get<
double>();
2905 aSetter( min, max );
2910 loadScale(
"fixedY1scale",
2911 [&](
double min,
double max )
2916 loadScale(
"fixedY2scale",
2917 [&](
double min,
double max )
2922 loadScale(
"fixedY3scale",
2923 [&](
double min,
double max )
2929 if( tab_js.contains(
"legend" ) )
2931 const nlohmann::json& legend_js = tab_js[
"legend" ];
2932 plotTab->
SetLegendPosition( wxPoint( legend_js.value(
"x", 0 ), legend_js.value(
"y", 0 ) ) );
2936 if( tab_js.contains(
"margins" ) )
2938 const nlohmann::json& margins_js = tab_js[
"margins" ];
2940 margins_js.value(
"right", 70 ),
2941 margins_js.value(
"bottom", 45 ),
2942 margins_js.value(
"left", 70 ) );
2949 if( js.contains(
"user_defined_signals" ) )
2951 for(
const nlohmann::json& signal_js : js[
"user_defined_signals"] )
2957 m_simulatorFrame->LoadSimulator( simTab->GetSimCommand(), simTab->GetSimOptions() );
2960 firstTab->SetLastSchTextSimCommand( wxString( js.value(
"last_sch_text_sim_command",
"" ) ) );
2964 int tempCustomCursorsCnt = js.value(
"custom_cursors", 2 );
2974 int aCursorId,
const nlohmann::json& aCursor_js )
2976 if( aCursorId >= 1 )
2978 aPlotTab->
EnableCursor( aTrace, aCursorId, aSignalName );
2982 nlohmann::json position = aCursor_js.value(
"position", nlohmann::json() );
2984 if( position.is_number() )
2987 cursor->SetCoordX( position.get<
double>() );
2991 wxString xFormat( aCursor_js.value(
"x_format",
"" ) );
2992 wxString yFormat( aCursor_js.value(
"y_format",
"" ) );
2995 if( aCursorId == -1 )
2997 else if( aCursorId < 3 )
2998 formatSlot = aCursorId - 1;
3000 formatSlot = aCursorId;
3002 if( !xFormat.IsEmpty() )
3005 if( !yFormat.IsEmpty() )
3009 for(
const auto& [plotTab, traces_js] : traceInfo )
3011 for(
const nlohmann::json& trace_js : traces_js )
3013 int traceType = trace_js.value(
"trace_type", (
int)
SPT_UNKNOWN );
3014 wxString signalName( trace_js.value(
"signal",
"" ) );
3016 if( signalName.IsEmpty() || traceType ==
SPT_UNKNOWN )
3021 int viewIndex = trace_js.contains(
"view" ) ? (int) trace_js[
"view"] : 0;
3022 SIM_VIEW* view = plotTab->GetView( viewIndex );
3025 view = plotTab->GetDefaultView();
3027 TRACE* trace = plotTab->GetOrAddTrace( vectorName, traceType, view );
3031 int yScaleIndex = trace_js.contains(
"yScaleView" ) ? (int) trace_js[
"yScaleView"]
3034 if(
SIM_VIEW* yScaleView = plotTab->GetView( yScaleIndex ) )
3037 if( trace_js.contains(
"cursorD" ) )
3038 addCursor( plotTab, trace, signalName, -1, trace_js[
"cursorD"] );
3040 std::vector<const char*> aVec;
3043 for(
int i = 1; i <= tempCustomCursorsCnt; i++ )
3045 wxString str =
"cursor" + std::to_string( i );
3046 aVec.emplace_back( str.c_str() );
3048 if( trace_js.contains( aVec[i - 1] ) )
3049 addCursor( plotTab, trace, signalName, i, trace_js[aVec[i - 1]] );
3052 if( trace_js.contains(
"color" ) )
3055 color.Set( wxString( trace_js[
"color"].get<wxString>() ) );
3057 plotTab->UpdateTraceStyle( trace );
3062 plotTab->UpdatePlotColors();
3065 catch( nlohmann::json::parse_error& error )
3067 wxLogTrace(
traceSettings, wxT(
"Json parse error reading %s: %s" ), aPath, error.what() );
3071 catch( nlohmann::json::type_error& error )
3073 wxLogTrace(
traceSettings, wxT(
"Json type error reading %s: %s" ), aPath, error.what() );
3077 catch( nlohmann::json::invalid_iterator& error )
3079 wxLogTrace(
traceSettings, wxT(
"Json invalid_iterator error reading %s: %s" ), aPath, error.what() );
3083 catch( nlohmann::json::out_of_range& error )
3085 wxLogTrace(
traceSettings, wxT(
"Json out_of_range error reading %s: %s" ), aPath, error.what() );
3091 wxLogTrace(
traceSettings, wxT(
"Error reading %s" ), aPath );
3100 int cursorIdAfterD = aCursorId;
3103 cursorIdAfterD = cursorIdAfterD - 1;
3108 nlohmann::json cursor_js =
3114 double position =
cursor->GetCoords().x;
3116 if( std::isfinite( position ) )
3117 cursor_js[
"position"] = position;
3119 aTraceJs[
"cursor" + wxString(
"" ) << aCursorId] = cursor_js;
3124 aTraceJs[
"cursorD"] = nlohmann::json( { {
"x_format",
m_cursorFormatsDyn[2][0].ToString() },
3134 wxFileName filename = aPath;
3139 file.Create( filename.GetFullPath(),
true );
3141 if( !file.IsOpened() )
3144 nlohmann::json tabs_js = nlohmann::json::array();
3155 nlohmann::json commands_js = nlohmann::json::array();
3162 commands_js.push_back(
".kicad adjustpaths" );
3165 commands_js.push_back(
".save all" );
3168 commands_js.push_back(
".probe alli" );
3171 commands_js.push_back(
".probe allp" );
3174 commands_js.push_back(
".kicad esavenone" );
3177 {
"commands", commands_js } } );
3181 nlohmann::json traces_js = nlohmann::json::array();
3183 auto findSignalName =
3184 [&](
const wxString& aVectorName ) -> wxString
3186 wxString vectorName;
3189 if( aVectorName.EndsWith(
_(
" (phase)" ) ) )
3190 suffix =
_(
" (phase)" );
3191 else if( aVectorName.EndsWith(
_(
" (gain)" ) ) )
3192 suffix =
_(
" (gain)" );
3194 vectorName = aVectorName.Left( aVectorName.Length() - suffix.Length() );
3199 return signal + suffix;
3205 for(
const auto& [
name, trace] : plotTab->GetTraces() )
3207 nlohmann::json trace_js =
3208 nlohmann::json( { {
"trace_type", (int) trace->GetType() },
3209 {
"signal", findSignalName( trace->GetDisplayName() ) },
3211 {
"view", plotTab->GetViewIndex( trace->GetView() ) },
3212 {
"yScaleView", plotTab->GetViewIndex( trace->GetYScaleView() ) } } );
3217 if( trace->GetCursor( 1 ) || trace->GetCursor( 2 ) )
3219 trace_js[
"cursorD"] = nlohmann::json( { {
"x_format",
m_cursorFormatsDyn[2][0].ToString() },
3223 traces_js.push_back( trace_js );
3226 nlohmann::json measurements_js = nlohmann::json::array();
3228 for(
const auto& [
measurement, format] : plotTab->Measurements() )
3230 measurements_js.push_back( nlohmann::json( { {
"expr",
measurement },
3231 {
"format", format } } ) );
3234 tab_js[
"traces" ] = traces_js;
3235 tab_js[
"measurements" ] = measurements_js;
3236 tab_js[
"dottedSecondary" ] = plotTab->GetDottedSecondary();
3237 tab_js[
"showGrid" ] = plotTab->IsGridShown();
3238 tab_js[
"smithMode" ] = plotTab->IsSmithMode();
3240 if( plotTab->IsSmithMode() )
3242 tab_js[
"smithZoom"] = plotTab->GetSmithZoom();
3243 tab_js[
"smithPanX"] = plotTab->GetSmithPan().x;
3244 tab_js[
"smithPanY"] = plotTab->GetSmithPan().y;
3248 nlohmann::json stashedTraces_js = nlohmann::json::array();
3252 stashedTraces_js.push_back( nlohmann::json( { {
"vector", stashed.vectorName },
3253 {
"name", stashed.displayName },
3254 {
"base_type", stashed.baseType } } ) );
3257 if( !stashedTraces_js.empty() )
3258 tab_js[
"smithStashedTraces"] = stashedTraces_js;
3260 nlohmann::json stashedCursors_js = nlohmann::json::array();
3264 nlohmann::json cursor_js = nlohmann::json( { {
"id", stashed.id },
3265 {
"vector", stashed.vectorName },
3266 {
"base_type", stashed.baseType },
3267 {
"sub_type", stashed.subType } } );
3269 if( std::isfinite( stashed.frequency ) )
3270 cursor_js[
"frequency"] = stashed.frequency;
3272 stashedCursors_js.push_back( cursor_js );
3275 if( !stashedCursors_js.empty() )
3276 tab_js[
"smithStashedCursors"] = stashedCursors_js;
3279 tab_js[
"viewCount"] = plotTab->GetViewCount();
3285 [&](
const char* aKey,
double aMin,
double aMax )
3287 if( std::isfinite( aMin ) && std::isfinite( aMax ) )
3288 tab_js[aKey] = nlohmann::json( { {
"min", aMin }, {
"max", aMax } } );
3291 if( plotTab->GetY1Scale( &min, &max ) )
3292 saveScale(
"fixedY1scale", min, max );
3294 if( plotTab->GetY2Scale( &min, &max ) )
3295 saveScale(
"fixedY2scale", min, max );
3297 if( plotTab->GetY3Scale( &min, &max ) )
3298 saveScale(
"fixedY3scale", min, max );
3300 if( plotTab->IsLegendShown() )
3302 tab_js[
"legend"] = nlohmann::json( { {
"x", plotTab->GetLegendPosition().x },
3303 {
"y", plotTab->GetLegendPosition().y } } );
3306 mpWindow* plotWin = plotTab->GetPlotWin();
3308 tab_js[
"margins"] = nlohmann::json( { {
"left", plotWin->
GetMarginLeft() },
3314 tabs_js.push_back( tab_js );
3317 nlohmann::json userDefinedSignals_js = nlohmann::json::array();
3320 userDefinedSignals_js.push_back( signal );
3323 nlohmann::json js = nlohmann::json( { {
"version", 8 },
3324 {
"tabs", tabs_js },
3325 {
"user_defined_signals", userDefinedSignals_js },
3338 std::stringstream buffer;
3339 buffer << std::setw( 2 ) << js << std::endl;
3341 bool res = file.Write( buffer.str() );
3368 wxFAIL_MSG( wxString::Format( wxS(
"Unhandled simulation type: %d" ), (
int) aType ) );
3388 &fStart, &fStop, &saveAll );
3397 bool isShown = aPanel->IsShown();
3400 aSashPosition = aSplitterWindow->GetSashPosition();
3402 aPanel->Show( !isShown );
3404 aSplitterWindow->SetSashInvisible( isShown );
3405 aSplitterWindow->SetSashPosition( isShown ? -1 : aSashPosition,
true );
3407 aSplitterWindow->UpdateSize();
3408 m_parent->Refresh();
3445 for(
size_t page = 0; page <
m_plotNotebook->GetPageCount(); page++ )
3472 wxString vectorName;
3473 wxString displayName;
3478 std::vector<SHOWN_VECTOR> shownVectors;
3484 wxString vectorName;
3490 std::vector<SAVED_CURSOR> savedCursors;
3492 for(
const auto& [
id, trace] : plotTab->
GetTraces() )
3501 for(
const SHOWN_VECTOR& sv : shownVectors )
3502 seen |= sv.vectorName == vectorName;
3505 shownVectors.push_back( { vectorName, trace->GetName(), baseType, trace->GetView() } );
3507 for(
const auto& [cursorId,
cursor] : trace->GetCursors() )
3510 savedCursors.push_back( { cursorId, vectorName, baseType, subType,
cursor->GetCoords().x } );
3516 [](
const wxString& aName ) ->
bool
3518 long response, drive;
3521 return response == drive;
3532 stashedTraces.clear();
3533 stashedCursors.clear();
3535 for(
const SHOWN_VECTOR& sv : shownVectors )
3537 if( !isReflection( sv.vectorName ) )
3538 stashedTraces.push_back( { sv.vectorName, sv.displayName, sv.baseType } );
3541 for(
const SAVED_CURSOR& saved : savedCursors )
3542 stashedCursors.push_back( { saved.id, saved.vectorName, saved.baseType, saved.subType, saved.coordX } );
3551 for(
const SHOWN_VECTOR& sv : shownVectors )
3552 seen |= sv.vectorName == stashed.vectorName;
3556 shownVectors.push_back( { stashed.vectorName, stashed.displayName, stashed.baseType,
3562 for(
const SHOWN_VECTOR& sv : shownVectors )
3565 plotTab->
DeleteTrace( sv.vectorName, sv.baseType | subType );
3570 for(
const SHOWN_VECTOR& sv : shownVectors )
3572 std::vector<int> subTypes;
3576 if( !isReflection( sv.vectorName ) )
3586 for(
int subType : subTypes )
3588 updateTrace( sv.vectorName, sv.baseType | subType, plotTab,
nullptr,
false, sv.view );
3590 if(
TRACE* trace = plotTab->
GetTrace( sv.vectorName, sv.baseType | subType ) )
3591 trace->SetName( sv.displayName );
3598 for(
const SAVED_CURSOR& saved : savedCursors )
3604 if( !trace || trace->
GetCursor( saved.id ) )
3611 if( std::isfinite( saved.coordX ) )
3612 cursor->SetCoordX( saved.coordX );
3623 if( stashed.id == aId && stashed.vectorName == aVectorName )
3630 auto restoreCursor =
3631 [&](
int aId,
const wxString& aVectorName,
int aBaseType,
int aSubType,
double aFreq ) ->
bool
3635 if(
TRACE* trace = plotTab->
GetTrace( aVectorName, aBaseType | wantSubType ) )
3640 if( std::isfinite( aFreq ) )
3643 cursor->SetCoordX( aFreq );
3652 std::vector<int> restoredIds;
3655 for(
const SAVED_CURSOR& saved : savedCursors )
3659 if( restoreCursor( saved.id, saved.vectorName, saved.baseType,
3662 restoredIds.push_back( saved.id );
3670 if( isReflection( stashed.vectorName ) )
3673 if( std::find( restoredIds.begin(), restoredIds.end(), stashed.id ) != restoredIds.end() )
3676 restoreCursor( stashed.id, stashed.vectorName, stashed.baseType, stashed.subType, stashed.frequency );
3679 stashedTraces.clear();
3680 stashedCursors.clear();
3728 std::vector<std::pair<wxString, wxString>>& measurements = plotTab->Measurements();
3730 measurements.clear();
3768 simulator()->
Command(
"setplot " + simTab->GetSpicePlotName().ToStdString() );
3785 for(
const auto& [
measurement, format] : plotTab->Measurements() )
3793 if( plotTab->GetSimType() ==
ST_TRAN || plotTab->GetSimType() ==
ST_AC || plotTab->GetSimType() ==
ST_DC
3794 || plotTab->GetSimType() ==
ST_SP )
3833 wxGridCellAttr* attr =
new wxGridCellAttr;
3834 attr->SetReadOnly();
3898 while( tokens.HasMoreTokens() )
3902 if( tokens.GetNextToken().ToLong( &offset ) && offset >= 0 && offset <
SMITH_CURSOR_COLS )
3913 if( !smithCursor || !smithTrace )
3921 if( smithTrace->
GetDataX().empty() )
3924 const wxRealPoint& gamma = smithCursor->
GetGamma();
3936 double gm = std::hypot( gamma.x, gamma.y );
3940 if( std::isfinite( rl ) )
3942 else if( std::isinf( rl ) )
3945 if( std::isfinite( vswr ) )
3947 else if( std::isinf( vswr ) )
3969 CURSOR* cursor1 =
nullptr;
3970 wxString cursor1Name;
3971 wxString cursor1Units;
3972 CURSOR* cursor2 =
nullptr;
3973 wxString cursor2Name;
3974 wxString cursor2Units;
3977 [&](
TRACE* aTrace ) -> wxString
4002 [&](
TRACE* aTrace ) -> wxString
4005 return _(
"Refl. Coeff." );
4026 [
this](
double aValue,
int aCursorId,
int aCol ) -> wxString
4028 if( ( !
m_simulatorFrame->SimFinished() && aCol == 1 ) || std::isnan( aValue ) )
4039 cursor1Name = getNameY( trace );
4040 cursor1Units = getUnitsY( trace );
4042 wxRealPoint coords =
cursor->GetCoords();
4063 cursor2Name = getNameY( trace );
4064 cursor2Units = getUnitsY( trace );
4066 wxRealPoint coords =
cursor->GetCoords();
4082 if( cursor1 && cursor2 && cursor1Units == cursor2Units )
4091 signal = wxString::Format( wxS(
"%s[2 - 1]" ), cursor2->
GetName() );
4093 signal = wxString::Format( wxS(
"%s - %s" ), cursor2->
GetName(), cursor1->
GetName() );
4104 wxString valColName =
_(
"Value" );
4106 if( !cursor1Name.IsEmpty() )
4108 if( cursor2Name.IsEmpty() || cursor1Name == cursor2Name )
4109 valColName = cursor1Name;
4111 else if( !cursor2Name.IsEmpty() )
4113 valColName = cursor2Name;
4127 wxString cursName = getNameY( trace );
4128 wxString cursUnits = getUnitsY( trace );
4130 wxRealPoint coords =
cursor->GetCoords();
4146 valColName =
_(
"Value" );
4149 valColName = cursName;
4175 plotTab->ResetScales(
true );
4195 if( messages.IsEmpty() )
4205 std::vector<wxString> signals;
4207 for(
const std::string& vec :
simulator()->AllVectors() )
4208 signals.emplace_back( vec );
4216 std::vector<wxString> signals;
4218 for(
const wxString& signal :
m_signals )
4219 signals.emplace_back( signal );
4222 signals.emplace_back( signal );
4242 bool storeMultiRun =
false;
4248 storeMultiRun =
true;
4263 if( aFinal && simType ==
ST_FFT )
4267 if( !spicePlotName.IsEmpty() )
4282 if( simType ==
ST_NOISE && aFinal )
4284 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
4293 for(
const std::string& vec :
simulator()->AllVectors() )
4298 msg.Printf( wxS(
"%s: %sV\n" ), vec, value );
4309 wxCHECK_RET( plotTab, wxString::Format( wxT(
"No SIM_PLOT_TAB for: %s" ), magic_enum::enum_name( simType ) ) );
4318 std::map<TRACE*, TRACE_INFO> traceMap;
4321 traceMap[trace] = { wxEmptyString,
SPT_UNKNOWN,
false };
4326 for(
const wxString& signal :
m_signals )
4331 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
4332 traceMap[trace] = { vectorName, traceType,
false };
4340 if( simType ==
ST_AC )
4346 if(
TRACE* trace = plotTab->
GetTrace( vectorName, subType ) )
4347 traceMap[trace] = { vectorName, subType, !aFinal };
4350 else if( simType ==
ST_SP )
4356 if(
TRACE* trace = plotTab->
GetTrace( vectorName, subType ) )
4357 traceMap[trace] = { vectorName, subType, !aFinal };
4362 if(
TRACE* trace = plotTab->
GetTrace( vectorName, traceType ) )
4363 traceMap[trace] = { vectorName, traceType, !aFinal };
4369 for(
const auto& [trace, traceInfo] : traceMap )
4371 if( traceInfo.Vector.IsEmpty() )
4375 for(
const auto& [trace,
info] : traceMap )
4377 std::vector<double> data_x;
4379 if( !
info.Vector.IsEmpty() )
4399 else if( simType ==
ST_OP && aFinal )
4401 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
4404 for(
const std::string& vec :
simulator()->AllVectors() )
4408 if( val_list.empty() )
4415 const size_t tab = 25;
4416 size_t padding = ( signal.length() < tab ) ? ( tab - signal.length() ) : 1;
4420 case SPT_VOLTAGE: value.Append( wxS(
"V" ) );
break;
4421 case SPT_CURRENT: value.Append( wxS(
"A" ) );
break;
4422 case SPT_POWER: value.Append( wxS(
"W" ) );
break;
4423 default: value.Append( wxS(
"?" ) );
break;
4426 msg.Printf( wxT(
"%s%s\n" ),
4427 ( signal + wxT(
":" ) ).Pad( padding, wxUniChar(
' ' ) ),
4434 signal = signal.SubString( 2, signal.Length() - 2 );
4437 signal += wxS(
":power" );
4439 m_schematicFrame->Schematic().SetOperatingPoint( signal, val_list.at( 0 ) );
4442 else if( simType ==
ST_PZ && aFinal )
4444 m_simConsole->AppendText(
_(
"\n\nSimulation results:\n\n" ) );
4512 std::vector<TUNER_SLIDER*> multiTuners;
4517 multiTuners.push_back( tuner );
4520 if( multiTuners.empty() )
4552 else if( tunersChanged )
4561 for(
const auto& entry : step.
overrides )
4567std::vector<SIMULATOR_FRAME_UI::MULTI_RUN_STEP>
4570 std::vector<MULTI_RUN_STEP> steps;
4572 if( aTuners.empty() )
4575 std::vector<std::vector<double>> tunerValues;
4576 tunerValues.reserve( aTuners.size() );
4583 double startValue = tuner->GetMin().ToDouble();
4584 double endValue = tuner->GetMax().ToDouble();
4585 int stepCount = std::max( 2, tuner->GetStepCount() );
4590 double increment = ( endValue - startValue ) /
static_cast<double>( stepCount - 1 );
4592 std::vector<double> values;
4593 values.reserve( stepCount );
4595 for(
int ii = 0; ii < stepCount; ++ii )
4596 values.push_back( startValue + increment * ii );
4598 tunerValues.push_back( std::move( values ) );
4606 std::vector<double> currentValues( aTuners.size(), 0.0 );
4609 [&](
auto&& self,
size_t depth ) ->
void
4611 if( steps.size() >=
static_cast<size_t>( limit ) )
4614 if( depth == aTuners.size() )
4618 for(
size_t ii = 0; ii < aTuners.size(); ++ii )
4619 step.
overrides.emplace( aTuners[ii], currentValues[ii] );
4621 steps.push_back( std::move( step ) );
4625 for(
double value : tunerValues[depth] )
4627 currentValues[depth] = value;
4628 self( self, depth + 1 );
4630 if( steps.size() >=
static_cast<size_t>( limit ) )
4635 generate( generate, 0 );
4643 return fmt::format(
"{}|{}", aVectorName.ToStdString(), aTraceType );
4648 const std::vector<double>& aY )
4650 if( aX.empty() || aY.empty() )
4661 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
virtual 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.
Renders a combobox cell's text with an always-visible dropdown arrow, so it reads as a dropdown even ...
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)
@ 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.
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
std::vector< int > m_smithCursorWidths
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
void autoSizeGridColumn(WX_GRID *aGrid, int aCol, int aMinWidth, int aExtraPadding=0)
Grow (but never shrink below aMinWidth) a grid column to fit its current contents.
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.
wxArrayString getYScaleChoices(SIM_PLOT_TAB *aPlotTab, SIM_VIEW *aOwnView) const
The Signals grid's "Y Scale" column label for a trace ("Default" if not explicitly linked).
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).
wxString getViewLabel(SIM_PLOT_TAB *aPlotTab, SIM_VIEW *aView) const
The views a trace's Y-axis scale could be linked to: every view except its own (since linking to its ...
void updateSmithCursorColumns(bool aSmithMode)
Add or remove the Smith-only cursor columns, carrying their shown/hidden state across.
void SaveCursorToWorkbook(nlohmann::json &aTraceJs, TRACE *aTrace, int aCursorId)
void updateMeasurementsFromGrid()
bool LoadWorkbook(const wxString &aPath)
Load plot, signal, cursor, measurement, etc.
wxString getYScaleLabel(SIM_PLOT_TAB *aPlotTab, TRACE *aTrace) const
void applySmithCursorColumns()
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 updateTrace(const wxString &aVectorName, int aTraceType, SIM_PLOT_TAB *aPlotTab, std::vector< double > *aDataX=nullptr, bool aClearData=false, SIM_VIEW *aView=nullptr)
Update a trace in a particular SIM_PLOT_TAB.
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.
void fillSmithCursorRow(int aRow, CURSOR *aCursor, TRACE *aTrace)
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 rememberSmithCursorColumns()
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)
wxString m_smithCursorColumns
wxArrayString getViewChoices(SIM_PLOT_TAB *aPlotTab) const
The Signals grid's "Plot" column label for a given view ("Disabled" if null).
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::vector< SIM_VIEW * > getYScaleTargetViews(SIM_PLOT_TAB *aPlotTab, SIM_VIEW *aOwnView) const
The Signals grid's "Y Scale" column choices: "Default" plus one entry per eligible view.
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()
Toggle the current S-parameter tab between Smith chart and amplitude/phase views.
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
double getSmithPortImpedance(const wxString &aVectorName)
void setSmithCursorColumnLabels()
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
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, std::span< const wxString > 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)
int GetViewCount() const
The view new traces default to, and legacy (single-view) settings apply to.
void UpdateSmithReferenceImpedance()
The saved/restored pan and zoom track the default view.
wxString GetLabelY1() const
mpWindow * GetPlotWin() const
Get (or create, on aView) the TRACE for a signal.
void SetSmithView(double aZoom, double aPanX, double aPanY)
SIM_VIEW * GetView(int aIndex) 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={})
const std::vector< SIM_VIEW * > & GetViews() const
wxString GetUnitsY2() const
void SetY2Scale(bool aLock, double aMin, double aMax)
TRACE * GetTrace(const wxString &aVecName, int aType) const
void SetSmithMode(bool aEnable)
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)
SIM_VIEW * GetDefaultView() const
Add a new (empty) view, stacked below the existing ones.
SIM_VIEW * AddView()
Remove a view.
std::vector< std::pair< wxString, wxString > > & Measurements()
void UpdateTraceStyle(TRACE *trace)
Update plot colors.
void SetLegendPosition(const wxPoint &aPosition)
TRACE * GetOrAddTrace(const wxString &aVectorName, int aType, SIM_VIEW *aView)
void ResetScales(bool aIncludeX)
Update trace line style.
std::vector< SMITH_STASHED_TRACE > & SmithStashedTraces()
void ShowLegend(bool aEnable)
wxString GetLabelY2() const
void EnableCursor(TRACE *aTrace, int aCursorId, const wxString &aSignalName)
int GetViewIndex(SIM_VIEW *aView) const
bool IsSmithMode() const
Refresh the grid z0 from the shown Smith traces, on every view.
wxString GetUnitsX() const
Get the display units (e.g. "V", "A", "dB") for a given trace's own view.
void EnsureThirdYAxisExists()
std::vector< SMITH_STASHED_CURSOR > & SmithStashedCursors()
Turn on/off the cursor for a particular trace.
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, on every view.
wxString GetUnitsY3() const
int GetSimOptions() const
const wxString & GetSpicePlotName() 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 double ToDouble(const std::string &aString, double aDefault=NAN)
static std::string ToSpice(const std::string &aString)
A single stacked plot area within a SIM_PLOT_TAB.
Trace hidden while the tab is in Smith mode, kept so leaving the mode restores it.
const wxRealPoint & GetGamma() const
Cursor that snaps along a Smith chart locus, keyed by frequency.
double GetReferenceImpedance() const
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 std::vector< double > GetImaginaryVector(const std::string &aName, int aMaxLen=-1)=0
Return a requested vector with imaginary values.
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
Overlay layer drawing the Smith chart grid (constant resistance and reactance circles)
bool IsYScaleDefault() const
Clears an explicit Y-scale link if it pointed at a view that no longer exists.
void SetTraceColour(const wxColour &aColour)
SIM_VIEW * GetView() const
bool HasCursor(int aCursorId)
SIM_VIEW * GetYScaleView() const
const std::vector< double > & GetDataX() const
CURSOR * GetCursor(int aCursorId)
void SetYScaleView(SIM_VIEW *aView)
True if this trace's Y-axis scale hasn't been explicitly linked to another view (i....
Custom widget to handle quick component values modification and simulation on the fly.
wxString GetSymbolRef() const
A modified version of the wxInfoBar class that allows us to:
void ShowMessageFor(const wxString &aMessage, int aTime, int aFlags=wxICON_INFORMATION, MESSAGE_TYPE aType=WX_INFOBAR::MESSAGE_TYPE::GENERIC)
Show the infobar with the provided message and icon for a specific period of time.
A wrapper for reporting to a wxString object.
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.
int GetMarginRight() const
int GetMarginBottom() const
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
static std::string ToStdString(const wxString &aStr)
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)
double VSWR(double aGammaMag)
bool ParseSParamPorts(const wxString &aVectorName, long *aResponsePort, long *aDrivePort)
bool GammaToImpedance(double aRe, double aIm, double aZ0, double &aResistance, double &aReactance)
< Impedance of a reflection coefficient, z = z0 ( 1 + gamma ) / ( 1 - gamma ), false at the gamma = 1...
double ReturnLoss(double aGammaMag)
Series equivalent element of a reactance at one frequency, henries for aReactance > 0,...
SIM_TYPE
< Possible simulation types
void sortSignals(std::vector< wxString > &signals)
static bool smithColumnsShown(const WX_GRID *aGrid)
wxString vectorNameFromSignalId(int aUserDefinedSignalId)
MEASUREMENTS_GIRD_COLUMNS
@ MYID_DELETE_MEASUREMENT
static constexpr int SMITH_CURSOR_COLS
SIM_TRACE_TYPE operator|(SIM_TRACE_TYPE aFirst, SIM_TRACE_TYPE aSecond)
std::vector< FAB_LAYER_COLOR > dummy
wxString smith_cursor_columns
int measurements_panel_height
SIM_PREFERENCES preferences
std::map< const TUNER_SLIDER *, double > overrides
std::vector< std::vector< double > > xRuns
std::vector< std::vector< double > > yValues
std::vector< double > xValues
Contains preferences pertaining to the simulator.
Cursor recorded when entering Smith mode, so leaving restores it to its original trace.
IbisParser parser & reporter
wxString result
Test unit parsing edge cases and error handling.
Definition of file extensions used in Kicad.