user1640402
user1640402

Reputation: 1

How to extract the required lines from a file using TCL?

My file looks like this below. I want to extract only id, pos and type from file so that I can use it further. Should I need to treat this data as a list and use lindex syntax to retrieve.

{particles {id pos type v f} {0 442.3601602032813 775.8494355067412 339.7428247245854 0 -1.0649468656691174 0.3118359585805807 0.7974629587243917 -7.856415738784473 120.82920096524781 80.7680149353967} {1 75.78431491144367 187.28007812237516 279.3569202413006 0 0.3317344469183915 3.0716559473604916 -1.679965732986453 2.573367640795655 -11.46026754809828 125.75306472245369} {2 44.167251258358164 371.8839725825084 80.32709197838003 0 -0.6260768510694417 0.9493261445672099 0.9445444874655268 -98.8132600015945 -80.10617403827258 43.578514821777155} {3 289.0168944249348 193.4364952458922 96.30251497465443 0 -0.5327035586676473 1.028492567403681 4.364969924730662 139.09290151549465 75.46717320097427 -29.955066397359094} {4 324.94257366360085 404.9215380451672 799.3481016151578 0 -1.2801842708841038 -4.320355658821216 2.9394195915181567 -109.72971491904342 -44.06068452005151 118.2802261191011} {5 598.4521733790556 447.74320547029174 750.4399422142899 0 1.740414834859398 -0.5926143788565617 1.5937397085063156 -155.08309023301794 186.08101953841978 177.1804659692657} }

This is the code I have used below. Can anyone tel me the code which I used is correct or not.

set num_part 6
set mol1 0.1666
set mol2 0.8333
set num_conf 2
for {set i 0} {$i < $num_conf} {incr i} {
set f [open "config_$i" "r"]
set part [while { [blockfile $f read auto] != "eof" } {} ]
set g [open "positions" "w"]
blockfile $g write particles {id pos type}
close $f
close $g
set g [open "positions" "r"]
set data [read $g]
close $g
set num0 0
for {set j 0} {$j < [expr { $num_part + 1 }]} {incr j} {
    set type [lindex $data 0 $j 4]
    if { $type == 0 } {
        set tlist [expr $i]
        set x0 [lindex $data 0 $j 1]
        set y0 [lindex $data 0 $j 2]
        set z0 [lindex $data 0 $j 3]
        set total1 [ expr { sqrt(($x0 * $x0) + ($y0 * $y0)+ ($z0 * $z0)) }]+0]
        incr num0
        puts " $i :: $num0 "
        set dum 0
        for {set k 0} {$k < [expr { $num_part + 1 }]} {incr k} {
            set type [lindex $data 0 $k 4]
            if { $type == 1 } {
                set tlist [expr $i]
                set x1 [lindex $data 0 $k 1]
                set y1 [lindex $data 0 $k 2]
                set z1 [lindex $data 0 $k 3] 
                set total2 [ expr { sqrt(($x1 * $x1) + ($y1 * $y1)+ ($z1 * $z1)) }]+0]
                incr dum
                puts " $i :: $dum "
                }
            }   
        }   
    }
}
set h [open "dist12" "w"]
set dist12 [ expr {($mol1 * $total1)-($mol2 * $total2)}]
puts "Distance between cross particles $dist12"
puts $h "\#   t  $dist12 "
foreach t $tlist dist" $dist12  { puts $h "$t $dist_12" } 
close $h

Upvotes: 0

Views: 422

Answers (1)

Donal Fellows
Donal Fellows

Reputation: 137557

You've a few lines that look suspicious.

1:

set part [while { [blockfile $f read auto] != "eof" } {} ]

The result of while is an empty string, so the above code probably isn't doing what you hope. Not quite sure how to fix it though; blockfile isn't a standard Tcl command.

2:

for {set j 0} {$j < [expr { $num_part + 1 }]} {incr j} {

Not really a correctness issue, but that could be written as:

for {set j 0} {$j < $num_part + 1} {incr j} {

The bytecode generated will be virtually identical, but it's shorter and easier to read.

3:

set tlist [expr $i]

This looks unnecessary and suspcious. We know i is a numeric variable (in fact it contains an integer), so there's no need to pretend it is an expression. It slows things down for no benefit.

You've two occurrences of this.

4:

set total1 [ expr { sqrt(($x0 * $x0) + ($y0 * $y0)+ ($z0 * $z0)) }]+0]

This line is definitely wrong. The number of ] characters doesn't match the number of [ characters, so what you get will be “unexpected”, and that +0 is either useless or harmful. It's probably best to write a procedure to help you with this. Put the procedure at the top of the script.

proc length {x y z} {
    expr { sqrt($x*$x + $y*$y + $z*$z) }
}

Then just call it later on:

set total1 [length $x0 $y0 $z0]

The same applies to the calculation of total2 later.

5:

foreach t $tlist dist" $dist12  { puts $h "$t $dist_12" } 

Looks like this has a typo: dist" instead of dist. The failure to use dist inside the loop also looks odd; I think you're going wrong here, and should take another look and think about what you actually want to do.

Upvotes: 1

Related Questions