lua torch, how to get the print() output into a string - lua

require 'nn'
criterion = nn.ClassNLLCriterion()
print(criterion)
this outputs
nn.ClassNLLCriterion
{
sizeAverage : true
output : 0
gradInput : DoubleTensor - empty
output_tensor : DoubleTensor - size: 1
target : LongTensor - size: 1
total_weight_tensor : DoubleTensor - size: 1
}
I would like to get this print output for logging purposes. Does anyone know how to do that?

Hmm I'm not sure how you get this output. When I run this code I get nn.ClassNLLCriterion. Maybe different Lua/Torch versions?
Anyway, if you want to have this info in a string, you might have to extract it yourself. This can easily be done doing a simple loop:
for k,v in pairs(criterion) do
print(k,v)
end
If you want the fancy print output then I suggest you look at TREPL's code (like #nobody suggested in the comments). It's all in Lua so it's very easy to replicate. More precisely, I recommend their sizestr(), print_new() and printvar() functions. Simply change them so instead of printing, they construct a string.
A quick example using their sizestr function:
-- Copy/Paste from trepl/init.lua
local function sizestr(x)
local strt = {}
if _G.torch.typename(x):find('torch.*Storage') then
return _G.torch.typename(x):match('torch%.(.+)') .. ' - size: ' .. x:size()
end
if x:nDimension() == 0 then
table.insert(strt, _G.torch.typename(x):match('torch%.(.+)') .. ' - empty')
else
table.insert(strt, _G.torch.typename(x):match('torch%.(.+)') .. ' - size: ')
for i=1,x:nDimension() do
table.insert(strt, x:size(i))
if i ~= x:nDimension() then
table.insert(strt, 'x')
end
end
end
return table.concat(strt)
end
local function sutoringu(elem)
local str = ''
if torch.isTensor(elem) then
str = sizestr(elem)
else
str = tostring(elem)
end
return str
end
local str = '{\n'
local tab = ' '
for k,v in pairs(criterion) do
str = str .. tab .. k .. ' : ' .. sutoringu(v) .. '\n'
end
str = str .. '}'
print(str)
This outputs the same thing as what you wished for, constructing a string in the process. It's far from optimal but it's a start.

Related

Lua-Logging data from Device to a file-Excel- Lua scripts

I have the following Lua script that collects temperature values from a device and I would like to log the output data below to an excel spreadsheet. Any help would be greatly appreciated.
if globalsFile == nil then
dofile("globals.lua")
end
if utilFile == nil then
dofile("util.lua")
end
heaterDuration = 0
heaterInterval = 2
heaterTimeout = 20
index = 1
heater.ON()
print("The heaters have been turned on")
print("Temperatures will be updated below every " .. heaterInterval .. " seconds")
print("Item,Time Point,Top,Bottom,Ambient")
tempIncrease = 'n'
while (heaterDuration < heaterTimeout) do
topTemp = heater.top()
bottomTemp = heater.bottom()
ambientTemp = temperature.ambient()
print(index .. "," .. heaterDuration .. "," .. topTemp .. "," .. bottomTemp .. "," .. ambientTemp)
heaterDuration = heaterDuration + heaterInterval
os.sleep(heaterInterval * 1000)
end
Output
Item,Time Point,Top,Bottom,Ambient
1,0,37.022136688232,37.202819824219,28.257425308228
1,2,37.022136688232,37.202819824219,28.282178878784
1,4,37.022136688232,37.202819824219,28.282178878784
1,6,37.022136688232,37.202819824219,28.282178878784
1,8,37.022136688232,37.202819824219,28.282178878784
1,10,37.022136688232,37.202819824219,28.282178878784
1,12,37.022136688232,37.202819824219,28.282178878784
1,14,37.022724151611,37.202819824219,28.282178878784
1,16,37.022136688232,37.202819824219,28.282178878784
1,18,37.022136688232,37.202819824219,28.282178878784```
If you replace the while loop with something like this, depending on the environment that your Lua runs in, you should be creating a CSV file, which is a readable plain text file with literally just values (or strings, but then it can get more complicated) values separated by commas, or tabs, but let's stick to commas here.
The biggest differences are the creation of the mycsv file object, switchin the print to mycsv:write() (while making sure there is a newline), and then closing (and maybe flushing unwritten data) the file object at the end.
mycsv = io.open("mydata.csv", "w")
mycsv:write("Item,Time Point,Top,Bottom,Ambient\n")
while (heaterDuration < heaterTimeout) do
topTemp = heater.top()
bottomTemp = heater.bottom()
ambientTemp = temperature.ambient()
mycsv:write(index .. "," .. heaterDuration .. "," .. topTemp .. "," ..
bottomTemp .. "," .. ambientTemp .. "\n")
heaterDuration = heaterDuration + heaterInterval
os.sleep(heaterInterval * 1000)
end
mycsv:close()
See also: https://luabyexample.org/docs/files/

How to set up output to certain specifications

I figured out the main concept of my code which reads in a file and sets it to a key then reads in another file and displays the info based on that file. How do I add line 1, line 2. line 3 and so on in front of the output? As well as add ------------ above and below each new line.
-- see if the file exists
function file_exists(file)
local f = io.open("data.txt", "rb")
if f then f:close() end
return f ~= nil
end
-- get all lines from a file, returns an empty
-- list/table if the file does not exist
function lines_from(file)
if not file_exists(file) then return {} end
lines = {}
for line in io.lines("data.txt") do
first_word = string.match(line, "%a+") -- word
lines[first_word] = line
lines[#lines + 1] = lin
end
return lines
end
local lines = lines_from(file)
function key_file(file)
if not file_exists(file) then return {} end
keys = {}
for line in io.lines("keys.txt") do
key = string.match(line, "%a+")
table.insert(keys, key)
end
return keys
end
local lines = lines_from("data.txt")
local keys = key_file("keys.txt")
for _, key in ipairs(keys) do
print(lines[key])
end
I'll answer this in a more general way as your code is not working atm.
You can simply add print commands in the for loop that prints the lines. Or you alter the texts by in some way. See Lua reference documentation for string manipulation and concat operator ..
local numLine = 0
for _, key in pairs(keys) do
numLine = numLine + 1
print("Line " .. numLine .. ": " .. lines[key])
print("----------")
end

How do we change the way print displays a table

Assuming I have a piece of code such as the following
aTable = {aValue=1}
aTable_mt = {}
print(aTable)
What must I do to make Lua print something like aTable current aValue = 1 as opposed to table: 0x01ab1d2.
So far I've tried setting the __tostring metamethod but that doesn't seem to be invoked by print. Is there some metamethod I've been missing or does the answer have nothing to do with metamethods?
__tostring works:
aTable = {aValue=1}
local mt = {__tostring = function(t)
local result = ''
for k, v in pairs(t) do
result = result .. tostring(k) .. ' ' .. tostring(v) .. ''
end
return result
end}
setmetatable(aTable, mt)
print(aTable)
This prints aValue 1 (with one extra whitespace, remove it in real code). The aTable part is not available, because aTable is a variable that references the table, not the content of the table itself.
I'm not sure how you set the metamethod, but the following code prints "stringified" for me:
local aTable = {a = 1, b = 2}
setmetatable(aTable, {__tostring = function() return "stringified" end})
print(aTable)
If you want lua to generally print all tables human readable, you could
hook up/overwrite the print function:
local orig_print = print
print = function(...)
local args = {...}
for i,arg in ipairs(args) do
if type(arg) == 'table' then
args[i] = serialize(arg)
end
end
orig_print(table.unpack(args))
end
serialize could be serpent or some other lib from here
Note that this must be done before any other module/script is loaded.

Scanning folders using lua

I'm trying to get the name of all the file saved in two folders, the name are saved as :
1.lua 2.lua 3.lua 4.lua and so on
the folders name are :
first folder : "/const/"
second folder: "/virt/"
what I'm trying to do is only get the number of the files and this works but not in the right order, when I get the 17 file for example I get the 17th delivered from the function before the 15 and this causes for me a problem here the code of the function that I'm using :
local virt_path = "/virt/"
local const_path = "/const"
local fs = require "lfs"
local const = {}
for num = 1, (numberoffile)do -- numberoffile is predfined and can't be change
const[num] = assert(
dofile (const_path .. mkfilename(num)),
"Failed to load constant ".. num ..".")
end
local function file_number() --this is the function that causes me a headach
local ci, co, num = ipairs(const)
local vi, vo, _ = fs.dir(virt_path)
local function vix(o)
local file = vi(o)
if file == nil then return nil end
local number = file:match("^(%d+).lua$")
if number == nil then return vix(o) end
return tonumber(number)
end
local function iter(o, num)
return ci(o.co, num) or vix(o.vo, num)
end
return iter, {co=co, vo=vo}, num
end
As I said the function delive the need return values but not the right Arithmetic order.
any idea what I'm doing wrong here ?
I use my path[1] library.
1 We fill table with filenames
local t = {}
for f in path.each("./*.lua", "n") do
t[#t + 1] = tonumber((path.splitext(f)))
end
table.sort(t)
for _, i in ipairs(t) do
-- do work
end
2 We check if files exists
for i = 1, math.huge do
local p = "./" .. i .. ".lua"
if not path.exists(p) then break end
-- do work
end
[1] https://github.com/moteus/lua-path

lua - calling a function from a string

From what I've read on this site the below should work.
Can some kindly soul please point out where I'm going wrong?
I've embedded more description and print returns in the code hopefully to make easier reading
local m = {
{opt = "Solar Panels", cmd = "solarPanel"}
-- There are many more options here.
}
function doTheMenu()
print("Welcome to Spyder's Factory")
print("")
print("What would you like to make?")
local n = 1
local l = #m - 1
while true do --This while loop may or may not be relevant to the question, it's the menu
term.clear() --this is ComputerCraft lua, the term function is defined
term.setCursorPos(1,2) --elsewhere in an API
for i, j in pairs(m) do
if i == n then
if i < 10 then print(i, " ["..j.opt.."]") else print(i, " ["..j.opt.."]") end
fsel = j.cmd --set fsel to the function name I require in case of a break
tsel = j.opt --Ditto, tsel, human-friendly name
else
if i < 10 then print(i, " "..j.opt) else print(i, " "..j.opt) end
end
end
local a, b = os.pullEvent("key")
if b == 200 and n > 1 then n = n - 1 end
if b == 208 and n <= l then n = n + 1 end
if b == 28 then break end
end
write("\nSure, how many "..tsel.."? ")
qty = tonumber(read())
req[fsel] = req[fsel] + qty
str = fsel.."("..qty..")"
print("Loading function '"..fsel.."("..qty..")'") --Returns "Loading function 'solarPanel(1)'"
func = loadstring(str)
print(func) --Returns "function: 2cdfc5a7"
print("Loading function")
func() --The error line, Returns "string:1: attempt to call nil"
--tellUserWhatNeed()
--makeItHappen()
end
doTheMenu()
The issue is the code fails to run with the error:
string:1 attempt to call nil
Also what is term variable, if that's all your code, term is not defined and is null)
That said: either _G[fsel] is nil or fsel is nil ?
Are you sure you have function declared in _G with the name stored in fsel?
e.i. call before the problem line print (_G[fsel]) to see what it gives you.
This was the solution that ended up working:
local f = loadstring(str)
if f then
setfenv(f, getfenv())
f()
end
This replaces the lines above:
print("Loading function '"..fsel.."("..qty..")'")
func = loadstring(str)
print(func)
print("Loading function")
func()
As well as adding basic error handling for loading the function

Resources