28
$\begingroup$

My init.m Feels Like it's Missing Something

Although I am familiar with about a dozen or so programming languages I am only sort of, kind of, halfway competent in about three. MMA with it's boxes, expressions, patterns, symbols, and cells is a whole new beast to me. It forces you to forget everything you think you know about programming and think differently. Then it throws a wrench into the whole mess hy introducing the init.m without a good explanation.

The following working code is what I have so far. It is what I call my pre-alpha init.m. My concerns are that it may be missing something that MMA experts normally place in there. For example is this a good place to clean out old temp files, remove obsolete symbols or delete obsolete objects, create persistent objects, set new paths, set $HistoryLength, ClearSystemCache, is using Once here okay, etc.? My other concern is where should I drop copies of init.m if I want it to survive a refreshed Kernel or a crashed FrontEnd?

(* overload immediately needed repository resources *)

Once@(
   Quiet@PersistResourceFunction["PersistResourceFunction"];
   Quiet@PersistResourceFunction["SymbolQ"];
   Quiet@PersistResourceFunction["ResourceFunctionMessage"];
   Quiet@ResourceUpdate[ResourceObject["PersistResourceFunction"]];
   );

(* overload immediately needed packages *)

Once@Map[Get,{"Alphas`", "NBEssentials`", "NBTaskmate`","NBStyles`"}];

(* other cool tasks TBD *)

Since I have your attention is it okay to do this: Once@Get /@ {"Alphas", "NBEssentials", "NBTaskmate","NBStyles"};?

There is Almost No Help Published by Wolfram

Some of our most essential code is hidden away in a file that we can just drop 'n' forget. Although the proper contents of this infamous file is expected to be well understood by all seasoned programmers the official documentation at Wolfram only hints at but gives no solid examples of the kind of things to put in there. This would help coders like me who are not programmers but come from a different field like physics and engineering who need to employ coding with their work and must adhere to best practices to go with it.

What Mathematica Stack Exchange Has to Offer

As of this writing a search for init.m yields 419 help posts. However these are all about fixing specific-area applications or broken code not about building a proper init.m.

There are a few "big-list" posts such as the ambitious undisputed world heavyweight that grew into Godzilla which I really like, Where can I find examples of good Mathematica programming practice?, unfortunately in its quest to answer all best practices under the sun it forgets to even mention the init.m. Another one I really like is the more focused Getting serious about Mathematica programming but it too omits the init.m. There are others. This is just a very small sampling that stood out to me as expected to have a dedicated category on the init.m.

The Five Secondary Goals of this Post Are to Help Build Best Practices

Of course the primary goal is to examine my init.m which will help me figure out what is good to put in there and what not to put in there. Along the way we can help many others by identifying some best practices.

  1. Let others learn from your best practices by sharing your code in an Answer.
  2. Let others share their expertise in how to improve your shared code.
  3. By identifying what every init.m file should have and why.
  4. By identifying what what every init.m file should NOT have and why.
  5. By identifying in which directories we should drop 'n' forget our init.m and why.

With posts like these there are no losers, everybody wins. The only catch is we all need to participate to win.

$\endgroup$
12
  • 2
    $\begingroup$ Great question! I too would like advice on how to improve my init.m $\endgroup$ May 20 at 6:48
  • 1
    $\begingroup$ @DrMrstheMonarch you can probably get the ball rolling by sharing your init.m regardless of how satisfied or unsatisfied you may be with it and ask for a critique. if too long remove the fat. if it has private data remove or obscurificate those details.. i intend to share my init.m in the next 2 or 3 days. $\endgroup$ May 20 at 9:38
  • 1
    $\begingroup$ I set this to CW for the time being; if anyone wants to discuss on whether we should keep this, please open something on Meta. $\endgroup$ May 20 at 22:27
  • 3
    $\begingroup$ I disagree. This question should be closed as too broad ("Needs more focus"), but by making it CW, I'm in favor of keeping it open, similar to other CW posts with a broad focus ("Pitfalls", "good examples", etc.). Now closure would be more like sending it to a gulag. But here we are debating the issue, which should be happening on meta. $\endgroup$
    – Michael E2
    May 30 at 0:15
  • 2
    $\begingroup$ I like the question. I'm going to look over all the answers and pick-and-choose from the ideas presented. I'm sure other Mathematica users will benefit in the same way. So I'd prefer to keep this open and accepting answers. If it needs to be CW to do that, fine by me. TBH, I don't understand the distress of the OP. The Q has attracted interest, and good answers. Over time there will be more answers. What's not to like? (I hope it isn't a matter of rep ...) $\endgroup$
    – davidbak
    May 30 at 0:49

6 Answers 6

16
$\begingroup$

I am an init.m ascetic. And I doubt after 30+ years of using Mathematica I will change. Everyone else, who wishes to, may proclaim how it is indispensable to their workflow, and I will accept their pronouncements without comment or criticism.

My Kernel init.m has nothing in it. My Front End init.m has whatever the FE puts in there from setting preferences, some history from the SEUploader palette, and hopefully little else. I try to avoid SetOptions[$FrontEnd,...] and use SetOptions[$FrontEndSession,...] instead.

I do have a notebook I always use to open Mathematica with some standard things, like $HistoryLength = 5, tucked away in section called "Init" that I select and execute whenever the Kernel starts or restarts. Many years ago I put something in one of the init.m files that caused bugs in something I was working on. It took me a long time to figure out what was causing the problem, because it's hard to remember everything you put in a file you never see. Once I had something in init.m that caused the kernel to crash. After few problem like that, I decided sometime in the 1990s to ditch using init.m and perform initializations optionally and separately from starting the kernel. Since then I've generally come to realize that learning to use a tool as it was designed is easier than trying to make a tool into something else. That's not an absolute rule though, and this tool, Mathematica, comes designed with init.m and SetOptions[], among other things. So others may have different opinions as well as good reasons for their particular setup. I will add this: If you are working with others, it's helpful for everyone to have the same setup.

Here are the "Init" codes I use:

$HistoryLength = 5;
Needs["NDSolve`FEM`"];
Needs["GeneralUtilities`"];
Needs["CompiledFunctionTools`"];
traceView2[..] := ... (*https://mathematica.stackexchange.com/a/29340/4999*)
traceView2i[..] := ... (*=traceView2[] + TraceInternal->True*)
BoxForm`UseApproximations = False;
(* add Okabe-Ito colorblind palette to ColorData[]
     per https://mathematica.stackexchange.com/a/57893/4999 *)
Typeset`$InformationGridOpen = False;(* start ?symbol closed *)
qlink[..] := ... (* create link to Mma.SE question;
     see https://mathematica.stackexchange.com/questions/87375/plotting-the-tangent-of-a-curve#comment237773_87375 *)
echo = (Print[#]; #) &; (* for debugging (don't like Echo[]) *)
dbecho[lbl_] := (Print[lbl -> #]; #) &; (* ditto *)

Plus a few useless utilities I won't mention because I've never used them. In fact I forgot they were there, until looking up my "Init" codes for this answer.


P.S. I think this Q&A might ought to be a "Community Wiki." I feel my answer is strongly opinionated and what is best will depend on individual situations. So what seems the best answer to one person may seem a bad answer to another.


Update 2022.06.12

Here's one of those useless things I used today....

I hate it when users leave off semicolons that would suppress unnecessary output on a dozen or two input lines. I'd only use this function on this site, so more useful to someone like me.

addsemis[c_CellObject] := Module[{ce},
  ce = NotebookRead@c;
  SelectionMove[c, After, Cell];
  NotebookWrite[ParentNotebook[c],
   Replace[ce, {
     e : RowBox[{_, ";"}] :> e,
     e_RowBox :> RowBox[{e, ";"}]}, 3]];
  NotebookDelete[c]
  ]

Example usage: addsemis[PreviousCell[]].

Caveat: 1. It writes in a notebook, so I'd use it only on a temporary notebook in case I trashed it. 2. In a month or two, I'll forget all about this function again, or forget its name, and then think it's faster to type 20 semicolons than to look up the function again.

Acknowledgement: I probably got the idea from Cell splitting in mathematica, since a couple of the lines are identical.

$\endgroup$
2
  • $\begingroup$ i also had a buggy init.m so i stopped using it. this time im building it up from scratch based on best practices or examples contributed here. although a mod did move this post to the gulag aka "communist" wiki i am asking to have it moved back. it is where posts go to die a slow grueling death as is evident by examining lively activity before and other than my own the zero activity afterwards. i also have an echo in which if placed inside a function it will automatically Echo any symbol's name along with value. it has more difficulty with arguments but i fixed that too. $\endgroup$ May 29 at 6:29
  • 2
    $\begingroup$ @JulesManson 2 answers before CW, 4 more answers after. More upvoting after CW, (my impression, I didn't count everyone's; but 13/14 upvotes on my post came after CW). Doesn't seem a gulag to me. $\endgroup$
    – Michael E2
    May 29 at 14:07
10
$\begingroup$

I tend to put a lot of little functions in my init.m file, functions that take arguments and use module variables. I found that I would now have Global symbols like x, var, date, name, etc, before even running any commands.

So the interesting thing I have in my init.m file is a package structure:

BeginPackage["Init`"]

<exported functions list>

Begin["`Private`"]
<implement functions>
End[]
EndPackage[]

never regretted it.

$\endgroup$
1
  • 1
    $\begingroup$ Could also simplify the init.m to use an explicitly designed package, i.e. just put in it something like Needs["JasonTools`"] to avoid needing to define a bunch of functions in a portion of the layout that is less discoverable $\endgroup$
    – b3m2a1
    Jun 6 at 19:21
6
$\begingroup$
(** User Mathematica initialization file **)

$PrePrint = Replace[# , mat_?MatrixQ :> MatrixForm[mat]] &;

Needs["Let`"];

Needs["sprintf`"];

Get["AcademicTheme`"];

The reason to keep it relatively empty is to avoid problems when sharing a notebook with someone else (who may not have the same init.m customizations).

One thing I used to have was a hook in $Pre (or maybe $PreRead?) that removed some front-end formatting. It's usually a mistake if eg. MatrixForm is in the input if you use the above $PrePrint. I ultimately removed it. The combination can be good for new users who are sometimes mistakenly learn that the construction // MatrixForm is a formatting directive, rather than // is a form of composition.

$\endgroup$
2
  • $\begingroup$ I've been thinking more about this, and I think the reason I've kept it so bare is really the difficulty a highly-customized init.m poses when sharing my work. Changing a plot theme or how matrices are presented is fine, that just changes what I see. But adding functions that others might have would cause an issue if they tried to rerun the notebook. $\endgroup$
    – evanb
    May 23 at 8:06
  • $\begingroup$ i like how you mixed Get with Needs. i just use Get for all my packs but i can identify two that should only be called with Needs. ill do that too. thanks for sharing. $\endgroup$ May 29 at 21:26
5
$\begingroup$
SetOptions[$FrontEnd, 
  EvaluationCompletionAction->{"ShowTiming"}, 
  CodeAssistOptions->{"FloatingElementEnable" -> False, "MaxGlobalMatches" -> 10}, 
  ShowPredictiveInterface->False, 
  FractionBoxOptions->{AllowScriptLevelChange->False},
  Graphics3DBoxOptions -> {SphericalRegion -> True},
  "EvaluationQueueActions"->{"Icon","Flash","NotificationCenter","ProgressIndicator"},
  MessageOptions -> {"InsufficientVersionWarning" -> False, "KernelMessageAction" -> "PrintToNotebook"},
  "NotebookSecurityOptions" -> {"TrustByDefault" -> True},
  PrivateFrontEndOptions->{"ShowAtStartup"->"NewDocument"},
  RenderingOptions->{"HardwareAntialiasingQuality"->1}
];

If[$VersionNumber>=12,SetSystemOptions[ "TypesetOptions" -> "NumericalApproximationForms" -> False]];
$\endgroup$
7
  • $\begingroup$ i <3 how you set FE options here. right now i only use the Options Inspector which is a easy to reset to defaults because something becomes corrupted but a pain to set back to preferred settings. your way makes it easy to reset back to preferred settings. im going to do that from now on. thank you for sharing. $\endgroup$ May 29 at 21:31
  • $\begingroup$ @chyanog Those that I understand, are great. I find no support for "EvaluationQueueActions", what do those do? $\endgroup$
    – Nicholas G
    May 31 at 5:20
  • $\begingroup$ @NicholasG Relevant discussion, when-calculating-the-taskbar-icon-will-not-change-in-mathematica-12-2 $\endgroup$
    – chyanog
    May 31 at 6:54
  • 1
    $\begingroup$ @JulesManson I'm glad it helped. $\endgroup$
    – chyanog
    May 31 at 7:04
  • 1
    $\begingroup$ I see, the answer to my question "What does ` "EvaluationQueueActions"->{"Icon","Flash","NotificationCenter","ProgressIndicator"}` do?" is that in a Windows or Mac it makes the Mathematica Icon at the taskbar or dock flash when an evaluation is completed while Mathematica is minimized (in a way analogous to how Outlook tries to get your attention for a meeting notification). $\endgroup$
    – Nicholas G
    May 31 at 14:00
4
$\begingroup$

As I mentioned in a comment, I do not use an init.m file, I paste my frequently used functions from project notebook to project notebook as an initialization cell. That having been said, my initialization cell is:

If[False, {(* 
  true for saving to PDF at true dimensions and ImageResolution of \
1200 PDI, false for large graphs for screen and saving as PNG, 
  see  https://mathematica.stackexchange.com/a/234591/43662*)
  ftsz = 12,(*fontsize 12 for graph publication quality PDFs*)
  imgsz = 100, 
  imgrez = 2400}(*imagesize coefficient 57/was100 equal to one inch*)
\

 , {ftsz = 38, imgsz = 267, 
  imgrez = 72}];(*else for large images and publishing PNG graphs \
42/200*)
fntandsz = {FontFamily -> (fntFam = "Georgia")(*"Times"*), 
  FontSize -> ftsz};
$HistoryLength = 5;
txt[a_, b_, c : {_?NumericQ, _?NumericQ} : {0, 0}, 
  d : {_?NumericQ, _?NumericQ} : {1, 0}, opt : OptionsPattern[]] := 
 Text[Style[a, opt, FontFamily -> "Georgia"(*"Times"*), 
   FontSize -> ftsz], b, c, 
  d](* This simplifies the input for text in raphics to avoid the \
need to nest Text[Style[ ] ] in every graphic. The options at the end \
get passed to Style[]. The previous arguments are made optional by \
getting a default value ":{0,0}" while a test prevents the code from \
confusing an option for those with ":{_?NumericQ,_NumericQ}" *) 
fpath = (NotebookBrowseDirectory /. Options[$FrontEnd]) <> 
  "\\";(*save in notebook path*)
(*stop evaluation if the path does not end in \Documents\*)
If[StringTake[fpath, -11] != "\\Documents\\",
 (*Remove cells from evaluation queue*)(
  SelectionMove[EvaluationNotebook[], All, Notebook, 
   AutoScroll -> False];
  FrontEndExecute@FrontEndToken@"RemoveFromEvaluationQueue";
  SelectionMove[EvaluationCell[], After, Cell, AutoScroll -> False];
  (*set $Pre to abort current cell but before that schedule a task to \
un-define $Pre*)
  SessionSubmit[ScheduledTask[$Pre =., {Quantity[3, "Seconds"]}]];
  MessageDialog[
   "Wrong working directory! Open and close a file in /Documents and \
rerun."];
  $Pre = Abort[] &; 
  Abort[];)];(*end of sequence stopping evaluation if the directory \
is false*)
droptrailingperiod[x_] := 
 If[Round[x] == x,(*is the rightmost a period, from some precision?*)

  
  Round[x](*then use Round to drop the trailing period*)
  , x](*else not*)
adollartick[
  x_] := {x,(*define a function that creates a tick label pair for \
dollar amounts*)
  NumberForm[droptrailingperiod@x, NumberSigns -> {"-$", "$"}, 
   DigitBlock -> 
    3](*put dollar sign and comma and drop the trailing period*)
  }
dollarticks[min_, max_] := 
 adollartick[#] & /@ 
  N[FindDivisions[{min, max}, 
    3]](*to produce dollar amounts as tick marks with three tickmarks*)


dollarticks7[min_, max_] := 
 adollartick[#] & /@ 
  N[FindDivisions[{min, max}, 
    7]](*to produce dollar amounts as tick marks with seven tickmarks*)


apercenttick[x_] := {x,(*function of tick pair for percentages*)
  ToString[
    droptrailingperiod[
     100 x]](*multiply by 100 and drop trailing period*)
   <> "%"}(*and append a % sign*)
percentticks[min_, max_] := 
 apercenttick[#] & /@ N[FindDivisions[{min, max}, 7]]
fewpercentticks[min_, max_] := 
 apercenttick[#] & /@ N[FindDivisions[{min, max}, 4]]
fewticks[min_, max_] := 
 droptrailingperiod[#] & /@ N[FindDivisions[{min, max}, 4]]
acommatick[x_] := {x, AccountingForm[x]}
commaticks[min_, max_] := 
 acommatick[#] & /@ FindDivisions[{min, max}, 7]
fewcommaticks[min_, max_] := 
 acommatick[#] & /@ FindDivisions[{min, max}, 4]
seagreen = 
 RGBColor[{46/255, 139/255, 
   87/255}];(*also define some extra colors*)
yellowgreen = RGBColor[{173/255, 1, 47/255}];
darkyellow = RGBColor[{204/255, 204/255, 0}];
(*a very complex function for placing text in 3D:*)
text3D[str_, location_ : {0, 0, 0}, 
  scaling : {_?NumericQ, _?NumericQ} : { 1, 1}, 
  longitude : _?NumericQ : 0, elevation : _?NumericQ : 0, 
  tilt : _?NumericQ : 0, opt : OptionsPattern[]] := 
 Module[{mesh = 
    DiscretizeGraphics[
     Text[
      Style[str, opt, FontFamily -> "Georgia"(*"Times"*), 
       FontSize -> 12(*don't scale with ftsz*)]], _Text, 
     MaxCellMeasure -> 0.04],
   rotmatrx = 
    RotationMatrix[longitude, {0, 0, 1}] . 
     RotationMatrix[-elevation, {0, 1, 0}] . 
     RotationMatrix[tilt, {1, 0, 0}]}, 
  Join[{EdgeForm[]}, 
   MeshPrimitives[mesh, 
     2] /. {x_?NumberQ, 
      y_?NumberQ} :> (rotmatrx . (scaling~Join~{1} {x, y, 0}) + 
       location)
   (*,{Black},MeshPrimitives[BoundaryMesh[mesh],1]/.{x_?NumberQ,y_?
   NumberQ}\[RuleDelayed](rotmatrx.(scaling~Join~{1} {x,y,0})+
   location)REMOVE REM IF NEEDING OUTLINES, see https://
   mathematica.stackexchange.com/a/131842/43662*)]]
twoYrDigitAbbrev[yr_] := 
 "\[CloseCurlyQuote]" <> 
  StringTake[ToString[yr], -2](*Show 1964 as '64*)
twoDgNo[x_] := 
 NumberForm[
  x, {5, 2}](*Show 3.1415923 as 3.14; no not use for numbers with \
over 5 digits*)
numericOrPercent[num_, digits_ : {2, 0}] := Which[
  0 <= num <= 1 && NumericQ[num], 
  Style[PercentForm[num, digits], FontSlant -> Plain],
  NumericQ[num], Style[num, FontSlant -> Plain],
  True, num]
tblFm2Dgt[x_List, opt : OptionsPattern[]] /; Length@Dimensions@x > 1 :=
  TableForm[Map[twoDgNo[#] &, x, {2}], 
  opt](*to make tables show two digits while exportable with built-in \
precision*)
(*define the chi-squared test*)
chiSquareTest[obs_List, exp_List] /; 
  Dimensions[obs] == Dimensions[exp] := 
 Block[{t}, t = Total[(Flatten@obs - Flatten@exp)^2/Flatten@exp] // N;
  {Rule["chisqr", t], 
   Rule[pval, 
    SurvivalFunction[
     ChiSquareDistribution[
      Times @@ 
       Table[Dimensions[exp][[i]] - 1, {i, Length@Dimensions@exp}]], 
     t]]}]
expTable[u_List] := Module[(*Create null hypothesis matrix*)
  {rs = Plus @@ u,
   cs = Plus @@ Transpose[u],
   n = Total[Flatten[u]]},
  Transpose@Outer[Times, rs, cs]/n]
lineAndPoints[lst_List] := {Line[lst], 
  Tooltip[Point[#], #[[2]]] & /@ lst}
percent[n_] := 
 If[n > 1 || n < 0, "Erroneous use of percent.", 
  If[n == 1, "100%", StringTake[ToString[twoDgNo[n]], -2] <> "%"]]
SetOptions[AccountingForm, 
  DigitBlock -> 3];(*Use AccountingForm to see 
numbers with commas and spaces every third decimal digit.*)

I also have some functions for abbeviations according to the Blue Book citation system that legal practice uses, if anyone is interested I 'd gladly share.

$\endgroup$
1
  • $\begingroup$ i used to do that. i had two very long init cells. then one day i decided to tie everything in each cell to user defined function as a persistent symbol. it worked. all i then needed was one init cell calling two persistent symbols once. give it a try. it should work. :) $\endgroup$ May 29 at 21:20
2
$\begingroup$

The documentation for init.m is functional, if sparse. There are no Examples, and there is no Applications section.

The init.m documentation points to Wolfram System Setup under "Related Guides", but that topic apparently doesn't point back to init.m, or at least, not directly.

The "See Also" for init.m contains four items, three of which are not helpful in the least. Those three are wolfram, mathematica, and Mathematica, all of which appear to be largely nonsensical in this context.

$\endgroup$
5
  • 2
    $\begingroup$ You can write your observations in the comments below the answer. Or, you can expand this answer to include a use-case/scenario originating from an entry in a typical init.m file that, at least partially, addresses the question. Thanks. $\endgroup$
    – Syed
    May 20 at 15:42
  • $\begingroup$ @StevenBlack i love how you summed up the lack of good documentation by wolfram site. do you mind if i add it to my post as a slightly edited or paraphrased quote by you? $\endgroup$ May 29 at 5:58
  • $\begingroup$ @JulesManson 👍🏻 $\endgroup$ May 30 at 11:35
  • 2
    $\begingroup$ One of the "nonsensical" items explicitly points out how to add an init.m file or importantly, to prevent it from being loaded. To me that's a sensible reason to include it. I wonder if the others have the same options, even though it is not mentioned. $\endgroup$
    – Michael E2
    Jun 1 at 5:23
  • $\begingroup$ @MichaelE2 even my own rudimentary init.m (shown in Question post) would probably have been very useful in giving noobs like me ideas of how to use the init.m. $\endgroup$ Jun 5 at 21:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.