Tcl 8.4 - Plotting a bar graph - tcl

I wanted to create a histogram (Look more like a bar chart) of a table with 5 rows and 2 columns, each of the column being an x-axis and y-axis.
I am new to TCL, and before posting here I have tried multiple things! I found that there is a package called plot chart, downloaded form the wiki and tried!
#! /bin/env tclsh
lappend auto_path /u/vbhaskar/work/proj2/ECE_x81_PROJECT_2
package require plotchart
canvas .c -background white -width 400 -height 200
pack .c -fill both
#
# Create the plot with its x- and y-axes
#
set s [::Plotchart::createXYPlot .c {0.0 100.0 10.0} {0.0 100.0 20.0}]
foreach {x y} {0.0 32.0 10.0 50.0 25.0 60.0 78.0 11.0 } {
$s plot series1 $x $y
}
$s title "Data series"
exit 0
Tried the above code, didn't understand completely but better.
I get the error saying package not found.
Is there a simple way of achieving my functionality in Tcl 8.4 version ? I am doing source <file_name.tcl> in the Synopsys DC shell

I will not use any library, but some simple code.
set mylist [list 0 1 2 8 3 9 4 2 5 19 6 12]
array set arr $mylist
#parray arr
foreach element [array names arr] {
puts -nonewline "x($element) "
for {set i 0} {$i <= $arr($element)} {incr i} {
puts -nonewline "-"
}
puts -nonewline "$arr($element)"
puts "\n"
}
Check the o/p:
x(4) ---2
x(0) --1
x(5) --------------------19
x(6) -------------12
x(2) ---------8
x(3) ----------9
Hope it helps.

Related

I am trying to form a rectangle with 2 pairs of Coordinate in TCL

I am new to TCL and hardware design. I am currently doing a script that could verify all the ports at an edge and make a rectangle box that cover all the ports at an edge.
Since I am new to TCL, I think there is something wrong in the syntax.
The error msg is:
Error: Invalid coordinates '$bbox_coor_x1 [expr $bbox_coor_y2-30]' in list. (NDMUI-100)
Error: Empty or invalid geometry specified for the '-boundary' argument of the command. (NDMUI-337).
Please help me.
Your problem is that variables and commands are not interpolated inside curly braces. Please learn the difference between curlies and double quotes.
For example:
set x 5
set y 10
# Curlies
puts {$x $y}
--> $x $y (literally)
puts {$x [expr $y+1]}
--> $x [expr $y+1] (literally)
# Double quotes
puts "$x $y"
--> 5 10
# List command
puts [list $x $y]
--> 5 10
puts [list $x [expr $y+1]]
--> 5 11
When making a list of lists, like a bbox, anything inside outer-most curlies will interpolate:
puts "{$x $x} {$y $y}"
--> {5 5} {10 10}
One more thing, note that lindex can take multiple indexes. Do this instead of calling lindex twice.
lindex $bbox 0 1

Calculate average of columns of column with Tcl

I want to calculate the average for this column with tcl
please help me
frame Elec
1 50
2 40
3 30
4 20
If this is for a standalone script, (Warning: Self promotion ahead), I wrote a program called tawk that's like awk except using TCL for scripting, which does most of the work for you:
$ tawk 'line {$NR > 1} { incr sum $F(2) }
END { puts [expr {double($sum) / ($NR - 1)}] }' input.txt
35
# Equivalent awk:
$ awk 'NR > 1 { sum += $2 } END { print (sum / (NR - 1)) }' input.txt
35
If it's part of a larger program, you have to open the file and read and split lines yourself. Maybe something like
# Column number is 1-based
proc avg_column {filename column} {
set f [open $filename r]
gets $f ;# Read and discard header line
set sum 0
set nlines 0
while {[gets $f line] >= 0} {
set columns [regexp -all -inline {\S+} $line]
incr sum [lindex $columns $column-1]
incr nlines
}
close $f
return [expr {double($sum) / $nlines}]
}
puts [avg_column input.txt 2]
Not an answer, but some tips. You need to:
open the file
read the header with gets
use a while loop to read lines of the file
use split or regexp to get the 2nd field
sum the values (and count the lines) with expr, or incr if the values are only integers
If your input happens to be (some sort of CSV), or you can steer it into this direction, then you may use tcllib's csv package:
package require csv
package require struct::matrix
struct::matrix dm
set f [open mydata.csv]
while {[gets $f l] >= 0} {
# sanitize input, line-wise
set l [regsub -all {\s+} $l " "]
csv::split2matrix dm $l " " auto
}
close $f
set columnData [lrange [dm get column 1] 1 end]; # strip off header
puts [expr {double([tcl::mathop::+ {*}$columnData])/[llength $columnData]}]; # compute avg
Some hints:
gets will read your input file line by line;
csv::split2matrix puts each line into a struct::matrix;
/matrix/ get column /n/ gives access to one data column (incl. header field);
tcl::mathop::+ gives access to the built-in addition operator (outside of the [expr] command) and supports 2+ summands.

How to convert .tcl file with tcl/tk commands into executables for windows and linux?

Please answer this question in support with links of available software (with appropriate s/w version that can support that) and with clear one-on-one steps.
Sample tcl/tk program to convert into executables :
#!/usr/bin/wish
proc every {ms body} {eval $body; after $ms [info level 0]}
proc drawhands w {
$w delete hands
set secSinceMidnight [expr {[clock sec]-[clock scan 00:00:00]}]
foreach divisor {60 3600 43200} length {45 40 30} width {1 3 7} {
set angle [expr {$secSinceMidnight * 6.283185 / $divisor}]
set x [expr {50 + $length * sin($angle)}]
set y [expr {50 - $length * cos($angle)}]
$w create line 50 50 $x $y -width $width -tags hands
}
}
proc toggle {w1 w2} {
if [winfo ismapped $w2] {
foreach {w2 w1} [list $w1 $w2] break ;# swap
}
pack forget $w1
pack $w2
}
#-- Creating the analog clock:
canvas .analog -width 100 -height 100 -bg white
every 1000 {drawhands .analog}
pack .analog
#-- Creating the digital clock:
label .digital -textvar ::time -font {Courier 24}
every 1000 {set ::time [clock format [clock sec] -format %H:%M:%S]}
bind . <1> {toggle .analog .digital}
For windows and linux:
download freewrap673.zip and freewrap673.tar.gz respectively from https://sourceforge.net/projects/freewrap/files/freewrap/freeWrap%206.73/
extract them
go to win64 for windows64bit system, go to linux64 for linux64bit system
copy your .tcl files into this folder
Run using :
freewrap filename.tcl for windows
./freewrap filename.tcl for linux

Sum of elements/numbers in N lists in Tcl?

How to add elements/numbers from n lists in tcl ?
I have tried in python and it worked using below:
[sum(x) for x in zip(*C)]
How to do this in tcl?
Is there a zip function in tcl?
Is there any other way to achieve this ?
I have 2 lists for now:
l1 {11 333 4 567 129}
l2 {23 47 56 10 13}
I can have N-number of lists
I need to return element wise sum from these lists.
for two lists I implemented below :
set result {}
foreach x $l1 y $l2 {
lappend result [expr {$x + $y}]
}
My concern is: I can have one or many lists. So in that scenario how do I implement?
To get a new list of the pairwise sums of the elements of two lists:
set result [lmap a $list1 b $list2 { expr {$a + $b} }]
Make the obvious addition for three lists, four lists, etc.
There are no function similar to zip in Tcl as far as I'm aware. You can however create one if you want to. A rough one might be like this:
proc zip {lists} {
set result {}
for {set i 0} {$i < [llength [lindex $lists 0]]} {incr i} {
set elem {}
foreach list $lists {
if {$i >= [llength $list]} {return $result}
lappend elem [lindex $list $i]
}
lappend result $elem
}
return $result
}
Then you can use it like this:
set l1 {11 333 4 567 129}
set l2 {23 47 56 10 13}
set ln [list $l1 $l2]
set sum [lmap x [zip $ln] {::tcl::mathop::+ {*}$x}]
# 34 380 60 577 142
Then you don't want a variable per list, you want something else like a list of lists.
This is my take on the above recommendation by Shawn:
set l1 {11 333 4 567 129}
set l2 {23 47 56 10 13}
lappend l $l1 $l2
proc zippedSum {p} {
set inner [llength [lindex $p 0]]
set result [list]
for {set i 0} {$i < $inner} {incr i} {
lappend result [::tcl::mathop::+ {*}[lmap sublist $p {lindex $sublist $i}]]
}
return $result
}
zippedSum $l
You would not maintain separate variables, but a list of lists (l). Then you would process the sublists per index (with the maximum index determined by the first sublist), using the lmap/lindex combo recommended elsewhere for what you call zipping.

How to perform an arithmetic action on all the elements of a list in Tcl

I have a very long list of values and I want to divide them all by the same number, is there a way to do this in one command instead of doing this by member:
set new_list [list ]
foreach member $list {
lappend new_list [expr $member / 1E9]
}
Nope. And always brace your expressions.
proc map {lst expr} {
foreach item $lst { lappend r [expr [string map {%x $item} $expr]] }
return $r
}
map [list 2.3 4.5 6.7] {%x * %x + 0.5}
map [list ...] {%x / 1e9}
might be a solution if you want - but there is nothing builtin for that.
Tcllib's ::struct::list package has a mapping function:
package require struct::list
set lst {1 2 3 4 5}
set new [::struct::list mapfor x $lst {expr {$x * $x}}]
# => 1 4 9 16 25