Cómo crear un cuaderno con una expresión formateada correctamente
Pregunta
Tengo una expresión de Mathematica generada por otro programa, que me gustaría abrir en un cuaderno, formateado correctamente. Por ejemplo, el otro programa genera esto:
Plot[{Exp[x],Interpolation[Table[{k/5,Exp[(k-1/2)/5]},{k,0,5}],
InterpolationOrder->0][x]},{x,0,1},Filling->{1->{{2},{Yellow,Orange}}},
PlotLabel->Style["Formatting",Blue,FontFamily->"Courier"]]
El texto se escribe en un archivo, sufijo crudo ".nb", y se lanza, y la expresión se abre en un cuaderno sin formatear. Para lograr el formato, escribir un archivo manualmente con BoxData parece poco práctico.
El archivo en realidad se está lanzando desde .net usando Process.Start ("FileName.nb"), pero un lanzamiento de la línea de comandos parece igualmente problemático.
Solución 4
Aquí está la solución que adopté. Gracias por toda la ayuda.
El paso principal de la solución es formatear el comando a través del núcleo:-
FullForm[ToBoxes[
Defer[Plot[{Exp[x],
Interpolation[Table[{k/5, Exp[(k - 1/2)/5]}, {k, 0, 5}],
InterpolationOrder -> 0][x]}, {x, 0, 1},
Filling -> {1 -> {{2}, {Yellow, Orange}}},
PlotLabel ->
Style["Formatting", Blue, FontFamily -> "Courier"]]]]]
Luego, los datos formateados están encapsulados para crear un cuaderno:-
Notebook[{Cell[BoxData[
... ( inserted box-formatted output ) ...
], "Input"]
},
WindowSize->{615, 750},
WindowMargins->{{328, Automatic}, {Automatic, 76}},
StyleDefinitions->"Default.nb"
]
Esto se escribe en un archivo, sufijo ".nb". Todo bien y dandy.
Este enfoque funciona bien para bloques de código de estados múltiples, pero se incluyó un procesamiento adicional para formatear una llamada de función única de la función de formulario [expresión, opciones] para agregar un descanso de línea antes de cada opción. Aquí está el código C# utilizado para producir ambos tipos de salida:-
public static class MathematicaHelpers
{
public static string CreateNotebook(string mathCommand, string fileLocation, MathKernel kernel, bool addNewLines)
{
if (addNewLines) {
mathCommand = string.Format("{0}{1}{2}", "Module[{boxoutput,b2},boxoutput=FullForm[ToBoxes[Defer[", mathCommand, "]]];b2=boxoutput[[1,1,3,1]];boxoutput[[1,1,3,1]]=Join[Flatten[Riffle[Partition[b2,2],\"\\[IndentingNewLine]\"],1],{\"\\[IndentingNewLine]\",Last[b2]}];boxoutput]");
} else {
mathCommand = string.Format("{0}{1}{2}", "FullForm[ToBoxes[Defer[", mathCommand, "]]]");
}
fileLocation = Path.ChangeExtension(fileLocation, ".nb");
mathCommand = ComputeMathCommand(mathCommand, kernel);
mathCommand = string.Format("{0}{1}{2}", "Notebook[{Cell[BoxData[", mathCommand,
"], \"Input\"]},WindowSize->{615, 750}, WindowMargins->{{328, Automatic}, {Automatic, 76}},StyleDefinitions->\"Default.nb\"]");
File.WriteAllText(fileLocation, mathCommand);
return fileLocation;
}
private static string ComputeMathCommand(string command, MathKernel kernel)
{
kernel.Compute(command);
return kernel.Result.ToString();
}
}
Otros consejos
Qué tal esto:
Export["C:\\Temp\\formatTest1.nb",
ToExpression[Import["C:\\Temp\\formatTest.nb", "Text"], InputForm, MakeBoxes]]
Lo probé y parece funcionar (importando desde el archivo simple, exportando al que luego abrirá). Esto crea cajas explícitas, pero con muy poco esfuerzo en el lado del usuario. No probé, pero debería poder ejecutar este código en el modo de script, desde la línea de comando.
EDITAR
Para probar desde Mathematica, puede usar EG
Export["C:\\Temp\\formatTest.nb",
ToString@HoldForm@FullForm@
Plot[{Exp[x],Interpolation[Table[{k/5, Exp[(k - 1/2)/5]}, {k, 0, 5}],
InterpolationOrder -> 0][x]}, {x, 0, 1},
Filling -> {1 -> {{2}, {Yellow, Orange}}},
PlotLabel -> Style["Formatting", Blue, FontFamily -> "Courier"]],
"Text"]
Antes de ejecutar el código anterior.
Puedes usar la siguiente envoltura:
nb = CreateWindow[
DocumentNotebook[{
Plot[{Exp[x],
Interpolation[Table[{k/5, Exp[(k - 1/2)/5]}, {k, 0, 5}],
InterpolationOrder -> 0][x]}, {x, 0, 1},
Filling -> {1 -> {{2}, {Yellow, Orange}}},
PlotLabel ->
Style["Formatting", Blue, FontFamily -> "Courier"]]
}]]
Luego, los comandos NotebookSave y NotebookClose se pueden usar para guardar y cerrar la cosa;)
A menos que cree el BoxData
Expresiones explícitamente no hay forma de formatear su expresión sin invocar al menos el interfaz de Mathematica.
Lo más cercano que se me ocurre es que agregas lo siguiente:
SelectionMove[EvaluationNotebook[], Next, EvaluationCell];
FrontEndExecute[{FrontEndToken[FrontEnd`InputNotebook[],
"SelectionConvert", "StandardForm"]}];
Plot[{Exp[x], Interpolation[Table[{k/5, Exp[(1/5)*(k - 1/2)]}, {k, 0, 5}],
InterpolationOrder -> 0][x]}, {x, 0, 1},
Filling -> {1 -> {{2}, {Yellow, Orange}}},
PlotLabel -> Style["Formatting", Blue, FontFamily -> "Courier"],
Evaluated -> True]
SelectionMove[EvaluationNotebook[], After, GeneratedCell];
que formatea automáticamente el Plot
comando cuando se evalúa la celda. (Por cierto: probablemente deberías agregar Evaluate
frente a la lista o agregue el (no tan bien documentado) Evaluate->True
opción.