top of page

QA0008

ZIP with MATLAB scripts:

Small tag OK.jpg
How to calculate MIMO channel figures of merit
  • Channel Capacity Loss ( CCL ),
  • Envelope Correlation Coefficient ( ECC )  
  • Total Angle Reflection Coefficient ( TARC )
from scattering parameter files that have been inadvertently modified leaving behind multiple delimiter characters in each Sij.txt file. I also highlight limitations of obsolete command dlmread as well as for the one that is supposed to replace it readmatrix :

QA0008 note:

Small tag OK.jpg
question1-2.jpg
question1-1.jpg

This QA addresses the problem of attempting to calculate the above figures of merit out of scattering S parameters in files s11.txt s12.txt s21.txt s22.txt that have different delimiters (TAB '\t' and space ' ') in same file.

 

Sometimes this happens when data manually merged by different operators. If other people processing such data wrongly assume that just one type of delimiter is used per file one can only realise when inspecting the source files.

 

Simplified calculations of

  • CCL: Channel Capacity Loss

  • ECC: Envelope Correlation Coefficient

  • TARC: Total Angle Reflection Coefficient

from S parameters in txt files with mixed delimiters

 

The initial MATLAB approach is often dlmread

QA1=dlmread('s11.txt')

 

 

 

 

QA1=dlmread('s11.txt')

 

Error using dlmread (line 147)

Mismatch between file and format character vector.

Trouble reading 'Numeric' field from file (row number 1, field number 1) ==> #\n

 

Error using dlmread (line 147)

Mismatch between file and format character vector.

Trouble reading 'Numeric' field from file (row number 1, field number 1) ==> #\n

QA1=dlmrec

On checking the contents of the source files:

dbtype s11.txt 1:10

1     #

2     #"Frequency / GHz"        "S1,1 [Re]"              "S1,1 [Im]"              "Ref.Imp. [Re]"       "Ref.Imp. [Im]"

3     #-------------------------------------------------------------------------

4     2.0000000000000            -0.43436479568481 -0.27583473920822 49.499982587419   0.00000000000000

5     2.0130000114441             -0.43212774395943 -0.25979641079903 49.499982587419   0.00000000000000

6     2.0260000228882            -0.42928242683411 -0.24402607977390 49.499982587419   0.00000000000000

7     2.0390000343323            -0.42584636807442 -0.22855253517628 49.499982587419   0.00000000000000

8     2.0520000457764            -0.42183887958527 -0.21340312063694 49.499982587419   0.00000000000000

9     2.0650000572205            -0.41728088259697 -0.19860377907753 49.499982587419   0.00000000000000

10    2.0780000686646           -0.41219443082809 -0.18417946994305 49.499982587419   0.00000000000000

The yellow space between 1st and 2nd column is not space but TAB. The space between 2nd 3rd, 3rd 4th, and so on are spaces.

dbtype s12.txt 1:10

1     #

2     #"Frequency / GHz"        "S1,2 [Re]"              "S1,2 [Im]"

3     #-----------------------------------------

4     2.0000000000000            -0.0087176365777850            0.19573307037354

5     2.0130000114441            -0.00025198308867402          0.19772811233997

6     2.0260000228882            0.0083699077367783             0.19926650822163

7     2.0390000343323            0.017119051888585               0.20033770799637

8     2.0520000457764            0.025965791195631               0.20093321800232

9     2.0650000572205            0.034879870712757               0.20104672014713

10    2.0780000686646           0.043830763548613               0.20067396759987

Another discrepancy is the different amount of columns. If all S parameter files have same amount of columns, separated by same type of delimiter, processing them is easier.
Since Mathworks recommends replacing dlmread with readmatrix next logic step is for instance:

d_S11=readmatrix('s11.txt');

d_S12=readmatrix('s12.txt');

d_S21=readmatrix('s21.txt');

d_S22=readmatrix('s22.txt');

 

size(d_S11)

size(d_S12)

size(d_S21)

size(d_S22)

 

 

 

 

 

 

 

 

=        1001           5

=        1001           3

=         994           3

=        1001           5

This approach has 2 problems; firstly NaN values show up despite dbtype just showed above that there isn’t any within the initial 10 lines of any of the source files.

d_S12(1,:)

 

 

 

 

d_S11(1,:)

 

 

 

 

 

 

d_S21(1,:)

 

 

 

 

d_S22(1,:)

=  Columns 1 through 2

   2.000000000000000  -0.008717636577785

  Column 3

   0.195733070373540

 

= Columns 1 through 2

   2.000000000000000  -0.434364795684810

  Columns 3 through 4

  -0.275834739208220  49.499982587418998

  Column 5

              0

 

= Columns 1 through 2

   2.091000080108600                 NaN

  Column 3

           NaN

 

 =  Columns 1 through 2

   2.000000000000000  -0.434202671051030

  Columns 3 through 4

  -0.277085989713670  49.499805239380997

  Column 5

             0

With Notepad, doing ctrl+F: NaN in all source files, there is no such string. Then how many NaN generated from readmatrix reading anyway?

nnz(isnan(d_S11))

nnz(isnan(d_S12))

nnz(isnan(d_S21))

nnz(isnan(d_S22))

 =     0

 =     0

 =    12

 =     0

And secondly, the size checks done above show that while files s11.txt s12.txt and s22.txt have 1001 lines of data (the 1st 3 lines of all files are preceded by Python’s comment character #, the equivalent to % in MATLAB) s21.txt only seems to have 994. However, on checking directly with Notepad how many lines Notepad says all source files have, here are the readings:
002.jpg

[fG_S11,S11_]=read_Sf('s11.txt');

[fG_S12,S12_]=read_Sf('s12.txt');

[fG_S21,S21_]=read_Sf('s21.txt');

[fG_S22,S22_]=read_Sf('s22.txt');

 

 

Is there any NaN now?

 

nnz(isnan(S11_))                                                    

nnz(isnan(S12_))                             

nnz(isnan(S21_))

nnz(isnan(S22_))

size(S11_)

size(S12_)

size(S21_)

size(S22_)

Is there any numerical data rows columns discrepancy?

sz1=min([size(S11_,1) size(S12_,1) size(S21_,1) size(S22_,1)])

 

 

sz2=min([size(fG_S11,1) size(fG_S12,1) size(fG_S21,1) size(fG_S22,1)])

Generating the frequency vector:

Although it’s not strictly needed to complete the sought calculations in this question, it’s good practice to put all S parameters in a single variable. On the right, how to generate S(f) without for loops:

sz1 =   1001

 

sz2 =   1001

% f=fG_S11*1e9;   % fG_Sij are equal length, GHz to Hz 

f=fG_S11;

S11=S11_(:,1)+1j*S11_(:,2);                                 

S12=S12_(:,1)+1j*S12_(:,2);  

S21=S21_(:,1)+1j*S21_(:,2);  

S22=S22_(:,1)+1j*S22_(:,2);

S=[reshape(S11,1,1,sz1) reshape(S12,1,1,sz1) ;  ...  

      reshape(S21,1,1,sz1)  reshape(S22,1,1,sz1)];

Here is not the case, but it may also happen that even with the same amount of points, frequencies do not coincide on few points, then interpolation would be required.

 

Checking a couple of lines, 1st and last, that reshape used correctly

isequal([ S11(1)  S12(1); S21(1) S22(1)], S(:,:,1))

isequal([ S11(end)  S12(end); S21(end) S22(end)], S(:,:,end))

ans = logical

   1

ans = logical

   1

Now all clear to calculate CCL ECC and TARC

 

CCL: Channel Capacity Loss

 

Psi_r=[reshape((1-S11.*conj(S11)-S21.*conj(S21)),1,1,sz1) ...   

       reshape(conj(S11).*S12+conj(S21).*S12,1,1,sz1 ) ;  ...

       reshape(conj(S22).*S21+conj(S12).*S21,1,1,sz1) ...

       reshape((1-S22.*conj(S22)-S12.*conj(S12)),1,1,sz1)];

 

CCL=zeros(1,numel(S11));

for k=1:1:1

      C_loss(k)=log2(abs(det(Psi_r(:,:,k))));

end

 

 

 

ECC: Envelope Correlation Coefficient

 

ECC=(conj(S11).*S12+conj(S21).*S22).*conj(conj(S11).*S12+conj(S21).*S22)./...

        ((1-S11.*conj(S11)-S21.*conj(S21)).*(1-S22.*conj(S22)-S12.*conj(S12)));

 

MEG1=.5*(1-S11.*conj(S11)-S12.*conj(S12));

MEG2=.5*(1-S12.*conj(S12)-S22.*conj(S22));

 

etha1=.7

etha2=.7

 

 

etha1 etha2 : antennas efficiencies, maybe optimistic antenna efficiency value.

 

peak efficiency

 

etha_max=(etha1*etha2*(1-(ECC).^2)).^.5;

 

 

 

TARC: Total Angle Reflection Coefficient

 

gamma_TARC has to be calculated on each frequency. For frequency f point gamma_TARC has numel(theta) points

 

theta=pi/180*[30 60 90 120 150 180]                     % angle, grads to rads

 

gamma_TARC=zeros(numel(S11),numel(theta));

for k=1:1:numel(S11)

gamma_TARC(k,:)= ...

             2^(-.5)*((abs(S11(k)+S12(k)*exp(1j*theta))).^2+ ...

                      (abs(S21(k)+S22(k)*exp(1j*theta))).^2).^.5;

end

gamma_TARC(1,:)=0;

CCL graph

 

 

 

figure(1);

plot(f,CCL);grid on

xlabel('f: frequency[GHz]');

ylabel('CCL : Channel Capacity Loss')

title('CCL(f)')

 

 

 

 

 

 

 

 

MEG1 MEG2 graphs

 

 

figure(2);

plot(f,MEG1);

hold on;

plot(f,MEG2); grid on

xlabel('f: frequency[GHz]');

ylabel('MEG : Mean Effective Gain') ;

title('MEG(f)')

legend('port1','port2')

 

 

 

ECC graph

 

 

figure(3);

plot(f,ECC); grid on

xlabel('f : frequency[GHz]');

ylabel('ECC : Envelope Correlation Coefficient');

title('ECC(f)')

001 CCL.jpg
002 MEG.jpg
003 ECC.jpg
bottom of page