How to format csv to contain displacements for several time increments?
I want to read in displacement data from a csv-file and then write it as h3d.
The data will be for several time increments and each time increment contains node id, x-displacement, y-displacement and z-displacement.
I think, tutorial Compose-3010 gives me some ideas, but I am not sure how to put it in praxis.
An elegant way seems to be using fscanf, so if my file had the datalines in a regular format %i,%f,%f,%f (meaning node id as integer and the in a comma separated way, x-, y- and z-displacements as floats), but the problem is those time increments. I am entirely free to format the csv-file in anywhich way I want.
based on the tutorial I could try folllowing
clc; clear all; close all; fid = fopen('E:\work\Compose\read_results\csvsimple.csv','rt'); A = fscanf(fid,'%d,%f,%f,%f',[4 inf]); fclose(fid); disp(A')
now for a simple data set of 4 nodes:
1,0,0,0 2,0,0,0 3,0,0,0 4,0,0,0
I get what I want, but if I want to provide the data for multiple time increments I have no idea how to do the separation. Essentially I would have something like:
time,0.0 1,0,0,0 2,0,0,0 3,0,0,0 4,0,0,0 time,0.1 1,1.,0,0 2,1.,0,0 3,1.,0,0 4,1.,0,0
now I get empty matrix. I could put the "time" in an additional column, before the node id, but I think it is wasteful and I think not very practical. In the end I might have something like 200000 nodes and maybe 100 time increments. As far as I can see scanf would suck in the whole data and I think it would be too much. So in the end it would be better to do some sequential reading here. Search for some sort of time information and then read the datalines until next increment. At that moment I would also write the data to a h3dfile.
I would appreciate some insight how to do a lean code here, unfortunately the tutorials and help do not give enough guidance.
Answers
-
Ok, apparently I need to answer myself. I got this far:
clc; clear all; close all; fid = fopen('E:\work\Compose\read_results\csvsimple.csv','rt'); %A = fscanf(fid,'%f,%f'); while ~feof(fid) line = fgetl(fid); t = sscanf(line,'time,%f') A = fscanf(fid,'%d,%f,%f,%f',[4 inf]); disp(A'); end fclose(fid);
It assumes a format headerline and then datalines. Apparently, the fscanf reads until the next headerline or eof. To me the code seems a bit shakey, but I need to experiment a bit. However, there is this sscanf entry and the way I did works, but when I used a formatting t = sscanf(line,'%s,%f') I get a load of nonsense, propably ASCII Codes of the characters or whatnot. Do I need to go for a regexp here or what is the best way to split the singular line between the commas? I would like to add here information about the coming datalines, for example:
time,0.1,displacements
displacements keyword will then define the type of data, of course I could go for an integer as an identifier here and then I could easily use sscanf more or less as before but I think there is a more elegant way?
0 -
Hi Jyrki,
Have you tried using function csvread already? This function will be much easier to use and will return a single matrix containing all your data.
After doing that, you must create a new h3d file (createh3dfile), declare a vector datatype (createh3ddatatype), create a subcase (createh3dsubcase) and write the data with writeh3ddata before closing the file.
0 -
No, somehow the possibility did not even occur to me, but I would be interested to try it out.
However, I see a couple of challenges. First one being the "header" lines defining the coming data type and the subcase. I do not know exactly how many data lines will follow, but I could, of course put that info to these leading lines. Another alternative would be writing this information into entirely separate file and keep the csv file as pure data. So the "reading instructions" would say something like the csv-file will contain 10 subcases of displacements, each having 100000 lines and then comes the reaction forces again 10 subcases and 100000 lines etc.
However I am not sure how to accomplish that, propably with the range option then...I certainly can not suck in the whole csv on one go as it is potentially a huge set of data. I think I have no other option, but to try and read it in sequentially (one subcase after another) and write the data into the h3dfile.
0 -
Jyrki Majamäki said:
No, somehow the possibility did not even occur to me, but I would be interested to try it out.
However, I see a couple of challenges. First one being the "header" lines defining the coming data type and the subcase. I do not know exactly how many data lines will follow, but I could, of course put that info to these leading lines. Another alternative would be writing this information into entirely separate file and keep the csv file as pure data. So the "reading instructions" would say something like the csv-file will contain 10 subcases of displacements, each having 100000 lines and then comes the reaction forces again 10 subcases and 100000 lines etc.
However I am not sure how to accomplish that, propably with the range option then...I certainly can not suck in the whole csv on one go as it is potentially a huge set of data. I think I have no other option, but to try and read it in sequentially (one subcase after another) and write the data into the h3dfile.
Hi Jyrki,
Correct, there are many possibilities. You could work with two different files as you said or maybe the first column could be the subcase number as well, that way you could use some logic to split the data between subcases after reading the data in one chunk.
Apart from CSV reading and writing functions, OML also features functions for handling Excel files (CSV files can be read with these as well) if you are running Compose on Windows. You could try those as well.
Maybe creating a CSV for each subcase will make the process less demanding on your machine as well? Sequentially reading and closing each CSV afterwards might be interesting.
Rafael
0