simulating ROSNR

As a (late) Christ­mas present I thought I’d share my method of deter­min­ing the required OSNR (ROSNR) val­ue for a trans­mis­sion sys­tem in sim­u­la­tions by means of the Monte Car­lo method. Recent­ly, I do pre­fer the error vec­tor mag­ni­tude (EVM) as a fig­ure of mer­it, but not a lot of peo­ple share this view. Many seem to love the ROSNR, espe­cial­ly Bell Lab­sers, and who am I to tell them oth­er­wise?

For those that are not so famil­iar with the ROSNR: The ROSNR describes the noise spec­tral density$^1$ in the opti­cal domain that can be tol­er­at­ed to achieve a cer­tain BER. It thus sep­a­rates ampli­fi­er noise from oth­er, more deter­min­is­tic impair­ments. For more infor­ma­tion, see e.g. [1]. Usu­al­ly, the BER val­ue is tak­en to be $10^{-3}$ – low­er tar­get BER val­ues would make the cal­cu­la­tion take for­ev­er. The sim­u­la­tion runs noise­less (opti­cal ampli­fiers add no noise at all), and all the noise pow­er is added just before the receiv­er. This way, non­lin­ear noise inter­ac­tions dur­ing prop­a­ga­tion can­not be tak­en into account, but these are sel­dom rel­e­vant (one should check this, though).

What we need in order to deter­mine the ROSNR of a trans­mis­sion link is access to the opti­cal field just before the receiv­er, the input and out­put data, and the free OptiLux sim­u­la­tion pack­age [Source­Forge] from the Uni­ver­si­ty of Par­ma – actu­al­ly, we need only one of the sup­ple­men­tary func­tions in this pack­age to save us some pro­gram­ming tedium.$^2$

Adding Noise

The prin­ci­ple of Monte Car­lo ROSNR deter­mi­na­tion is to find the right amount of noise to add to the sig­nal so that the BER at the receiv­er out­put equals some pre­de­ter­mined val­ue. This usu­al­ly is a tri­al-and-error or opti­miza­tion prob­lem. Per­son­al­ly, I like to take a few select­ed val­ues of noise pow­er, deter­mine their BER and then inter­po­late. This is often much quick­er, but more on that lat­er. The MATLAB code to add the noise is

signalPower = mean(abs(Signalx).^2 + abs(Signaly).^2);
noisePower = signalPower / 10^(OSNR/10) * (sampleRate / 12.5e9);
noiseSamples = randn(length(Signalx), 4) * sqrt(noisePower/4);
noisySignalx = Signalx + noiseSamples(:,1) + 1i*noiseSamples(:,2);
noisySignaly = Signaly + noiseSamples(:,3) + 1i*noiseSamples(:,4);

where OSNR is the OSNR in dB and sampleRate is the sim­u­la­tion band­width. Since the OSNR is defined as the noise pow­er in a 12.5 GHz (0.1 nm) band­width, the total noise in the sim­u­la­tion band­width is cor­re­spond­ing­ly high­er. Signalx and Signaly are the orig­i­nal sig­nal sam­ples in both polar­iza­tions, noisySignalx / noisySignaly are the “noisy” sam­ples. Each quad­ra­ture in each polar­iza­tion, all being inde­pen­dent of one anoth­er, receives a quar­ter of the total noise pow­er. If we sim­u­late only a sin­gle polar­iza­tion, we can omit the last line.

The noisy sig­nal is then received by what­ev­er receiv­er we have pro­grammed and the received data are com­pared to the sent data in order to deter­mine the sam­ple BER.

Determining BER

Unless we sim­u­late an immense­ly long bit sequence, we will usu­al­ly only see a few errors for the OSNR val­ues of inter­est (with a BER near $10^{-3}$). This sam­ple BER val­ue has lit­tle sta­tis­ti­cal sig­nif­i­cance [Wikipedia] – one error more or less may sig­nif­i­cant­ly alter the obtained BER val­ue. Often, sim­u­la­tions are repeat­ed until at least 100 errors are obtained in order to have some con­fi­dence in the results. We can avoid hav­ing to run the whole sim­u­la­tion mul­ti­ple times (which can take eons to com­plete) by sim­ply adding a dif­fer­ent set of noise sam­ples to the sig­nals Signalx and Signaly just in front of the receiv­er and then adding up the errors from all runs. In essence, many sam­ples of a Gauss­ian noise vari­able are added to each sig­nal sam­ple and its error prob­a­bil­i­ty deter­mined. Forestieri’s algo­rithm does this ana­lyt­i­cal­ly, but is applic­a­ble to only a few receiv­er types [2].

The cor­re­spond­ing MATLAB code uses OptiLux’ ber_estimate func­tion and looks some­thing like this:

cond = true;
while cond
% code to add noise from above goes here

% receiver implementation goes here

[cond, avgber, nruns, stdber] = ber_estimate(rxpat, txpat, ...
struct('nmin', 1000));
% or [cond, avgber, nruns, stdber] = ber_estimate(rxpat, ...
txpat, struct('stop', [0.05 99]));
BER(kk) = avgber;

The loop runs until the func­tion returns cond = false, which hap­pens here after 1000 errors have been count­ed. The vari­able rxpat con­tains the received bit sequence and txpat cor­re­spond­ing­ly the sent sequence. These can be matri­ces, all their ele­ments are com­pared and mis­match­es count­ed. For QPSK sig­nals in a sin­gle polar­iza­tion I use two colums of bipo­lar bina­ry data (“1” and “–1” – one col­umn for the in-phase and one for the quad­ra­ture data) – for two polar­iza­tion there would be four columns of data. nruns con­tains the num­ber of com­pared bits (matrix ele­ments). The alter­na­tive (com­ment­ed out) func­tion call uses a rel­a­tive accu­ra­cy and con­fi­dence val­ue pair as a stop­ping cri­te­ri­on, both cri­te­ria can also be com­bined. Be sure to make some test runs and check the run­ning time using tic and toc, because the num­ber of runs can eas­i­ly become exces­sive when using bad val­ues. A typ­i­cal con­ver­gence graph is shown in Fig. 1 (plot­ting avgber over avgber*nruns after each run of ber_estimate), the stop­ping cri­te­ri­on here was an accu­ra­cy of 0.025 with 95% con­fi­dence. Often, sev­er­al thou­sand count­ed errors are need­ed for the BER to con­verge suf­fi­cient­ly. How­ev­er, depend­ing on the sig­nal and OSNR val­ue, your mileage may vary.

Final­ly, we pro­to­col the total BER into a vari­able – here, kk runs over dif­fer­ent OSNR val­ues in an out­er loop (not shown).

Fig. 1: con­ver­gence of BER esti­mate with num­ber of count­ed errors in a Monte Car­lo BER esti­ma­tion. OSNR is 11 dB, length of sim­u­lat­ed sym­bol sequence was $2^{14}$.

Interpolating the ROSNR

Okay, so now we have the BER val­ues for a cou­ple of OSNR val­ues, but very like­ly none of these is exact­ly $10^{-3}$. We could run some opti­miza­tion algo­rithms, chang­ing the OSNR slight­ly and run­ning the BER loop again, but this takes very long. I don’t have that much time. It is much eas­i­er to just inter­po­late the data we have. I usu­al­ly only look at inte­ger OSNR val­ues and inter­po­late any­thing in between.

ROSNR = interp1(log10(BER), 8:12, -3, 'pchip', NaN);
catch exception

where BER con­tains the BERs for inte­ger OSNR val­ues between 8 and 12. I like to wrap the inter­po­la­tion in a try/catch seg­ment, because some­times it’ll throw an error (e.g. if input data is not monot­o­nous) and this way it won’t stop the whole script, but sim­ply gives a NaN result. Using the log­a­rithm of the BER makes the inter­po­la­tion eas­i­er (the changes are small­er), espe­cial­ly at very low BERs. We could also use log10(-log10(BER)), since plot­ting this over the OSNR (in dB) is an pret­ty much lin­ear func­tion and most sim­ple to inter­po­late – but then again, tak­ing the log­a­rithm twice makes a lin­ear func­tion out of almost every­thing. Fig. 2 com­pares the var­i­ous BER curves and their MATLAB “pchip” inter­po­la­tion.

Fig. 2: exem­plary char­ac­ter­is­tic of var­i­ous func­tions of the BER vs. OSNR. (bot­tom) lin­ear plot, (mid­dle) log­a­rith­mic BER scale, (top) twice-log­a­rith­mic BER. The sym­bols denote sim­u­la­tion results and lines are MATLAB ‘pchip’ inter­po­la­tions. The result­ing required OSNR val­ues for a BER of 0.001 are also indi­cat­ed.

We now know the required OSNR for this par­tic­u­lar bit sequence over the trans­mis­sion link in ques­tion. Unless the sys­tem is pure­ly lin­ear and has small mem­o­ry, the ROSNR val­ue will depend on the par­tic­u­lar bit sequence, even when this sequence is very long. To be on the safe side, we would have to repeat the sim­u­la­tion with dif­fer­ent sequences and aver­age their results – be care­ful, though: we have to aver­age the BERs pri­or to cal­cu­lat­ing the ROSNR and not the ROS­NRs itself in order to do it cor­rect­ly from a sta­tis­ti­cal point of view.

If you think I am doing some­thing wrong or if you have an idea how to improve the code, let me know in the com­ments.

1 Since the OSNR is nor­mal­ized to a 12.5 GHz band­width, it rather describes a noise spec­tral den­si­ty (which does depend on the usable sig­nal pow­er) than a sig­nal-to-noise ratio in the com­mu­ni­ca­tions sci­ence sense.

2 Optilux is actu­al­ly a pret­ty clever sim­u­la­tion tool that incor­po­rates the split-step Fouri­er algo­rithm for opti­cal fibers as well as many algo­rithms need­ed for coher­ent detec­tion and much more. Once you get used to its unusu­al nor­mal­iza­tion of fre­quen­cies, it’s very pow­er­ful.

[1] R.-J. Essi­ambre, G. Ray­bon and B. Mikkelsen, “Pseu­do-Lin­ear Trans­mis­sion of High-Speed TDM Sig­nals: 40 and 160 Gb/s,” in Opti­cal Fiber Telecom­mu­ni­ca­tions IV B, Aca­d­e­m­ic Press, 2002.

[2] E. Forestieri, “Eval­u­at­ing the error prob­a­bil­i­ty in light­wave sys­tems with chro­mat­ic dis­per­sion, arbi­trary pulse shape and pre- and post­de­tec­tion fil­ter­ing,” Jour­nal of Light­wave Tech­nol­o­gy, vol. 21, no. 6, pp. 1592ff., June 2003.

last posts in MATLAB:


  • Dear Mar­cus,
    Recent­ly, I’m also doing some sim­u­la­tion on BER ver­sus OSNR. And Optilux is also used in my sim­u­la­tion. The per­pose is reserch­ing the per­for­mance of opti­cal sys­tem with PMD improved by Reed-Solomon (RS) code. But I find for a giv­en BER (e.g. 10-3), the OSNR is larg­er than oth­er reserch­es which stat­ed in the papers. On the oth­er hand, I do not quite under­stand the OSNR in the Optilux. Can you give me some advice on how to sim­u­lat­ing OSNR in Optilux? Thanks very much.
    A col­lege stu­dent, LML

  • Marcus wrote:

    Every­thing that I could answer is already with­in the post. It is not unusu­al that ROSNR val­ues dif­fer in dif­fer­ent papers, depend­ing on how well the authors checked for con­ver­gence of their val­ues. The dif­fer­ence are usu­al­ly small, much less than a dB or so…

  • Hemalatha wrote:

    How to use optilux in mat­lab?
    Do help me in this regard.

Post a Comment

Your email is never shared.