ioe-rf-calculations
v0.3.1
Published
IOE RF/Microwave calculation utilities and ready-made React components: single & double stub matching, transistor stability, power gain, maximum gain, and microwave filter design.
Maintainers
Readme
RF-IOE-Calculations
RF/Microwave calculation utilities and ready-made React components for undergraduate RF & microwave engineering (IOE curriculum).
npm install ioe-rf-calculations
Table of Contents
- Features
- Installation
- Styling
- React components
- Calculation functions (framework-free)
- Recipes
- Development
- Contributing
- License
Features
| Tool | Component | Function | Description |
| --- | --- | --- | --- |
| Single Shunt-Stub Matching | <SingleStubMatch /> | singleStubMatch | Stub position & length (open/short) for impedance matching |
| Double Shunt-Stub Matching | <DoubleStubMatch /> | doubleStubMatch | Two-stub matching with configurable spacing |
| Transistor Stability Analysis | <StabilityAnalyzer /> | analyzeStability | K, μ, μ′ tests, Δ, stability circles |
| Bilateral & Unilateral Power Gain | <PowerGain /> | calculateGain | GP, GA, GT with S-parameters |
| GaAs FET Maximum Gain | <MaxGain /> | calculateMaxGain | Max gain + single-stub matching networks |
| Microwave Filter Design | <FilterDesign /> | designFilter | Butterworth/Chebyshev LPF, HPF, BPF, BSF |
- Two APIs in one package: pure calculation functions usable anywhere (Node, browser, plain JS/TS) and ready-made React calculator components.
- Plain CSS, no frameworks: components are styled with a single hand-written stylesheet (
rf-components.css) — no Tailwind, no Radix, no CVA, no CSS-in-JS, no icon libraries. Visual style matches the NerdStudyHub admin interface's own components. - Optional
onInsertprop: get results as HTML to embed into any rich-text editor or anywhere else you need. - MIT licensed.
Installation
npm install ioe-rf-calculationsPeer dependencies:
| Package | Version |
| --- | --- |
| react | >= 18 |
| react-dom | >= 18 |
The package has zero runtime dependencies — no need to install Tailwind or anything else.
Styling
The React components use plain CSS (no Tailwind classes, no CSS variables, no library). Import the stylesheet once in your app:
// main.tsx / App entry — anywhere before rendering the components
import "ioe-rf-calculations/rf-components.css";…or via a <link> tag:
<link rel="stylesheet" href="https://unpkg.com/ioe-rf-calculations/rf-components.css" />That's it — the components are fully styled and ready to render. There is nothing else to configure.
React components
Individual tools
Render any tool as a complete, self-contained calculator. Just drop the component in — it brings its own inputs, buttons, and results UI:
import { SingleStubMatch } from "ioe-rf-calculations";
export function MyPage() {
return (
<SingleStubMatch />
);
}Or use several together:
import {
SingleStubMatch,
DoubleStubMatch,
StabilityAnalyzer,
PowerGain,
MaxGain,
FilterDesign,
} from "ioe-rf-calculations";
export function MyPage() {
return (
<div className="mx-auto max-w-3xl space-y-8">
<SingleStubMatch />
<StabilityAnalyzer />
<FilterDesign />
</div>
);
}All-in-one selector
import { RFAnalysisSelector } from "ioe-rf-calculations";
export function ToolsPage() {
return <RFAnalysisSelector />;
}RFAnalysisSelector renders a card grid of all six tools and lets users switch between them — perfect for a single "Calculators" page.
Component API
Every tool component can be used with no props at all — it renders everything it needs (<SingleStubMatch />). There is one optional prop:
| Prop | Type | Description |
| --- | --- | --- |
| onInsert | (html: string) => void | Optional. Receives the results rendered as HTML when the user clicks "Insert into Content". Useful when you want to capture the results programmatically. |
MaxGain also accepts an optional freqGHz frequency field for cm-dimension stub matching.
Building blocks
Want to compose your own calculator UI? The shared building blocks are exported:
import {
ToolCard, // Card wrapper with title + description
Field, // labeled Input
FieldGrid, // responsive 2-col grid of Fields
ActionBar, // Calculate + Insert buttons
ResultCard, // results container
ResultSection, // titled result group
ResultRow, // label → value row (with optional StatusBadge)
StatusBadge, // ✓ / ✗ status badge
SParameterInputs, // reusable S11/S12/S21/S22 mag+angle inputs
Divider,
} from "ioe-rf-calculations";Calculation functions (framework-free)
Import any function directly — no React, no Tailwind required.
import {
singleStubMatch,
doubleStubMatch,
analyzeStability,
calculateGain,
calculateMaxGain,
designFilter,
fromPolar,
} from "ioe-rf-calculations";Complex number helpers
The library represents complex numbers as { re: number; im: number } objects.
import { complex, add, sub, mul, div, conjugate, abs, phase, fromPolar, toPolar, formatComplex, formatPolar, db } from "ioe-rf-calculations";
const z = complex(3, 4); // 3 + j4
fromPolar(1, 45); // from magnitude + angle (degrees)
toPolar(z); // { mag: 5, angleDeg: 53.13 }
formatComplex(z); // "3.0000 + j4.0000"
formatPolar(fromPolar(1, 45)); // "1.0000 ∠ 45.00°"
db(10); // 20 (10x power -> 20 dB)Single stub matching
const result = singleStubMatch({
inputType: "gamma", // "gamma" | "zl"
Z0: 50,
freqGHz: 2.4, // optional — adds cm dimensions
gammaMag: 0.7, // used when inputType === "gamma"
gammaAngle: 120, // degrees
// or, for inputType === "zl":
// zlRe: 25, zlIm: 10,
});
console.log(result.ZL, result.Gamma, result.VSWR);
console.log(result.zL, result.yL);
result.solutions.forEach((sol) => {
console.log(sol.d, sol.b_stub, sol.open, sol.short);
});
// → stub position (λ), stub susceptance, open & short stub lengths (λ + cm when freqGHz is set)Double stub matching
const result = doubleStubMatch({
inputType: "zl",
Z0: 50,
zlRe: 25,
zlIm: 10,
d1Lambda: 0.25, // distance from load to first stub
spacingLambda: 0.375, // stub separation in wavelengths
});
if (result.solutions.length === 0) {
console.log("No solution exists for this configuration.");
} else {
result.solutions.forEach((sol) => {
console.log(sol.B_total, sol.b_stub1, sol.b_stub2, sol.open1, sol.short1, sol.open2, sol.short2);
});
}Stability analysis
const result = analyzeStability({
S11: fromPolar(0.6, 160),
S12: fromPolar(0.05, 10),
S21: fromPolar(2.5, -20),
S22: fromPolar(0.5, -130),
});
console.log(result.Delta, result.Delta_mag);
console.log(result.K); // Rollett stability factor
console.log(result.mu, result.mu_prime);
console.log(result.stability); // e.g. "UNCONDITIONALLY STABLE"
console.log(result.CL, result.RL); // load stability circle (if any)
console.log(result.CS, result.RS); // source stability circle (if any)Power gain
const result = calculateGain({
S11: fromPolar(0.6, 160),
S12: fromPolar(0.05, 10),
S21: fromPolar(2.5, -20),
S22: fromPolar(0.5, -130),
Z0: 50,
ZS: 50,
ZL: 50,
});
// Bilateral (S12 ≠ 0)
console.log(result.Gamma_S, result.Gamma_L, result.Gamma_in, result.Gamma_out);
console.log(result.GP_B, result.GA_B, result.GT_B);
// Unilateral (S12 = 0 approximation)
console.log(result.GP_U, result.GA_U, result.GT_U);Maximum gain (GaAs FET)
const result = calculateMaxGain(
fromPolar(0.6, 160), // S11
fromPolar(0.05, 10), // S12
fromPolar(2.5, -20), // S21
fromPolar(0.5, -130), // S22
50, // Z0
9.5 // freqGHz — optional, adds cm stub dimensions
);
console.log(result.isUnconditional, result.K, result.Delta_mag);
// Bilateral design: ΓS, ΓL, GT,max + single-stub input/output matching networks
console.log(result.bilateral.Gamma_S, result.bilateral.Gamma_L, result.bilateral.GT_max);
console.log(result.bilateral.inputMatch[0]); // { d, open, short }
console.log(result.bilateral.outputMatch[0]);
// Unilateral design (S12 = 0)
console.log(result.unilateral.Gamma_S, result.unilateral.Gamma_L, result.unilateral.GTU_max);Filter design
const result = designFilter({
approximation: "chebyshev", // "butterworth" | "chebyshev"
filterType: "lpf", // "lpf" | "hpf" | "bpf" | "bsf"
N: 3, // optional — computed from specs if omitted
fc: 2.4, // cutoff frequency (GHz) for LPF / HPF
fx: 3.5, // attenuation frequency (GHz)
attenuation_db: 30, // required attenuation @ fx
ripple_db: 0.2, // Chebyshev only
f1: 1.8, // lower cutoff (GHz) for BPF / BSF
f2: 2.4, // upper cutoff (GHz) for BPF / BSF
Z0: 50,
});
console.log(result.N); // computed order
console.log(result.g); // prototype g-values
result.elements.forEach((el) => {
console.log(el.k, el.topology, el.L, el.C);
});Recipes
Capture results as HTML (any editor)
Use the optional onInsert prop to grab the results as HTML — for a rich-text editor, a preview pane, or anything else:
import { useState } from "react";
import { SingleStubMatch } from "ioe-rf-calculations";
export function CalculatorWithOutput() {
const [html, setHtml] = useState("");
return (
<>
<SingleStubMatch onInsert={setHtml} />
{html && <div dangerouslySetInnerHTML={{ __html: html }} />}
</>
);
}Public calculator page
import { RFAnalysisSelector } from "ioe-rf-calculations";
export default function CalculatorsPage() {
return (
<section className="container py-10">
<h1 className="mb-6 text-2xl font-bold">RF/Microwave Calculators</h1>
<RFAnalysisSelector />
</section>
);
}Use in plain Node.js
npm install ioe-rf-calculationsimport { designFilter } from "ioe-rf-calculations"; // ESM
// const { designFilter } = require("ioe-rf-calculations"); // CJS
const f = designFilter({
approximation: "butterworth",
filterType: "lpf",
fc: 2.4,
fx: 3.5,
attenuation_db: 30,
Z0: 50,
});
console.log(f.N, f.elements);Development
git clone https://github.com/SahajShakya/RF-IOE-Calculations.git
cd RF-IOE-Calculations
npm install
npm run build # typecheck + vite library build → dist/
npm run typecheck # tsc --noEmit onlyThe repo mirrors the two-layer design:
src/
├── calculations.ts # pure RF/microwave math (framework-free)
├── components/ # React tool components built on the primitives below
└── lib/ # tiny class-name helper (no external deps)The styling for every component lives in rf-components.css (plain CSS, no Tailwind, no UI library), styled to match the NerdStudyHub admin UI's own components (Card, InputField, SelectField, SubmitButton). There is no UI library to configure — just import the stylesheet.
Contributing
- Fork the repository.
- Create a feature branch (
git checkout -b feat/my-feature). - Commit your changes.
- Open a pull request.
Bug reports and new RF/microwave tool ideas are welcome via Issues.
License
MIT © 2026 Sahaj Shakya
