Popen samtools not running - subprocess

I am writing a function of a class to convert a sam file to bam file, then sort it and index it in python (I know it is easy to fulfill in bash, but it does not hurt to learn more).
A sam file has already been generated in the defined directory (cwd) by another function of the class already.
Here is the code:
def sam2bam(self):
"""
return a sorted and index bam file in the working directory
"""
if str(self.fq)[7:9] == '24':
# create bam
comnd = "samtools view -bS " + str(self.fq)[0:10] + ".sam > " + str(self.fq)[0:10] + ".bam"
print("Converting sam to bam ... (executed command: {})\n".format(comnd))
comnd_input = shlex.split(comnd)
with open((str(self.fq)[0:10] + '.bam'), 'w') as f:
Popen(comnd_input, stdout = f, stderr = PIPE, cwd = 'G24/' + str(self.fq))
# sort bam
comnd2 = "samtools sort " + str(self.fq)[0:10] + ".bam -o " + str(self.fq)[0:10] + ".sorted.bam"
print('Sorting bam ... (executed command: {}\n)'.format(comnd2))
comnd_input2 = shlex.split(comnd2)
with open((str(self.fq)[0:10] + 'sorted.bam'), 'w') as f_sort:
Popen(comnd_input2, stdout = f_sort, stderr = PIPE, cwd = 'G24/' + str(self.fq))
# index bam
comnd3 = "samtools index " + str(self.fq)[0:10] + ".sorted.bam"
print('Indexing bam ... (executed command: {}\n)'.format(comnd3))
comnd_input3 = shlex.split(comnd3)
with open((str(self.fq)[0:10] + 'sorted.bam'), 'w') as f_index:
Popen(comnd_input3, stdout = f_index, stderr = PIPE, cwd = 'G24/' + str(self.fq))
But nothing came out
I tried:
Popen(comnd_input, stdout = PIPE, stderr = PIPE, cwd = 'G24/' + str(self.fq))
yet nothing either. Tried save it as a variable and do .communicate(), nothing.
So I don't know what wrong I did?
thanks,
Xp

refer to here.
It is because of the '>' redirecting. I modified the code to:
Popen(comnd, stdout = PIPE, stderr = PIPE, shell = True, cwd = 'G14/' + str(self.fq))
And it worked.

Related

Returning from /bin/sh Functions

I've written a lot of Bash, but I now need to port some of my code into /bin/sh, and I'm observing strange behavior.
I have a function:
path_exists() {
path="$1" && shift
echo "$PATH" | tr ':' '\n' | while read path_entry ; do
test "$path" = "$path_entry" && return 0
done
return 1
}
I'm calling it like so:
if path_exists "/usr/bin" ; then
echo "it exists"
else
echo "it does not exist"
fi
If I run it with set -x, I see that return codes are overwritten:
+ path_exists /usr/bin
+ path=/usr/bin
+ shift
+ echo /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
+ tr : \n
+ read path_entry
+ test /usr/bin = /usr/local/sbin
+ read path_entry
+ test /usr/bin = /usr/local/bin
+ read path_entry
+ test /usr/bin = /usr/sbin
+ read path_entry
+ test /usr/bin = /usr/bin
+ return 0
+ return 1
+ echo it does not exist
Why is my function not respecting my return codes?
Why is my function not respecting my return codes?
Because pipe spawns a subshell, and you are only returning from a subshell. The same way:
echo | exit 0
will not exit your shell, only exit from | { the subshell on the right side of pipe; }. Or the same way func() { ( return 1; echo 123; ); return 0; }; func - the return 1 only affects the subshell.
The behavior is the same in ash, dash and in bash, but I think in POSIX sh it would be unspecified.
Aaaaanyway:
path_exists() {
case ":$PATH:" in
*:"$1":*) ;;
*) false; ;;
esac
}

Subprocess.Popen system can't find the file

I'm not sure why subprocess can't find my file. I keep getting this error
WindowsError: [Error 2] The system cannot find the file specified
Here is my code:
import subprocess
from subprocess import PIPE
file= r'C:\Users\NIA\Desktop\2.py'
x = 'python' + file + str(7) + str(8)
process = subprocess.Popen([x], stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
if stderr:
print stderr
else:
print stdout

Could not read from the file with contents of 'stdout=file_object' in python

I was trying to experiment with subprocess.Popen() constructor by using file object for the stdout. When I run the below code, the file gets created (with the contents) but contents are not displayed on the console. I cannot understand what I am missing. Can anyone please point out my mistake(if any)?
file_name = "abc.txt"
fo = open(file_name, 'w')
cmd = 'dir'
child = subprocess.Popen(cmd, stdout=fo, stderr=fo, shell=True)
fo.close()
with open(file_name, 'r') as fo: print(fo.read())
You have to wait for subprocess finish before reading the content.
#!/usr/bin/env python
import subprocess
file_name = "abc.txt"
fo = open(file_name, 'w')
cmd = 'dir'
child = subprocess.Popen(cmd, stdout=fo, stderr=fo, shell=True)
child.wait()
fo.flush()
fo.close()
with open(file_name) as fo:
print(fo.read())
# print (child.poll())

Extracting information from a .gtf to a new text file using PERL

I have the the below .gtf file, i need to extract only 4 variables (chromosome, start/stop codon and transcripst i.d.
1 Cufflinks transcript 11869 14412 1000 + . gene_id "CUFF.1"; transcript_id "CUFF.1.2"; FPKM "0.3750000000"; frac "0.000000"; conf_lo "0.375000"; conf_hi "0.375000"; cov "1.470346"; full_read_support "yes";
1 Cufflinks transcript 11869 14412 444 + . gene_id "CUFF.1"; transcript_id "CUFF.1.3"; FPKM "0.1666666667"; frac "0.000000"; conf_lo "0.166667"; conf_hi "0.166667"; cov "0.653487"; full_read_support "yes";
2 Cufflinks transcript 11869 14412 333 + . gene_id "CUFF.1"; transcript_id "CUFF.1.4"; FPKM "0.1250000000"; frac "0.000000"; conf_lo "0.125000"; conf_hi "0.125000"; cov "0.490115"; full_read_support "yes";**
My questions is how does a script know to work on a selected file?
Do you used:
(1) my $file = 'transcripts_selected.gtf'
(2) Also can this script be used to extract the sected data:
say $data->{"chromosome_number"}->{"start_codon"}->{"stop_codon"}->{"transcript_id"};
or should:
BioSeq->new(-chromosome_number, -start_codon...) method be used?
(3) Finally this scripts is taken from the BioperlHOWTO:
my $seq_in = Bio::SeqIO->new( -file => "<$infile", -format => $infileformat,);
my $seq_out = Bio::SeqIO->new( -file => ">$outfile", -format => $outfileformat,);
while (my $inseq = $seq_in->next_seq) {$seq_out->write_seq($inseq);
where is says the variables $infile/$outfile should the name of the .gtf file be placed here and the name of the new file with selected data replace $outfile?
the easiest way to specify the filenames is to write something like:
my $infile = shift;
my $outfile = shift;
above the code block from the HOWTO, then type:
perl ScriptName transcripts_selected.gtf OutFileName
at the command line

Copying a string(passed as command line arguments to Perl) into text file

I have a string containing lots of text with white-spaces like:
String str = "abc xyz def";
I am now passing this string as a command line argument to a perl file using C# as in:
Process p = new Process();
p.StartInfo.FileName = "c:\\perl\\bin\\perl.exe";
p.StartInfo.Arguments = "c:\\root\\run_cmd.pl " + str + " " + text_file;
In the run_cmd.pl file, I have the follwing:
open FILE, ">$ARGV[1]" or die "Failed opening file";
print FILE $ARGV[0];
close FILE;
On printing, I am able to copy only part of the string i.e. "abc" into text_file since Perl interprets it as a single argument.
My question is, is it possible for me to copy the entire string into the text file including the white spaces?
If you want a white space separated argument treated as a single argument, with most programs, you need to surround it with " "
e.g run_cmd.pl "abc xyz def" filename
Try
p.StartInfo.Arguments = "c:\\root\\run_cmd.pl \"" + str + "\" " + text_file;
Side note:
I don't know about windows, but in Linux there's a number of arguments and maximum length of one argument limit so you might want to consider passing the string some other way, reading it from a tmp file for example.
It's a little bit of a hack, but
$ARGV[$#ARGV]
would be the last item in #ARGV, and
#ARGV[0 .. ($#ARGV - 1)]
would be everything before that.
It's not perl -- it's your shell. You need to put quotes around the arguments:
p.StartInfo.Arguments = "c:\\root\\run_cmd.pl '" + str + "' " + text_file;
If text_file comes from user input, you'll likely want to quote that, too.
(You'll also need to escape any existing quotes in str or text_file; I'm not sure what the proper way to escape a quote in Windows is)
#meidwar said: "you might want to consider passing the string some other way, reading it from a tmp file for example"
I'll suggest you look into a piped-open. See http://search.cpan.org/~jhi/perl-5.8.0/pod/perlopentut.pod#Pipe_Opens and http://perldoc.perl.org/perlipc.html#Using-open()-for-IPC
These let you send as much data as your called code can handle and are not subject to limitations of the OS's command-line.