Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Managing arrays 2

Status
Not open for further replies.

robpbyw

Technical User
Mar 26, 2011
8
SE
Hi folks

I am a noob at Perl, but I want to write a script that will convert x,y,z cartesian coordinates from atomic units to angstroms, the conversion factor is %convfact in the script (see below). First, here is one line of the array holding the coordinates. I want to return the line as it is - the character at $column[0] unchanged, and the three coordinates each multiplied by %convfact. I've tried everything (like $column[1]*%convfact - but that is illegal, it seems). Any help welcome, I'm desperate now !!!

Line of input file:
C1 -8.52485691 6.79961254 4.40504608

Script:
use warnings;
use strict;

my $convfact = 0.529177239;
print $convfact;

my @records;
open FILE, "C0out.xyz" or die $!;
#we will read the file line by line
while(<FILE>)
{
# read each line in $_
# chomp the trailing newline from $_
chomp;
my @columns = split ", ", $_;
push @records, \@columns;
}

# print the array
foreach my $record(@records) {
foreach my $column(@{$record}) {

# test the last column

if(\$column == \$$record[-1]) {
print $column;
}
else {
print $column;
}
}
print "\n";
}
 
audiopro pointed out what is probably a bug. I suggest you try printing out your data structures at each step of your program to see if you can debug whatever is leading to problems. You simply need to include Data::Dumper

Code:
use Data::Dumper;

while(<FILE>) {
  # read each line in $_  
  # chomp the trailing newline from $_ 
  chomp;
  my @columns = split ", ", $_;
  print Dumper(\@columns);

This should help you debug your code.

- Miller
 
Thanks guys.

Good advice.

To be honest, I am not sure why I am splitting on the commas, because there are no commas in the input file ! But if I don't do that split (", "), the output is spewed out with the four items on each line concatenated into a single string (I'm aware that I can remedy that with \t or some kind of format statement, but I want to "keep it simple".)

The Dumper idea was a good one.

But what I really can't figure out is why I can't write (for example):

print $column[0],$column[1]*$convfact,$column[2]*$convfact,$column[3]*$convfact

i.e. why can't I do arithmetical operations on the variables on the fly?

Even if I write this:
print $column[0],$column[1],$column[2],$column[3]
I get an error message that I don't understand. Why is that illegal?

But anyway, that is not what I want. I want each of the three numerical
columns (the second, third and fourth columns (i.e. [1],[2] and [3])
to be converted into other units by multiplying by the conversion factor. surely, that should be simple in Perl

Thanx for any illumination of this problem.







 
What's the error that you get? Kind of a key piece of information

Also note, if things aren't behaving as you desire, always consider adding excessive parenthesis to be sure perl is doing what you want.

Code:
print $column[0] . ($column[1]*$convfact) . ($column[2]*$convfact) . ($column[3]*$convfact);
 
Thanx for prompt response.

I tried this
print ($column[0]),($column[1]),($column[2]),($column[3]);
and got these error messages:

$ perl convau2ang.pl
print (...) interpreted as function at convau2ang.pl line 29.
print (...) interpreted as function at convau2ang.pl line 32.
Global symbol "@column" requires explicit package name at convau2ang.pl line 29.
Global symbol "@column" requires explicit package name at convau2ang.pl line 29.
Global symbol "@column" requires explicit package name at convau2ang.pl line 29.
Global symbol "@column" requires explicit package name at convau2ang.pl line 29.
Global symbol "@column" requires explicit package name at convau2ang.pl line 32.
Global symbol "@column" requires explicit package name at convau2ang.pl line 32.
Global symbol "@column" requires explicit package name at convau2ang.pl line 32.
Global symbol "@column" requires explicit package name at convau2ang.pl line 32.
Execution of convau2ang.pl aborted due to compilation errors.
 
But if I don't do that split (", "), the output is spewed out with the four items on each line concatenated into a single string
If you don't do a split, the line will be returned as it appears in the file.
You need to split it on the space ie.
Code:
my @columns = split " ", $_;

Keith
 
OK.

I've removed the comma, and now split as you advise above.

But I get the same error messages as before.
 
That's a strictures error because you're using a variable out of spoke. Share all your code and we can help you with it. Please enclose your code in [&#91;]code] [&#91;]/code] tags.

- Miller
 
If it is not splitting on spaces, it might be an idea to show the file you are reading the data from.
I know you are a noob but don't let that worry you, from my experience, the guys here like a challenge and if you have a problem and are willing to do some of the work, they will help you all they can.

Keith
 
>Share all your code and we can help you with it.
Thanks.
> Please enclose your code in
Code:
tags.
Not sure what that means. The entire script is very short (37 lines) so I just reproduce it here. Following that, a truncated input file.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Code:

use warnings;
use strict;

## use Data::Dumper;

my $convfact = 0.529177239;
#print $convfact;

my @records;
open FILE, "C0out.xyz" or die $!;
#we will read the file line by line
while(<FILE>)
{
# read each line in $_
# chomp the trailing newline from $_
chomp;
my @columns = split " ", $_;
push @records, \@columns;
## print Dumper(\@columns);
}

# print the array
foreach my $record(@records) {
foreach my $column(@{$record}) {

# test the last column

if(\$column == \$$record[-1]) {
print ($column[0]),($column[1]),($column[2]),($column[3]);
}
else {
print ($column[0]),($column[1]),($column[2]),($column[3]);
# print $column;
}
}
print "\n";
}

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><

Truncated input file (called C0out.xyz in this case):

C1 -8.52485691 6.79961254 4.40504608
H2 -7.88476887 6.13913437 2.54434615
H3 -9.55052466 8.58691551 4.15832344
H4 -6.80690689 7.24934846 5.49133625
C5 -10.04740924 4.81364267 5.72430169
O6 -10.91226130 2.90781607 4.62604955
N7 -10.52176830 5.06038421 8.29191037
.
.
.
.
.
 
Without bothering to point out the problems with your code, it looks like you want something like the following, at least to start from:

Code:
use warnings;
use strict;

my $convfact = 0.529177239;
my $file = "C0out.xyz";

#open my $fh, $file or die $!;

my @records;
while (<DATA>) {
#while (<$fh>) {
	chomp;
	push @records, [split ' '];
}

foreach my $record (@records) {
	print "$record->[0] $record->[1] $record->[2] $record->[3]\n";
}

__DATA__
C1 -8.52485691 6.79961254 4.40504608
H2 -7.88476887 6.13913437 2.54434615
H3 -9.55052466 8.58691551 4.15832344
H4 -6.80690689 7.24934846 5.49133625
C5 -10.04740924 4.81364267 5.72430169
O6 -10.91226130 2.90781607 4.62604955
N7 -10.52176830 5.06038421 8.29191037
 
That looks much better. Thanks once again for your help.

I still need to do the multiplication ( on $record->, i= 1,2,3) )
so I tried this
print "$record->[0] ($record->[1])*($convfact) ($record->[2])*($convfact) ($record->[3])*($convfact)\n";

and got this, i.e. perl is not doing the sums for me:

C1 (-8.52485691)*(0.529177239) (6.79961254)*(0.529177239) (4.40504608)*(0.529177239)
H2 (-7.88476887)*(0.529177239) (6.13913437)*(0.529177239) (2.54434615)*(0.529177239)
H3 (-9.55052466)*(0.529177239) (8.58691551)*(0.529177239) (4.15832344)*(0.529177239)
H4 (-6.80690689)*(0.529177239) (7.24934846)*(0.529177239) (5.49133625)*(0.529177239)
C5 (-10.04740924)*(0.529177239) (4.81364267)*(0.529177239) (5.72430169)*(0.529177239)
O6 (-10.91226130)*(0.529177239) (2.90781607)*(0.529177239) (4.62604955)*(0.529177239)
N7 (-10.52176830)*(0.529177239) (5.06038421)*(0.529177239) (8.29191037)*(0.529177239)

 
That's because you're doing your math inside of a string. Gotta pull it out:

Code:
print "results = 5*8\n"; # results = 5*8
print "results = " . (5*8) . "\n"; # results = 40

- Miller
 
Getting close now.

But I'm sorry to be a pain.

This print line ( "$record->[0]" is a text string to be printed as it was read in, hence the " " ) >>>>

print "$record->[0]" . ($record->[1]*$convfact) ($record->[2]*$convfact) ($record->[3]*$convfact) . "\n";

still doesn't do the sums, I get;

$ perl newconv.pl
syntax error at newconv.pl line 18, near ") ("
Execution of newconv.pl aborted due to compilation errors.

So, I still haven't got the syntax right.

A general question, why $record->[1] (etc.) and not $record[1] ?

Sorry to be a pain, but thanks to your help, I feel it's getting close now.



 
Success !!

Big thanx to MillerH and audiopro

Did calcs before the print command & got the syntax right at last.

robpbyw
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top