Ich bin Student in einem Einführungskurs in Perl und suche nach Vorschlägen und Feedback zu meinem Ansatz, ein kleines (aber kniffliges) Programm zu schreiben, das Daten über Atome analysiert. Mein Professor ermutigt zu Foren. Ich habe keine Erfahrung mit Perl-Subs oder -Modulen (einschließlich Bioperl), also beschränken Sie Ihre Antworten bitte auf ein angemessenes "Anfängerniveau", damit ich Ihre Vorschläge und/oder Ihren Code verstehen und daraus lernen kann (bitte beschränken Sie auch "Magic").
Die Anforderungen des Programms sind wie folgt:
Liest eine Datei (mit Daten über Atome) aus der Befehlszeile und erstellt ein Array von Atomdatensätzen (ein Datensatz/Atom pro Zeilenumbruch). Für jeden Datensatz muss das Programm speichern:
- Die Seriennummer des Atoms (Spalten 7 - 11)
- Der aus drei Buchstaben bestehende Name der Aminosäure, zu der sie gehört (Spalten 18 - 20)
- Die drei Koordinaten des Atoms (x, y, z) (Spalten 31 - 54)
- Die ein- oder zweibuchstabige Elementbezeichnung des Atoms (z. B. C, O, N, Na) (Spalten 77-78)Aufforderung zur Eingabe eines von drei Befehlen: freq, length, density d (d ist eine Zahl):
- freq - wie viele Atome jeder Art in der Datei enthalten sind (z. B. Stickstoff, Natrium usw. würden wie folgt angezeigt werden: N: 918 S: 23
- Länge - Die Abstände zwischen den Koordinaten
- Dichte d (wobei d eine Zahl ist) - das Programm fragt nach dem Namen einer Datei, in der die Berechnungen gespeichert werden sollen und die den Abstand zwischen diesem Atom und jedem anderen Atom enthält. Wenn dieser Abstand kleiner oder gleich der Zahl d ist, wird die Anzahl der Atome, die sich innerhalb dieses Abstands befinden, in der Datei erhöht, es sei denn, diese Anzahl ist Null. Die Ausgabe sieht dann etwa so aus:
1: 5
2: 3
3: 6
... (sehr große Datei) und wird geschlossen, wenn sie fertig ist.
Ich bin auf der Suche nach Feedback zu dem, was ich im untenstehenden Code geschrieben habe (und schreiben muss). Ich freue mich besonders über jede Rückmeldung, wie ich beim Schreiben meiner Unterprogramme vorgehen soll. Ich habe unten ein Beispiel für die Eingabedaten angefügt.
Die Programmstruktur und Funktionsbeschreibungen, wie ich sie sehe:
$^W = 1; # turn on warnings
use strict; # behave!
my @fields;
my @recs;
while ( <DATA> ) {
chomp;
@fields = split(/\s+/);
push @recs, makeRecord(@fields);
}
for (my $i = 0; $i < @recs; $i++) {
printRec( $recs[$i] );
}
my %command_table = (
freq => \&freq,
length => \&length,
density => \&density,
help => \&help,
quit => \&quit
);
print "Enter a command: ";
while ( <STDIN> ) {
chomp;
my @line = split( /\s+/);
my $command = shift @line;
if ($command !~ /^freq$|^density$|length|^help$|^quit$/ ) {
print "Command must be: freq, length, density or quit\n";
}
else {
$command_table{$command}->();
}
print "Enter a command: ";
}
sub makeRecord
# Read the entire line and make records from the lines that contain the
# word ATOM or HETATM in the first column. Not sure how to do this:
{
my %record =
(
serialnumber => shift,
aminoacid => shift,
coordinates => shift,
element => [ @_ ]
);
return\%record;
}
sub freq
# take an array of atom records, return a hash whose keys are
# distinct atom names and whose values are the frequences of
# these atoms in the array.
sub length
# take an array of atom records and return the max distance
# between all pairs of atoms in that array. My instructor
# advised this would be constructed as a for loop inside a for loop.
sub density
# take an array of atom records and a number d and will return a
# hash whose keys are atom serial numbers and whose values are
# the number of atoms within that distance from the atom with that
# serial number.
sub help
{
print "To use this program, type either\n",
"freq\n",
"length\n",
"density followed by a number, d,\n",
"help\n",
"quit\n";
}
sub quit
{
exit 0;
}
# truncating for testing purposes. Actual data is aprox. 100 columns
# and starts with ATOM or HETATM.
__DATA__
ATOM 4743 CG GLN A 704 19.896 32.017 54.717 1.00 66.44 C
ATOM 4744 CD GLN A 704 19.589 30.757 55.525 1.00 73.28 C
ATOM 4745 OE1 GLN A 704 18.801 29.892 55.098 1.00 75.91 O