#------------------------------------------------------------------------------ """ printmat([fh::IO],x...;colNames=[],rowNames=[], width=10,prec=3,NoPrinting=false,StringFmt="",cell00="") Print all elements of a matrix (or several) with predefined formatting. It can also handle OffsetArrays. StringFmt = "csv" prints using a csv format. # Input - `fh::IO`: (optional) file handle. If not supplied, prints to screen - `x::Array(s)`: (of numbers, dates, strings, ...) to print - `colNames::Array`: of strings with column headers - `rowNames::Array`: of strings with row labels - `width::Int`: (keyword) scalar, minimum width of printed cells - `prec::Int`: (keyword) scalar, precision of printed cells - `NoPrinting::Bool`: (keyword) bool, true: no printing, just return formatted string [false] - `StringFmt::String`: (keyword) string, "", "csv" - `cell00::String`: (keyword) string, for row 0, column 0 # Output - str (if NoPrinting) string, (otherwise nothing) # Examples ``` x = [11 12;21 22] printmat(x) ``` ``` x = [1 "ab"; Date(2018,10,7) 3.14] printmat(x,width=20,colNames=["col 1","col 2"]) ``` ``` printmat([11,12],[21,22]) ``` Can also call as ``` opt = Dict(:rowNames=>["1";"4"],:width=>10,:prec=>3,:NoPrinting=>false,:StringFmt=>"") printmat(x;colNames=["a","b"],opt...) #notice ; and ... ``` (not all keywords are needed) # Requires - fmtNumPs # Notice - The prefixN and suffixN could potentially be made function inputs. This would allow a fairly flexible way to format tables. Paul.Soderlind@unisg.ch """ function printmat(fh::IO,x...;colNames=[],rowNames=[], width=10,prec=3,NoPrinting=false,StringFmt="",cell00="") isempty(x) && return nothing #do nothing is isempty(x) typeTestQ = any(!=(eltype(x[1])),[eltype(z) for z in x]) #test if eltype(x[i]) differs if typeTestQ #create matrix from tuple created by x... x = hcat(Matrix{Any}(hcat(x[1])),x[2:end]...) #preserving types of x[i] else x = hcat(x...) end (m,n) = (size(x,1),size(x,2)) (length(rowNames) == 1 < m) && (rowNames = [string(rowNames[1],i) for i = 1:m]) #"ri" (length(colNames) == 1 < n) && (colNames = [string(colNames[1],i) for i = 1:n]) #"ci" if StringFmt == "csv" (prefixN,suffixN) = (fill("",n),vcat(fill(",",n-1),"")) #prefix and suffix for column 1:n (prefixC0,suffixC0) = ("",",") #prefix and suffix for column 0 else (prefixN,suffixN) = (fill("",n),fill("",n)) (prefixC0,suffixC0) = ("","") end if length(rowNames) == 0 #width of column 0 (cell00 and rowNames) col0Width = 0 else col0Width = maximum(length,vcat(cell00,rowNames)) + length(prefixC0) + length(suffixC0) end colWidth = [width + length(prefixN[j]) + length(suffixN[j]) for j=1:n] #widths of column 1:n iob = IOBuffer() if !isempty(colNames) #print (cell00,colNames), if any !isempty(cell00) ? txt0 = string(prefixC0,cell00,suffixC0) : txt0 = "" print(iob,rpad(txt0,col0Width)) for j = 1:n #loop over columns print(iob,lpad(string(prefixN[j],colNames[j],suffixN[j]),colWidth[j])) end print(iob,"\n") end #print rowNames and x (i0,j0) = (1 - first(axes(x,1)),1 - first(axes(x,2))) #i+i0,j+j0 give traditional indices for i in axes(x,1) #loop over rows !isempty(rowNames) && print(iob,rpad(string(prefixC0,rowNames[i+i0],suffixC0),col0Width)) for j in axes(x,2) #loop over columns print(iob,fmtNumPs(x[i,j],width,prec,"right",prefix=prefixN[j+j0],suffix=suffixN[j+j0])) end print(iob,"\n") end str = String(take!(iob)) if NoPrinting #no printing, just return str return str else #print, return nothing print(fh,str,"\n") return nothing end end #when fh is not supplied: printing to screen printmat(x...;colNames=[],rowNames=[],width=10,prec=3,NoPrinting=false,StringFmt="",cell00="") = printmat(stdout::IO,x...;colNames,rowNames,width,prec,NoPrinting,StringFmt,cell00) #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ """ printlnPs([fh::IO],z...;width=10,prec=3) Subsitute for println, with predefined formatting. # Input - `fh::IO`: (optional) file handle. If not supplied, prints to screen - `z::String`: string, numbers and arrays to print Paul.Soderlind@unisg.ch """ function printlnPs(fh::IO,z...;width=10,prec=3) for x in z #loop over inputs in z... if isa(x,AbstractArray) iob = IOBuffer() for i = 1:length(x) print(iob,fmtNumPs(x[i],width,prec,"right")) end print(fh,String(take!(iob))) else print(fh,fmtNumPs(x,width,prec,"right")) end end print(fh,"\n") end #when fh is not supplied: printing to screen printlnPs(z...;width=10,prec=3) = printlnPs(stdout::IO,z...;width,prec) #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ """ fmtNumPs(z,width=10,prec=2,justify="right";prefix="",suffix="") Create a formatted string of a float (eg, "%10.4f"), nothing (""), while other values are passed through. Strings are right (or left) justified and can optionally be given prefix and suffix (eg, ",") # Notice - With prec > 0 and isa(z,Integer), then the string is padded with 1+prec spaces to align with the printing of floats with the same prec. # Requires - Printf (for 1.6-), fmtNumPsC (for < 1.6) """ function fmtNumPs(z,width=10,prec=2,justify="right";prefix="",suffix="") isa(z,Bool) && (z = convert(Int,z)) #Bool -> Int if isa(z,AbstractFloat) #example: 101.0234, prec=3 if VERSION < v"1.6-" fmt = "%$(width).$(prec)f" zRound = round(z,digits=prec) strLR = fmtNumPsC(fmt,zRound) #C fallback solution else fmt = Printf.Format("%$(width).$(prec)f") strLR = Printf.format(fmt,z) end elseif isa(z,Nothing) strLR = "" elseif isa(z,Integer) && prec > 0 #integer followed by (1+prec spaces) strLR = string(z," "^(1+prec)) else #Int, String, Date, Missing, etc strLR = string(z) end strLR = string(prefix,strLR,suffix) if justify == "left" #justification strLR = rpad(strLR,width+length(prefix)+length(suffix)) else strLR = lpad(strLR,width+length(prefix)+length(suffix)) end return strLR end #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ """ fmtNumPsC(fmt,z) c fallback solution for formatting of floating point number. Used if VERSION < v"1.6-" """ function fmtNumPsC(fmt,z) #c fallback solution if ismissing(z) || isnan(z) || isinf(z) #asprintf does not work for these cases str = string(z) else strp = Ref{Ptr{Cchar}}(0) len = ccall(:asprintf,Cint,(Ptr{Ptr{Cchar}},Cstring,Cdouble...),strp,fmt,z) str = unsafe_string(strp[],len) Libc.free(strp[]) end return str end #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ function printblue(x...) foreach(z->printstyled(z,color=:blue,bold=true),x) print("\n") end function printred(x...) foreach(z->printstyled(z,color=:red,bold=true),x) print("\n") end function printmagenta(x...) foreach(z->printstyled(z,color=:magenta,bold=true),x) print("\n") end function printyellow(x...) foreach(z->printstyled(z,color=:yellow,bold=true),x) print("\n") end #------------------------------------------------------------------------------