Skip to main content

stylesheet - Automatic generation of cell tags


A similar question has been asked before, with no answers. I would love to have a way to easily reference objects associated with counters. To provide such a capability for things like figures, tables, etc., it would be great if it was possible to automatically create tags as part of a Stylesheet definition. Can this be done?


For example, I have a Stylesheet definition for my figure captions that reads like this:


Cell[StyleData["FigureCaption", StyleDefinitions -> StyleData["SmallText"]],
TextAlignment->Center,
TextJustification->0.,
CounterIncrements->"Figure",

MenuSortingValue->10000,
FontFamily->"Source Sans Pro",
FontSize->12,
FontWeight->"Plain",
FontSlant->"Plain",
FontVariations->{"StrikeThrough"->False,
"Underline"->False},
FontProperties->{"ScreenResolution"->Automatic}]

Is it possible to add to this some code that will automatically create a tag of the form, say, "figctr", where ctr would be the value of the counter associated with the caption?



CLARIFICATION: Suppose I have a document that includes many FigureCaption cells that reference the counter above. Is it possible to programmatically create CellTags that reference the current value of the counter on each of these cells?


For example, I would like the 5th FigureCaption cell in notebook to have the CellTag "fig'ctr'", where 'ctr' is 5.


I use CellTags for navigation in a lecture notebook. It would very helpful to have the ability to add and delete FigureCaption cells in the notebook and then have some code that would update the cell tags to their appropriate values. Here is a related question I asked.


Note: As outlined in my comment, updating cell tags after having inserted more figures cannot be done in isolation: If we update the tags, the question comes up as to what happens to links after you edit the notebook. The part that's problematic about this is of course not the updating of the CellTags, but the fact that if we simply update the tags so they correspond to the counters, then existing references will point to the wrong cells. This means that we also need to search for and update the references to all of the tags.



Answer



Here's a solution. The inspiration for much of the code came from Eric Schulz's lecture on "Wisdom Gained from Publishing a CDF ebook" as well as as some code from this post. Below are the components for creating automatic cell tags for FigureCaption cells, but the idea can be extended to more than one type. The following are the components needed to keep everything updated for the cell type "FigureCaption" but can be used for multiple cell types.




  1. A custom stylesheet that includes a definition for a "FigureCaption" cell. Make sure to setup the counters as shown.


    Cell[StyleData["FigureCaption"], CellMargins->{{54, 24}, {10, -5}}, TextAlignment->Center, LineSpacing->{1, 2}, ParagraphSpacing->{0, 5}, LanguageCategory->"NaturalLanguage", ScriptLevel->1, CounterIncrements->"FigureCaption", FontFamily->"Times New Roman", FontSize->12]





  2. A notebook that contains some FigureCaption cells. This is the notebook we will be manipulating I will refer to as the lecture notebook.




  3. A function that builds the cell tags for the lecture notebook. The function is located in the Action Menu below.




DynamicModule[{found}, celltagdialog = Tooltip[Dynamic[ ActionMenu[ "C", {"Build Cell Tags" :> {SelectionMove[InputNotebook[], Before, Notebook]; found = NotebookFind[InputNotebook[], "FigureCaption", Next, CellStyle]; While[! FailureQ[found], SetOptions[NotebookSelection[], CellTags -> "Figure " <> ToString[ CurrentValue[ NotebookSelection[InputNotebook[]], {"CounterValue", "FigureCaption"}]]]; found = NotebookFind[InputNotebook[], "FigureCaption", Next, CellStyle];];}}, Appearance -> "Palette", FrameMargins -> None, Alignment -> Center, BaselinePosition -> Axis, ImageSize -> {24, 24}]], "Show Gridbox Dialog", TooltipDelay -> 0]]




  1. A function that creates the links to the cell tags in the lecture notebook. These are basically pointers that point to updated tags so that you can hyperlink to them... and them opens and closes groups to make it look nice.


CreateLinks[nb_] := Module[{tagLis = {}, data, imax, i}, SelectionMove[nb, Before, Notebook]; SelectionMove[nb, Next, Cell]; data = NotebookRead[nb]; While[data =!= {}, tagLis = Join[tagLis, Cases[data, Rule[CellTags, tg_] :> tg]]; SelectionMove[nb, Next, Cell]; data = NotebookRead[nb]]; MapThread[ Which[StringContainsQ[#1, "Figure"], " " <> #1, True, Style[#1, Bold]] :> {FrontEndExecute[FrontEndToken["SelectAll"]]; FrontEndExecute[{FrontEndToken[InputNotebook[], "SelectionCloseAllGroups"]}]; NotebookLocate[#1], FrontEndExecute[{FrontEndToken[ "SelectionOpenAllGroups"]}];} &, {tagLis}]]


Applying the functions given in 3 will keep the cell tags automatically generated so that even when you insert a new cell, the cell tags are renamed using 3. The function in 4 will rebuild the links which can be used for hyperlinking. These need to be rebuilt whenever we add or remove or move cells that have cell tags in the notebook or they won't match up. Let me know if you would like to see more code.


Below is a short gif I made to illustrating how we can do this in pratice. I have many cells with tags and some of them with counters that I reference in the tags. As you can see, I used a docked cell with a dropdown menu to rebuild the celltags.


enter image description here


The pointers created in 4 can be used for hyperlinks to any celltag in the notebook. Below is a gif illustrating how this can be implemented. Make sure to rebuild the docked cell to keep these pointers updated. I prefer to update the docked cell at the same time as I build the celltags, so it's one click instead of two. Again I used a dropdown menu and use the CreateLinks function above for its content.


enter image description here


Comments

Popular posts from this blog

plotting - Filling between two spheres in SphericalPlot3D

Manipulate[ SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, Mesh -> None, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], {n, 0, 1}] I cant' seem to be able to make a filling between two spheres. I've already tried the obvious Filling -> {1 -> {2}} but Mathematica doesn't seem to like that option. Is there any easy way around this or ... Answer There is no built-in filling in SphericalPlot3D . One option is to use ParametricPlot3D to draw the surfaces between the two shells: Manipulate[ Show[SphericalPlot3D[{1, 2 - n}, {θ, 0, Pi}, {ϕ, 0, 1.5 Pi}, PlotPoints -> 15, PlotRange -> {-2.2, 2.2}], ParametricPlot3D[{ r {Sin[t] Cos[1.5 Pi], Sin[t] Sin[1.5 Pi], Cos[t]}, r {Sin[t] Cos[0 Pi], Sin[t] Sin[0 Pi], Cos[t]}}, {r, 1, 2 - n}, {t, 0, Pi}, PlotStyle -> Yellow, Mesh -> {2, 15}]], {n, 0, 1}]

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]

plotting - Mathematica: 3D plot based on combined 2D graphs

I have several sigmoidal fits to 3 different datasets, with mean fit predictions plus the 95% confidence limits (not symmetrical around the mean) and the actual data. I would now like to show these different 2D plots projected in 3D as in but then using proper perspective. In the link here they give some solutions to combine the plots using isometric perspective, but I would like to use proper 3 point perspective. Any thoughts? Also any way to show the mean points per time point for each series plus or minus the standard error on the mean would be cool too, either using points+vertical bars, or using spheres plus tubes. Below are some test data and the fit function I am using. Note that I am working on a logit(proportion) scale and that the final vertical scale is Log10(percentage). (* some test data *) data = Table[Null, {i, 4}]; data[[1]] = {{1, -5.8}, {2, -5.4}, {3, -0.8}, {4, -0.2}, {5, 4.6}, {1, -6.4}, {2, -5.6}, {3, -0.7}, {4, 0.04}, {5, 1.0}, {1, -6.8}, {2, -4.7}, {3, -1.