3

I'm generating 3D coordinates (x,y,z) to a file with the following code.

for (my $x = 0.000; $x < 4.200; $x += 1.400) {
    for (my $y = 0.000; $y < 4.200; $y += 1.400) {
        for (my $z = 0.000; $z < 4.200; $z += 1.400) {
            push @arr_grid, "$x  $y  $z\n";
        }
    }
}  
foreach (@arr_grid) {
    say "HETATM 1 O  HOH  1  $_   O";
}

Now, my problem is that I want to get the output with a precise format (PDB) with Index values like,

1-6    7-11 13-16 18-20 23-26    31-38   39-46    47-54                      77-78  
(Name) (S.No)                     (x)     (y)      (z)
HETATM    1  O    HOH     1      -8.863  16.944  14.289                       N  
HETATM  100  O    HOH    16     -15.352  11.525   5.325                       N  
HETATM  117  O    HOH    16     -12.954   9.717   5.182                       C  
HETATM  126  O    HOH    17     -19.225  11.667  -0.391                       C  
HETATM 1005  O    HOH    97       9.246  23.287  11.503                       O  

Here the x,y,z coordinates shoulb be of data type real(8.2) and others are right justified. x,y,z values are not those generated from program. I placed arbitrary values. Please help me.

3
  • I don't understand your question. Perl isn't a strictly typed language, so it doesn't natively have a concept of "data type real". Commented Jan 8, 2012 at 3:04
  • @JackManey, que is i want to get output as i shown, i haf mentioned index values on the first line, i dont need first two lines in output. just to make understand , i have written first two lines. Commented Jan 8, 2012 at 3:12
  • There are a few perl modules that read/write PDB files. Take a look at metacpan.org/module/Chemistry::File::PDB Commented Jan 8, 2012 at 3:28

3 Answers 3

4

You want to use perl's format options for presenting output data in predefined ways.

You can read about it here.

Your example, rewritten a bit:

for ($x = 0.000; $x < 4.200; $x += 1.400) {
    for ($y = 0.000; $y < 4.200; $y += 1.400) {
        for ($z = 0.000; $z < 4.200; $z += 1.400) {
        write;
        }
    }
}

format STDOUT_TOP =
1-6    7-11 13-16 18-20 23-26    31-38   39-46    47-54                      77-78
(Name) (S.No)                     (x)     (y)      (z)
.

format STDOUT =
HETATM    1  O    HOH     1      @<<<<<< @<<<<<<  @<<<<<<                     N
                                 $x      $y       $z
.

The FORMAT_TOP is printed every $= (or $FORMAT_LINES_PER_PAGE) so reset this variable if you want it printed more rarely or a ridiculously high number if you want it printed only once.

Output example:

1-6    7-11 13-16 18-20 23-26    31-38   39-46    47-54                      77-78
(Name) (S.No)                     (x)     (y)      (z)
HETATM    1  O    HOH     1      0       0        0                           N
HETATM    1  O    HOH     1      0       0        1.4                         N
HETATM    1  O    HOH     1      0       0        2.8                         N
HETATM    1  O    HOH     1      0       0        4.2                         N
HETATM    1  O    HOH     1      0       1.4      0                           N
HETATM    1  O    HOH     1      0       1.4      1.4                         N
HETATM    1  O    HOH     1      0       1.4      2.8                         N
HETATM    1  O    HOH     1      0       1.4      4.2                         N

I have got one more problem: when I'm printing numbers with decimal points like

HETATM    1  O    HOH     1      -10     -3.4    -8                          N
HETATM    1  O    HOH     1      -10     -3.4    -6.6                        N
HETATM    1  O    HOH     1      -10     -3.4    -5.2                        N
HETATM    1  O    HOH     1      -10     -3.4    -3.8                        N
HETATM    1  O    HOH     1      -10     -3.4    -2.4                        N
HETATM    1  O    HOH     1      -10     -3.4    -1                          N
HETATM    1  O    HOH     1      -10     -3.4    0.4                         N
HETATM    1  O    HOH     1      -10     -3.4    1.8                         N
HETATM    1  O    HOH     1      -10     -3.4    3.2                         N
HETATM    1  O    HOH     1      -10     -3.4    4.6                         N
HETATM    1  O    HOH     1      0     -3.4    6                           N

In the above columns, I need to print the dot of decimal in the same index. When I'm doing calculations and updating values, the dots in decimals are shifting. i need output like

HETATM    1  O    HOH     1      -10     -3.4    -8.0                        N
HETATM    1  O    HOH     1      -10     -3.4    -6.6                        N
HETATM    1  O    HOH     1      -10     -3.4    -5.2                        N
HETATM    1  O    HOH     1      -10     -3.4    -3.8                        N
HETATM    1  O    HOH     1      -10     -3.4    -2.4                        N
HETATM    1  O    HOH     1      -10     -3.4    -1.0                        N
HETATM    1  O    HOH     1      -10     -3.4     0.4                        N
HETATM    1  O    HOH     1      -10     -3.4     1.8                        N
HETATM    1  O    HOH     1      -10     -3.4     3.2                        N
HETATM    1  O    HOH     1      -10     -3.4     4.6                        N
HETATM    1  O    HOH     1      -10     -3.4     6.0                        N

Edit 1:
Example to a dumpfile:

open(DUMPFILE,">output.txt");

for ($x = 0.000; $x < 4.200; $x += 1.400) {
    for ($y = 0.000; $y < 4.200; $y += 1.400) {
        for ($z = 0.000; $z < 4.200; $z += 1.400) {
        write DUMPFILE;
        }
    }
}

close(DUMPFILE);


format DUMPFILE_TOP =
1-6    7-11 13-16 18-20 23-26    31-38   39-46    47-54                      77-78
(Name) (S.No)                     (x)     (y)      (z)
.

format DUMPFILE =
HETATM    1  O    HOH     1      @<<<<<< @<<<<<<  @<<<<<<                     N
                                 $x      $y       $z
.
Sign up to request clarification or add additional context in comments.

4 Comments

+1 for formats, an underused Perl feature, and possibly exactly the right tool here
I hear Perl6::Form (Perl6-style forms for Perl5) are much better than the builtin ones.
@Mattias , How to write this form output to a File ? like output.txt other than program>>output.txt
I updated the answer with an example that outputs the result to a file instead of STDOUT; you open a file, define the FORMAT to go to that filehandle, then write the output to the FILEHANDLE. In my example I've left out all kinds of error handling that you might normally want to add, so its a bit quick'n'dirty but works. :)
1

Presumably, you could replace the existing:

        push @arr_grid, "$x  $y  $z\n";

with some suitable variation of:

        push @arr_grid, sprintf("%8.2f  %8.2f  %8.2f\n", $x, $y, $z);

This gives you control over the format of the numbers.

Comments

1

You can use printf to specify spacing, alignment, and significant digits. Something like this might work:

my @arr_grid;
for (my $x = 0.000; $x < 4.200; $x += 1.400) {
    for (my $y = 0.000; $y < 4.200; $y += 1.400) {
        for (my $z = 0.000; $z < 4.200; $z += 1.400) {
            push @arr_grid, [$x, $y, $z];
        }
    }
} 
foreach (@arr_grid) {
    printf "HETATM%5d %2s%2s HOH     1    %8.3f%8.3f%8.3f\n", 1, 'O', '', @$_;
}

It might might make more sense though to use a perl module designed for the PDB format such as Chemistry::File::PDB or Bio::Structure::IO::pdb

2 Comments

@gthmgeeky, its a good thing to try, but as you go notice that some special cases (often called corner cases) can get very tricky. This same thing occurs for comma separated (csv) data; it seems like it should be easy, but its not. Once you have had fun learning, usually its best to take advantage of available modules as they often have dealt with all the corner cases for you.
@JoelBerger..I have no prob in using modules, but i have one doubt that, what ever the code im generating, if the other person dint have modules, the he faces problem in executing the code. Thats why i want to generate clean code that do not depend on modules.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.