你的Mathematica工具包里有什么?
我们都知道Mathematica很棒,但是它也经常缺乏关键的function。 Mathematica使用什么样的外部包/工具/资源?
我将编辑(并邀请其他任何人也这样做)这个主要的职位,把重点放在科学研究的一般适用性的资源,并尽可能多的人会觉得有用。 随意提供任何东西,甚至是小代码片段(正如我在下面做的定时例程)。
另外,在Mathematica 7及更高版本中,您无法find自己的文档或有用的function,或者从某些纸张/网站挖出来的文档是非常受欢迎的。
请包括一个简短的描述或评论,为什么是伟大的或它提供了什么效用。 如果您通过会员链接链接到亚马逊书籍,请提及它,例如,在链接后面加上您的名字。
包:
-
LevelScheme
是一个可以大大扩展Mathematica生成好看图的能力的软件包。 我用它,如果没有其他的东西,那么对于帧/轴刻度的大大改进的控制。 它的最新版本被称为SciDraw,并将在今年的某个时候发布。 - David Park的
Presentation Package
(US $ 50 – 免费更新) - Jeremy Michelson的
grassmannOps
软件包为Grassmannvariables和运算符提供了代数和微积分的资源,这些variables和运算符具有非平凡的整数关系。 - John Brown的
GrassmannAlgebra
代数包和Grassmann和Clifford代数的书。 - RISC(符号计算研究所)有多种可供下载的Mathematica(及其他语言)软件包。 特别是在Algorithmic Combinatorics组的软件页面上 ,有自动定理certificate的定理,以及符号求和,差分方程等的众多包。
工具:
-
MASH
是Daniel Reeves出色的Perl脚本,主要为Mathematica v7提供脚本支持。 (现在使用-script
选项内置于Mathematica 8中。) - 一个具有GNU readlineinput的
alternate Mathematica shell
(仅使用python,* nix) - ColourMaths软件包允许您直观地selectexpression式的一部分并对其进行处理。 http://www.dbaileyconsultancy.co.uk/colour_maths/colour_maths.html
资源:
-
Wolfram自己的存储库
MathSource
有很多有用的,如果狭窄的笔记本电脑的各种应用程序。 另外检查其他部分,如-
Current Documentation
, - 讲课
Courseware
, - 和
Demos
,以及演示。
-
-
Mathematica维基教科书 。
图书:
- Mathematica编程: Leonid Shifrin(
web
,pdf
) 的高级介绍是必须阅读的,如果您想在Mathematica中做更多的For循环。 我们很高兴让Leonid
本人在这里回答问题。 - Mathematica的量子方法 James F. Feagin( 亚马逊 )
- Stephen Wolfram 的Mathematica书 ( 亚马逊 )(
web
) - 绍姆的纲要 ( 亚马逊 )
- Stan Wagon( 亚马逊 )的Mathematica在行动 – 600页整洁的例子,并且提供给Mathematica版本7.可视化技术特别好,你可以在作者的
Demonstrations Page
看到其中的一些。 - 理查德·盖洛德( Mathematica Programming Fundamentals)由理查德·盖洛德(Richard Gaylord)撰写(
pdf
) – 对你需要了解的大部分关于Mathematica编程的简要介绍。 - 由O'Reilly出版的Sal Mangano的Mathematica食谱2010 832页。 – 着名的O'Reilly Cookbook风格:问题 – 解决scheme。 对于中间体。
- Mathematica微分方程,第3版。 Elsevier 2004 Amsterdam by Martha L. Abell,James P. Braselton – 893页初学者,同时学习求解DE和Mathematica。
未logging(或几乎没有logging)的function:
- 如何自定义Mathematica键盘快捷键。 看到
this question
。 - 如何检查Mathematica自己的函数使用的模式和函数。 看到
this answer
- 如何在Mathematica中实现GraphPlots的一致大小? 看到
this question
。 - 如何用Mathematica制作文档和演示文稿。 看到
this question
。
我之前提到过这个 ,但是我发现最有用的工具是Reap
和Sow
一个应用,它模仿/扩展了GatherBy
的行为:
SelectEquivalents[x_List,f_:Identity, g_:Identity, h_:(#2&)]:= Reap[Sow[g[#],{f[#]}]&/@x, _, h][[2]];
这使我可以按任何标准对列表进行分组,并在过程中进行转换。 它的工作方式是标准函数( f
)标记列表中的每个项目,每个项目然后被第二个提供的函数( g
)转换,具体的输出由第三个函数( h
)控制。 函数h
接受两个参数:标签和具有该标签的收集项目的列表。 这些项目保留原来的顺序,所以如果你设置h = #1&
那么你会得到一个未分类的Union
,就像Reap
的例子 。 但是,它可以用于二次加工。
作为其实用的一个例子,我一直在与Wannier90一起工作, 它将空间依赖的哈密尔顿算子输出到一个文件中,其中每一行是matrix中不同的元素,如下
rx ry rz ij Re[Hij] Im[Hij]
为了将这个列表转换成一组matrix,我收集了包含相同坐标的所有子列表,将元素信息转换成规则(即{i,j} – > Re [Hij] + I Im [Hij]),然后把收集到的规则变成一个SparseArray
,
SelectEquivalents[hamlst, #[[;; 3]] &, #[[{4, 5}]] -> (Complex @@ #[[6 ;;]]) &, {#1, SparseArray[#2]} &]
老实说,这是我的瑞士军刀,它使复杂的事情变得非常简单。 我的其他大多数工具都是某些领域特定的,所以我可能不会发布它们。 但是,大多数(如果不是全部的话)引用SelectEquivalents
。
编辑 :它不完全模仿GatherBy
,因为它不能像GatherBy
那样简单地对expression式的多个层次进行GatherBy
。 但是, Map
对我所需要的大部分工作正常。
例如 :@ Yaroslav Bulatov已经要求一个独立的例子。 这里有一个我的研究已经大大简化了。 所以,假设我们在飞机上有一组点
In[1] := pts = {{-1, -1, 0}, {-1, 0, 0}, {-1, 1, 0}, {0, -1, 0}, {0, 0, 0}, {0, 1, 0}, {1, -1, 0}, {1, 0, 0}, {1, 1, 0}}
我们希望通过一组对称操作来减less点数。 (为了好奇,我们正在生成每个点的小组 )。对于这个例子,让我们使用围绕z轴的四重旋转轴
In[2] := rots = RotationTransform[#, {0, 0, 1}] & /@ (Pi/2 Range[0, 3]);
使用SelectEquivalents
我们可以在这些操作下将产生相同图像集合的点进行分组,即它们是相等的,使用以下
In[3] := SelectEquivalents[ pts, Union[Through[rots[#] ] ]& ] (*<-- Note Union*) Out[3]:= {{{-1, -1, 0}, {-1, 1, 0}, {1, -1, 0}, {1, 1, 0}}, {{-1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {1, 0, 0}}, {{0,0,0}}}
产生3个包含等价点的子列表。 (注意, Union
在这里是绝对重要的,因为它确保每个点产生相同的图像。原来,我使用了Sort
,但是如果一个点位于对称轴上,那么在该轴的旋转下它是不变的,因此, Union
消除了这些额外的图像,而且, GatherBy
会产生相同的结果)在这种情况下,点已经在我将使用的forms,但我只需要每个分组的代表点, d喜欢相当于点数。 因为我不需要转换每个点,所以我在第二个位置使用Identity
函数。 对于第三个function,我们需要小心。 传递给它的第一个参数将是旋转下的点的图像,对于点{0,0,0}
是四个相同元素的列表,并且使用它将会抛出计数。 然而,第二个参数只是所有具有该标签的元素的列表,所以它将只包含{0,0,0}
。 在代码中,
In[4] := SelectEquivalents[pts, Union[Through[rots[#]]]&, #&, {#2[[1]], Length[#2]}& ] Out[4]:= {{{-1, -1, 0}, 4}, {{-1, 0, 0}, 4}, {{0, 0, 0}, 1}}
请注意,最后一步可以轻松完成
In[5] := {#[[1]], Length[#]}& /@ Out[3]
但是,用这个和上面的不太完整的例子很容易看到用最less的代码可以实现非常复杂的转换。
Mathematica笔记本界面的好处之一就是它可以用任何语言评估expression式,而不仅仅是Mathematica。 作为一个简单的例子,可以考虑创build一个新的Shellinput单元格types,将所包含的expression式传递给操作系统shell进行评估。
首先,定义一个将文本命令评估委托给shell的函数:
shellEvaluate[cmd_, _] := Import["!"~~cmd, "Text"]
第二个理由是必要的,因为稍后会出现的原因而被忽略。 接下来,我们要创build一个名为Shell的新风格:
- 打开一个新的笔记本。
- select菜单项格式/编辑样式表…
- 在对话框中,在input样式名称旁input
Shell
。 - select新样式旁边的单元格支架。
- select菜单项Cell / Show Expression
- 用下面给出的步骤6文本覆盖单元格expression式。
- 再一次,select菜单项Cell / Show Expression
- closures对话框。
使用下面的单元格expression式作为步骤6文本 :
Cell[StyleData["Shell"], CellFrame->{{0, 0}, {0.5, 0.5}}, CellMargins->{{66, 4}, {0, 8}}, Evaluatable->True, StripStyleOnPaste->True, CellEvaluationFunction->shellEvaluate, CellFrameLabels->{{None, "Shell"}, {None, None}}, Hyphenation->False, AutoQuoteCharacters->{}, PasteAutoQuoteCharacters->{}, LanguageCategory->"Formula", ScriptLevel->1, MenuSortingValue->1800, FontFamily->"Courier"]
大部分expression式直接从内置的程序风格中复制。 关键的变化是这些行:
Evaluatable->True, CellEvaluationFunction->shellEvaluate, CellFrameLabels->{{None, "Shell"}, {None, None}},
Evaluatable
启用单元格的SHIFT + ENTERfunction。 评估将调用CellEvaluationFunction
传递单元格内容和内容types作为参数( shellEvaluate
忽略后一个参数)。 CellFrameLabels
只是一个CellFrameLabels
让我们的用户确定这个单元格是不寻常的。
有了这一切,我们现在可以input和评估一个shellexpression式:
- 在上述步骤中创build的笔记本中,创build一个空单元格并select单元格支架。
- select菜单项Format / Style / Shell 。
- 在单元格中键入一个有效的操作系统shell命令(例如Unix上的'ls'或Windows上的'dir')。
- 按SHIFT + ENTER。
最好将这个定义的样式保存在一个位于中心的样式表中。 此外,诸如shellEvaluate
评估函数最好在init.m
使用DeclarePackage定义为存根。 这两项活动的细节超出了这个回应的范围。
有了这个function,人们可以创build包含任何感兴趣语法的inputexpression式的笔记本。 评估函数可以用纯粹的Mathematica编写,或将评估的任何或所有部分委托给外部机构。 请注意,还有其他钩子与细胞评估相关,如CellEpilog
, CellProlog
和CellDynamicExpression
。
常见的模式是将inputexpression式文本写入临时文件,用某种语言编译文件,运行程序并捕获输出,以便在输出单元中进行最终显示。 在实现这种完整的解决scheme(如正确捕获错误消息)时有很多细节需要解决,但是我们必须意识到,不仅可以做这样的事情,而且是实用的。
就个人而言,它是这样的function,使笔记本界面成为我的编程世界的中心。
更新
以下帮助函数对于创build这样的单元格非常有用:
evaluatableCell[label_String, evaluationFunction_] := ( CellPrint[ TextCell[ "" , "Program" , Evaluatable -> True , CellEvaluationFunction -> (evaluationFunction[#]&) , CellFrameLabels -> {{None, label}, {None, None}} , CellGroupingRules -> "InputGrouping" ] ] ; SelectionMove[EvaluationNotebook[], All, EvaluationCell] ; NotebookDelete[] ; SelectionMove[EvaluationNotebook[], Next, CellContents] )
它是这样使用的:
shellCell[] := evaluatableCell["shell", Import["!"~~#, "Text"] &]
现在,如果对shellCell[]
进行求值,那么input单元将被删除,并replace为一个新的input单元,将其内容评估为一个shell命令。
托德Gayley(沃尔夫勒姆研究)只是给我一个很好的黑客,它允许“包装”与任意代码的内置函数。 我觉得我必须分享这个有用的工具。 以下是托德对我的question
的回答。
一些有趣的(?)历史:“包装”内置函数的破解风格是1994年Robby Villegas和I发明的,具有讽刺意味的是,我为Mathematica Journal编写了一个名为ErrorHelp的包,那时候 从那以后,它被许多人使用了很多次。 这是一个内幕人士的诡计,但我认为这已经成为将自己的代码注入到内置函数定义中的标准方式。 它很好地完成了工作。 当然,您可以将$ inMsgvariables放入您希望的任何私有上下文中。
Unprotect[Message]; Message[args___] := Block[{$inMsg = True, result}, "some code here"; result = Message[args]; "some code here"; result] /; ! TrueQ[$inMsg] Protect[Message];
这不是一个完整的资源,所以我把它扔在答案部分,但是我发现它在找出速度问题(这不幸是Mathematica编程的很大一部分)非常有用。
timeAvg[func_] := Module[ {x = 0, y = 0, timeLimit = 0.1, p, q, iterTimes = Power[10, Range[0, 10]]}, Catch[ If[(x = First[Timing[(y++; Do[func, {#}]);]]) > timeLimit, Throw[{x, y}] ] & /@ iterTimes ] /. {p_, q_} :> p/iterTimes[[q]] ]; Attributes[timeAvg] = {HoldAll};
用法就是简单的timeAvg@funcYouWantToTest
。
编辑:巫师先生提供了一个简单的版本,抛弃了Throw
和Catch
并且更容易parsing:
SetAttributes[timeAvg, HoldFirst] timeAvg[func_] := Do[If[# > 0.3, Return[#/5^i]] & @@ Timing @ Do[func, {5^i}] ,{i, 0, 15}]
编辑:这是从acl的一个版本(从这里采取):
timeIt::usage = "timeIt[expr] gives the time taken to execute expr, \ repeating as many times as necessary to achieve a total time of 1s"; SetAttributes[timeIt, HoldAll] timeIt[expr_] := Module[{t = Timing[expr;][[1]], tries = 1}, While[t < 1., tries *= 2; t = Timing[Do[expr, {tries}];][[1]];]; t/tries]
Internal`InheritedBlock
我最近从官方新闻组的Daniel Lichtblau的这个消息中了解到Internal`InheritedBlock
这样有用的function的存在。
据我所知, Internal`InheritedBlock
允许在Block
范围内传递一个出站函数的副本:
In[1]:= Internal`InheritedBlock[{Message}, Print[Attributes[Message]]; Unprotect[Message]; Message[x___]:=Print[{{x},Stack[]}]; Sin[1,1] ] Sin[1,1] During evaluation of In[1]:= {HoldFirst,Protected} During evaluation of In[1]:= {{Sin::argx,Sin,2},{Internal`InheritedBlock,CompoundExpression,Sin,Print,List}} Out[1]= Sin[1,1] During evaluation of In[1]:= Sin::argx: Sin called with 2 arguments; 1 argument is expected. >> Out[2]= Sin[1,1]
我觉得这个function对于需要临时修改内置函数的人来说非常有用!
与Block的比较
让我们定义一些函数:
a := Print[b]
现在我们希望将这个函数的副本传递给Block
作用域。 天真的审判不给我们想要的:
In[2]:= Block[{a = a}, OwnValues[a]] During evaluation of In[9]:= b Out[2]= {HoldPattern[a] :> Null}
现在尝试在Block
的第一个参数中使用延迟定义(这也是一个未logging的function):
In[3]:= Block[{a := a}, OwnValues[a]] Block[{a := a}, a] Out[3]= {HoldPattern[a] :> a} During evaluation of In[3]:= b
我们看到在这种情况下a
作品,但是我们还没有得到Block
范围内原始a
副本。
现在让我们试试Internal`InheritedBlock
:
In[5]:= Internal`InheritedBlock[{a}, OwnValues[a]] Out[5]= {HoldPattern[a] :> Print[b]}
我们已经获得了Block
范围内原始定义的副本,我们可以按照我们想要的方式对其进行修改,而不会影响到全局定义。
Mathematica是一个尖锐的工具,但它可能会削弱你的一些无意义的行为和雪崩的神秘诊断信息 。 处理这个问题的一个方法是定义遵循这个习惯用法的函数:
ClearAll@zot SetAttributes[zot, ...] zot[a_] := ... zot[b_ /; ...] := ... zot[___] := (Message[zot::invalidArguments]; Abort[])
这是很多的样板,我经常试图跳过。 特别是在Mathematica发生很多原型时。 所以,我使用了一个名为define
的macros,它允许我保持纪律,而且less了一些样板。
define
的基本用法是这样的:
define[ fact[0] = 1 ; fact[n_ /; n > 0] := n * fact[n-1] ] fact[5] 120
起初看起来不多,但有一些隐藏的好处。 define
的第一个服务是自动将ClearAll
应用于正在定义的符号。 这确保了没有剩余的定义 – 在函数的最初开发过程中经常发生。
第二个服务是被定义的function被自动“closures”。 通过这个我的意思是,该函数将发出一个消息,并中止,如果它是与一个参数列表不匹配的定义之一:
fact[-1] define::badargs: There is no definition for 'fact' applicable to fact[-1]. $Aborted
这是define
的主要价值,它捕获了一个非常常见的错误类。
另一个便利是在被定义的函数上指定属性的简洁方法。 让我们使Listable
函数:
define[ fact[0] = 1 ; fact[n_ /; n > 0] := n * fact[n-1] , Listable ] fact[{3, 5, 8}] {6, 120, 40320}
除了所有常规属性之外, define
接受一个名为Open
的附加属性。 这可以防止define
添加catch-all错误定义到函数:
define[ successor[x_ /; x > 0] := x + 1 , Open ] successor /@ {1, "hi"} {2, successor["hi"]}
可以为一个函数定义多个属性:
define[ flatHold[x___] := Hold[x] , {Flat, HoldAll} ] flatHold[flatHold[1+1, flatHold[2+3]], 4+5] Hold[1 + 1, 2 + 3, 4 + 5]
毫不费力,下面是define
:
ClearAll@define SetAttributes[define, HoldAll] define[body_, attribute_Symbol] := define[body, {attribute}] define[body:(_Set|_SetDelayed), attributes_List:{}] := define[CompoundExpression[body], attributes] define[body:CompoundExpression[((Set|SetDelayed)[name_Symbol[___], _])..], attributes_List:{}] := ( ClearAll@name ; SetAttributes[name, DeleteCases[attributes, Open]] ; If[!MemberQ[attributes, Open] , def:name[___] := (Message[define::badargs, name, Defer@def]; Abort[]) ] ; body ; ) def:define[___] := (Message[define::malformed, Defer@def]; Abort[]) define::badargs = "There is no definition for '``' applicable to ``."; define::malformed = "Malformed definition: ``";
展示的实现既不支持上值也不支持curring,也不支持比简单函数定义更普遍的模式。 但它仍然有用。
没有打开空白的笔记本开始
Mathematica开始打开一个空白的笔记本,我很困扰。 我可以用脚本来closures这个笔记本,但是它仍然会短暂地闪烁。 我的破解是创build一个文件Invisible.nb
包含:
Notebook[{},Visible->False]
并将其添加到我的Kernel\init.m
:
If[Length[Notebooks["Invisible*"]] > 0, NotebookClose[Notebooks["Invisible*"][[1]]] ] SetOptions[$FrontEnd, Options[$FrontEnd, NotebooksMenu] /. HoldPattern["Invisible.nb" -> {__}] :> Sequence[] ]
我现在通过打开Invisible.nb
启动Mathematica
可能有更好的办法,但是这对我来说很好。
自定义的Fold
和Fold
FoldList
Fold[f, x]
等同于Fold[f, First@x, Rest@x]
顺便说一句,我相信这可能会find未来版本的Mathematica的方式。
惊喜! 这已经实施,虽然目前没有logging。 我被告知,它是在2011年由Oliver Ruebenkoenig实施的,显然不久之后我发布了这个。 谢谢你Oliver Ruebenkoenig!
Unprotect[Fold, FoldList] Fold[f_, h_[a_, b__]] := Fold[f, Unevaluated @ a, h @ b] FoldList[f_, h_[a_, b__]] := FoldList[f, Unevaluated @ a, h @ b] (* Faysal's recommendation to modify SyntaxInformation *) SyntaxInformation[Fold] = {"ArgumentsPattern" -> {_, _, _.}}; SyntaxInformation[FoldList] = {"ArgumentsPattern" -> {_, _., {__}}}; Protect[Fold, FoldList]
更新以允许这样做:
SetAttributes[f, HoldAll] Fold[f, Hold[1 + 1, 2/2, 3^3]]
f[f[1 + 1, 2/2], 3^3]
“dynamic分区”
参见Mathematica.SE post#7512了解这个函数的新版本。
我经常想根据一系列的长度来划分一个列表。
伪代码示例:
partition[{1,2,3,4,5,6}, {2,3,1}]
输出: {{1,2}, {3,4,5}, {6}}
我想出了这个:
dynP[l_, p_] := MapThread[l[[# ;; #2]] &, {{0} ~Join~ Most@# + 1, #} &@Accumulate@p]
然后我完成了这个,包括论证testing:
dynamicPartition[l_List, p : {_Integer?NonNegative ..}] := dynP[l, p] /; Length@l >= Tr@p dynamicPartition[l_List, p : {_Integer?NonNegative ..}, All] := dynP[l, p] ~Append~ Drop[l, Tr@p] /; Length@l >= Tr@p dynamicPartition[l_List, p : {_Integer?NonNegative ..}, n__ | {n__}] := dynP[l, p] ~Join~ Partition[l ~Drop~ Tr@p, n] /; Length@l >= Tr@p
第三个参数控制分割规范之外的元素发生了什么。
索博尔奇的Mathematica技巧
我使用最频繁的是粘贴表格数据调色板
CreatePalette@ Column@{Button["TSV", Module[{data, strip}, data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]]; strip[s_String] := StringReplace[s, RegularExpression["^\\s*(.*?)\\s*$"] -> "$1"]; strip[e_] := e; If[Head[data] === String, NotebookWrite[InputNotebook[], ToBoxes@Map[strip, ImportString[data, "TSV"], {2}]]]]], Button["CSV", Module[{data, strip}, data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]]; strip[s_String] := StringReplace[s, RegularExpression["^\\s*(.*?)\\s*$"] -> "$1"]; strip[e_] := e; If[Head[data] === String, NotebookWrite[InputNotebook[], ToBoxes@Map[strip, ImportString[data, "CSV"], {2}]]]]], Button["Table", Module[{data}, data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]]; If[Head[data] === String, NotebookWrite[InputNotebook[], ToBoxes@ImportString[data, "Table"]]]]]}
修改Compile
外部数据
Daniel Lichtblau最近展示了我以前从未见过的这种方法。 在我看来,它大大扩展了Compile
的效用
ll = {2., 3., 4.}; c = Compile[{{x}, {y}}, ll[[1]] = x; y]; c[4.5, 5.6] ll (* Out[1] = 5.6 *) (* Out[2] = {4.5, 3., 4.} *)
一般PDF / EMF出口问题和解决scheme
1)这是完全意想不到的,但是Mathematica使用一组样式定义来输出和保存PDF和EPS格式的graphics,这些定义与用于在屏幕上显示笔记本的定义不同。 By default Notebooks are displayed on screen in the "Working" style environment (which is default value for the ScreenStyleEvironment
global $FrontEnd
option) but are printed in the "Printout"
style environment (which is default value for the PrintingStyleEnvironment
global $FrontEnd
option). When one exports graphics in raster formats such as GIF and PNG or in EMF format Mathematica generates graphics that looks exactly like it looks inside Notebook. It seems that the "Working"
style environment is used for rendering in this case. But it is not the case when you export/save anything in PDF or EPS formats! In this case the "Printout"
style environment is used by default that differs very deeply from the "Working" style environment. First of all, the "Printout"
style environment sets Magnification
to 80% . Secondly, it uses its own values for the font sizes of different styles and this results in inconsistent font size changes in the genarated PDF file as compared with the original on-screen representation. The latter can be called FontSize fluctuations which are very annoying. But happily this can be avoided by setting the PrintingStyleEnvironment
global $FrontEnd
option to "Working" :
SetOptions[$FrontEnd, PrintingStyleEnvironment -> "Working"]
2) The common problem with exporting to EMF format is that most of programs (not only Mathematica ) generate a file that looks nice at the default size but becomes ugly when you zoom it in. It is because metafiles are sampled at screen resolution fidelity . The quality of the generated EMF file can be enhanced by Magnify
ing the original graphical object so that exactness of sampling of the original graphics becomes much more precise. Compare two files:
graphics1 = First@ImportString[ ExportString[Style["a", FontFamily -> "Times"], "PDF"], "PDF"]; graphics2 = Magnify[graphics1, 10]; Export["C:\\test1.emf", graphics1] Export["C:\\test2.emf", graphics2]
If you insert these files into Microsoft Word and zoom them in you will see that the first "a" has sawtooth on it while the second has not (tested with Mathematica 6).
Another way through ImageResolution
was suggested by Chris Degnen (this option has effect at least starting from Mathematica 8):
Export["C:\\test1.emf", graphics1] Export["C:\\test2.emf", graphics1, ImageResolution -> 300]
3) In Mathematica we have three ways to convert graphics into metafile: via Export
to "EMF"
(strongly recommended way: produces metafile with highest possible quality), via Save selection As...
menu item ( produces much lesser precise figure , not recommended) and via Edit ► Copy As ► Metafile
menu item ( I strongly recommend against this route ).
By popular demand, the code to generate the top-10 SO answerers plot (except annotations ) using the SO API .
getRepChanges[userID_Integer] := Module[{totalChanges}, totalChanges = "total" /. Import["http://api.stackoverflow.com/1.1/users/" <> ToString[userID] <> "/reputation?fromdate=0&pagesize=10&page=1", "JSON"]; Join @@ Table[ "rep_changes" /. Import["http://api.stackoverflow.com/1.1/users/" <> ToString[userID] <> "/reputation?fromdate=0&pagesize=10&page=" <> ToString[page], "JSON"], {page, 1, Ceiling[totalChanges/10]} ] ] topAnswerers = ({"display_name", "user_id"} /. #) & /@ ("user" /. ("top_users" /. Import["http://api.stackoverflow.com/1.1/tags/mathematica/top-\ answerers/all-time", "JSON"])) repChangesTopUsers = Monitor[Table[ repChange = ReleaseHold[(Hold[{DateList[ "on_date" + AbsoluteTime["January 1, 1970"]], "positive_rep" - "negative_rep"}] /. #) & /@ getRepChanges[userID]] // Sort; accRepChange = {repChange[[All, 1]], Accumulate[repChange[[All, 2]]]}\[Transpose], {userID, topAnswerers[[All, 2]]} ], userID]; pl = DateListLogPlot[ Tooltip @@@ Take[({repChangesTopUsers, topAnswerers[[All, 1]]}\[Transpose]), 10], Joined -> True, Mesh -> None, ImageSize -> 1000, PlotRange -> {All, {10, All}}, BaseStyle -> {FontFamily -> "Arial-Bold", FontSize -> 16}, DateTicksFormat -> {"MonthNameShort", " ", "Year"}, GridLines -> {True, None}, FrameLabel -> (Style[#, FontSize -> 18] & /@ {"Date", "Reputation", "Top-10 answerers", ""})]
Caching expressions
I find these functions very helpful to cache any expression. The interesting thing here for these two functions is that the held expression itself is used as a key of the hashtable/symbol Cache or CacheIndex, compared to the well-known memoization in mathematica where you can only cache result if the function is defined like f[x_] := f[x] = … So you can cache any part of a code, this is useful if a function is to be called several times but just some parts of the code must not be recomputed.
To cache an expression independently of its arguments.
SetAttributes[Cache, HoldFirst]; c:Cache[expr_] := c = expr; Ex: Cache[Pause[5]; 6] Cache[Pause[5]; 6]
The second time the expression returns 6 without waiting.
To cache an expression using an alias expression that can depend on an argument of the cached expression.
SetAttributes[CacheIndex, HoldRest]; c:CacheIndex[index_,expr_] := c = expr; Ex: CacheIndex[{"f",2},x=2;y=4;x+y]
If expr takes some time to compute, it is much faster to evaluate {"f",2} for example to retrieve the cached result.
For a variation of these functions in order to have a localized cache (ie. the cache memory is automatically released outside the Block construct) see this post Avoid repeated calls to Interpolation
Deleting cached values
To delete cached values when you don't know the number of definitions of a function. I consider that definitions have a Blank somewhere in their arguments.
DeleteCachedValues[f_] := DownValues[f] = Select[DownValues[f], !FreeQ[Hold@#,Pattern]&];
To delete cached values when you know the number of definitions of a function (goes slightly faster).
DeleteCachedValues[f_,nrules_] := DownValues[f] = Extract[DownValues[f], List /@ Range[-nrules, -1]];
This uses the fact that definitions of a function are at the end of their DownValues list, cached values are before.
Using symbols to store data and object-like functions
Also here are interesting functions to use symbols like objects.
It is already well known that you can store data in symbols and quickly access them using DownValues
mysymbol["property"]=2;
You can access the list of keys (or properties) of a symbol using these functions based on what dreeves submitted in a post on this site:
SetAttributes[RemoveHead, {HoldAll}]; RemoveHead[h_[args___]] := {args}; NKeys[symbol_] := RemoveHead @@@ DownValues[symbol(*,Sort->False*)][[All,1]]; Keys[symbol_] := NKeys[symbol] /. {x_} :> x;
I use this function a lot to display all infos contained in the DownValues of a symbol:
PrintSymbol[symbol_] := Module[{symbolKeys}, symbolKeys = Keys[symbol]; TableForm@Transpose[{symbolKeys, symbol /@ symbolKeys}] ];
Finally here is a simple way to create a symbol that behaves like an object in object oriented programming (it just reproduces the most basic behaviour of OOP but I find the syntax elegant) :
Options[NewObject]={y->2}; NewObject[OptionsPattern[]]:= Module[{newObject}, newObject["y"]=OptionValue[y]; function[newObject,x_] ^:= newObject["y"]+x; newObject /: newObject.function2[x_] := 2 newObject["y"]+x; newObject ];
Properties are stored as DownValues and methods as delayed Upvalues in the symbol created by Module that is returned. I found the syntax for function2 that is the usual OO-syntax for functions in Tree data structure in Mathematica .
For a list of existing types of values each symbol has, see http://reference.wolfram.com/mathematica/tutorial/PatternsAndTransformationRules.html and http://www.verbeia.com/mathematica/tips/HTMLLinks/Tricks_Misc_4.html .
For example try this
x = NewObject[y -> 3]; function[x, 4] x.function2[5]
You can go further if you want to emulate object inheritance using a package called InheritRules available here http://library.wolfram.com/infocenter/MathSource/671/
You could also store the function definition not in newObject but in a type symbol, so if NewObject returned type[newObject] instead of newObject you could define function and function2 like this outside of NewObject (and not inside) and have the same usage as before.
function[type[object_], x_] ^:= object["y"] + x; type /: type[object_].function2[x_] := 2 object["y"]+x;
Use UpValues[type] to see that function and function2 are defined in the type symbol.
Further ideas about this last syntax are introduced here https://mathematica.stackexchange.com/a/999/66 .
Improved version of SelectEquivalents
@rcollyer: Many thanks for bringing SelectEquivalents to the surface, it's an amazing function. Here is an improved version of SelectEquivalents listed above with more possibilities and using options, this makes it easier to use.
Options[SelectEquivalents] = { TagElement->Identity, TransformElement->Identity, TransformResults->(#2&) (*#1=tag,#2 list of elements corresponding to tag*), MapLevel->1, TagPattern->_, FinalFunction->Identity }; SelectEquivalents[x_List,OptionsPattern[]] := With[ { tagElement=OptionValue@TagElement, transformElement=OptionValue@TransformElement, transformResults=OptionValue@TransformResults, mapLevel=OptionValue@MapLevel, tagPattern=OptionValue@TagPattern, finalFunction=OptionValue@FinalFunction } , finalFunction[ Reap[ Map[ Sow[ transformElement@# , {tagElement@#} ]& , x , {mapLevel} ] , tagPattern , transformResults ][[2]] ] ];
Here are examples of how this version can be used:
Using Mathematica Gather/Collect properly
How would you do a PivotTable function in Mathematica?
Mathematica fast 2D binning algorithm
Internal`Bag
Daniel Lichtblau describes here an interesting internal data structure for growing lists.
Implementing a Quadtree in Mathematica
Debugging functions
These two posts point to useful functions for debugging:
How to debug when writting small or big codes using Mathematica? workbench? mma debugger? or something else? (ShowIt)
Here's another function based on Reap and Sow to extract expressions from different parts of a program and store them in a symbol.
SetAttributes[ReapTags,HoldFirst]; ReapTags[expr_]:= Module[{elements}, Reap[expr,_,(elements[#1]=#2/.{x_}:>x)&]; elements ];
这是一个例子
ftest[]:=((*some code*)Sow[1,"x"];(*some code*)Sow[2,"x"];(*some code*)Sow[3,"y"]); s=ReapTags[ftest[]]; Keys[s] s["x"] PrintSymbol[s] (*Keys and PrintSymbol are defined above*)
其他资源
Here's a list of interesting links for learning purpose:
A collection of Mathematica learning resources
Updated here: https://mathematica.stackexchange.com/a/259/66
My utility functions (I have these built in to MASH, which is mentioned in the question):
pr = WriteString["stdout", ##]&; (* More *) prn = pr[##, "\n"]&; (* convenient *) perr = WriteString["stderr", ##]&; (* print *) perrn = perr[##, "\n"]&; (* statements. *) re = RegularExpression; (* I wish mathematica *) eval = ToExpression[cat[##]]&; (* weren't so damn *) EOF = EndOfFile; (* verbose! *) read[] := InputString[""]; (* Grab a line from stdin. *) doList[f_, test_] := (* Accumulate list of what f[] *) Most@NestWhileList[f[]&, f[], test]; (* returns while test is true. *) readList[] := doList[read, #=!=EOF&]; (* Slurp list'o'lines from stdin. *) cat = StringJoin@@(ToString/@{##})&; (* Like sprintf/strout in C/C++. *) system = Run@cat@##&; (* System call. *) backtick = Import[cat["!", ##], "Text"]&; (* System call; returns stdout. *) slurp = Import[#, "Text"]&; (* Fetch contents of file as str. *) (* ABOVE: mma-scripting related. *) keys[f_, i_:1] := (* BELOW: general utilities. *) DownValues[f, Sort->False][[All,1,1,i]]; (* Keys of a hash/dictionary. *) SetAttributes[each, HoldAll]; (* each[pattern, list, body] *) each[pat_, lst_, bod_] := ReleaseHold[ (* converts pattern to body for *) Hold[Cases[Evaluate@lst, pat:>bod];]]; (* each element of list. *) some[f_, l_List] := True === (* Whether f applied to some *) Scan[If[f[#], Return[True]]&, l]; (* element of list is True. *) every[f_, l_List] := Null === (* Similarly, And @@ f/@l *) Scan[If[!f[#], Return[False]]&, l]; (* (but with lazy evaluation). *)
One trick I've used, which allows you to emulate the way most built-in functions work with bad arguments (by sending a message and then returning the whole form unevaluated) exploits a quirk of the way Condition
works when used in a defintion. If foo
should only work with one argument:
foo[x_] := x + 1; expr : foo[___] /; (Message[foo::argx, foo, Length@Unevaluated[expr], 1]; False) := Null; (* never reached *)
If you have more complex needs, it's easy to factor out the argument validation and message generation as an independent function. You can do more elaborate things by using side effects in Condition
beyond just generating messages, but in my opinion most of them fall into the "sleazy hack" category and should be avoided if possible.
Also, in the "metaprogramming" category, if you have a Mathematica package ( .m
) file, you can use the "HeldExpressions"
element to get all the expressions in the file wrapped in HoldComplete
. This makes tracking things down much easier than using text-based searches. Unfortunately, there's no easy way to do the same thing with a notebook, but you can get all the input expressions using something like the following:
inputExpressionsFromNotebookFile[nb_String] := Cases[Get[nb], Cell[BoxData[boxes_], "Input", ___] :> MakeExpression[StripBoxes[boxes], StandardForm], Infinity]
Lastly, you can use the fact that Module
emulates lexical closures to create the equivalent of reference types. Here's a simple stack (which uses a variation the Condition
trick for error handling as a bonus):
ClearAll[MakeStack, StackInstance, EmptyQ, Pop, Push, Peek] With[{emptyStack = Unique["empty"]}, Attributes[StackInstance] = HoldFirst; MakeStack[] := Module[{backing = emptyStack}, StackInstance[backing]]; StackInstance::empty = "stack is empty"; EmptyQ[StackInstance[backing_]] := (backing === emptyStack); HoldPattern[ Pop[instance : StackInstance[backing_]]] /; ! EmptyQ[instance] || (Message[StackInstance::empty]; False) := (backing = Last@backing; instance); HoldPattern[Push[instance : StackInstance[backing_], new_]] := (backing = {new, backing}; instance); HoldPattern[Peek[instance : StackInstance[backing_]]] /; ! EmptyQ[instance] || (Message[StackInstance::empty]; False) := First@backing]
Now you can print the elements of a list in reverse order in a needlessly convoluted way!
With[{stack = MakeStack[], list}, Do[Push[stack, elt], {elt, list}]; While[!EmptyQ[stack], Print[Peek@stack]; Pop@stack]]
Printing system symbol definitions without context prepended
The contextFreeDefinition[]
function below will attempt to print the definition of a symbol without the most common context prepended. The definition then can be copied to Workbench and formatted for readability (select it, right click, Source -> Format)
Clear[commonestContexts, contextFreeDefinition] commonestContexts[sym_Symbol, n_: 1] := Quiet[ Commonest[ Cases[Level[DownValues[sym], {-1}, HoldComplete], s_Symbol /; FreeQ[$ContextPath, Context[s]] :> Context[s]], n], Commonest::dstlms] contextFreeDefinition::contexts = "Not showing the following contexts: `1`"; contextFreeDefinition[sym_Symbol, contexts_List] := (If[contexts =!= {}, Message[contextFreeDefinition::contexts, contexts]]; Internal`InheritedBlock[{sym}, ClearAttributes[sym, ReadProtected]; Block[{$ContextPath = Join[$ContextPath, contexts]}, Print@InputForm[FullDefinition[sym]]]]) contextFreeDefinition[sym_Symbol, context_String] := contextFreeDefinition[sym, {context}] contextFreeDefinition[sym_Symbol] := contextFreeDefinition[sym, commonestContexts[sym]]
withRules[]
Caveat: This function does not localize variables the same way With
and Module
do, which means that nested localization constructs won't work as expected. withRules[{a -> 1, b -> 2}, With[{a=3}, b_ :> b]]
will replace a
and b
in the nested With
and Rule
, while With
doesn't do this.
This is a variant of With
that uses rules instead of =
and :=
:
ClearAll[withRules] SetAttributes[withRules, HoldAll] withRules[rules_, expr_] := Internal`InheritedBlock[ {Rule, RuleDelayed}, SetAttributes[{Rule, RuleDelayed}, HoldFirst]; Unevaluated[expr] /. rules ]
I found this useful while cleaning up code written during experimentation and localizing variables. Occasionally I end up with parameter lists in the form of {par1 -> 1.1, par2 -> 2.2}
. With withRules
parameter values are easy to inject into code previously written using global variables.
Usage is just like With
:
withRules[ {a -> 1, b -> 2}, a+b ]
Antialiasing 3D graphics
This is a very simple technique to antialias 3D graphics even if your graphics hardware doesn't support it natively.
antialias[g_, n_: 3] := ImageResize[Rasterize[g, "Image", ImageResolution -> n 72], Scaled[1/n]]
这是一个例子:
Note that a large value for n
or a large image size tends to expose graphics driver bugs or introduce artefacts.
Notebook diff functionality
Notebook diff functionality is available in the <<AuthorTools`
package, and (at least in version 8) in the undocumented NotebookTools`
context. This is a little GUI to diff two notebooks that are currently open:
PaletteNotebook@DynamicModule[ {nb1, nb2}, Dynamic@Column[ {PopupMenu[Dynamic[nb1], Thread[Notebooks[] -> NotebookTools`NotebookName /@ Notebooks[]]], PopupMenu[Dynamic[nb2], Thread[Notebooks[] -> NotebookTools`NotebookName /@ Notebooks[]]], Button["Show differences", CreateDocument@NotebookTools`NotebookDiff[nb1, nb2]]}] ]
Recursive pure functions ( #0
) seem to be one of the darker corners of the language. Here are a couple of non-trivial examples of their use , where this is really useful (not that they can not be done without it). The following is a pretty concise and reasonably fast function to find connected components in a graph, given a list of edges specified as pairs of vertices:
ClearAll[setNew, componentsBFLS]; setNew[x_, x_] := Null; setNew[lhs_, rhs_]:=lhs:=Function[Null, (#1 := #0[##]); #2, HoldFirst][lhs, rhs]; componentsBFLS[lst_List] := Module[{f}, setNew @@@ Map[f, lst, {2}]; GatherBy[Tally[Flatten@lst][[All, 1]], f]];
What happens here is that we first map a dummy symbol on each of the vertex numbers, and then set up a way that, given a pair of vertices {f[5],f[10]}
, say, then f[5]
would evaluate to f[10]
. The recursive pure function is used as a path compressor (to set up memoization in such a way that instead of long chains like f[1]=f[3],f[3]=f[4],f[4]=f[2], ...
, memoized values get corrected whenever a new "root" of the component is discovered. This gives a significant speed-up. Because we use assignment, we need it to be HoldAll, which makes this construct even more obscure and more attractive ). This function is a result of on and off-line Mathgroup discussion involving Fred Simons, Szabolcs Horvat, DrMajorBob and yours truly. 例:
In[13]:= largeTest=RandomInteger[{1,80000},{40000,2}]; In[14]:= componentsBFLS[largeTest]//Short//Timing Out[14]= {0.828,{{33686,62711,64315,11760,35384,45604,10212,52552,63986, <<8>>,40962,7294,63002,38018,46533,26503,43515,73143,5932},<<10522>>}}
It is certainly much slower than a built-in, but for the size of code, quite fast still IMO.
Another example: here is a recursive realization of Select
, based on linked lists and recursive pure functions:
selLLNaive[x_List, test_] := Flatten[If[TrueQ[test[#1]], {#1, If[#2 === {}, {}, #0 @@ #2]}, If[#2 === {}, {}, #0 @@ #2]] & @@ Fold[{#2, #1} &, {}, Reverse[x]]];
例如,
In[5]:= Block[ {$RecursionLimit= Infinity}, selLLNaive[Range[3000],EvenQ]]//Short//Timing Out[5]= {0.047,{2,4,6,8,10,12,14,16,18,20,22,24,26,28,30, <<1470>>,2972,2974,2976,2978,2980,2982,2984,2986,2988,2990, 2992,2994,2996,2998,3000}}
It is however not properly tail recursive, and will blow the stack (crash the kernel) for larger lists. Here is the tail-recursive version:
selLLTailRec[x_List, test_] := Flatten[ If[Last[#1] === {}, If[TrueQ[test[First[#1]]], {#2, First[#1]}, #2], (* else *) #0[Last[#1], If[TrueQ[test[First[#1]]], {#2, First[#1]}, #2] ]] &[Fold[{#2, #1} &, {}, Reverse[x]], {}]];
例如,
In[6]:= Block[{$IterationLimit= Infinity}, selLLTailRec[Range[500000],EvenQ]]//Short//Timing Out[6]= {2.39,{2,4,6,8,10,12,14,16,18,20,22, <<249978>>,499980,499982,499984,499986,499988,499990,499992, 499994,499996,499998,500000}}
This is recipe from Stan Wagon's book…use it when built-in Plot behaves erratically due to lack of precision
Options[PrecisePlot] = {PrecisionGoal -> 6}; PrecisePlot[f_, {x_, a_, b_}, opts___] := Module[{g, pg}, pg = PrecisionGoal /. {opts} /. Options[PrecisePlot]; SetAttributes[g, NumericFunction]; g[z_?InexactNumberQ] := Evaluate[f /. x -> z]; Plot[N[g[SetPrecision[y, \[Infinity]]], pg], {y, a, b}, Evaluate[Sequence @@ FilterRules[{opts}, Options[Plot]]]]];
I often use the following trick from Kristjan Kannike's when I need "dictionary-like" behavior from Mathematica's downvalues
index[downvalue_, dict_] := (downvalue[[1]] /. HoldPattern[dict[x_]] -> x) // ReleaseHold; value[downvalue_] := downvalue[[-1]]; indices[dict_] := Map[#[[1]] /. {HoldPattern[dict[x_]] -> x} &, DownValues[dict]] // ReleaseHold; values[dict_] := Map[#[[-1]] &, DownValues[dict]]; items[dict_] := Map[{index[#, dict], value[#]} &, DownValues[dict]]; indexQ[dict_, index_] := If[MatchQ[dict[index], HoldPattern[dict[index]]], False, True]; (* Usage example: *) (* Count number of times each subexpression occurs in an expression *) expr = Cos[x + Cos[Cos[x] + Sin[x]]] + Cos[Cos[x] + Sin[x]] Map[(counts[#] = If[indexQ[counts, #], counts[#] + 1, 1]; #) &, expr, Infinity]; items[counts]
When evaluation results are confusing, sometimes it helps to dump evaluation steps into a text file
SetAttributes[recordSteps, HoldAll]; recordSteps[expr_] := Block[{$Output = List@OpenWrite["~/temp/msgStream.m"]}, TracePrint[Unevaluated[expr], _?(FreeQ[#, Off] &), TraceInternal -> True]; Close /@ $Output; Thread[Union@ Cases[ReadList["~/temp/msgStream.m", HoldComplete[Expression]], symb_Symbol /; AtomQ@Unevaluated@symb && Context@Unevaluated@symb === "System`" :> HoldComplete@symb, {0, Infinity}, Heads -> True], HoldComplete] ] (* Usage example: *) (* puts steps of evaluation of 1+2+Sin[5]) into ~/temp/msgStream.m *) recordSteps[1+2+Sin[5]]
It is possible to run MathKernel in batch mode by using undocumented command-line options -batchinput
and -batchoutput
:
math -batchinput -batchoutput < input.m > outputfile.txt
(where input.m
is the batch input file ending with the newline character, outputfile.txt
is the file to which the output will be redirected).
In Mathematica v.>=6 the MathKernel has undocumented command-line option:
-noicon
which controls whether the MathKernel will have visible icon on the Taskbar (at least under Windows).
The FrontEnd (at least from v.5) has undocumented command-line option
-b
which disables the splash-screen and allows to run the Mathematica FrontEnd much faster
and option
-directlaunch
which disables the mechanism which launches the most recent Mathematica version installed instead of launching the version associated with .nb files in the system registry.
Another way to do this probably is :
Instead of launching the Mathematica.exe binary in the installation directory, launch the Mathematica.exe binary in SystemFiles\FrontEnd\Binaries\Windows. The former is a simple launcher program which tries its hardest to redirect requests for opening notebooks to running copies of the user interface. The latter is the user interface binary itself.
It is handy to combine the last command line option with setting global FrontEnd option VersionedPreferences->True
which disables sharing of preferences between different Mathematica versions installed :
SetOptions[$FrontEnd, VersionedPreferences -> True]
(The above should be evaluated in the most recent Mathematica version installed.)
In Mathematica 8 this is controlled in the Preferences dialog, in the System pane, under the setting "Create and maintain version specific front end preferences" .
It is possible to get incomplete list of command-line options of the FrontEnd by using undocumented key -h
(the code for Windows):
SetDirectory[$InstallationDirectory <> "\\SystemFiles\\FrontEnd\\Binaries\\Windows\\"]; Import["!Mathematica -h", "Text"]
得到:
Usage: Mathematica [options] [files] Valid options: -h (--help): prints help message -cleanStart (--cleanStart): removes existing preferences upon startup -clean (--clean): removes existing preferences upon startup -nogui (--nogui): starts in a mode which is initially hidden -server (--server): starts in a mode which disables user interaction -activate (--activate): makes application frontmost upon startup -topDirectory (--topDirectory): specifies the directory to search for resources and initialization files -preferencesDirectory (--preferencesDirectory): specifies the directory to search for user AddOns and preference files -password (--password): specifies the password contents -pwfile (--pwfile): specifies the path for the password file -pwpath (--pwpath): specifies the directory to search for the password file -b (--b): launches without the splash screen -min (--min): launches as minimized
其他选项包括:
-directLaunch: force this FE to start -32: force the 32-bit FE to start -matchingkernel: sets the frontend to use the kernel of matching bitness -Embedding: specifies that this instance is being used to host content out of process
Are there other potentially useful command-line options of the MathKernel and the FrontEnd? Please share if you know.
Related question .
My favorite hacks are small code-generating macros that allow you to replace a bunch of standard boilerplate commands with one short one. Alternatively, you can create commands for opening/creating notebooks.
Here is what I've been using for a while in my day-to-day Mathematica workflow. I found myself performing the following a lot:
- Make a notebook have a private context, load package(s) I need, make it autosave.
- After working with this notebook for a while, I'd want to do some throw away scratch computations in a separate notebook, with its own private context, while having access to definitions I've been using in the "main" notebook. Because I set up the private context, this requires to manually adjust $ContextPath
Doing all this by hand over and over is a pain, so let's automate! First, some utility code:
(* Credit goes to Sasha for SelfDestruct[] *) SetAttributes[SelfDestruct, HoldAllComplete]; SelfDestruct[e_] := (If[$FrontEnd =!= $Failed, SelectionMove[EvaluationNotebook[], All, EvaluationCell]; NotebookDelete[]]; e) writeAndEval[nb_,boxExpr_]:=( NotebookWrite[nb, CellGroupData[{Cell[BoxData[boxExpr],"Input"]}]]; SelectionMove[nb, Previous, Cell]; SelectionMove[nb, Next, Cell]; SelectionEvaluate[nb]; ) ExposeContexts::badargs = "Exposed contexts should be given as a list of strings."; ExposeContexts[list___] := Module[{ctList}, ctList = Flatten@List@list; If[! MemberQ[ctList, Except[_String]],AppendTo[$ContextPath, #] & /@ ctList, Message[ExposeContexts::badargs]]; $ContextPath = DeleteDuplicates[$ContextPath]; $ContextPath] Autosave[x:(True|False)] := SetOptions[EvaluationNotebook[],NotebookAutoSave->x];
Now, let's create a macro that's going to put the following cells in the notebook:
SetOptions[EvaluationNotebook[], CellContext -> Notebook] Needs["LVAutils`"] Autosave[True]
And here's the macro:
MyPrivatize[exposedCtxts : ({__String} | Null) : Null]:= SelfDestruct@Module[{contBox,lvaBox,expCtxtBox,assembledStatements,strList}, contBox = MakeBoxes[SetOptions[EvaluationNotebook[], CellContext -> Notebook]]; lvaBox = MakeBoxes[Needs["LVAutils`"]]; assembledStatements = {lvaBox,MakeBoxes[Autosave[True]],"(*********)"}; assembledStatements = Riffle[assembledStatements,"\[IndentingNewLine]"]//RowBox; writeAndEval[InputNotebook[],contBox]; writeAndEval[InputNotebook[],assembledStatements]; If[exposedCtxts =!= Null, strList = Riffle[("\"" <> # <> "\"") & /@ exposedCtxts, ","]; expCtxtBox = RowBox[{"ExposeContexts", "[", RowBox[{"{", RowBox[strList], "}"}], "]"}]; writeAndEval[InputNotebook[],expCtxtBox]; ] ]
Now when I type in MyPrivatize[]
is creates the private context and loads my standard package. Now let's create a command that will open a new scratch notebook with its own private context (so that you can hack there with wild abandon without the risk of screwing up the definitions), but has access to your current contexts.
SpawnScratch[] := SelfDestruct@Module[{nb,boxExpr,strList}, strList = Riffle[("\"" <> # <> "\"") & /@ $ContextPath, ","]; boxExpr = RowBox[{"MyPrivatize", "[", RowBox[{"{", RowBox[strList], "}"}], "]"}]; nb = CreateDocument[]; writeAndEval[nb,boxExpr]; ]
The cool thing about this is that due to SelfDestruct
, when the command runs it leaves no trace in the current notebook — which is good, because otherwise it would just create clutter.
For extra style points, you can create keyword triggers for these macros using InputAutoReplacements
, but I'll leave this as an exercise for the reader.
PutAppend with PageWidth -> Infinity
In Mathematica using of the PutAppend
command is the most straightforward way to maintain a running log file with results of intermediate computations. But it uses by default PageWith->78
setting when exporting expressions to a file and so there is no guarantee that every intermediate output will take only one line in the log.
PutAppend
does not have any options itself but tracing its evaluations reveals that it is based on the OpenAppend
function which has the PageWith
option and allows changing its default value by the SetOptions
command:
In[2]:= Trace[x>>>"log.txt",TraceInternal->True] Out[2]= {x>>>log.txt,{OpenAppend[log.txt,CharacterEncoding->PrintableASCII],OutputStream[log.txt,15]},Null}
So we can get PutAppend
to append only one line at a time by setting:
SetOptions[OpenAppend, PageWidth -> Infinity]
UPDATE
There is a bug introduced in version 10: SetOptions
no longer affects the behavior of OpenWrite
and OpenAppend
.
A workaround is to implement your own version of PutAppend
with explicit PageWidth -> Infinity
option:
Clear[myPutAppend] myPutAppend[expr_, pathtofile_String] := (Write[#, expr]; Close[#];) &[OpenAppend[pathtofile, PageWidth -> Infinity]]
Note that we also may implement it via WriteString
as shown in this answer, but in this case it will be necessary to preliminarily convert the expression into the corresponding InputForm
via ToString[expr, InputForm]
.
I was just looking through one of my packages for inclusion in this, and found some messages that I defined that work wonders: Debug::<some name>
. By default, they are turned off, so don't produce much overhead. But, I can litter my code with them, and turn them on if I need to figure out exactly how a bit of code is behaving.
One of the things that bothers me about the built-in scoping constructs is that they evaluate all of the local variable definitions at once, so you can't write for example
With[{a = 5, b = 2 * a}, ... ]
So a while ago I came up with a macro called WithNest that allows you to do this. I find it handy, since it lets you keep variable bindings local without having to do something like
Module[{a = 5,b}, b = 2 * a; ... ]
In the end, the best way I could find to do this was by using a special symbol to make it easier to recurse over the list of bindings, and I put the definition into its own package to keep this symbol hidden. Maybe someone has a simpler solution to this problem?
If you want to try it out, put the following into a file called Scoping.m
:
BeginPackage["Scoping`"]; WithNest::usage= "WithNest[{var1=val1,var2=val2,...},body] works just like With, except that values are evaluated in order and later values have access to earlier ones. For example, val2 can use var1 in its definition."; Begin["`Private`"]; (* Set up a custom symbol that works just like Hold. *) SetAttributes[WithNestHold,HoldAll]; (* The user-facing call. Give a list of bindings and a body that's not our custom symbol, and we start a recursive call by using the custom symbol. *) WithNest[bindings_List,body:Except[_WithNestHold]]:= WithNest[bindings,WithNestHold[body]]; (* Base case of recursive definition *) WithNest[{},WithNestHold[body_]]:=body; WithNest[{bindings___,a_},WithNestHold[body_]]:= WithNest[ {bindings}, WithNestHold[With[List@a,body]]]; SyntaxInformation[WithNest]={"ArgumentsPattern"->{{__},_}}; SetAttributes[WithNest,{HoldAll,Protected}]; End[]; EndPackage[];
This code makes a palette that uploads the selection to Stack Exchange as an image. On Windows, an extra button is provided that gives a more faithful rendering of the selection.
Copy the code into a notebook cell and evaluate. Then pop out the palette from the output, and install it using Palettes -> Install Palette...
If you have any trouble with it, post a comment here. Download the notebook version here .
Begin["SOUploader`"]; Global`palette = PaletteNotebook@DynamicModule[{}, Column[{ Button["Upload to SE", With[{img = rasterizeSelection1[]}, If[img === $Failed, Beep[], uploadWithPreview[img]]], Appearance -> "Palette"], If[$OperatingSystem === "Windows", Button["Upload to SE (pp)", With[{img = rasterizeSelection2[]}, If[img === $Failed, Beep[], uploadWithPreview[img]]], Appearance -> "Palette"], Unevaluated@Sequence[] ] }], (* Init start *) Initialization :> ( stackImage::httperr = "Server returned respose code: `1`"; stackImage::err = "Server returner error: `1`"; stackImage[g_] := Module[ {getVal, url, client, method, data, partSource, part, entity, code, response, error, result}, getVal[res_, key_String] := With[{k = "var " <> key <> " = "}, StringTrim[ First@StringCases[ First@Select[res, StringMatchQ[#, k ~~ ___] &], k ~~ v___ ~~ ";" :> v], "'"] ]; data = ExportString[g, "PNG"]; JLink`JavaBlock[ url = "http://stackoverflow.com/upload/image"; client = JLink`JavaNew["org.apache.commons.httpclient.HttpClient"]; method = JLink`JavaNew[ "org.apache.commons.httpclient.methods.PostMethod", url]; partSource = JLink`JavaNew[ "org.apache.commons.httpclient.methods.multipart.\ ByteArrayPartSource", "mmagraphics.png", JLink`MakeJavaObject[data]@toCharArray[]]; part = JLink`JavaNew[ "org.apache.commons.httpclient.methods.multipart.FilePart", "name", partSource]; part@setContentType["image/png"]; entity = JLink`JavaNew[ "org.apache.commons.httpclient.methods.multipart.\ MultipartRequestEntity", {part}, method@getParams[]]; method@setRequestEntity[entity]; code = client@executeMethod[method]; response = method@getResponseBodyAsString[]; ]; If[code =!= 200, Message[stackImage::httperr, code]; Return[$Failed]]; response = StringTrim /@ StringSplit[response, "\n"]; error = getVal[response, "error"]; result = getVal[response, "result"]; If[StringMatchQ[result, "http*"], result, Message[stackImage::err, error]; $Failed] ]; stackMarkdown[g_] := "![Mathematica graphics](" <> stackImage[g] <> ")"; stackCopyMarkdown[g_] := Module[{nb, markdown}, markdown = Check[stackMarkdown[g], $Failed]; If[markdown =!= $Failed, nb = NotebookCreate[Visible -> False]; NotebookWrite[nb, Cell[markdown, "Text"]]; SelectionMove[nb, All, Notebook]; FrontEndTokenExecute[nb, "Copy"]; NotebookClose[nb]; ] ]; (* Returns available vertical screen space, taking into account screen elements like the taskbar and menu *) screenHeight[] := -Subtract @@ Part[ScreenRectangle /. Options[$FrontEnd, ScreenRectangle], 2]; uploadWithPreview[img_Image] := CreateDialog[ Column[{ Style["Upload image to the Stack Exchange network?", Bold], Pane[ Image[img, Magnification -> 1], {Automatic, Min[screenHeight[] - 140, 1 + ImageDimensions[img][[2]]]}, Scrollbars -> Automatic, AppearanceElements -> {}, ImageMargins -> 0 ], Item[ ChoiceButtons[{"Upload and copy MarkDown"}, \ {stackCopyMarkdown[img]; DialogReturn[]}], Alignment -> Right] }], WindowTitle -> "Upload image to Stack Exchange?" ]; (* Multiplatform, fixed-width version. The default max width is 650 to fit Stack Exchange *) rasterizeSelection1[maxWidth_: 650] := Module[{target, selection, image}, selection = NotebookRead[SelectedNotebook[]]; If[MemberQ[Hold[{}, $Failed, NotebookRead[$Failed]], selection], $Failed, (* There was nothing selected *) target = CreateDocument[{}, WindowSelected -> False, Visible -> False, WindowSize -> maxWidth]; NotebookWrite[target, selection]; image = Rasterize[target, "Image"]; NotebookClose[target]; image ] ]; (* Windows-only pixel perfect version *) rasterizeSelection2[] := If[ MemberQ[Hold[{}, $Failed, NotebookRead[$Failed]], NotebookRead[SelectedNotebook[]]], $Failed, (* There was nothing selected *) Module[{tag}, FrontEndExecute[ FrontEndToken[FrontEnd`SelectedNotebook[], "CopySpecial", "MGF"]]; Catch[ NotebookGet@ClipboardNotebook[] /. r_RasterBox :> Block[{}, Throw[Image[First[r], "Byte", ColorSpace -> "RGB"], tag] /; True]; $Failed, tag ] ] ]; ) (* Init end *) ] End[];
I'm sure a lot of people have encountered the situation where they run some stuff, realizing it not only stuck the program, but they also haven't saved for the last 10 minutes!
编辑
After suffering from this for some time, I one day found out that one can create auto-save from within the Mathematica code. I think that using such auto-save have helped me a lot in the past, and I always felt that the possibility itself was something that not a lot of people are aware that they can do.
The original code I used is at the bottom. Thanks to the comments I've found out that it is problematic, and that it is much better to do it in an alternative way, using ScheduledTask
(which will work only in Mathematica 8).
Code for this can be found in this answer from Sjoerd C. de Vries
(Since I'm not sure if it's OK to copy it to here, I'm leaving it as a link only.)
The solution below is using Dynamic
. It will save the notebook every 60 seconds, but apparently only if its cell is visible . I'm leaving it here only for completion reasons. (and for users of Mathematica 6 and 7)
/编辑
To solve it I use this code in the beginning of a notebook:
Dynamic[Refresh[NotebookSave[]; DateString[], UpdateInterval -> 60]]
This will save your work every 60 seconds.
I prefer it to NotebookAutoSave[]
because it saves before the input is processed, and because some files are more text than input.
I originally found it here: http://en.wikipedia.org/wiki/Talk:Mathematica#Criticisms
Note that once running this line, saving will happen even if you close and re-open your file (as long as dynamic updating is enabled).
Also, since there is no undo in Mathematica , be careful not to delete all your content, since saving will make it irreversible (as a precaution move, I remove this code from every finished notebook)
This one was written by Alberto Di Lullo, (who doesn't appear to be on Stack Overflow).
CopyToClipboard
, for Mathematica 7 (in Mathematica 8 it's built in)
CopyToClipboard[expr_] := Module[{nb}, nb = CreateDocument[Null, Visible -> False, WindowSelected -> True]; NotebookWrite[nb, Cell[OutputFormData@expr], All]; FrontEndExecute[FrontEndToken[nb, "Copy"]]; NotebookClose@nb];
Original post: http://forums.wolfram.com/mathgroup/archive/2010/Jun/msg00148.html
I have found this routine useful for copying large real numbers to the clipboard in ordinary decimal form. Eg CopyToClipboard["123456789.12345"]
Cell[OutputFormData@expr]
neatly removes the quotes.
Remember that The Mathematica Book is also available online at http://reference.wolfram.com/legacy/v5_2/ – though it's superseded by the current documentation at http://reference.wolfram.com
I find it really useful when developing packages to add this keyboard shortcut to my SystemFiles/FrontEnd/TextResources/Windows/KeyEventTranslations.tr
file.
(* Evaluate Initialization Cells: Real useful for reloading library changes. *) Item[KeyEvent["i", Modifiers -> {Control, Command}], FrontEndExecute[ FrontEndToken[ SelectedNotebook[], "EvaluateInitialization"]]],
Next for every Packagename.m
I make a PackagenameTest.nb
notebook for testing and the first 2 cells of the test notebook are set as initialization cells. In the first cell I put
Needs["PackageManipulations`"]
to load the very useful PackageManipulations library which was written by Leonid. The second cell contains
PackageRemove["Packagename`Private`"] PackageRemove["Packagename`"] PackageReload["Packagename`"]
which all do the actual package reloading. Note the first two lines are there only to Remove
all symbols as I like to keep the contexts as clean as possible.
Then the workflow for writing and testing a package becomes something like this.
- Save changes to
Packagename.m
. - Go to
PackagenameTest.nb
and doCTRL + ALT + i
.
This causes the initialization cells to reload the package, which makes testing real simple.
Following function format[expr_]
can be used to indent/format unformatted mathematica
expressions that spans over a page
indent[str_String, ob_String, cb_String, delim_String] := Module[{ind, indent, f, tab}, ind = 0; tab = " "; indent[i_, tab_, nl_] := nl <> Nest[tab <> ToString[#] &, "", i]; f[c_] := (indent[ind, "", " "] <> c <> indent[++ind, tab, "\n"]) /;StringMatchQ[ob, ___ ~~ c ~~ ___]; f[c_] := (indent[--ind, "", " "] <> c <> indent[ind, tab, "\n"]) /;StringMatchQ[cb, ___ ~~ c ~~ ___]; f[c_] := (c <> indent[ind, tab, "\n"]) /;StringMatchQ[delim, ___ ~~ c ~~ ___]; f[c_] := c; f /@ Characters@str // StringJoin]; format[expr_] := indent[expr // InputForm // ToString, "[({", "])}", ";"]; (* format[Hold@Module[{ind, indent, f, tab}, ind = 0; tab = " "; indent[i_, tab_, nl_] := nl <> Nest[tab <> ToString[#] &, "", i]; f[c_] := (indent[ind, "", " "] <> c <> indent[++ind, tab, "\n"]) /;StringMatchQ[ob, ___ ~~ c ~~ ___]; f[c_] := (indent[--ind, "", " "] <> c <> indent[ind, tab, "\n"]) /;StringMatchQ[cb, ___ ~~ c ~~ ___]; f[c_] := (c <> indent[ind, tab, "\n"]) /;StringMatchQ[delim, ___ ~~ c ~~ ___]; f[c_] := c; f /@ Characters@str // StringJoin]] *)
ref: https://codegolf.stackexchange.com/questions/3088/indent-a-string-using-given-parentheses