How to make a .m file read an input csv file passed as a parameter? - linux

I am new in Matlab and facing difficulty in making a .m file read the input csv file that I am passing as an argument from the command prompt. I understand that a function has to be written to read the input file as a parameter. Here is the code I wrote inside the .m file to accept the input file:
function data=input(filename);
addpath(genpath('./matlab_and_R_scripts'));
tic
D=csvread(filename,1,1);
I want the filename passed as an argument to be read by the function "csvread" and save it in D. I am using the following command to execute the script:
matlab -nodisplay -nosplash -nodesktop -r "input 'exp2_1_DMatrix.csv';run('matlab_filename.m');exit;"
I am able to execute the script without any errors but it is not reading the input file as the downstream analysis should have saved a new file if it was able to read the file and execute some functions on it.
Can anyone please suggest how to read the input file in my matlab script and the proper command to pass?

Try using this function. Take care on not using reserved names:
readdat.m
function data=readdat(filename);
addpath(genpath('./matlab_and_R_scripts'));
tic;
data=csvread(filename,1,1);
toc;
For testing, you can execute this function directly in the Command Window and editing in the Matlab Editor, which is where most functions, most of the time, are tested until you are fully satisfied with your processing.
>> data=readdat(filename);
Looking at data you can realize if the file was or not read as it should.
>> data(:,1)
You can keep running other scripts, such as matlab_filename.m. But the best choice is having a function working with everything:
processdat.m
function data=processdat(filename)
% Original Function
addpath(genpath('./matlab_and_R_scripts'));
tic;
data=csvread(filename,1,1);
toc;
% Paste in here all the matlab_filename.m code, or do a call:
matlab_filename;
% Do not uncomment this exit in here, since you want to keep working until the function do what you need
% exit;
Later, if you want some serious automation and want some programming tasks having repetitions of your code under some schedule, you can of course arrange a Windows bat command, and in this case, you can uncomment that exit; terminator at the end of processdat.m.
processdat.bat
matlab -nodisplay -nosplash -nodesktop -r processdat
Remember to ensure the OS can access matlab, and that Matlab can access processdat. If in doubt, place the proper paths:
processdat.bat
c\programs\bin\matlab -nodisplay -nosplash -nodesktop -r c\files\processdat.m

I solved the problem by gaining some insight from #Brethlosze's answer. If you want to avoid a local function then function shouldn't have a name but start with an []. Here is what I did to pass an input argument in my myScript.m script:
function [] = myScript(input_file, output_file)
addpath(genpath('../matlab_and_R_scripts'));
tic
D=csvread(input_file,1,1);
% Some code operations
save(output_file,'save_what_you_want')
toc
end
And I executed the script from command line using the following command:
matlab -nodisplay -nosplash -nodesktop -r "myScript 'example.csv' 'example.mat'"
The input_file is 'example.csv' and output_file is 'example.mat'.

Related

invoking function with txt file input using GNU parallel

I want to use shell script function like below using gnu parallel.
This is part of my code.
#!/bin/bash
# Figure out script absolute path
pushd `dirname $0` > /dev/null
BIN_DIR=`pwd`
popd > /dev/null
ROOT_DIR=`dirname $BIN_DIR`
export ROOT_DIR
CLASS_NAME=$3
export CLASS_NAME
invoke_driver() {
$ROOT_DIR/DRIVER_DIR $CLASS_NAME $1
}
export -f invoke_driver
parallel invoke_driver :::: 'method_list.txt'
In 'method_list.txt' file, name of method is listed line by line like below.
method1
method2
...
Driver file only gets two arguments as input.
Driver in this code is fuzzing tool which runs endlessly.
So I want to give function each method as input and run this tool in parallel.
For example, if there are 3 methods in a txt file, I would like to write code that fuzzes each method in parallel.
But when I run this code, error occurs.
So please let me know how to solve this problem.

os.system(cmd) call fails with redirection operator

My Python 3.7.1 script generates a fasta file called
pRNA.sites.fasta
Within the same script, I call following system command:
cmd = "weblogo -A DNA < pRNA.sites.fasta > OUT.eps"
os.system(cmd)
print(cmd) #for debugging
I am getting the following error message and debugging message on the command line.
Error: Please provide a multiple sequence alignment
weblogo -A DNA < pRNA.sites.fasta > OUT.eps
"OUT.eps" file is generated but it's emtpy. On the other hand, if I run the following 'weblogo' command from the command line, It works just find. I get proper OUT.eps file.
$ weblogo -A DNA<pRNA.sites.fasta>OUT.eps
I am guessing my syntax for os.system call is wrong. Can you tell me what is wrong with it? Thanks.
Never mind. It turned out to be that I was not closing my file, "pRNA.sites.fasta" before I make system call that uses this file.

How to understand and avoid non-interactive mode errors when running ispell from script?

Background
Ispell is a basic command line spelling program in linux, which I want to call for a previously collected list of file names. These file names are recursively collected from a latex root file for example. This is usefull when requiring to spell all recursively included latex files, and no other files. However, calling ispell from the command line turns out to be non-trivial as ispell gives errors of the form
"Can't deal with non-interactive use yet." in some cases.
(As a side not, ideally I would like to call ispell programmatically from java using the ProcessBuilder class, and without requiring bash. The same error seems to pester this approach however.)
Question
Why is it that ispell gives the error "Can't deal with non-interactive use yet." in certain cases, when called in bash from a loop involving the read method, but not in other cases, as shown in the below code example?
The below minimal code example creates two small files
(testFileOne.txt, testFileTwo.txt) and a file containing the paths of the two created files (testFilesListTemp.txt).
Next, ispell is called for testFilesListTemp.txt in three different ways:
1. With the help of "cat"
2. By first collecting the names as a string, then looping over the substrings in the collected string, and calling ispell for each of them.
3. By looping over the contents of testFilesListTemp.txt directly, and
calling ispell for the extracted paths.
For some reaons the third method does not work, and yields an error
"Can't deal with non-interactive use yet.". Why exactly does this error
occur, and how can it be prevented, and/or is there perhaps another variation
of the third approach that would work without errors?
#!/bin/bash
#ispell ./testFiles/ispellTestFile1.txt
# Creating two small files and a file with file paths for testing
printf "file 1 contents" > testFileOne.txt
printf "file 2 contents. With a spelling eeeeror." > testFileTwo.txt
printf "./testFileOne.txt\n./testFileTwo.txt\n" > testFilesListTemp.txt
COLLECTED_LATEX_FILE_NAMES_FILE=testFilesListTemp.txt
# Approach 1: produce list of file names with cat and
# pass as argumentto ispell
# WORKS
ispell $(cat $COLLECTED_LATEX_FILE_NAMES_FILE)
# Second approach, first collecting file names as long string,
# then looping over substrings and calling ispell for each one of them
FILES=""
while read p; do
echo "read file $p"
FILES="$FILES $p"
done < $COLLECTED_LATEX_FILE_NAMES_FILE
printf "files list: $FILES\n"
for latexName in $FILES; do
echo "filename: $latexName"
ispell $latexName
done
# Third approach, not working
# ispell compmlains in this case about not working in non-interactive
# mode
#: "Can't deal with non-interactive use yet."
while read p; do
ispell "$p"
done < $COLLECTED_LATEX_FILE_NAMES_FILE
The third example does not work, because you redirect standard input. ispell needs a terminal and a user interaction. When you write code like this:
while read p; do
ispell "$p"
done < $COLLECTED_LATEX_FILE_NAMES_FILE
everything that is read from standard input by any program within the loop will be taken from the $COLLECTED_LATEX_FILE_NAMES_FILE file. ispell detects that and refuses operating. However, you can use "description redirection" to make read p read from the file, and ispell "$p" read from the "real" terminal. Just do:
exec 3<&0
while read p; do
ispell "$p" 0<&3
done < $COLLECTED_LATEX_FILE_NAMES_FILE
exec 3<&0 "copies" (saves) your standard input (0, the "terminal") to descriptor 3. And later on you redirect standard input (0) to ispell from that descriptor, by typing 0<&3 (you can omit 0 if you like).

Missing something in the linux terminal after launching matlab from the command line

I'm having a weird behaviour when launching matlab from the command line in linux.
I've a bash script in linux that execute a function in matlab from the command line and does other operations with custom functions written in C++ as follows:
#!/bin/bash
# prepare input data just to be sure it has not been written by other test!
matlab2011a -nodesktop -nosplash -r "prepare_data_matlab( 'A' ); quit"
# launch C++ program
...
# prepare more data
matlab2011a -nodesktop -nosplash -r "prepare_data_matlab( 'B' ); quit"
When the script is finished I can not see what I'm writing in the terminal, although the commands have effects. I need to reset the terminal.
The fact is that everything works fine if I only launch matlab with the prepare_data_matlab( 'A' ) but the problem comes when I execute the function with option prepare_data_matlab( 'B' ).
I have commented line by line and found that the problem is with option B that call the function
dlmwrite(file_name, B, ' ');
which is not used in prepare_data_matlab( 'A' ).
So, how should I execute the matlab from the command line to avoid this behaviour? Is there a known bug with the dlmwrite() function?
I'm using Ubuntu 12.04 64 bits, GNU bash, versiĆ³n 4.2.24(1)-release (x86_64-pc-linux-gnu) and matlab2011a.
EDITED: The output generated for prepare_data_matlab( 'A' ) is
The output generated for prepare_data_matlab( 'B' ) is
EDITED: file_name is created as strcat(path_to_data,f); where path_to_data = /tmp/ and f = data_out.txt. Matrix B is not displayed before or after.
The only output to the terminal before or after the MATLAB script is generated from the bash script as follow:
echo "#### SELECT DATA FROM WORKSPACE ####"
matlab2011a -nodesktop -nosplash -r "prepare_data_matlab( 'B' ); quit";
echo "#### Process Data as input in a C++ programs ####"
The MATLAB function select data from the workscape and save it to disk as follows:
function [ ] = prepare_data_matlab( type )
if strcmp(type,'A')
% load data from workscape
load ('workspace_with_my_arrays.mat', 'A');
% save data as a standalone variable
save('/tmp/A.mat', 'A');
elseif strcmp(type,'B')
% load data from workscape
load ('workspace_with_my_arrays.mat', 'B');
path_to_data = '/tmp/';
f = 'data_out.txt';
file_name = strcat(path_to_data,f);
% save data as a txt file
dlmwrite(file_name, B, ' ');
end
end
EDITED: whos -file workspace_with_my_arrays.mat
Name Size Bytes Class Attributes
A 610x340x103 170897600 double
B 610x340x103 170897600 double
P 610x340 1659200 double
t1 38855x100 31084000 double
t2 3921x2x100 6273600 double
There are more arrays in the workspace but those are which I load.
The prepare_data_matlab function is the same as posted above but with an argument error checking as follow:
%% Load data from file
% Data is saved in a MATLAB variable or in TXT
if nargin ~= 1
error('Use: prepare_data_matlab( [ A | B ] )')
end
and the following command:
cd /data/matlab;
which is executed after the arguments error check in both cases (option Aand option B), that is, before the if statement.
The problem is not with dlmwrite. This seems to be a bug in some versions of MATLAB, as reported in this link.
The proposed solution (if you have a buggy version of MATLAB) is to use nohup:
nohup matlab -nodesktop -nosplash -r ...........
UPDATE:
Per #Amro 's suggestion, #pQB reported the problem to MathWorks Support. Their response was:
The problem is a known issue in versions prior to R2012a. Run MATLAB under a different shell. For example, neither tcsh or zsh have this issue.
OLD answer:
The problem is not with dlmwrite, but with the content of your matrix. Furthermore, unless file_name points to stdout (e.g., file_name='/dev/stdout';), the dlmwrite function will not write anything to screen and will not mess your terminal. Either file_name points to stdout or you are displaying the matrix B right before (or after) the dlmwrite call.
In any case, the problem is with the contents of your matrix B (see the strange characters in your output). You need to fix the problem with your matrix B. Perhaps the method you are using to read its input data is faulty.
If you want to ignore output from MATLAB (like the banner printed at the beginning), launch the process and redirect both the standard input and error to /dev/null device:
#!/bin/sh
echo '### running MATLAB ###'
matlab -nodesktop -nosplash -r "..." > /dev/null 2>&1
echo '### done ###'
./other_script.sh
matlab -nodesktop -nosplash -r "..." > /dev/null 2>&1
Note that you should be careful since MATLAB process returns immediately possibly before it has finished running, which could cause problems if your next program depends on files produced by MATLAB. See here for a possible solution.

How do I make a Perl script stop when running Matlab code fails?

I would like to make the Perl script run some Matlab code, then wait, then run another Matlab code in Linux. If the Matlab code fails, then it should give an error message. The Perl script below would run through even when Matlab code 1 or 2 has an error. How do I make the Perl script stop and give an error message when the Matlab codes fails?
print("run Matlab code 1!\n");
`matlab -nodisplay -r myfile1`;
print("run Matlab code 2!\n");
`matlab -nodisplay -r myfile2`;
print("End!\n");
First, store the return code of the command you are running:
my $returnCode = system("matlab -nodisplay -r myfile1");
Then, before you move to the next step, make sure the return code is 0 (or whatever indicates success in your case):
if ($returnCode != 0) {
die "Command did not finish successfully.";
}
Just determine what is a valid return code and tell the script to die in any other case.

Resources