Read text data and create array?

I have a .txt file with ISS orbital parameters that I'm looking to import into Matlab and use to plot things like satellite position, for example.
I have successfully pulled the data from the website and printed to the attached .txt file but when I use readtable(), Matlab generates a 212x1 matrix instead of splitting the columns and creating a full array. Unfortunately, the format from the website hosting the orbit data features an unequal number of delimiters as well.
Any help and/or guidance on how to read this data, split it into columns, and create variables from it would be much appreciated. I do not need the string data (i.e. "ISS (ZARYA) ") from the top of each two row data set. Thanks.

6 Comments

Is there description of the data file content so know what it is are looking at? What, for instance is the interpretation of the two fields containing "00000-0 -30560-5" in first record?
You'll have to read each set of three individually; there is no prebuilt function to handle such specific file formats automagically.
You might see if an online search will locate someobody has already written a script for such files; sometimes you can be amazed at what is already out there.
I'll look online to see if someone's already written a script. It actually makes me feel better that there is no prebuilt function for this because I've been pulling my hair out trying to figure out how to make this work.
Here is a description of the two-line format:
This is a case where it would probably be easiest to loop doing fgetl() and indexing into the character vectors to extract parts, and converting the parts to numeric as needed.
There are also approaches based upon using regexp() and a bunch of named tokens and the 'names' option. That would give you a struct array of character vectors that you would still need to convert to numeric.
Ah! Since are fixed width fields, the fixedWidthImportOptions object may be of help here...how big are the files? If one could load into memory readily as string array, then every third record is a given record type that could be parsed and then the pieces put back together. I've not had occasion to do such, but don't see why wouldn't be pretty straightforward to do so.
WRT to the above comment and the table...how you want to name stuff? For example, there are multiple pieces of data buried in some of the variables like the Satellite Number and Classification are run together in one string but are separate fields--you want/need both of the composite?
Similar with the Designator excepting it has three composite pieces buried in it.
And, continues with the epoch year/day that are also run together.
Need to define what pieces you need as the individual variables or what you want to leave as encoded and deal with separating out the pieces on an as-needed basis.
You make a list of wanted variables and I'll see about encoding...since the guv now has us on lockdown, too, guess will not push the issue too hard.
I actually followed your advice above and turns out someone did do something just like this.
Matlab linked to their code at GitHub here.

Sign in to comment.

 Accepted Answer

Ameer Hamza
Ameer Hamza on 30 Mar 2020
Edited: Ameer Hamza on 30 Mar 2020
Try this:
%% read data
f = fopen('issd.txt');
data = {};
while true
line = fgetl(f);
if line == -1
break;
end
data{end+1} = line;
end
fclose(f);
%% split data
data(2:2:end) = []; % delete empty lines
names = data(1:3:end);
line1 = cell2mat(data(2:3:end)');
line2 = cell2mat(data(3:3:end)');
%% Parse data
% helper functions
f = @(x) mat2cell(line1(:,x), ones(size(line1,1),1), numel(x), 1);
g = @(x) num2cell(str2num(line1(:,x)));
h = @(x,y) num2cell(str2num(strcat('.', line1(:,x))) .* 10.^str2num(line1(:,y)));
line1_split = [f(1) g(3:7) f(8) g(10:11) g(12:14) f(15:17) g(19:20) g(21:32) ...
g(34:43) h(46:50,51:52) h(55:59,60:61) g(63) g(65:68) g(69)];
g = @(x) num2cell(str2num(line2(:,x)));
line2_split = [f(1) g(3:7) g(9:16) g(18:25) g(27:33) g(35:42) g(44:51) ...
g(53:63) g(64:68) g(69)];
%% create table
T = cell2table([names' line1_split line2_split]);
T.Properties.VariableNames = {'Name', ...
'LN1', ...
'Satellite Number', ...
'Classification', ...
'Intl. Designator (launch year)', ...
'Intl. Designator (number of the year)', ...
'Intl. Designator (piece of the launch)', ...
'Epoch Year', ...
'Epoch Day', ...
'First Derivative (Mean Motion)', ...
'Second Derivative (Mean Motion)', ...
'Drag term', ...
'Ephemeris type', ...
'Element set number', ...
'Checksum1', ...
'LN2', ...
'Catalog number', ...
'Inclination', ...
'Right Ascension', ...
'Eccentricity', ...
'Argument of Perigee', ...
'Mean Anomaly', ...
'Mean Motion', ...
'Revolution number', ...
'Checksum2'};

6 Comments

This works very well.
Would it also be possible to pull the two line mean element data set for the ISS specifically from NASA's feed here?
The data format is the same but the only thing I need to extract from the page are the two line element sets below each title that says, "TWO LINE MEAN ELEMENT SET."
Thanks much for your help.
Do you want to read value from this webpage as text?
Doesn't necessarily need to be read as text.
Just need to be able to create the variables from the numerical data and process it within my Matlab code. Similar to what you were able to do with the other site.
Since the webpage is well structured, I have hard-coded all the indexed. The code gives the general idea, you can improve it as required
data = webread('https://spaceflight.nasa.gov/realdata/sightings/SSapplications/Post/JavaSSOP/orbit/ISS/SVPOST.html');
pattern = 'TWO LINE MEAN ELEMENT SET';
idx = strfind(data, pattern);
num_occurance = numel(idx);
names = cell(1,num_occurance);
line1 = cell(1,num_occurance);
line2 = cell(1,num_occurance);
for i=1:num_occurance
names{i} = data(idx(i)+33:idx(i)+35);
line1{i} = data(idx(i)+41:idx(i)+109);
line2{i} = data(idx(i)+115:idx(i)+183);
end
line1 = cell2mat(line1');
line2 = cell2mat(line2');
%% Parse data
% helper functions
f = @(x) mat2cell(line1(:,x), ones(size(line1,1),1), numel(x), 1);
g = @(x) num2cell(str2num(line1(:,x)));
h = @(x,y) num2cell(str2num(strcat('.', line1(:,x))) .* 10.^str2num(line1(:,y)));
line1_split = [f(1) g(3:7) f(8) g(10:11) g(12:14) f(15:17) g(19:20) g(21:32) ...
g(34:43) h(46:50,51:52) h(55:59,60:61) g(63) g(65:68) g(69)];
g = @(x) num2cell(str2num(line2(:,x)));
line2_split = [f(1) g(3:7) g(9:16) g(18:25) g(27:33) g(35:42) g(44:51) ...
g(53:63) g(64:68) g(69)];
%% create table
T = cell2table([names' line1_split line2_split]);
T.Properties.VariableNames = {'Name', ...
'LN1', ...
'Satellite Number', ...
'Classification', ...
'Intl. Designator (launch year)', ...
'Intl. Designator (number of the year)', ...
'Intl. Designator (piece of the launch)', ...
'Epoch Year', ...
'Epoch Day', ...
'First Derivative (Mean Motion)', ...
'Second Derivative (Mean Motion)', ...
'Drag term', ...
'Ephemeris type', ...
'Element set number', ...
'Checksum1', ...
'LN2', ...
'Catalog number', ...
'Inclination', ...
'Right Ascension', ...
'Eccentricity', ...
'Argument of Perigee', ...
'Mean Anomaly', ...
'Mean Motion', ...
'Revolution number', ...
'Checksum2'};
This works very well. Thanks much for your help!
Glad to be of help.

Sign in to comment.

More Answers (0)

Categories

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!