I have the function
fid = fopen(filename,'w');
if exist('fid')
check = true;
else
check = false;
end
for i=1:length(persons)
fprintf(fid, '%s\n',serialize_person(persons(i)));
end
end
Where serialize_person is
function [output] = serialize_person(person)
fprintf ( '<%s>#' , person.name ) ;
serialize_date ( person.date_of_birth ) ;
fprintf ( '#<%i>\n' , person.phone ) ;
end
Which takes is a personalia and writes out 'name.day.month.year.phonenumber'
Firstly I need to make this come out as a single string of text in 'output' for it to(I assume)work in the first function, how would I go about this?
Secondly, the first function takes is a filename and a cell of persons. I want it to come out on a textfile with the name 'filename' with one personalia per line.
Yesterday I had it working up to the for loop, but somehow I cant get beyond the first line today without hitting an error message.
Could you give me some advice here, I don't know whats wrong.
To write output to a character array rather than the console, use sprintf. Also, to join the strings with a '.' between strings, try strjoin with a delimiter set:
function [output] = serialize_person(person)
delim = '.';
output = strjoin(sprintf ( '<%s>#' , person.name ), ...
serialize_date ( person.date_of_birth ), ...
sprintf ( '#<%i>\n' , person.phone ), delim);
end
Modify serialize_date similarly.
Related
I'm not afraid this question might be too obscure, but here it goes!
I have limited experience with scripting, and I wrote this script to sum two neural maps (that contain "c1" or "c2" in their names) with SPM12:
dataPath=fileparts(pwd);
dataPath=fullfile(dataPath,'/MATLAB Drive/Target Files');
filterStrC1='^c1';
filterStrC2='^c2';
fileNameC1=spm_select('FPListRec',dataPath,filterStrC1);
fileNameC2=spm_select('FPListRec',dataPath,filterStrC2);
for iSubj=1:size(fileNameC1,1)
disp(iSubj);
[filePath, fileName]=fileparts(fileNameC1(iSubj,:));
fileName=fileName(3:end);
V0_fileName=[ filePath, filesep, 'sum_c12_' ,fileName, '.nii'];
tpm(iSubj)=spm_imcalc([fileNameC1(iSubjs,:) ;fileNameC2(iSubj,:)], V0_fileName,'i1+i2');
end
disp('sum done!')
However, for some reason, the for loop keeps getting skipped, and the fileName variables are empty every time I run the script.
Can you spot any obvious mistakes with my script?
I think you're right and that spm_select returns an empty array.
So spm_select is used to select a 'c1' and 'c2' image of one subject? If you know that there's always a 'c2' for every 'c1' then it would be easier just to use ls:
c1files = ls ( [ DataPath '/*/*/c1*.nii' ] ); % depending on tree depth
c1files = textscan ( c1files, '%s' );
c1files = c1files {1};
for i = 1: length ( c1files )
c1 = c1files { i };
c2 = strrrep ( c1, 'c1', 'c2' );
tpm ( i ) = spm_imcalc ( [ c1; c2 ], 'i1+i2' );
end
As you can see, you need to manipulate the output of the 'ls' command a bit (as well as the command itself, depending on how many directories down you are): it is just a matrix of characters, that textscan can turn into a cell array of file names. (it's actually a nested array, that's why the other line is needed).
But then you have a list of 'c1' files from which you can build the 'c2' files. You may want to print its size just in case it's 0. Hopefully the modified call to spm_imcalc still works - the syntax should be ok, not sure what the shape of tpm is.
I managed to fix it by deleting the first four lines and directly substituting the values in the spm_select command. I suspect there was something wrong with the dataPath variable.
Also, there's an extra "s" in the line following line, making a new variable iSubjs instead of using iSubj:
tpm(iSubj)=spm_imcalc([fileNameC1(iSubjs,:) ;fileNameC2(iSubj,:)], V0_fileName,'i1+i2');
Which I deleted, so it became:
tpm(iSubj)=spm_imcalc([fileNameC1(iSubj,:) ;fileNameC2(iSubj,:)], V0_fileName,'i1+i2');
I'm still not completely sure why that worked, but now it works.
I have a function that replaces a piece of text, and it became relevant that this function needs to issue an error in case it fails to do so.
One way to do so would be:
text_var = 'The whole big text';
if(~contains(text_var,'The part that will be replaced')))
throw(MException('MF:error','The part to be replaced is not in the text!'))
else
text_var = strrep(text_var,'The part that will be replaced','The replacement');
end
However, this seems not to be efficient. I can assume the text, if it appears does so only once. But I'd like to make a single call to a function operating on text_var. Is there no text replacement function in Matlab that returns an error if the replacement failed?
You could do the replace, and just check if the new string's length is unchanged (this assumes the original and replacement strings are different lengths)
text_var = 'the whole big text';
n = numel( text_var );
text_var = strrep( text_var, 'replace me', 'with this' );
if numel( text_var ) == n
error( 'No replacements made' );
end
If you can't make that assumption, you could use strfind to get the indices of the string. This will be empty if not found (so error), or you can use it to manually remove the string. Especially easy as you state it will appear at most once.
text_var = 'the whole big text';
removeStr = 'replace this';
k = strfind( text_var, removeStr );
if isempty( k )
error( 'No replacements made' );
end
text_var( k:k+numel(removeStr)-1 ) = []; % Remove string
Because you're only matching once, you might find that regexp is quicker than strfind, as you can use the 'once' argument of regexp to make it stop on the first match
k = regexp( text_var, removeStr, 'once' ); % instead of using strfind
I've looked through the posts on StackOverflow and can't seem to find the answer I am looking for. I have a large CSV file (450 MB) with hex data that looks like this:
63C000CF,6000002F,603000AF,6000C06F,617300EF,6C7C001F,6000009F,0%,63C000CF...
That is a very truncated example, but basically I have approximately 78 different hex values separated by commas, then there will be the '0%', then 78 more hex values. This will continue for a very long time. I've been using textscan like this:
data = textscan(fid, '%s', 1, 'delimiter', '%');
data = textscan(data{1}{1}, '%s', 'delimiter', ',');
data = data{1};
count = size(data);
outstring = ['%', sprintf('\n')];
for idx = 1:count(1)
string = data{idx};
stringSize = size(string);
if stringSize(2) > 1
outstring = [outstring, string, sprintf('\n')];
end
end
fprintf(output_fid, '%s', outstring)
This allowed me to format the csv file in a way to which I could use fgetl() to analyze whether or not I was looking at the data I needed. Because the data repeats itself, I can use fseek() to jump to the next occurrence before calling fgetl() again.
What I need is a way to skip to the ending. I want to just be able to use something like fgetl() but have it only return the first hex value it encounters. I will know how many bytes to shift through the file. Then I need to make sure I can read other hex values. Is what I'm asking possible? My code using textscan above takes far too long on a csv file that is 90 MB let alone 450 MB.
Answer obtained from user Cedric Wannaz on the Mathworks MATLAB Central Answers page.
NEW solution
Here is a more efficient solution; I am using a 122MB file, so you have an idea about the timing
% One line for reading the whole file. To perform once only.
tic ;
content = fileread( 'adam_1.txt' ) ;
fprintf( 'Time for reading the file : %.2fs\n', toc ) ;
% One line for defining an extraction function. To perform once only.
extract = #(label) content(bsxfun( #plus, ...
strfind( content, [label,','] ).' - 6, ...
0 : 5 )) ;
% Then it is one call per label to extract data.
tic ;
data = extract( 'CF' ) ;
fprintf( 'Time for extracting one label: %.2fs\n', toc ) ;
Running this, I obtain
Time for reading the file : 0.52s
Time for extracting one label: 0.62s
FORMER solution
Would the following work for you?
% Read file content. To do once only.
content = fileread( 'myFile.txt' ) ;
% Define regexp-based extraction function. To do once only.
getByLabel = #(label) regexp( content, sprintf( '\\w{6}(?=%s)', label ), ...
'match' ) ;
% Get all entries for e.g. label 'CF'.
entries_CF = getByLabel( 'CF' ) ;
% Get all entries for e.g. label '6F'.
entries_6F = getByLabel( '6F' ) ;
I am not completely clear on what you need to achieve ultimately; if I had to design a GUI where users can choose a label and get corresponding data, I would process the data much further during the init phase, e.g. by grouping them by label in a cell array. Regexp is not the most efficient approach in this case I guess, but the principle would be..
labels = {'CF', '6F', 'AF', ..} ;
nLabels = numel( labels ) ;
data = cell{ 1, nLabels ) ;
for lId = 1 : nLabels
data{lId} = getByLabel( labels{lId} ) ;
end
and then when a user selects 'CF' ..
lId = strcmpi( label, labels ) ;
dataForThisLabel = data{lId} ;
I want to add property-values pair in a txt file which contains property-values pairs and the properties should be sorted alphabetically, where a property is between square brackets and its value in the line below. This is an example file: On top of that i want to ignore the comment lines started with '#'.
#
[system]
#
programming
#
[information]
#
application
Like:-
function [] = updateFile( fileName,property,propertyValue )
% all inputs in strings
%
rfh = fopen( fileName, 'r' ); % read handle
tname = tempname(); % temporary file name
wfh = fopen( tname, 'w' )
In this example, ´system´ is a property and ´programming´ its value. The same way, ´information´ is another property and ´application´ its value.
I want to call my function with a property-value pair and update the txt file with the new property-value pairs.
Since you are updating a file you should open it in "append" mode. You use the sort function to sort your data. Assuming the variables property and propertyValue are cell arrays, your code would look something like this
function [] = updateFile( fileName,property,propertyValue )
% all inputs in strings
fid = fopen(fileName, 'a' ); % file handle
[property_sorted,sort_index] = sort(property); % sort file
for count = 1:length(sort_index)
fprintf(fid,'%s\n%s\n',property_sorted(count),propertyValue(sort_index(count)));
end
fclose(fid);
See the documentation for sort (doc sort) for more information.
Hi there I'm currently trying to find a way to save 2 variables from my workspace into a file. I want the file name to be put together using the original and the current date.
I only want the max value from the variables so:
max(streaking)
and
max(tap_total)
The original file name is:
3_FM001_02_05460$BandP$64_24000_FWD_1x1_PRI_PRI_PRI_PRI_15_17_ActivePixelMeans.csv
The only portion of this original file name that I would like to use is:
3_FM001_02_05460$BandP$64_24000_FWD_1x1
These can be saved in a text file or spreadsheet, it doesnt matter.
An example of the new file name would be something like this:
3_FM001_02_05460$BandP$64_24000_FWD_1x1_7-26-2012
Also,
If something could be done in the file to display which variable is which, for example:
Streaking: 1.272 % this would come from the variable max(streaking)
Tap_Total: 2.252 % this would come from the varaible max(tap_total)
EDIT:
% Construct a questdlg with three options
choice = questdlg('Would you like to save?', ...
'Save Options', ...
'Yes','No','Cancel','Cancel');
% Handle response
switch choice
case 'Yes'
disp([choice ' processing.'])
save_option = 1;
case 'No'
disp([choice ' processing.'])
save_option = 0;
case 'Cancel'
disp('Canceled.')
save_option = 2;
end
file_to_get = evalin( 'base', 'file_to_get' );
streaking = evalin( 'base', 'streaking' );
tap_total = evalin( 'base', 'tap_total' );
if save_option == 0
elseif save_option == 1
max_streak = max(streaking);
max_tap = max(tap_total);
str_streak = mat2str(max_streak);
str_tap = mat2str(max_tap);
fname = file_to_get;
pruned_fname = regexprep(fname,'_PRI(\w*).(\w*)','');
new_fname = [pruned_fname '_' date '.csv'];
path1 = '\\pfile01thn\bbruffey$\My Documents\analysis data\Banding and Streaking Results';
fid = fopen([path1 new_fname], 'w');
fprintf(fid,['Max Banding: %s\nMax Streaking: %s'],str_tap,str_streak)
fclose(fid);
elseif save_option == 2
end
This would be a great place to use the regexprep command to prune the original filename down.
Example:
fname = '3_FM001_02_05460$BandP$64_24000_FWD_1x1_PRI_PRI_PRI_PRI_15_17_ActivePixelMeans.csv';
pruned_fname = regexprep(fname,'_PRI(\w*).(\w*)','');
pruned_fname =
3_FM001_02_05460$BandP$64_24000_FWD_1x1
Now, a note about the regexprep command I used here. This is specific for the filename you provided here. Since it looks like you want to trim off everything after the the first _PRI I used a tag (\w*) which means any combination of [a-z A-Z _ 0-9] can follow. Notice that since this is a filename there is a . there hence why I added a period in and followed that with another (\w*) to finish out the csv. You can find more info on these sorts of operators here.
Now that you have the pruned_fname you can simply add whatever you want to it. So if you want to add the date in with an underscore to space it just simply do something like this:
new_fname = [pruned_fname '_' date '.csv'];
new_fname =
3_FM001_02_05460$BandP$64_24000_FWD_1x1csv_26-Jul-2012.csv
Now you simply need to open the file to write to it. you might need to append the path to where you want to save it, I'm just going to call it path for now. It would be something like C:\Documents\
fid = fopen([path new_fname], 'w')
Now with the fid you have the id of the file you want to write to. This should be a new file and if it isn't you are going to overwrite the file contents if you do it this way. Just be aware =)
Next you can simply write those first two lines to the file using fwrite fprintf, just to name a few possible functions.
Hopefully that'll get you setup there!