Scientific & Engineering Programming

Lecture IV

Inputs and outputs in Mathematica

Robert Muszyński

Department of Cybernetics and Robotics
Wrocław University of Science and Technology

Copyright 2017-2020 RM

General remarks

All cells taking part in a computation process are either input cells or output cells

Functions in Mathematica have an input (arguments basically) and an output (a return value in general)

f[x_]:=Module[{tmp=0,lx=x},
While[tmp<3,
lx=lx+lx^2;tmp++];
lx]
f[5]
Clear[f]

Mathematica can read input from a file and save output to it

(* some prepartion to have a file :*)
2*a+3*b+46*c+31*d >> "example.exp"  
FilePrint["example.exp"]

FilePrint["example.exp"]
exvar=<<example.exp;
exvar
exvar/.{a->b,c->2}

%>>result.exp
FilePrint["result.exp"]

Function arguments

Patterns

f[x]+f[x+y]+f[x,y]+f[a]+f[4]/.f[a]->(a^2)
f[x]+f[x+y]+f[x,y]+f[a]+f[4]/.f[a_]->(a^2)
f[x]+f[x+y]+f[x,y]+f[a]+f[4]/.f[a__]->(a^2)
f[x]+f[x+y]+f[x,y]+f[a]+f[4]/.f[a_Integer]->(a^2)

({{_ (Blank), any expression}, {x_, any expression, to be referred to as x}, {__ (BlankSequence), any sequence of one or more expressions}, {_h, pattern with a specified head h}})

(a^2)+(b^3)+(c^4)+(x^3)/.x->d
(a^2)+(b^3)+(c^4)+(x^3)/.x_->d
(a^2)+(b^3)+(c^4)+(x^3)/.((x_)^3)->d
(a^2)+(b^3)+(c^4)+(x^3)/.x_^3->Sin[x]
(a^2)+(b^3)+(c^4)+(x^3)/.x_^_->d
(a^2)+(b^3)+(c^4)+(x^3)/.x_^y_->(d^y)

Remark: Rules and patterns work on heads as well

f[x]+g[y]+h[z]/.f->k
Sin[x+y]+Cos[z]/.Sin->Cos
{a,b,c}/.List->f
{4,5,6}/.List->Plus
Plus@@{4,5,6}          (* typical notion - Apply[] function *)

Patterns can be extended in many ways

{{a},{a,a},{b},{c},{x}}/.a->d
{{a},{a,a},{b},{c},{x}}/.a|b->d
{{a},{a,a},{b},{c},{x}}/.{a..}->{d}

{a,b,c,d,e,f,g}/.{x__,y__}->{{x},{y}}
{a,b,c,d,e,f,g}/.{Longest[x__],y__}->{{x},{y}}
{a,b,c,d,e,f,g}/.{x__,Longest[y__]}->{{x},{y}}
{a,b,c,d,e,f,g}/.{x__,Shortest[y__]}->{{x},{y}}

Example: Find the longest sequence of integers

{x,3,5,7,y,1,2,3,4,z}/.{a___,b__Integer,c___}->{b}
{x,3,5,7,y,1,2,3,4,z}/.{a___,Longest[b__Integer],c___}->{b}

({{___ (BlankNullSequence), any sequence of zero or more expressions}})

Defining functions

General rule - use patterns to introduce the arguments

Functions with a single argument

f[x_]:=x^2
f[4]
f[a]
f[x]
f[x+b]
f[x,b]
f[{x+b,a,4}]

(* f "works" on a list since the Power function is listable *)
??Power

f[a]:=alice
f[4]:=44
f[4]
f[a]
f[x]
f[x+b]
f[x,b]
f[{x+b,a,4}]         (* but be careful *)

?f

f[x_/;x<0]:=-x   (* conditional definition *)
f[-4]
(* observe the order of definitions *)
?f

g[x_Integer]:=x^2    (* specifying the argument type *)
g[4]
g[a]
g[x]
g[x+b]
g[x,b]
g[{x+b,a,5}]

Clear[g]
g[x_Symbol]:=x^3   (* another example *)
g[4]
g[a]
g[x]
g[x+b]
g[x,b]
g[{x+b,a,5}]

Functions with several arguments

f[x_,y_]:=x^2+y^2
f[x_,y]:=special
f[3,4]
f[a,4]
f[a+b,c+d]
f[a+b,y]

(* now we have the f function with both single and double arguments *)
?f

h[x__]:=x^2   (* several arguments via double _ *)
h[4]
h[a]
h[x+b]
h[x,b]
h[{x+b,a,5}]

Arguments behavior

Having an initialized variable we can increment it

var=3
var =var+7
var

But doing the same with an uninitialized variable

var1=var1+7

Consequently

proc[x_]:=(zm=Sqrt[x];x=zm+3;x)
proc[yu]
proc[5]
yi=7;
proc[yi]

Just use local variables

nproc[x_]:=Module[{lx,lzm},lzm=Sqrt[x];lx=lzm+3;lx]
nproc[z]
nproc[5]

Optional and default arguments

j[x_,y_:1,z_:2]:=jp[x,y,z]
j[a,b,c]
j[a,b]
j[c]

({{x_:v, an expression which, if omitted, is taken to have default value v}, {x_h:v, an expression with head h and default value v}, {x_., an expression with a built-in default value}})

{k[a],k[a+b]}/.k[x_+y_]->p[x,y]
{k[a],k[a+b]}/.k[x_+y_.]->p[x,y]

({{x_+y_., default for y is 0}, {x_y_., default for y is 1}, {x_^y_., default for y is 1}})

lin[a_.+b_. x_,x_]:=p[a,b]   (* return coeficients of a linear function *)
lin[a x+b,x]
lin[17 x+4,x]
lin[17x,x]
lin[x,x]
lin[5,x]

And beyond: variable number of arguments

(* pick out pairs of duplicated elements in w *)
d[a___,x_,b___,x_,c___]:=dd[x] d[a,b,c]
d[2,3,2,4,5,3]

Functions attributes

?f
f[a]   (* here is alice *)
f[4]   (* here is special value *)
f[{x+b,a,4}]   (* but here not *)

Attributes[f]
SetAttributes[f,Listable]
Attributes[f]

f[{x+b,a,4}] 
ClearAttributes[f,Listable]
f[{x+b,a,4}]    (* as we have previously *)
ClearAll[f]

Attributes[]			ClearAttributes[]	
 SetAttributes[]		ClearAll[]

Attributes[Plus]

External data operation

Reading and writing expressions

Manipulating numerical data

Streams and low level I/O

Importing, exporting, and manipulating files

Reading and writing expressions

Expand[(x+y)^3]>>tmp
Solve[(x+y)^3==9/.y->3,x]>>>tmp
FilePrint["tmp"]

<<tmp
sol=%

({{>>(Put), write to a file}, {>>> (PutAppend), append to a file}, {<< (Get) , read from a file}})

myvar=44;
f[x_]:=x^2
f[a]:=alice
f[4]:=myvar
?f

Save ["tmp1.m",f]
FilePrint["tmp1.m"]

({{Save, append definitions to a file}, {FilePrint, print out textual contents of a file}})

Manipulating numerical data

Numerical data - a group of information that is measurable

Data file formats

({{Comma-Separated Values, .csv, plaintext format that separates records with commas and new lines}, {Tab-Separated Values, .tsv, plaintext format that separates records with tabs and new lines}, {Table, .dat, plaintext format that separates records with tabs and new lines}, {Plain Text, .txt, plaintext files can store data using arbitrary record separators}, {Binary, *, binary data format; can have various file extensions, or none}})

Exemplary csv data

Functions & Strategies for Loading Data

({{Import, user-friendly, supports many formats}, {ReadList, fast, flexible control of types, supports streams}, {BinaryReadList, better performance than the two previous functions}, {Get(DumpSave), most efficient loading operation, preserves packed arrays}})

({{Import, high memory overhead, limited performance}, {ReadList, not as user-friendly, works best with plaintext formats}, {BinaryReadList, generally the least user-friendly, can involve a lot of data processing}, {Get(DumpSave), files are not transferable, need to be loaded by another mechanism first}})

(* some exemplary data :*)
FilePrint["ExampleData/numbers"]

var1=ReadList["ExampleData/numbers",Number]
var2=ReadList["ExampleData/numbers",{Number,Number}]
var3=ReadList["ExampleData/numbers",Number,RecordLists->True]

(* more exemplary data :*)
FilePrint["ExampleData/strings"]

var1=ReadList["ExampleData/strings",Word]
var2=ReadList["ExampleData/strings",Character]
var3=ReadList["ExampleData/strings",Byte]

(* some prepartion to have "big" data :*)
(data=Table[{x,x^2-2+0.2Sin[5x]},{x,-3,3,0.1}])//Short
ListPlot[data]
Export["function.dat",data,"Table"];

FilePrint["function.dat"]

fromfile=ReadList["function.dat",Number,RecordLists->True];
originalPlot=ListPlot[fromfile,Joined->True]
ListPlot[Sqrt[fromfile],Joined->True]

fit1=Fit[fromfile,{1,x},x]
Show[originalPlot,Plot[fit1,{x,-3,3},PlotStyle->Red]]

fit2=Fit[fromfile,{1,x,x^2,x^3},x]
Show[originalPlot,Plot[fit2,{x,-3,3},PlotStyle->Red]]

Working example: Filtering a noisy signal

(* some prepartion to have "noisy" data :*)
data=Table[Sin[i^2+i]+RandomReal[{-.2,.3}],{i,0,Pi,0.003}];
Export["measured.dat",data];

FilePrint["measured.dat"]

measures=ReadList["measured.dat",Number];
measuresPlot=ListLinePlot[measures]

ListLinePlot[LowpassFilter[measures,0.4]]

Manipulate[GraphicsColumn[ListLinePlot/@{measures,LowpassFilter[measures,ω]}],{{ω,1},.1,Pi}]

Appendix: Sounds and  sonification

Your numerical data can be sounds

Play[Sin[440 2Pi t],{t,0,1}]    (* a middle A *)

Sound[{SoundNote["C"],SoundNote["G"]}]   (* piano notes *)

Play[Sin[700 t+25 t Sin[350 t]],{t,0,4}]   (* something modulated *)

Sound[SoundNote[DeleteCases[3 Range[31] Reverse[#],0]-48,.1]&/@Transpose[CellularAutomaton[150,{{1},0},30]]]   (* an automaton *)

Appendix: Images and image processing

Your numerical data can be images

lena=Import["ExampleData/lena.tif"]

ExampleData[{"AerialImage","Pentagon"}]

cat=Import["cat.jpg"]

data=ImageData[cat,Interleaving-> False,DataReversed->True][[2]];
ListDensityPlot[data,Mesh->False,FrameTicks->None,ColorFunction->RGBColor]

data

ListDensityPlot[data^2,Mesh->False,FrameTicks->None,ColorFunction->RGBColor]

ListDensityPlot[Log[(Sqrt[data])],Mesh->False,FrameTicks->None,ColorFunction->RGBColor]

ListDensityPlot[Cos[2Pi data],Mesh->False,FrameTicks->None,ColorFunction->RGBColor]

ListDensityPlot[Sin[16 Pi data],Mesh->False,FrameTicks->None,ColorFunction->RGBColor]

ListContourPlot[data,ContourShading->False,Contours->6,FrameTicks->None]

Streams and low-level input and output

stmp=OpenWrite["tmp",FormatType->OutputForm]
Write[stmp,x^2+y^2," ",z^2];
Close[stmp];
FilePrint["tmp"]

stmp=OpenWrite["tmp"]
Options[stmp]
SetOptions[stmp,FormatType->CForm];
Write[stmp,x^2Sqrt[z]+y^2Cos[z]^2];
Close[stmp];
FilePrint["tmp"]

Requires the inclusion of mdefs.h header file - more at CForm help

(* Similarly there are other formats, e.g. TeXForm :*)
x^2 Sqrt[z]+y^2Cos[z]^2//TeXForm

(* Open an input stream to read from a string *)
str=StringToStream["12.3 456 789"]
Read[str,Number]
Read[str,Number]
Read[str,Number]
Read[str,Number]

Plenty of possibilities - more in the guide Low-Level File Operations

Importing and exporting files

Export["out1",{6.7,8.5,-5.3},"List"]
FilePrint["out1"]
Import["out1","List"]

Export["out2.txt",{"The first line.","The second line."},{"Text","Lines"}]
FilePrint["out2.txt"]
Import["out2.txt","Text"]//InputForm
Import["out2.txt",{"Text","Words"}]//InputForm

test=Plot[Sin[x],{x,0,10}];
Export["test.jpg",test]

Plot[Tan[x],{x,0,10}]

Then select the grap and save it using File->Save Selection As menu  item.

Or simply use Copy and Paste to export a graphic.

To import just do the oposite

Import["ExampleData/rose.gif"]

Manipulating files

({{CopyFile["(Subscript[file, 1])","(Subscript[file, 2])"], copy (Subscript[file, 1]) to (Subscript[file, 2])}, {RenameFile["(Subscript[file, 1])","(Subscript[file, 2])"], give (Subscript[file, 1]) the name (Subscript[file, 2])}, {DeleteFile["file"], delete a file}, {FileByteCount["file"], give the number of bytes in a file}, {FileDate["file"], give the modification date for a file}, {SetFileDate["file"], set the modification date for a file to be the current date}, {FileType["file"], give the type of a file as File, Directory, or None}})

({{FindFile["name"], find the file with the specified name that would be loaded by Get and related functions}, {FileExistsQ["name"], determine whether the file exists}})

({{CreateDirectory["name"], create a new directory}, {DeleteDirectory["name"], delete an empty directory}, {DeleteDirectory["name",DeleteContents->True], delete a directory and all files and directories it contains}, {RenameDirectory["(Subscript[name, 1])","(Subscript[name, 2])"], rename a directory}, {CopyDirectory["(Subscript[name, 1])","(Subscript[name, 2])"], copy a directory and all the files in it}})

({{Directory[], your current working directory}, {SetDirectory["dir"], set your current working directory}, {ResetDirectory[], revert to your previous working directory}})