diff --git a/Doc/UserManual/Assemblies.tex b/Doc/UserManual/Assemblies.tex index 3b04fe2a0430781d1261529f99922b8f310404bb..dbc9276c37b0f79ba9a32d6f32fe2f85ae3db0bd 100644 --- a/Doc/UserManual/Assemblies.tex +++ b/Doc/UserManual/Assemblies.tex @@ -422,7 +422,7 @@ of its shape function $S(\r)=\chi(\r)/\tilde\chi$, For hard-shell particles %the shape function $S(\r)$ only takes the values 0 and~1 so that the form factor becomes -the \textit{shape transform} +the \E{shape transform} \index{Shape transform}% \begin{equation}\label{EFFhardshell} F(\q)=\int_V {\rm d}^3r\, {\rm e}^{i\q\r}, diff --git a/Doc/UserManual/BornAgainManual.tex b/Doc/UserManual/BornAgainManual.tex index 4506bf4bc6efe78d04edf63d145f79bd4c53a81c..14b73ad9aa9eaa398941add8c8eaa8bcb4312986 100644 --- a/Doc/UserManual/BornAgainManual.tex +++ b/Doc/UserManual/BornAgainManual.tex @@ -45,7 +45,6 @@ Walter Van Herck, Joachim Wuttke} \include{Introduction} -\include{OnlineDocs} \include{SAS} \include{GisasFoundations} \include{PolarizedScattering} @@ -56,9 +55,15 @@ Walter Van Herck, Joachim Wuttke} %void \include{Roughness} %void \include{Experiment} +\include{ThreeAPIs} +\include{Usage} +%\include{Fitting} +%\include{IntensityData} + +\include{FormFactors} + \appendix %\addtocontents{toc}{\protect\setcounter{tocdepth}{1}} \include{Proofs} -\include{FormFactors} \otherchapter{Bibliography} \bibliographystyle{switch} diff --git a/Doc/UserManual/Fitting.tex b/Doc/UserManual/Fitting.tex new file mode 100644 index 0000000000000000000000000000000000000000..ef09e0cf9674c7612be593c9d19dad2048b218e3 --- /dev/null +++ b/Doc/UserManual/Fitting.tex @@ -0,0 +1,555 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Fitting} \label{sec:Fitting} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + \index{Fitting|(} + +In addition to the simulation of grazing incidence +X-ray and neutron scattering by +multilayered samples, \BornAgain\ also offers the option to +fit the numerical model to reference data by modifying a selection of +sample parameters from the numerical model. This aspect +of the software is discussed in the current chapter. + +%\cref{sec:FittingGentleIntroducion} gives a short introduction to the +%basic concepts of data fitting. Users familiar with fitting can +%directly proceed to \cref{sec:FittingImplementation}, which details the +%implementation of fittings in +%\BornAgain\ . +\cref{sec:FittingImplementation} details the +implementation of fittings in \BornAgain. +Python fitting examples with detailed +explanations of every fitting step are given in \cref{sec:FittingExamples}. Advanced fitting techniques, including fine tuning of minimization +algorithms, simultaneous fits of different data sets, parameters +correlation, are covered in +\cref{sec:FittingAdvanced}. \cref{sec:FittingRightAnswers} contains some practical advice, which might +help the user to get right answers from \BornAgain\ fitting. + + +\subsubsection{Implementation in BornAgain} \label{sec:FittingImplementation} + +Fitting in \BornAgain\ deals with estimating the optimum parameters +in the numerical model by minimizing the difference between +numerical and reference data. +%using $\chi^2$ or maximum likelihood methods. +The features include + +\begin{itemize} +\item a variety of multidimensional minimization algorithms and strategies. +\item the choice over possible fitting parameters, their properties and correlations. +\item the full control on objective function calculations, including applications of different normalizations and assignments of different masks and weights to different areas of reference data. +\item the possibility to fit simultaneously an arbitrary number of data sets. +\end{itemize} + +Figure ~\ref{fig:minimization_workflow} shows the general work flow of a typical fitting procedure. +\begin{figure}[htbp] +\centering + \resizebox{0.99\textwidth}{!}{% + \includegraphics{fig/drawing/minimization_workflow.pdf}} +\caption{ +Fitting work flow. +} +\label{fig:minimization_workflow} +\end{figure} + +Before running the fitting the user is required to prepare some data and to +configure the fitting kernel of \BornAgain\ . The required stages are + +\begin{itemize} +\item Preparing the sample and the simulation description (multilayer, beam, detector parameters). +\item Choosing the fitting parameters. +\item Loading the reference data. +\item Defining the minimization settings. +\end{itemize} + +The class \Code{FitSuite} contains the main functionalities to be used for the fit +and serves as the main interface between the user and the fitting work flow. +The later involves iterations during which + +\begin{itemize} +\item The minimizer makes an assumption about the optimal sample parameters. +\item These parameters are propagated to the sample. +\item The simulation is performed for the given state of the sample. +\item The simulated data (intensities) are propagated to the $\chi^2$ module. +\item The later calculates $\chi^2$ using the simulated and reference data. +\item The value of $\chi^2$ is propagated to the minimizer, which makes new assumptions about optimal sample parameters. +\end{itemize} + +The iteration process is going on under the control of the selected minimization +algorithm, without any intervention from the +user. It stops +\begin{itemize} +\item when the maximum number of iteration steps has been exceeded, +\item when the function's minimum has been reached within the tolerance window, +\item if the minimizer could not improve the values of the parameters. +\end{itemize} + +After the control is returned, fitting results can be retrieved. +They consist in the best $\chi^2$ value found, the corresponding +optimal sample parameters and the intensity map simulated with this set of parameters. + +%Details of \Code{FitSuite} class implementation and description of each interface are given in \cref{sec:FitSuiteClass}. +The following parts of this section will detail each of +the main stages necessary to run a fitting procedure. + + +\subsubsection{Preparing the sample and the simulation description} + +This step is similar for any simulation using \BornAgain\ (see \cref{sec:Simulation}). It consists in first characterizing the geometry of the system: the particles +(shapes, sizes, refractive +indices), the different layers (thickness, +order, refractive index, a possible roughness of the interface), the +interference between the particles and the way they are distributed in +the layers (buried particles or particles sitting on top of a +layer). +Then we specify the parameters of the input beam and of the +output detector. + + +%=============================================================================== +\subsubsection{Choice of parameters to be fitted} +%=============================================================================== + +In principle, every parameter used in the construction of the sample +can be used as a fitting parameter. For example, the particles' +heights, radii or the layer's roughness or thickness could be selected +using the +parameter pool mechanism. +This mechanism is explained in detail in +\cref{sec:WorkingWithSampleParameters} and it is therefore recommended +to read it before proceeding any further. + +The user specifies selected sample parameters as fit parameters using \Code{FitSuite} +and its \Code{addFitParameter} method +\begin{lstlisting}[language=shell, style=commandline] +fit_suite = FitSuite() +fit_suite.addFitParameter(<name>, <initial value>, <step>, <limits>) +\end{lstlisting} +where \Code{<name>} corresponds to the parameter name in the sample's parameter pool. +By using wildcards in the parameter name, a group of sample parameters, corresponding to the given +pattern, can be associated with a single fitting parameter and +fitted simultaneously to get a common optimal value (see \cref{sec:WorkingWithSampleParameters}). + +The second parameter \Code <initial value> correspond to the initial value of +the fitting parameter, while the third one +is responsible to the initial iteration steps size. +The last parameter \Code{<AttLimits>} corresponds to +the boundaries imposed on parameter value. It can be +\begin{itemize} +\item \Code{limitless()} by default, +\item \Code{fixed()}, +\item \Code{lowerLimited(<min\_value>)}, +\item \Code{upperLimited(<max\_value>)}, +\item \Code{limited(<min\_value>, <max\_value>)}. +\end{itemize} +where \Code{<min\_value>} and \Code{<max\_value>} are +double values corresponding to the lower and higher boundary, respectively. + + +%=============================================================================== +\subsubsection{Associating reference and simulated data} +%=============================================================================== + +The minimization procedure deals with a pair of reference data (normally +associated with experimental data) and the theoretical model (presented by the sample and the simulation descriptions). + +We assume that the experimental data are a two-dimensional intensity +matrix as function of the output scattering +angles $\alpha_f$ and $\phi_f$ (see \cref{fig:multil3d}). +The user is required to provide the data in the form of an ASCII file +containing an axes +binning description and the intensity data itself. +\vspace*{2mm} + +\Note +{We recognize the importance of supporting the most common data formats. We are going to provide +this feature in the following releases and welcome users' requests on this subject.} + +To associate the simulation and the reference data to the fitting engine, method \newline +\Code{addSimulationAndRealData} has to be used as shown +\begin{lstlisting}[language=python, style=eclipseboxed,numbers=none] +fit_suite = FitSuite() +fit_suite.addSimulationAndRealData(<simulation>, <reference>, <chi2_module>) +\end{lstlisting} + +Here \Code{<simulation>} corresponds to a \BornAgain\ simulation object +with the sample, beam and detector fully defined, \Code{<reference>} +corresponds to the experimental data object obtained from the ASCII file and \Code{<chi2\_module>} is an optional parameter for advanced +control of $\chi^2$ calculations. + +It is possible to call this given method more than once to submit more than one pair of +\Code{<simulation>, <reference>} to the fitting procedure. +In this way, simultaneous fits of +some combined data sets are performed. + +By using the third parameter, \Code{<chi2\_module>}, different normalizations and weights +can be applied to give user full control of the way $\chi^2$ is calculated. +This feature will be explained in \cref{sec:FittingAdvanced}. + + +%=============================================================================== +\subsection{Minimizer settings} +%=============================================================================== + +\BornAgain\ contains a variety of minimization engines from \Code{ROOT} and \Code{GSL} +libraries. They are listed in Table~\ref{table:fit_minimizers}. +By default \Code{Minuit2} minimizer with default settings will be used and no additional +configuration needs to be done. +The remainder of this section explains some of the expert settings, which can be applied to get better +fit results. + +The default minimization algorithm can be changed using +\Code{MinimizerFactory} as shown below +\begin{lstlisting}[language=python, style=eclipseboxed,numbers=none] +fit_suite = FitSuite() +minimizer = MinimizerFactory.createMinimizer("<Minimizer name>","<algorithm>") +fit_suite.setMinimizer(minimizer) +\end{lstlisting} + +where \Code{<Minimizer name>} and \Code{<algorithm>} can be chosen from the first and +second column of Table~\ref{table:fit_minimizers} respectively. +The list of minimization algorithms implemented in \BornAgain\ +can also be obtained using \Code{MinimizerFactory.printCatalogue()} command. + + +\begin{table}[h] + \small +\centering +\begin{tabular}{@{}lll@{}} +\hline +\hline +\textbf{Minimizer name} & \textbf{Algorithm} & \textbf{Description}\\ +\hline +\Code{Minuit2} \cite{MinuitURL} & \Code{Migrad} & According to +\cite{mntutorial} best minimizer for nearly all functions,\\ + & & variable-metric method with inexact line search, \\ + & & a stable metric updating scheme,\\ + & & and checks for positive-definiteness.\\ +\hline + & \Code{Simplex} & simplex method of + Nelder and Mead\\ + & & usually slower than \Code{Migrad}, \\ + & & rather robust with respect to gross fluctuations in the\\ & & function + value, gives no reliable information about \\ & & parameter errors, \\ +\hline + & \Code{Combined} & minimization with + \Code{Migrad} \\ + & & but switches to Simplex if + Migrad fails to converge.\\ +\hline + & \Code{Scan} & not intended to + minimize, just scans the + function,\\ + & & one parameter at a + time, retains the best value + after\\ & & each scan\\ +\hline + & \Code{Fumili} & optimized + method for least square and log + likelihood\\ & & minimizations \\ +\hline +\Code{GSLMultiMin} \cite{GSLMultiMinURL} & \Code{ConjugateFR} & Fletcher-Reeves conjugate gradient + algorithm,\\ +\hline +& \Code{ConjugatePR} & Polak-Ribiere conjugate gradient algorithm,\\ +\hline +& \Code{BFGS} & Broyden-Fletcher-Goldfarb-Shanno algorithm,\\ +\hline +& \Code{BFGS2} & improved version of BFGS,\\ +\hline +& \Code{SteepestDescent} & follows the downhill gradient of the function at each step\\ +\hline +\Code{GSLLMA} \cite{GSLMultiFitURL} & & Levenberg-Marquardt +Algorithm\\ +\hline +\Code{GSLSimAn} \cite{GSLSimAnURL}& & Simulated Annealing Algorithm\\ +\hline +\hline +\end{tabular} +\caption{List of minimizers implemented in \BornAgain. } +\label{table:fit_minimizers} +\index{Minimizers} +\end{table} + +There are several options common to every minimization algorithm, which can be changed +before starting the minimization. They are handled by \Code{MinimizerOptions} class: +\begin{lstlisting}[language=python, style=eclipseboxed, numbers = none] +fit_suite.getMinimizer().getOptions().setMaxFunctionCalls(10) +\end{lstlisting} +In the above code snippet, a number of ``maximum function calls'', +namely the maximum number of times the minimizer is allowed to call the simulation, is limited to 10. %The minimizer will take that number into consideration and will try to limit number of iterations by that value. + +There are also expert-level options common for all minimizers as well +as a number of options to tune individual minimization algorithms. +They will be explained in \cref{sec:FittingAdvanced}. + + +%=============================================================================== +\subsection{Running the fitting ant retrieving the results} +%=============================================================================== + +After the initial configuration of \Code{FitSuite} has been performed, the fitting +can be started using the command +\begin{lstlisting}[language=python, style=eclipseboxed, numbers = none] +fit_suite.runFit() +\end{lstlisting} + +Depending on the complexity of the sample and the number of free sample parameters the fitting +process can take from tens to thousands of iterations. The results of the fit can +be printed on the screen using the command +\begin{lstlisting}[language=python, style=eclipseboxed, numbers = none] +fit_suite.printResults() +\end{lstlisting} +\cref{sec:FittingExamples} gives more details about how to access the fitting results. + + +%=============================================================================== +\subsection{Basic Python fitting example} \label{sec:FittingExamples} +%=============================================================================== + +In this section we are going to go through a complete example of +fitting using \BornAgain. Each step will be associated with a +detailed piece of code written in Python. +The complete listing of +the script is given in Appendix (see Listing~\ref{PythonFittingExampleScript}). +The script can also be found at +\begin{lstlisting}[language=shell, style=commandline] +./Examples/python/fitting/ex002_FitCylindersAndPrisms/FitCylindersAndPrisms.py +\end{lstlisting} + +\noindent +This example uses the same sample geometry as in \cref{sec:Example1Python}. +Cylindrical and +prismatic particles in equal proportion are deposited on a substrate layer, with no interference +between the particles. We consider the following parameters to be unkown +\begin{itemize} +\item the radius of cylinders, +\item the height of cylinders, +\item the length of the prisms' triangular basis, +\item the height of prisms. +\end{itemize} + +Our reference data are a ``noisy'' two-dimensional intensity +map obtained from the simulation of the same geometry with a fixed +value of $5\,{\rm nm}$ for the height and radius of cylinders and for the +height of prisms which have a 10-nanometer-long side length. +Then we run our fitting using default minimizer settings +starting with a cylinder's height +of $4\,{\rm nm}$, a cylinder's radius of $6\,{\rm nm}$, +a prism's half side of $6\,{\rm nm}$ and a height equal to $4\,{\rm nm}$. +As a result, the fitting procedure is able to find the correct value of $5\,{\rm nm}$ +for all four parameters. + + +%------------------------------------------------------------------------------- +\subsubsection*{Importing Python libraries} +%------------------------------------------------------------------------------- + +\begin{lstlisting}[language=python, style=eclipseboxed] +from libBornAgainCore import * +from libBornAgainFit import * +\end{lstlisting} +We start from importing two \BornAgain\ libraries required to create +the sample description +and to run the fitting. + +%------------------------------------------------------------------------------- +\subsubsection*{Building the sample} +%------------------------------------------------------------------------------- + +\begin{lstlisting}[language=python, style=eclipseboxed, firstnumber=5] +def get_sample(): @\label{script2::get_sample}@ + """ + Build the sample representing cylinders and pyramids on top of substrate without interference. + """ + # defining materials + m_air = HomogeneousMaterial("Air", 0.0, 0.0) + m_substrate = HomogeneousMaterial("Substrate", 6e-6, 2e-8) + m_particle = HomogeneousMaterial("Particle", 6e-4, 2e-8) + + # collection of particles + cylinder_ff = FormFactorCylinder(1.0*nanometer, 1.0*nanometer) + cylinder = Particle(m_particle, cylinder_ff) + prism_ff = FormFactorPrism3(2.0*nanometer, 1.0*nanometer) + prism = Particle(m_particle, prism_ff) + particle_layout = ParticleLayout() + particle_layout.addParticle(cylinder, 0.5) + particle_layout.addParticle(prism, 0.5) + interference = InterferenceFunctionNone() + particle_layout.addInterferenceFunction(interference) + + # air layer with particles and substrate form multi layer + air_layer = Layer(m_air) + air_layer.addLayout(particle_layout) + substrate_layer = Layer(m_substrate) + multi_layer = MultiLayer() + multi_layer.addLayer(air_layer) + multi_layer.addLayer(substrate_layer) + return multi_layer +\end{lstlisting} +The function starting at line~\ref{script2::get_sample} creates a multilayered sample +with cylinders and prisms using arbitrary $1\,{\rm nm}$ value for all size's of particles. +The details about the generation of this multilayered sample are given in \cref{sec:Example1Python}. + +%------------------------------------------------------------------------------- +\subsubsection*{Creating the simulation} +%------------------------------------------------------------------------------- +\begin{lstlisting}[language=python, style=eclipseboxed, firstnumber=35] +def get_simulation(): @\label{script2::get_simulation}@ + """ + Create GISAXS simulation with beam and detector defined + """ + simulation = Simulation() + simulation.setDetectorParameters(100, -1.0*degree, 1.0*degree, 100, 0.0*degree, 2.0*degree) + simulation.setBeamParameters(1.0*angstrom, 0.2*degree, 0.0*degree) + return simulation +\end{lstlisting} +The function starting at line~\ref{script2::get_simulation} creates +the simulation object with the definition of the beam and detector parameters. + +%------------------------------------------------------------------------------- +\subsubsection*{Preparing the fitting pair} +%------------------------------------------------------------------------------- +\begin{lstlisting}[language=python, style=eclipseboxed, firstnumber=45] +def run_fitting(): @\label{script2::run_fitting}@ + """ + run fitting + """ + sample = get_sample() @\label{script2::setup_simulation1}@ + simulation = get_simulation() + simulation.setSample(sample) @\label{script2::setup_simulation2}@ + + real_data = IntensityDataIOFactory.readIntensityData('refdata_fitcylinderprisms.int.gz') @\label{script2::real_data}@ +\end{lstlisting} +Lines +~\ref{script2::setup_simulation1}-~\ref{script2::setup_simulation2} +generate the +sample and simulation description and assign the sample to the simulation. +Our reference data are contained in the file \Code{'refdata\_fitcylinderprisms.int.gz'}. + This reference had been generated by adding noise +on the scattered intensity from a numerical sample with a fixed length of 5~nm for the four fitting +parameters (\idest the dimensions of the cylinders and prisms). +Line ~\ref{script2::real_data} creates the real data object by loading +the ASCII data from the input file. + +%------------------------------------------------------------------------------- +\subsubsection*{Setting up \rm\bf{FitSuite}} +%------------------------------------------------------------------------------- +\begin{lstlisting}[language=python, style=eclipseboxed, firstnumber=55] + fit_suite = FitSuite() @\label{script2::fitsuite1}@ + fit_suite.addSimulationAndRealData(simulation, real_data) @\label{script2::fitsuite2}@ + fit_suite.initPrint(10) @\label{script2::fitsuite3}@ +\end{lstlisting} +Line ~\ref{script2::fitsuite1} creates a \Code{FitSuite} object which provides +the main interface to the minimization kernel of \BornAgain\ . +Line ~\ref{script2::fitsuite2} submits simulation description and real data pair to the +subsequent fitting. Line ~\ref{script2::fitsuite3} sets up \Code{FitSuite} to print on +the screen the information about fit progress once per 10 iterations. +\begin{lstlisting}[language=python, style=eclipseboxed, firstnumber=60] + fit_suite.addFitParameter("*FormFactorCylinder/height", 4.*nanometer, 0.01*nanometer, AttLimits.lowerLimited(0.01)) @\label{script2::fitpars1}@ + fit_suite.addFitParameter("*FormFactorCylinder/radius", 6.*nanometer, 0.01*nanometer, AttLimits.lowerLimited(0.01)) + fit_suite.addFitParameter("*FormFactorPrism3/height", 4.*nanometer, 0.01*nanometer, AttLimits.lowerLimited(0.01)) + fit_suite.addFitParameter("*FormFactorPrism3/length", 12.*nanometer, 0.02*nanometer, AttLimits.lowerLimited(0.01)) @\label{script2::fitpars2}@ +\end{lstlisting} +Lines ~\ref{script2::fitpars1}--~\ref{script2::fitpars2} enter the +list of fitting parameters. Here we use the cylinders' height and +radius and the prisms' height and side length. +The cylinder's length and prism half side are initially equal to $4\,{\rm nm}$, +whereas the cylinder's radius and the prism half side length are equal to $6\,{\rm nm}$ before the minimization. The +iteration step is equal to $0.01\,{\rm nm}$ and only the lower +boundary is imposed to be equal to $0.01\,{\rm nm}$. + +%------------------------------------------------------------------------------- +\subsubsection*{Running the fit and accessing results} +%------------------------------------------------------------------------------- +\begin{lstlisting}[language=python, style=eclipseboxed, firstnumber=66] + fit_suite.runFit() @\label{script2::fitresults1}@ + + print "Fitting completed." + fit_suite.printResults()@\label{script2::fitresults2}@ + print "chi2:", fit_suite.getMinimizer().getMinValue() + fitpars = fit_suite.getFitParameters() + for i in range(0, fitpars.size()): + print fitpars[i].getName(), fitpars[i].getValue(), fitpars[i].getError() @\label{script2::fitresults3}@ +\end{lstlisting} +Line ~\ref{script2::fitresults1} shows the command to start the fitting process. +During the fitting the progress will be displayed on the screen. +Lines ~\ref{script2::fitresults2}--~\ref{script2::fitresults3} shows different ways of +accessing the fit results. + + +More details about fitting, access to its results and visualization of +the fit progress using matplotlib libraries can be learned from the +following detailed example +\begin{lstlisting}[language=shell, style=commandline] +./Examples/python/fitting/ex002_FitCylindersAndPrisms/FitCylindersAndPrisms_detailed.py +\end{lstlisting} + + +%=============================================================================== +\subsection{Advanced fitting} \label{sec:FittingAdvanced} +%=============================================================================== + +\subsubsection{Affecting chi-square calculations} +\MissingSection +\subsubsection{Simultaneous fits of several data sets} +\MissingSection +\subsubsection{Using fitting strategies} +\MissingSection +\subsubsection{Masking the real data} +\MissingSection +\subsubsection{Tuning fitting algorithms} +\MissingSection +\subsubsection{Fitting with correlated sample parameters} +\MissingSection + + +%=============================================================================== +\subsection {How to get the right answer from fitting} + \label{sec:FittingRightAnswers} +%=============================================================================== + +%As it has already been mentioned in \cref{sec:FittingGentleIntroducion}, +One of the main difficulties in fitting the data with the model +is the presence of multiple +local minima in the objective function. Many problems can cause the +fit to fail, for example: +\begin{itemize} +\item an unreliable physical model, +\item an unappropriate choice of objective function +\item multiple local minima, +\item an unphysical behavior of the objective function, unphysical regions + in the parameters space, +\item an unreliable parameter error calculation in the presence of + limits on the parameter value, +\item an exponential behavior of the objective function and the + corresponding numerical inaccuracies, excessive numerical roundoff + in the calculation of its value and derivatives, +\item large correlations between parameters, +\item very different scales of parameters involved in the calculation, +\item not positive definite error matrix even at minimum. +\end{itemize} + + +The given list, of course, is not only related to \BornAgain\ +fitting. It remains applicable to any fitting program and any kind of theoretical model. +%To address all these difficulties some amount of manual tuning might be necessary. + Below we give some recommendations which might help the user to achieve reliable fit results. + +\subsection*{General recommendations} +\begin{itemize} +\item initially choose a small number of free fitting parameters, +\item eliminate redundant parameters, +\item provide a good initial guess for the fit parameters, +\item start from the default minimizer settings and perform some fine tuning after some experience has been acquired, +\item repeat the fit using different starting values for the parameters or their limits, +\item repeat the fit, fixing and varying different groups of parameters, +%\item use \Code{Minuit2} minimizer with \Code{Migrad} algorithm +% (default) to get the most reliable parameter error estimation, +%\item try \Code{GSLMultiFit} minimizer or \Code{Minuit2} minimizer with \Code{Fumili} %algorithm to get fewer iterations. +\end{itemize} + +\Work{... to be continued ...} + +%\subsection*{Interpretation of errors.} + +\index{Fitting|)} diff --git a/Doc/UserManual/FormFactors.tex b/Doc/UserManual/FormFactors.tex index 77334d605aea7a8ddb45258c3b92b90376fc860a..1de1dd6601346c2dc1a9d41dd2022c257e3e431b 100644 --- a/Doc/UserManual/FormFactors.tex +++ b/Doc/UserManual/FormFactors.tex @@ -13,6 +13,8 @@ %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\part{Reference}\label{PREF} + \chapter{Form factor library} \label{SFF} % Don't number subfigures in this chapter. @@ -23,7 +25,7 @@ % \lstset{language=python,style=eclipseboxed,numbers=none,nolol} \def\ffsection#1{\FloatBarrier\clearpage\ifodd\value{page} -\textit{Page intentionally left blank}\clearpage\else\fi +\E{Page intentionally left blank}\clearpage\else\fi \section{#1}} diff --git a/Doc/UserManual/IntensityData.tex b/Doc/UserManual/IntensityData.tex new file mode 100644 index 0000000000000000000000000000000000000000..ccbcdb6fd3ea5a96752c68318ee8f0574fff6cab --- /dev/null +++ b/Doc/UserManual/IntensityData.tex @@ -0,0 +1,146 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{User API} \label{UserAPI} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%=============================================================================== +\subsection{IntensityData} +%=============================================================================== + +The \Code{IntensityData} object stores the +simulated or real intensity data together with the axes definition of the detector in BornAgain's internal format. +During the simulation setup +it is created automatically when the user specifies the detector characteristics and is filled with the simulated intensities after the simulation is completed. + +\begin{lstlisting}[language=python, style=eclipseboxed] +simulation = Simulation() +simulation.setDetectorParameters(10, -5.0*degree, 5.0*degree, 5, 0.0*degree, 1.0*degree) +... +simulation.runSimulation() +intensity = simulation.getIntensityData() @\label{py:UserApi:intensity}@ +\end{lstlisting} + +The \Code{IntensityData} object retrieved in line~\ref{py:UserApi:intensity} corresponds to +the two dimensional detector pixel array as shown in \cref{fig:UserApi:IntensityData}. + +\begin{figure}[ht] + \centering + \includegraphics[clip=, width=120mm]{fig/drawing/UserAPI_IntensityDataLayout.eps} + \caption{The axes layout of IntensityData object.} + \label{fig:UserApi:IntensityData} +\end{figure} + +The x-axis and y-axis of the figure correspond to the $\phi_f$ and $\alpha_f$ axes of the detector. +The x-axis is divided into 10 bins, +with low edge of the first bin set to $-5.0\,{\rm deg}$ and upper edge of the last bin set to $+5.0\,{\rm deg}$. +The y-axis is divided into 5 bins, +with low edge of the first bin set to $0.0\,{\rm deg}$ and upper edge of the last bin set to $1.0\,{\rm deg}$. +There are 50 bins in total (they are marked on the plot with indexes from 0 to 49), each bin will contain one intensity value. + +During a standard simulation (i.e. no Monte-Carlo integration involved) intensities are calculated for $\phi_f, \alpha_f$ values corresponding to the bin centers, e.g. the intensity stored in bin\#42 will correspond to $\phi_f=3.5\,{\rm deg}, \alpha_f=0.5\,{\rm deg}$. +\vspace*{2mm} + + +\MakeRemark{}{ +The \Code{IntensityData} object is not intended for direct usage from Python API. The idea is +that the API provides the user with the possibility to export the data from BornAgain internal format to the format of his choice as well as import user's data into BornAgain. +For the moment this functionality is limited to a few options explained below. +We encourage users feedback to implement the support of most requested formats. +}\\ + + + +\subsubsection{Import/export of intensity data} +For the moment we provide following options: +\begin{itemize} +\item Import/export of \Code{IntensityData} object from/to \Code{numpy} array. +\item Import/export of \Code{IntensityData} object from/to text file. + +\end{itemize} + +\paragraph{Export to numpy array} + +To export intensity data into \Code{numpy} array the method \Code{getArray()} should be used +on \Code{IntensityData} object as shown in line \ref{py:UserApi:getArray} of +following code snippet. + +\begin{lstlisting}[language=python, style=eclipseboxed] +intensity = simulation.getIntensityData() +array = intensity.getArray() @\label{py:UserApi:getArray}@ +... +pylab.imshow(numpy.rot90(array, 1)) @\label{py:UserApi:imshow}@ +pylab.show() +\end{lstlisting} + +For the detector settings defined in the previous paragraph the dimensions of the resulting array will be (10,5). By using \Code{numpy} indexes the user can get access to the intensity values, e.g. +\Code{array[0][0]} corresponds to the intensity in bin\#0 of \cref{fig:UserApi:IntensityData}, +\Code{array[0][4]} to bin\#4, +\Code{array[1][0]} to bin\#5, +\Code{array[8][2]} to bin\#42, +\Code{array[9][4]} to bin\#49. + + +To plot this resulting numpy array with \Code{matplotlib} it has to be rotated counter-clockwise +to match \Code{matplotlib} conventions as shown in line~\ref{py:UserApi:imshow}. + + +%\subsubsection{Direct access to the data} +%User can access to the + +%\begin{lstlisting}[language=python, style=eclipseboxed] +%for i in range(0, intensity.getAllocatedSize()): +% print intensity[i] +%\end{lstlisting} + + +\subsubsection{Importing from numpy array} + +To use fitting the user has to load experimental data into BornAgain fitting kernel. +To read experimental data the user has to create +IntensityData object, fill it with the experimental intensity values and pass +this object to the fitting kernel. + +First, the user creates empty \Code{IntensityData} as shown +in line~\ref{py:UserApi:IntensityData} of the following code snippet. +\begin{lstlisting}[language=python, style=eclipseboxed] +data = IntensityData() @\label{py:UserApi:IntensityData}@ +data.addAxis(FixedBinAxis("phi_f", 10, -5.0*degree, 5.0*degree)) @\label{py:UserApi:phi_f}@ +data.addAxis(FixedBinAxis("alpha_f", 5, 0.0*degree, 1.0*degree)) @\label{py:UserApi:alpha_f}@ +... +array = numpy.zeros((10, 5)) # fill array with experimental intensities @\label{py:UserApi:create_array}@ +... +data.setRawDataVector(array.flatten().tolist()) @\label{py:UserApi:set_raw}@ + +fitSuite = FitSuite() @\label{py:UserApi:fit_suite}@ +fitSuite.addSimulationAndRealData(simulation, data) @\label{py:UserApi:add_real_data}@ +\end{lstlisting} + +In lines~\ref{py:UserApi:phi_f}, \ref{py:UserApi:alpha_f} two axes with fixed bin sizes +are defined to represent the detector layout as shown in \cref{fig:UserApi:IntensityData}. +The constructor of \Code{FixedBinAxis} object has the following signature + +\begin{lstlisting}[language=python, style=eclipse,numbers=none] +FixedBinAxis(title, nbins, min_angle, max_angle) +\end{lstlisting} + +The created \Code{IntensityData} object has to be filled with experimental intensities +using \Code{numpy} array prepared by the user (lines ~\ref{py:UserApi:create_array}-~\ref{py:UserApi:set_raw}). In lines \ref{py:UserApi:fit_suite},\ref{py:UserApi:add_real_data} the fitting kernel is created and initialized with \Code{Simulation} object and +\Code{IntensityData} object representing the experimental data. + + +\subsubsection{Saving intensity data to text file.} + +The special class \Code{IntensityDataIOFactory} is intended for saving the intensity data +in different datafile formats. For the moment, it only supports saving the data in specific BornAgain's text files (the file extention \Code{*.int}). + +\begin{lstlisting}[language=python, style=eclipseboxed] +intensity = simulation.getIntensityData() +IntensityDataIOFactory.writeIntensityData(intensity, 'file_name.int') +\end{lstlisting} + +\subsubsection{Reading intensity data from a text file.} +The same class is also intended for reading intensity data +from files with different formats. For the moment, it only supports reading the data from text files of special BornAgain's format (the file extention \Code{*.int}). + +\begin{lstlisting}[language=python, style=eclipseboxed] +intensity = IntensityDataIOFactory.readIntensityData('file_name.int') +\end{lstlisting} diff --git a/Doc/UserManual/Introduction.tex b/Doc/UserManual/Introduction.tex index ffcc4a351c4fbf6e3d51d0154dcd4fe1cffc025b..b15a9c427fac123a5c1312d9894bd604d6f1c397 100644 --- a/Doc/UserManual/Introduction.tex +++ b/Doc/UserManual/Introduction.tex @@ -101,18 +101,63 @@ Adhering to a strict object-oriented design, \BornAgain\ provides a solid base for future extensions in response to specific user needs. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\isection{Registration, contact, discussion forum}\label{Snews} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\index{Registration} +\index{Newsletter} +To stay informed about the ongoing development of \BornAgain, +register on the project homepage \url{http://www.bornagainproject.org} +(``Create new account''). +You will then receive our occasional newsletters, +and be authorized to post to the discussion forum. + +\index{Contact} +To contact the \BornAgain\ development and maintenance team +in the Scientific Computing Group +of Heinz Maier-Leibnitz Zentrum (MLZ) Garching, +write a mail to \url{contact@bornagainproject.org}, +or fill the form in the \textsc{Contact} section of the +project web site. + +\index{Forum} +For questions that might be of wider interest, +please consider posting to the discussion forum, +accessible through the \textsc{Forums} tab of the project web site. + +\index{Bug reports}% +Please contact us for any question not answered here +or in the online documentation. +We are grateful for all kind of feedback: +criticism, praise, bug reports, feature requests or contributed modules. +If questions go beyond normal user support, +we will be glad to discuss a scientific collaboration. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \isection{About this Manual} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -This user manual is complementary to the online documentation +This User Manual is complementary to the online documentation at \url{http://www.bornagainproject.org}. It does not duplicate information that is more conveniently read online. -Therefore, \Cref{sec:online} just contains a few pointers to the web site. -The remainder of this manual mostly contains background -on the scattering theory and on the sample models implemented in \BornAgain, -and some documentation of the corresponding \Python\ functions. +The online documentation covers in particular +how to download and install \BornAgain. + +This User Manual containes of three parts: +\Cref{PPHYS} provides some physics background +on the scattering theory and on the sample models implemented in \BornAgain. +\Cref{PUSE} describes how to use \BornAgain\ through its three different interfaces: +C$++$, Python, and graphical. +\index{C++!using BornAgain from} +\index{Python!using BornAgain from} +\index{GUI|see {Graphical User Interface}} +\index{Graphical User Interface} +It then continues with a detailed tutorial on the Python interface. +Finally, \cref{PREF} is a partial reference of the C$++$ and Python interfaces; +it concentrates on physics related component, +and thereby complements the automatically generated interface documentation +that can be found online at \url{http://www.bornagainproject.org/???}. % TODO. \Work{\indent This manual is incomplete. Several important chapters are still missing.} @@ -139,21 +184,6 @@ To avoid confusion, the manual carries the same version number as the software, even though it is in a less mature state. -\Emph{\indent We urge users to subscribe to our newsletter -(see \Cref{Snews}), -and to contact us for any question not answered here -or in the online documentation.} - -\index{Bug reports}% -We are grateful for all kind of feedback: -criticism, praise, bug reports, feature requests or contributed modules. -If questions go beyond normal user support, -we will be glad to discuss a scientific collaboration. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\isection{Typesetting conventions} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - In this manual, we use the following colored boxes to highlight certain information: @@ -180,10 +210,11 @@ with the software or the documentation.}} how the theory exposed in this manual is actually used in \BornAgain.}} \medskip -\demobox{\Tuto{\indent Such a box provides one or several links - to a usages examples in the online tutorial, - like the basic script \tuto{52}{cylinders in distorted wave Born approximation} - or the long list of \tuto{72}{all available form factors}.}} +\demobox{\Tuto{\indent This is a link to a usage example in the online tutorial. + To be merged into this manual \ldots}} + +\medskip +\demobox{\Link{\indent This is a link to the online docs.}} \bigskip Mathematical notations are explained in the symbol index, page~\pageref{Snomencl}. diff --git a/Doc/UserManual/Macros.tex b/Doc/UserManual/Macros.tex index ffd56fa1da7d51ef14170ee406ed24f4b0f7e2d8..4e520068feb148ee2dc95d1a1979caf1285634c6 100644 --- a/Doc/UserManual/Macros.tex +++ b/Doc/UserManual/Macros.tex @@ -39,8 +39,7 @@ % Fixed-font words \newcommand{\Code}[1]{\texttt{#1}} -\newcommand{\BornAgain}{\Code{Born\discretionary{}{}{}Again}}% -\newcommand{\Python}{\Code{Python}}% +\newcommand{\BornAgain}{{Born\discretionary{}{}{}Again}}% \newcommand{\IsGISAXS}{\Code{IsGISAXS}}% \newcommand{\FitGISAXS}{\Code{FitGISAXS}}% diff --git a/Doc/UserManual/OnlineDocs.tex b/Doc/UserManual/OnlineDocs.tex deleted file mode 100644 index 1a240cce2db43a076ed8de2d5dff49d4fb80674f..0000000000000000000000000000000000000000 --- a/Doc/UserManual/OnlineDocs.tex +++ /dev/null @@ -1,113 +0,0 @@ -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% -%% BornAgain User Manual -%% -%% homepage: http://www.bornagainproject.org -%% -%% copyright: Forschungszentrum Jülich GmbH 2015 -%% -%% license: Creative Commons CC-BY-SA -%% -%% authors: Scientific Computing Group at MLZ Garching -%% C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke -%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -\newpage -\chapter{Online documentation} - \label{sec:online} - -This User Manual is complementary to the online documentation -at the project web site \url{http://www.bornagainproject.org}. -It does not duplicate information that is more conveniently -read online. -This brief chapter contains no more than a few pointers to the web site. - -\begin{figure}[ht] -\begin{center} -\includegraphics[width=0.83\textwidth]{fig/screenshot/website.png} -\end{center} -\caption{A screenshot of the home page - \url{http://www.bornagainproject.org}.} -\label{fig:website} -\end{figure} - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\section{Download and installation} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - \index{Download}% - \index{Installation}% - -\BornAgain\ -\index{Platform (operating system)}% -\index{Operating system}% -is a multi-platform software. -We actively support the operating systems -Linux, -\index{Linux}% -MacOS -\index{MacOS}% -and Microsoft Windows. -\index{Windows|see {Microsoft Windows}}% -\index{Microsoft Windows}% -The \textsc{Download} section on the \BornAgain\ web site -points to the download location for -binary and source packages. -It also provides a link to our \Code{git} server -where the unstable development trunk is available -for contributors or for users who want to live on the edge. - -The \textsc{Documentation} section contains -pages with \textit{Installation instructions}. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\section{Further online information} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -The \textsc{Documentation} section of the project web site -contains in particular -\begin{itemize} -\item an overview of the software architecture, -\item a list of implemented functionality, -\item tutorials for ``Working with \BornAgain'', - using either the Graphical User Interface or - \Python\ scripts, - \index{Tutorials} -\item a comprehensive collection of tutorial examples that demonstrate - how to use \BornAgain\ for modeling various sample structures - and different experimental conditions, -\item a link to the API reference for using \BornAgain\ through - \Python\ scripts or C$++$ programs. -\index{API|see {Application programming interface}}% -\index{Application programming interface}% -\index{Python}% -\index{C++@C$++$} -\end{itemize} - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\section{Registration, contact, discussion forum}\label{Snews} -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\index{Registration} -\index{Newsletter} -To stay informed about the ongoing development of \BornAgain, -register on the project homepage \url{http://www.bornagainproject.org} -(``Create new account''). -You will then receive our occasional newsletters, -and be authorized to post to the discussion forum. - -To contact the \BornAgain\ development and maintenance team -in the Scientific Computing Group -of Heinz Maier-Leibnitz Zentrum (MLZ) Garching, -write a mail to \url{contact@bornagainproject.org}, -or fill the form in the \textsc{Contact} section of the -project web site. - -\index{Forum} -For questions that might be of wider interest, -please consider posting to the discussion forum, -accessible through the \textsc{Forums} tab of the project web site. diff --git a/Doc/UserManual/Proofs.tex b/Doc/UserManual/Proofs.tex index dd497f2df1e819f329973661b4e9ca9c44fbc050..fbbe4c24eedf78002ad320ff32f0d388a5c1f966 100644 --- a/Doc/UserManual/Proofs.tex +++ b/Doc/UserManual/Proofs.tex @@ -7,7 +7,7 @@ %% copyright: Forschungszentrum Jülich GmbH 2015 %% %% license: Creative Commons CC-BY-SA -%% +%% %% authors: Scientific Computing Group at MLZ Garching %% C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke %% @@ -93,7 +93,7 @@ in the boundary condition~\cref{Escabouco}, G(\r(R,\vartheta,\varphi),\rS) \doteq \frac{\e^{iKR}}{4\pi R} g(\vartheta,\varphi), \end{equation} -and similarly +and similarly \begin{equation} B(\r(R,\vartheta,\varphi),\rD) \doteq \frac{\e^{iKR}}{4\pi R} b(\vartheta,\varphi). @@ -109,7 +109,7 @@ It follows at once that (\text{$R$-dependent})(bg-gb) = 0. \end{equation} -From \cref{Eprerecipro} we obtain the \textit{reciprocity theorem} +From \cref{Eprerecipro} we obtain the \E{reciprocity theorem} \begin{equation}\label{Ereci} G(\rD,\rS) = B(\rS,\rD). \end{equation} diff --git a/Doc/UserManual/SAS.tex b/Doc/UserManual/SAS.tex index 7cc47421dc5703f3ab793e31f4e105ae118f8b79..ee70a48f6e255aff81e433b87d16ae723ae175fb 100644 --- a/Doc/UserManual/SAS.tex +++ b/Doc/UserManual/SAS.tex @@ -13,6 +13,8 @@ %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\part{Physics}\label{PPHYS} + \chapter{Foundations of small-angle scattering} \label{SSas} \chaptermark{Small-angle scattering} diff --git a/Doc/UserManual/Setup.tex b/Doc/UserManual/Setup.tex index 4fcecae3165a98ab4aeb6d2d2f6ec8a8aed0c61d..31f5b1ee9a6a26685fd0ca6d02a535ffcd065c7f 100644 --- a/Doc/UserManual/Setup.tex +++ b/Doc/UserManual/Setup.tex @@ -80,27 +80,54 @@ % Sectioning %------------------------------------------------------------------------------- -% Add rubber to white space around chapter header \makeatletter + \newif\ifnumberedchapter \def\@makechapterhead#1{\numberedchaptertrue\mychapterhead{#1}} \def\@makeschapterhead#1{\numberedchapterfalse\mychapterhead{#1}} +\newif\iffirstchapterinpart +\firstchapterinpartfalse +\renewcommand\part{% + \clearpage\firstchapterinparttrue + \thispagestyle{plain}% + \if@twocolumn + \onecolumn + \@tempswatrue + \else + \@tempswafalse + \fi + \vspace*{50\p@ plus 10\p@ minus 10\p@}% + \secdef\@part\@spart} + + +\def\@part[#1]#2{% + \refstepcounter{part}% + \addcontentsline{toc}{part}{Part~\thepart\hspace{1em}#1}% + \markboth{}{}% + {\interlinepenalty \@M + \normalfont + \ifnum \c@secnumdepth >-2\relax + \parindent \z@ \Large\bfseries \partname\nobreakspace\thepart + \par + \vskip 20\p@ + \fi + \parindent \z@ \huge \bfseries #2\par} + } + +\renewcommand\chapter{ + \iffirstchapterinpart\else\clearpage\fi + \firstchapterinpartfalse + \thispagestyle{plain}% + \global\@topnum\z@ + \@afterindentfalse + \secdef\@chapter\@schapter} + \def\mychapterhead#1{% \vspace*{50\p@ plus 10\p@ minus 10\p@}% {\parindent \z@ \normalfont - \ifnumberedchapter - \raggedright - \Large\bfseries \@chapapp\space \thechapter - \par\nobreak - \vskip 20\p@ plus 4\p@ minus 4\p@ - \interlinepenalty\@M - \fi -% \hrule - \vskip 10\p@ plus 2\p@ minus 2\p@ - \interlinepenalty\@M \raggedright - \huge \bfseries #1\par\nobreak + \LARGE \bfseries \ifnumberedchapter\thechapter~~\fi #1\par\nobreak \interlinepenalty\@M \vskip 10\p@ plus 2\p@ minus 2\p@ % \hrule @@ -108,6 +135,7 @@ \vskip 40\p@ plus 8\p@ minus 8\p@ }} +% Index, Bibliography, ... \def\otherchapter#1{ \clearpage \phantomsection @@ -253,21 +281,24 @@ \def\mdbreakoff{\makeatletter\booltrue{mdf@nobreak}\makeatother} \def\mdbreakon{\makeatletter\boolfalse{mdf@nobreak}\makeatother} -\def\marginSymbolLarge#1#2{\ifdraft{\textbf{#2~~~~}}{\raisebox{-3ex}% -{\includegraphics[width=3em]{#1}\hspace{10pt}}}} +\def\marginSymbolLarge#1#2{\raisebox{-3ex}{\includegraphics[width=3em]{#1}\hspace{10pt}}} \defineBox{boxWork}{boxxWork}{magenta!40}{magenta} {\marginSymbolLarge{fig/icons/Arbeiten.png}{TODO}} \defineBox{boxWarn}{boxxWarn}{magenta!40}{magenta} {\marginSymbolLarge{fig/icons/Achtung.png}{WARN}} \defineBox{boxNote}{boxxNote}{yellow!33}{yellow}{{}} -\defineBox{boxTuto}{boxxTuto}{blue!20}{blue}{{}} +\defineBox{boxTuto}{boxxTuto}{blue!25}{red} + {\marginSymbolLarge{fig/icons/Arbeiten.png}{TODO}} \defineBox{boxEmph}{boxxEmph}{green!20}{green}{{}} +\defineBox{boxLink}{boxxLink}{blue!25}{blue} + {\marginSymbolLarge{fig/icons/Weblink.png}{LINK}} \def\Warn#1{\begin{boxWarn}#1\end{boxWarn}} \def\Work#1{\begin{boxWork}#1\end{boxWork}} \def\Note#1{\begin{boxNote}#1\end{boxNote}} \def\Tuto#1{\begin{boxTuto}#1\end{boxTuto}} +\def\Link#1{\begin{boxLink}#1\end{boxLink}} \def\Emph#1{\begin{boxEmph}#1\end{boxEmph}} \def\Emphc#1{\begin{boxEmph}#1\vskip -5pt\end{boxEmph}} @@ -293,6 +324,9 @@ \crefformat{equation}{(#2#1#3)} \Crefformat{equation}{Equation~(#2#1#3)} +\crefformat{part}{Part~#2#1#3} +\Crefformat{part}{Part~#2#1#3} + \crefformat{chapter}{Chapter~#2#1#3} \Crefformat{chapter}{Chapter~#2#1#3} diff --git a/Doc/UserManual/ThreeAPIs.tex b/Doc/UserManual/ThreeAPIs.tex new file mode 100644 index 0000000000000000000000000000000000000000..c63e5892322a6b6ec02e89e88bbb169bbd9b8044 --- /dev/null +++ b/Doc/UserManual/ThreeAPIs.tex @@ -0,0 +1,249 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% BornAgain User Manual +%% +%% homepage: http://www.bornagainproject.org +%% +%% copyright: Forschungszentrum Jülich GmbH 2016 +%% +%% license: Creative Commons CC-BY-SA +%% +%% authors: Scientific Computing Group at MLZ Garching +%% M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\part{Usage}\label{PUSE} + +\chapter{The three interfaces of \BornAgain} \label{sec:API3} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Architectural overview} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +The overall architecture of \BornAgain\ is outlined in \cref{Farch1}. +The core of \BornAgain\ +\index{Core|see {\Code{libBornAgainCore}}} +comprises functionality to construct arbitrary hierarchical sample models, +to setup instrument models, +and to compute the expected detector image for any given sample and instrument model. +Furthermore \BornAgain\ comes with various minimizers that optimize model parameters +to fit the simulated detector image to a given experimental image. +All this functionality is implemented in a library, \Code{libBornAgainCore}. + +\begin{figure}[tbh] +\begin{center} +\includegraphics[width=0.7\textwidth]{fig/drawing/architecture1.ps} +\end{center} +\caption{Overall architecture of \BornAgain. +\index{Architecture!applications and libraries}% +Applications are shown as oval fields, libraries as rectangles. +Black arrows indicate ``depends on''. +Green fields designate software that is part of \BornAgain. +Gray fields are external dependences +(only two external libraries are explicitly shown; +several more are listed in the online compilation instructions). +Blue fields indicate stand-alone applications that use \BornAgain's +two Application Programming Interfaces (the C$++$ API and the Python API). +\index{C++!using BornAgain from} +\index{Python!using BornAgain from} +\index{Application Programming Interface} +While such applications are to be written by users, +some examples come with the \BornAgain\ source distribution, +and are explained in the following Manual chapters. +It is also possible to export a simulation setup from GUI as Python code. +The binding of C++ to Python is highly simplified here. +For a more accurate picture, see \Cref{FarchPy}.} +\label{Farch1} +\end{figure} + +\index{libBornAgainCore@\Code{libBornAgainCore}} +This library, in turn, depends on a number of other libraries. +One of these, the minimizer wrapper \Code{libBornAgainFit} +\index{libBornAgainFit@\Code{libBornAgainFit}} +\index{Minimizers|see \Code{libBornAgainFit}} +has been written specifically for use in \BornAgain, +and for the time being is only distributed as part of \BornAgain, +though in the future it may find applications in other contexts. +The other library dependences of \Code{libBornAgainCore} +are multi-purpose libraries that are easily available as open-source packages. +\index{Dependences!libraries} + +The library \Code{libBornAgainCore} can be used in three different ways: +From its graphical user interface (GUI), or +from user-written stand-alone applications in the programming languages C$++$ or Python. +These different approaches are briefly outlined below. +The Python interface is then described at length in the next chapters. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Using \BornAgain\ from its Graphical User Interface} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\index{Graphical User Interface|(} +\index{bornagain@\Code{bornagain}|see {Graphical User Interface}} +\index{Exectutable!bornagain@\Code{bornagain}|see {Graphical User Interface}} +\index{Binary|see {Executable}} +%\index{Project name!BornAgain@\BornAgain} + +The project \BornAgain\ comes with a stand-alone application called \Code{bornagain} +that provides a Graphical User Interface (GUI). +Note that we distinguish between the GUI executable \Code{bornagain}, +the underlying library \Code{libBornAgainCore}, and the project \BornAgain\ at large. + +The GUI allows users to quickly setup a simulation, to visualize simulated +detector images, to compare with experimental images, and to run fits. +It provides comfortable access to much, but not all the functionality +of \Code{libBornAgainCore}. +Depending on application fields, +users may sooner or later reach the limits of current GUI support. +Other users may have repetitive tasks that are cumbersome under a GUI. +In such cases, users can export their sample and instrument models from +the GUI as a Python script, +and continue work by directly editing the Python code. +\index{Export!Python from GUI} + +\Link{Documentation of the GUI is available online:\\ + \url{http://www.bornagainproject.org/documentation/usage/gui}} +\index{Graphical User Interface|)} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Using \BornAgain\ from Python} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\index{Python!using BornAgain from|(} +\index{Application Programming Interface!Python|(} + +\BornAgain\ simulations and fits can be set up and run from Python programs +or from a Python command-line interpreter like \Code{IPython}. +\index{IPython} +\index{Command line!Python} +A short program in an interpreted language like Python is customarily called +\index{Script!Python} +\index{Python!script} +a \E{script}, +and therefore in the following we will talk about \E{Python scripts}. +Of course this does not preclude the possibility that such scripts evolve into +complex programs, modules, or packages. +And anything we say about scripts also applies to usage of \BornAgain\ in an +interactive Python session.% +\index{Interactive!Python session}% +\index{Python!interactive use}% + +Usage of \BornAgain\ in a Python script should start with the command +\begin{lstlisting}[language=python, style=eclipseboxed,name=ex1,nolol] +import bornagain as ba @\label{import_as}\index{Import!\BornAgain\ to Python|(}@ +\end{lstlisting} +This then allows calls to \BornAgain\ in commands like +\pagebreak[2] +\begin{lstlisting}[language=python, style=eclipseboxed,name=ex1,nolol] +air = ba.HomogeneousMaterial("Air", 0.0, 0.0) @\label{constructor_beg}@ +air_layer = ba.Layer(air) +sample = ba.MultiLayer() @\label{constructor_end}@ +sample.addLayer(air_layer) @\label{class_func_call}@ +\end{lstlisting} +The function calls in lines \ref{constructor_beg}--\ref{constructor_end} +return new \E{objects}. +\index{Object!constructor} +These objects are instances of \E{classes} defined in \BornAgain. +\index{Class!Instantiation} +In the language of object-oriented programming, +a Function that returns a new instance of a class is called a \E{constructor}. +\index{Constructor} +In Python, as in C++, constructor names coincide with class names; +so the constructor function \Code{Layer(material)} will return an +object of class type \Code{Layer}. + +\begin{figure}[tb] +\begin{center} +\includegraphics[width=0.72\textwidth]{fig/drawing/architecturePy.ps} +\end{center} +\caption{Relation between the BornAgain C++ libraries and the Python layer. +\index{Architecture!Python binding}% +Python code is indicated by \textsl{slanted font}. +Colors as in \Cref{Farch1}. +Bold arrows indicate ``depends on'' for code that is automatically generated +by the software tool Swig.% +\index{Swig}% +\index{Python!Swig}% +} +\label{FarchPy} +\end{figure} + +To prevent accidental use of class or constructor names, +they are encapsulated in a \E{namespace} +\index{Namespace} +called \Code{bornagain}. +The \Code{import} command in the above code line~\ref{import_as} +makes this namespace available under the shortcut \Code{ba}. +\index{Import!\BornAgain\ to Python|)} +Note, however, that not all calls to \BornAgain\ require +(and can be recognized by) the prefix \Code{ba}. +The function call \Code{addLayer} in line~\ref{class_func_call} +is defined inside the \BornAgain\ class \Code{MultiLayer}. +The programmer is supposed to know that \Code{sample} is an instance of +class \Code{MultiLayer}, which is part of \BornAgain. +Therefore, there is no need (and no way) to adorn function calls like \Code{addLayer} +with the namespace label \Code{ba}. + +The entirety of classes and functions provided by \BornAgain\ +and exposed to Python forms the \E{BornAgain Python API}. +An API (Application Programming Interface) +\index{Application Programming Interface!Python} +is a kind of protocol that tells a programmer how to use a library. +In this perspective, the research scientist +who uses Python to set up simulations or fits +is seen as a \E{programmer} who writes an application program. +This notwithstanding, he is still a \E{user} +of the BornAgain Python library. +The relation of this library to the underlaying C++ library is explained +in \Cref{FarchPy}. + +The remaining chapters of this \Cref{PUSE} of the BornAgain Manual +contain tutorial examples how to use the BornAgain Python API. +\index{Tutorial} +\Cref{PREF} provides an incomplete reference. +\index{Reference} +For a full reference, see the online API documentation at +\url{bornagain.org/???}. +This documentation is automatically generated from the source code +(which for this purpose contains standardized comments in Doxygen format). +\index{Doxygen!API reference} +\index{Python!Doxygen API reference} +It is actually a documentation of the C++ API, +but usually it is not difficult to infer the form of the corresponding Python +function calls. + +\index{Application Programming Interface!Python|)} +\index{Python!using BornAgain from|)} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Using \BornAgain\ from C++} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\index{C++!using BornAgain from|(} +\index{Application Programming Interface!C++|(} + +Alternatively, BornAgain can also be used from the programs written +in the language~C++. +Since BornAgain itself is written in C++, +\index{C++!BornAgain written in}% +the BornAgain C++ API natively consists of +all classes and functions in \Code{libBornAgainCore} and \Code{libBornAgainFit}, +\index{libBornAgainCore@\Code{libBornAgainCore}}% +\index{libBornAgainFit@\Code{libBornAgainFit}}% +including internal ones that are not exposed to Python. +It empowers application programmers to use BornAgain +in ways we cannot foresee. + +Normal GISAS users, however, will find that their simulation and fit tasks +are well served by the Python API, +that edit-and-rerun cycles are faster with Python than with a compiled language, +and that there is no need to use BornAgain from C++. +Therefore, we provide not much documentation for the C++ API, +except for the automatically generated Doxygen reference at +\url{bornagain.org/???} and +\index{Doxygen!API reference} +\index{C++!Doxygen API reference} +for one basic example \url{Examples/cpp/CylindersAndPrisms} +in the source distribution. + + +\index{Application Programming Interface!C++|)} +\index{C++!using BornAgain from|)} diff --git a/Doc/UserManual/Usage.tex b/Doc/UserManual/Usage.tex new file mode 100644 index 0000000000000000000000000000000000000000..69e98e3b3202a56f3119f6bdfe3183d7f1bae826 --- /dev/null +++ b/Doc/UserManual/Usage.tex @@ -0,0 +1,519 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% BornAgain User Manual +%% +%% homepage: http://www.bornagainproject.org +%% +%% copyright: Forschungszentrum Jülich GmbH 2015 +%% +%% license: Creative Commons CC-BY-SA +%% +%% authors: Scientific Computing Group at MLZ Garching +%% C. Durniak, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\def\PyImport#1{% +\lstinputlisting[language=python,style=eclipseboxed,name=ex1,nolol]{../../Examples/python/#1}} + +\newpage +\chapter{Using the Python API} \label{sec:Usage} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Running a simulation} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +A simulation of GISAS using \BornAgain\ consists of the following steps: +\begin{itemize} +\item define materials by specifying name and refractive index, +\item define layers by specifying thickness, roughness, material, +\item define embedded particles by specifying shape, size, + constituting material, interference function, +\item embed the particles in layers, specifying density, position, orientation, +\item assemble a multilayered sample, +\item specify input beam and detector characteristics, +\item run the simulation, +\item save the simulated detector image. +\end{itemize} + +\noindent +All these steps can be organized in either a Graphical User Interface (GUI) or by providing a Python script with the simulation description. +In the following, we describe how to write a +\Code{Python} script which runs a \BornAgain\ simulation. For tutorials about this programming language, the users are referred to \cite{Lut09}. + + +% More information about the general software architecture and \BornAgain\ internal design are given in \cref{sec:SoftwareArchitecture}. + + +%=============================================================================== +\subsection{Units:} +%=============================================================================== +\index{Units} + +By default the angles are expressed in radians and the lengths are given in +nanometers. But it is possible to use other units by +specifying them right after the value of the corresponding +parameter like, for example, \Code{20.0*micrometer}. + + +%=============================================================================== +\subsection{A first example} \label{sec:Example1Python} +%=============================================================================== + +In this example, we simulate the scattering from a mixture of +cylindrical and prismatic nanoparticles without any interference +between them. These particles are placed in air, on top +of a substrate.\\ We are going to go through each step of the +simulation. The Python code snippet specific to each stage will be given at +the beginning of the description. +More examples can be found at our project web site \url{http://www.bornagainproject.org/documentation/python_examples} + +% But for the sake of completeness the full code is given +% in \cref{PythonSimulationExampleScript}. + +%------------------------------------------------------------------------------- +\subsubsection{Importing Python modules} +%------------------------------------------------------------------------------- + +\begin{lstlisting}[language=python, style=eclipseboxed,name=ex1,nolol] +import numpy @\label{import_lib_beg}@ +import matplotlib +import pylab @\label{import_lib_end}@ +from bornagain import * @\label{import_ba}@ +\end{lstlisting} +We start by importing different functions from external +modules, for example \Code{NumPy} (lines~\ref{import_lib_beg}-\ref{import_lib_end}), which +is a fundamental package for scientific computing with Python +\cite{s:numpy}. In particular, line~\ref{import_ba} +imports the features of \BornAgain\ software. + +%------------------------------------------------------------------------------- +\subsubsection{Defining the materials} +%------------------------------------------------------------------------------- + +\begin{lstlisting}[language=python, style=eclipseboxed,name=ex1,nolol] +def get_sample(): @\label{def_function}@ + """ + Build and return the sample representing cylinders and pyramids on top of substrate without interference. + """ + # defining materials @\label{material1}@ + m_air = HomogeneousMaterial("Air", 0.0, 0.0) @\label{material2}@ + m_substrate = HomogeneousMaterial("Substrate", 6e-6, 2e-8) @\label{material3}@ + m_particle = HomogeneousMaterial("Particle", 6e-4, 2e-8) @\label{materialparticle}@ + +\end{lstlisting} +Line~\ref{def_function} marks the beginning of the +function to define our sample. Lines~\ref{material2}, \ref{material3} and \ref{materialparticle} define different +materials using class \Code{HomogeneousMaterial}. The general syntax is the following +\begin{lstlisting}[language=python, style=eclipse,numbers=none] +<material_name> = HomogeneousMaterial("name", delta, beta) +\end{lstlisting} +where \Code{name} is the name of the +material associated with its complex refractive index +n=1-\Code{delta} +i \Code{beta}. \Code{<material\_name>} is later used when +referring to this particular material. The three materials defined in this example are \Code{Air} with a refractive +index of 1 (\Code{delta = beta = 0}), a \Code{Substrate} associated with a complex refractive index +equal to $1-6\times 10^{-6} +i2\times 10^{-8} $, and the material of the particles, whose refractive index is \Code{n}$=1-6\times 10^{-4}+i2\times 10^{-8}$. + +%------------------------------------------------------------------------------- +\subsubsection{Defining the particles} +%------------------------------------------------------------------------------- +\begin{lstlisting}[language=python,style=eclipseboxed,name=ex1,nolol] + # collection of particles @\label{particles1}@ + cylinder_ff = FormFactorCylinder(5*nanometer, 5*nanometer) @\label{particlescyl1}@ + cylinder = Particle(m_particle, cylinder_ff) @\label{particlescyl2}@ + prism_ff = FormFactorPrism3(10*nanometer, 5*nanometer) @\label{particlesprism1}@ + prism = Particle(m_particle, prism_ff) @\label{particlesprism2}@ +\end{lstlisting} +We implement two different shapes of particles: cylinders and +prisms (\idest elongated particles with a constant equilateral triangular cross section). + +All particles implemented in \BornAgain\ are defined by their +form factors (see \cref{app:ff}), their sizes and the material +they are made of. Here, for the +cylindrical particle, we input its radius and height. For the prism, +the possible inputs are the length of one side of its equilateral triangular +base and its height. + +In order to define a particle, we proceed in two steps. For example for +the cylindrical particle, we first specify the form factor of a cylinder with +its radius and height, both equal to 5 nanometers in this particular +case (see line~\ref{particlescyl1}). Then we associate this shape with +the constituting material as in line~\ref{particlescyl2}. +The same procedure has been applied for the prism in lines~\ref{particlesprism1} and \ref{particlesprism2}, respectively. + +%------------------------------------------------------------------------------- +\subsubsection{Characterizing particles assembly} +%------------------------------------------------------------------------------- +\begin{lstlisting}[language=python, style=eclipseboxed, name=ex1,nolol] + particle_layout = ParticleLayout() @\label{particlesdecor1}@ + particle_layout.addParticle(cylinder, 0.5) @\label{particlesdecor2}@ + particle_layout.addParticle(prism, 0.5)@\label{particlesdecor3}@ + interference = InterferenceFunctionNone() @\label{particlesnointerf}@ + particle_layout.addInterferenceFunction(interference) @\label{particlesinterf}@ +\end{lstlisting} +The object which holds the information about the positions and densities of particles +in our sample is called \Code{ParticleLayout} +(line~\ref{particlesdecor1}). We use the associated function \Code{addParticle} +for each particle shape (lines~\ref{particlesdecor2}, \ref{particlesdecor3}). Its general syntax is + +\begin{lstlisting}[language=python, style=eclipse,numbers=none] +addParticle(<particle_name>, abundance) +\end{lstlisting} +where \Code{<particle\_name>} is the name used to define the particles +(lines~\ref{particlescyl2} and \ref{particlesprism2}) and +\Code{abundance} is the proportion of this type of particles, +normalized to the total number of particles. Here we have 50\% of cylinders +and 50\% of prisms. + +\noindent Finally, lines~\ref{particlesnointerf} and +\ref{particlesinterf} specify that there is \textbf{no coherent interference} between +the waves scattered by these particles. In this case, the intensity is calculated by +the incoherent sum of the scattered waves: $\bra |F_j|^2\ket$, +where $F_j$ is the form factor associated with the particle of type $j$. The way these waves +interfere imposes the horizontal distribution of +the particles as +the interference reflects the long or short-range order of the +particles distribution (see \cref{sec:sect:interf}). On the contrary, the vertical position is +imposed when we add the particles in a given layer by parameter \Code{depth}, as shown in lines~\ref{particlesdecor2} and \ref{particlesdecor3}. + +%------------------------------------------------------------------------------- +\subsubsection{Multilayer} +%------------------------------------------------------------------------------- +\begin{lstlisting}[language=python, style=eclipseboxed,name=ex1,nolol] +# air layer with particles and substrate form multi layer @\label{sampleassembling}@ + air_layer = Layer(m_air) @\label{airlayer}@ + air_layer.addLayout(particle_layout) @\label{airlayerdecorator}@ + substrate_layer = Layer(m_substrate, 0) @\label{substratelayer}@ + multi_layer = MultiLayer() @\label{multilayercanvas}@ + multi_layer.addLayer(air_layer) @\label{layerairdecor}@ + multi_layer.addLayer(substrate_layer) @\label{layersubstrate}@ + return multi_layer @\label{returnmlayer}@ +\end{lstlisting} +We now have to configure our sample. For this first example, +the particles, \idest cylinders and prisms, are on top of a substrate in an +air layer. \textbf{The order in which we define these layers is important: we +start from the top layer down to the bottom one}. + +Let us start with the air layer. It contains the particles. In +line~\ref{airlayer}, we use the previously defined \Code{m\_air} +(="air" material) (line~\ref{material2}). The command in line~\ref{airlayerdecorator} shows that this layer contains particles +which are defined using particle layout object. The substrate layer +only contains the substrate material (line~\ref{substratelayer}). +%Note that the +%\Code{depth} is referenced to the bottom of the top layer (negative +%values would correspond to particles floating above layer 1 as +%the vertical axis is pointing upwards). + +There are different possible syntaxes to define a layer. As shown in +lines~\ref{airlayer} and \ref{substratelayer}, we can use +\Code{Layer(<material\_name>,thickness)} or +\Code{Layer(<material\_name>)}. The second case corresponds +to the default value of the \Code{thickness}, equal to 0. The \Code{thickness} is +expressed in nanometers. + +Our two layers are now fully characterized. The sample is assembled using +\Code{MultiLayer()} constructor (line~\ref{multilayercanvas}): we start with the air layer decorated +with the particles (line~\ref{layerairdecor}), which is the layer at +the top and end with the bottom layer, which is the +substrate (line~\ref{layersubstrate}). + +%------------------------------------------------------------------------------- +\subsubsection{Characterizing the input beam and output detector} +%------------------------------------------------------------------------------- + +\begin{lstlisting}[language=python, style=eclipseboxed,name=ex1,nolol] +def get_simulation(): @\label{run1}@ + """ + Create and return GISAXS simulation with beam and detector defined + """ + simulation = Simulation() @\label{run2}@ + simulation.setDetectorParameters(100, -1.0*degree, 1.0*degree, 100, 0.0*degree, 2.0*degree) @\label{rundetector}@ + simulation.setBeamParameters(1.0*angstrom, 0.2*degree, 0.0*degree) @\label{runbeam}@ + return simulation @\label{returnsimul}@ +\end{lstlisting} +The first stage is to create the \Code{Simulation()} object (line~\ref{run2}). Then we define the detector (line~\ref{rundetector}) and beam +parameters (line~\ref{runbeam}). %, which are associated with the +%sample previously defined (line~\ref{runsample}). Finally we run +%the simulation (line~\ref{runsimul}). +Those functions are part of the Simulation +class. The different incident and exit angles are +shown in \cref{fig:multil3d}. + +The detector parameters are set using ranges of angles via +the function: + +\begin{lstlisting}[language=python, style=eclipse,numbers=none] +setDetectorParameters(n_phi, phi_f_min, phi_f_max, n_alpha, alpha_f_min, alpha_f_max), +\end{lstlisting} + + +\noindent where number of bins \Code{n\_phi}, low edge of first bin \Code{phi\_f\_min} and +upper edge of last bin \Code{phi\_f\_max} all together define $\phi_f$ detector axis, +while \Code{n\_alpha}, \Code{alpha\_f\_min} and \Code{alpha\_f\_max} are related to +$\alpha_f$ detector axis. + +\Note{Axis binning: +By default axes are binned to provide constant bin size in k-space, which means slightly +non-equidistant binning in angle space. Other possible options, including user defined +axes with custom variable bin size are explained elsewhere.} + +%are the minimum and maximum values of $\phi_f$, respectively, \Code{n\_alpha} is +%the number of bins for $\alpha_f$ axis, \Code{alpha\_f\_min} and \Code{alpha\_f\_max} +%are the minimum and maximum values of +%$\alpha_f$, respectively. + +%\Code{isgisaxs\_style=True} (default value = \Code{False}) is a boolean +%used to characterise the structure of the output data. If +%\Code{isgisaxs\_style=True}, the output data is binned at constant +%values of the sine of the output angles, $\alpha_f$ and $\phi_f$, otherwise it is binned +%at constant values of these two angles.\\ + +\noindent To characterize the beam we use function +\begin{lstlisting}[language=python, style=eclipse,numbers=none] +setBeamParameters(lambda, alpha_i, phi_i), +\end{lstlisting} + +\noindent where \Code{lambda} is the incident beam wavelength, +\Code{alpha\_i} is the incident +grazing angle on the surface of the sample, +\Code{phi\_i} is the in-plane +direction of the incident beam (measured with respect to the $x$-axis). + + +%------------------------------------------------------------------------------- +\subsubsection{Running the simulation and plotting the results} +%------------------------------------------------------------------------------- + +\begin{lstlisting}[language=python, style=eclipseboxed,name=ex1,nolol] +def run_simulation(): @\label{run_simulation}@ + """ + Run simulation and plot results + """ + sample = get_sample() @\label{get_sample}@ + simulation = get_simulation() @\label{get_simulation}@ + simulation.setSample(sample) @\label{setsample}@ + simulation.runSimulation() @\label{runsimul}@ + result = simulation.getIntensityData().getArray() + 1 # for log scale @\label{outputdata}@ + pylab.imshow(numpy.rot90(result, 1), norm=matplotlib.colors.LogNorm(), extent=[-1.0, 1.0, 0, 2.0]) @\label{plot1}@ + pylab.show() @\label{plot2}@ +\end{lstlisting} +%In function \Code{run\_simulation()}, we associate the sample +%characterised by function \Code{get\_sample()} with the input beam and +%output detector, defined in function \Code{get\_simulation()} (line~\ref{runsample}). +The function, whose definition starts from line~\ref{run_simulation}, gathers all +items. We create the sample and the simulation objects at the lines +~\ref{get_sample} and \ref{get_simulation}, using calls to the previously defined functions. We assign the sample to the simulation at line ~\ref{setsample} and +finally launch the simulation at line ~\ref{runsimul}. + +In line~\ref{outputdata} we obtain the simulated intensity +as a function of outgoing angles $\alpha_f$ and $\phi_f$ for further +uses (plots, fits,\ldots) as a \Code{NumPy} array containing +\Code{n\_phi}$\times$\Code{n\_alpha} +datapoints. Lines~\ref{plot1}-\ref{plot2} produces the two-dimensional +contour plot of the intensity as a function of $\alpha_f$ and +$\phi_f$ shown in \cref{fig:output_ex1}. + +\begin{figure}[htbp] + \begin{center} + \includegraphics[clip=true, width=120mm]{fig/gisasmap/Manual_ex1.eps} + \end{center} + \caption[Example 1: Simulated grazing-incidence small-angle X-ray scattering from a mixture of +cylindrical and prismatic nanoparticles without any interference, deposited on top +of a substrate]{Simulated grazing-incidence small-angle X-ray scattering from a mixture of +cylindrical and prismatic nanoparticles without any interference, deposited on top +of a substrate. The input beam is characterized by a wavelength +$\lambda$ of 1~\AA\ and incident angles $\alpha_i=0.2^{\circ}$, $\phi_i=0^{\circ}$. The +cylinders have a radius and a height both equal to 5~nm, the prisms +are characterized by a side length equal to 10~nm and they are 5~nm high. The +material of the particles has a refractive index of $1-6\times 10^{-4}+i2\times 10^{-8}$. For the substrate +it is equal to $1-6\times 10^{-6} +i2\times 10^{-8} $. The color scale +is associated with the output intensity in arbitrary units. } +\label{fig:output_ex1} +\end{figure} + + +%=============================================================================== +\subsection{Working with sample parameters} + \label{sec:WorkingWithSampleParameters} +%=============================================================================== + + +This section gives additional details about the manipulation of sample parameters +during run time; that is after the sample has already been constructed. +For a single simulation this is normally not necessary. However it might be useful +during interactive work when the user tries to find optimal sample parameters by +running a series of simulations. +A similar task also arises when the theoretical model, composed of the +description of the sample and of the simulation, is used for fitting real data. +In this case, the fitting kernel requires a list of the existing sample parameters +and a mechanism for changing the values of these parameters in order to find +their optima. + +In \BornAgain\ this is done using the so-called sample parameter pool +mechanism. We are going to briefly explain this approach using the example +of \cref{sec:Example1Python}. + +In \BornAgain\ a sample is described by a hierarchical tree of objects. +For the multilayer created in the previous section this tree can be graphically +represented as shown in \cref{fig:sample_tree}. Similar trees can +be printed in a Python +session by running \Code{multi\_layer.printSampleTree()} + +\begin{figure}[p!] + +\tikzstyle{every node}=[draw=black,thick,anchor=west] +\tikzstyle{selected}=[draw=red,fill=red!30] +\tikzstyle{optional}=[dashed,fill=gray!50] +\begin{tikzpicture}[% + grow via three points={one child at (0.5,-0.7) and + two children at (0.5,-0.7) and (0.5,-1.4)}, + edge from parent path={(\tikzparentnode.south) |- (\tikzchildnode.west)}] + \node {MultiLayer} + child { node {Layer \#0} + child { node {ParticleLayout } + child { node {Particle Info 0} + child {node {Particle } + child { node {FormFactorCylinder} + child { node [optional] { radius:5.0} } + child { node [optional] { height:5.0} } + } + } + child [missing] {} + child [missing] {} + child [missing] {} + child {node [optional] { abundance:0.5} } + child {node [optional] { depth:0.0} } + } + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child { node {Particle Info 1} + child {node {Particle } + child { node {FormFactorPrism3} + child { node [optional] { length:10.0} } + child { node [optional] { height:5.0} } + } + } + child [missing] {} + child [missing] {} + child [missing] {} + child {node [optional] { abundance:0.5} } + child {node [optional] { depth:0.0} } + } + } + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child {node [optional] { thickness:0.0} } + } + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child [missing] {} + child { node {Layer interface \#0} + child {node { roughness} + child {node [optional] { corrlength:0.0} } + child {node [optional] { hurst:0.0} } + child {node [optional] { sigma:0.0} } + } + } + child [missing] {} + child [missing] {} + child [missing] {} + child { node {Layer \#1} + child {node [optional] { thickness:0.0} } + } + child [missing] {} + child { node [optional] {CrossCorrLength:0.0} }; + +\end{tikzpicture} +\caption{Tree representation of the sample structure.} +\label{fig:sample_tree} +\end{figure} + + +The top \Code{MultiLayer} object is composed of three children, namely +\Code{Layer \#0, Layer Interface \#0} and \Code{Layer \#1}. The +children objects might themselves also be decomposed into tree-like structures. For example, +\Code{Layer \#0} contains a \Code{ParticleLayout} object, which holds information +related to the two types of particles populating the layer. All numerical values used +during the sample construction (thickness of layers, size of particles, roughness parameters) are part of the same tree structure. +They are marked in the figure with shaded gray boxes. + +These values are registered in the sample parameter pool using the name +composed of the corresponding nodes' names. And they can be accessed/changed +during run time. For example, the \Code{height} of the cylinders +populating the first layer can be changed from the +current value of $5~\rm{nm}$ to $1~\rm{nm}$ by running the command + +\begin{lstlisting}[language=shell, style=commandline] +multi_layer.setParameterValue('/MultiLayer/Layer0/ParticleLayout/ParticleInfo0/Particle/FormFactorCylinder/height', 1.0) +\end{lstlisting} + + +A list of the names and values of all registered sample's parameters +can be displayed using the command + +\begin{lstlisting}[language=shell, style=commandline] +> multi_layer.printParameters() +The sample contains following parameters ('name':value) +'/MultiLayer/Layer0/ParticleLayout/ParticleInfo0/Particle/FormFactorCylinder/height':5 +'/MultiLayer/Layer0/ParticleLayout/ParticleInfo0/Particle/FormFactorCylinder/radius':5 +'/MultiLayer/Layer0/ParticleLayout/ParticleInfo0/abundance':0.5 +'/MultiLayer/Layer0/ParticleLayout/ParticleInfo0/depth':0 +'/MultiLayer/Layer0/ParticleLayout/ParticleInfo1/Particle/FormFactorPrism3/length':5 +'/MultiLayer/Layer0/ParticleLayout/ParticleInfo1/Particle/FormFactorPrism3/height':5 +'/MultiLayer/Layer0/ParticleLayout/ParticleInfo1/abundance':0.5 +'/MultiLayer/Layer0/ParticleLayout/ParticleInfo1/depth':0 +'/MultiLayer/Layer0/thickness':0 +'/MultiLayer/Layer1/thickness':0 +'/MultiLayer/LayerInterface/roughness/corrlength':0 +'/MultiLayer/LayerInterface/roughness/hurst':0 +'/MultiLayer/LayerInterface/roughness/sigma':0 +'/MultiLayer/crossCorrLength':0 +\end{lstlisting} + +Wildcards \Code{'*'} can be used to reduce typing or to work on a group +of parameters. In the example below, the first command will change the +height of all cylinders in the same way, as in the previous example. The second line will change simultaneously the height of {\it both} cylinders and prisms. +\begin{lstlisting}[language=shell, style=commandline] +multi_layer.setParameterValue('*FormFactorCylinder/height', 1.0) +multi_layer.setParameterValue('*height', 1.0) +\end{lstlisting} + +The complete example described in this section can be found at +\begin{lstlisting}[language=shell, style=commandline] +./Examples/python/fitting/ex001_SampleParametersIntro/SampleParametersIntro.py +\end{lstlisting} + +\section{UNDER CONSTRUCTION} + +\PyImport{simulation/ex01_BasicParticles/AllFormFactorsAvailable.py} diff --git a/Doc/UserManual/fig/drawing/architecture1.ps b/Doc/UserManual/fig/drawing/architecture1.ps new file mode 100644 index 0000000000000000000000000000000000000000..1b7abc3f2cd545ef32a2cdf038563c90fa42f422 --- /dev/null +++ b/Doc/UserManual/fig/drawing/architecture1.ps @@ -0,0 +1,1683 @@ +%!PS-Adobe-1.0 EPSF-1.0 +%%BoundingBox: 75 461 588 747 +%%Comment: Bounding box extracted by bboxx +%%+: A program by Dov Grobgeld 2003 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% FRIDA: fast reliable interactive data analysis %% +%% wups11a.ps: graphic macros %% +%% (C) Joachim Wuttke 1990-2016 %% +%% http://www.messen-und-deuten.de/frida %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Sections: +% - Programming, Page Formatting, Coordinate Transforms +% - Colors +% - Fonts and Text Blocks +% - Coordinate Frame +% - Data Plotting (Symbols and Curves) +% - Lists +% - Macro Collection + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Programming, Page Formatting, Coordinate Transforms %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% Framework: + +% For interleaving applications, isolate what follows in a dictionary +/WuGdict11a 400 dict def +WuGdict11a begin + + +%% Shortcuts: + +/np { newpath } bind def +/mv { moveto } bind def +/rm { rmoveto } bind def +/rl { rlineto } bind def +/li { lineto } bind def +/cp { closepath } bind def +/st { stroke } bind def +/x { exch } bind def + +/black { 0 setgray } bind def +/white { 1 setgray } bind def + +/F false def +/T true def + + +%% Constants: + +/pt { .018567 mul} bind def % for line widths and font sizes, reason unclear +/cm {28.346456 mul} bind def % typographic_point -> cm + +/twopi { 6.2831853072 } def + + +%% Math operators: + +/rnd { rand cvr 1 30 bitshift div 2 div 0 max 1 min } def % -> between 0 and 1 + +/min { 2 copy gt { x } if pop } def +/max { 2 copy lt { x } if pop } def + +/tan { dup sin x cos div } def +/cot { dup cos x sin div } def +/pol2xy{ 2 copy cos mul 3 1 roll sin mul } def % r phi | x y + +/eexp { 2.71828 x exp } def % "exp" is x^y, eexp is e^x +/tanh { 2.71828 x 2 copy exp 3 1 roll neg exp + 2 copy sub 3 1 roll add div } def + + +%% Page layout and global figure size: + +% shift origin +% The PostScript coordinate system starts in the lower left corner +% of the page, whereas we want our figures to be justified in the +% upper left corner. Therefore we need a vertical translation, +% depending on the paper size. A4 is 210x297 mm^2. By this occasion, +% we also provide a border of 7 mm. +/cmtranslate { % x y cmtranslate | - + cm x cm x translate } bind def +/originUpperLeft_A4{ .7 28.3 cmtranslate } bind def +/goffsetA4 { ungscale originUpperLeft_A4 gscale } def +/EdgeLeftDIN{ originUpperLeft_A4 } bind def % OBSOLETE since 11a + +% set absolute global scale and relative symbol size +/defsiz { % size(cm) symbolsize(rel) | - + /ftot x def + /gsiz x cm 10 div def + gscale % within 'size', coordinates run from 0 to 10 + } def +/gscale { + gsiz dup scale +} def +/ungscale { + 1 gsiz div dup scale +} def + +% symbol (and label?) size as sublinear function of figure size +/autolabel { % size(cm) | symbolsize(rel) + dup 7 div 2 add 4 mul % the simplest sublinear increase + x div % anticipate overall rescaling + } def + + +%% Frame size and shape, frame coordinates: + +% aspect ratios +/gyld {0.447214 mul} bind def /Gyld {0.447214 div} bind def % sqrt(5) +/guld {0.547723 mul} bind def /Guld {0.547723 div} bind def % sqrt(3) +/gold {0.618034 mul} bind def /Gold {0.618034 div} bind def % goldener Schnitt +/gild {0.707107 mul} bind def /Gild {0.707107 div} bind def % sqrt(2) : DIN +/geld {0.759836 mul} bind def /Geld {0.759836 div} bind def % sqrt(sqrt(3)) +/gald {0.817765 mul} bind def /Gald {0.817765 div} bind def % sqrt sqrt sqrt 5 + +% define frame coordinates +/defred { % x_reduction y_reduction label_reduction | - + /fmm x ftot mul def + /ymm x def + /xmm x def + + % conversion frame_coordinate -> global_coord + /xm {xmm mul} bind def + /ym {ymm mul} bind def + /fm {fmm mul} bind def + /xym {ym x xm x} bind def + + % prefer rescaling over explicit conversion (make more use of this !) + /mmscale { xmm ymm scale } bind def + /mmunscale { 1 xmm div 1 ymm div scale } bind def + + % graphic commands in frame coordinates + /offset { xym translate } bind def + /currentxy { currentpoint ymm div x xmm div x } bind def + /setline { pt fm setlinewidth [] 0 setdash } bind def + } def + +/stdred { % x_reduction y_reduction | - + 2 copy mul sqrt defred + } def + +%% World (= user application) coordinates: + +% user must declare x and y range +/xSetCoord { % log min max | - + /wxmax x def + /wxmin x def + /wxlog x 0 eq not def + % prepare conversion world coord -> frame coord + /wxdel wxmax wxmin wxlog { div log } { sub } ifelse def + /wxd { % dx(world) | dx(frame) + wxlog { log } if wxdel div 10 mul + } bind def + /wx { % x(world) | x(frame) + wxmin wxlog { div } { sub } ifelse + wxd + } bind def + } def +/ySetCoord { % log min max | - + /wymax x def + /wymin x def + /wylog x 0 eq not def + /wydel wymax wymin wylog { div log } { sub } ifelse def + /wyd { % dy(world) | dy(frame) + wylog { log } if wydel div 10 mul + } bind def + /wy { % y(world) | y(frame) + wymin wylog { div } { sub } ifelse + wyd + } bind def + } def + +% pair conversion +/wxy { % x,y(world) -> x,y(frame) + wy x wx x + } def + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Colors %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% Color operators: + +/setRGBcolor { + 3 { 255 div 3 1 roll } repeat setrgbcolor + } def + +/colormix { % weight(0..1) col1(R|G|B) col2(R|G|B) | col(R|G|B) + 7 -1 roll dup /weightA x def /weightB x 1 x sub def + 4 -1 roll weightA mul x weightB mul add 5 1 roll + 3 -1 roll weightA mul x weightB mul add 4 1 roll + 2 -1 roll weightA mul x weightB mul add 3 1 roll + } def + +/relcol { % i_col n_col | rel(0..1) : for one-dimensional choices + 1 sub div 0 max 1 min + } def + + +%% Named colors: + +/siemensorange { 255 153 0 setRGBcolor } bind def +/siemensblue { 0 102 153 setRGBcolor } bind def +/siemenstext { 0 51 102 setRGBcolor } bind def +/siemensred { 165 0 33 setRGBcolor } bind def +/siemenspink { 221 102 102 setRGBcolor } bind def +/siemensgrey { 221 221 221 setRGBcolor } bind def +/siemensdark { 102 102 102 setRGBcolor } bind def +/siemensgreen { 33 153 102 setRGBcolor } bind def +/siemensyellow { 255 221 0 setRGBcolor } bind def + +/red { 255 0 0 setRGBcolor } bind def + + +%% One-dimensional linear color choices: + +/iCol1 { % i i_max | - : default -2010, round the circle, RGBR + relcol dup 1 x % rel 1 rel + 360 mul 255 add cos 1 add dup mul neg .053 mul 1 add % modulate saturation + sethsbcolor + } def +/iCol2 { % i i_max | - : cyan - yellow - magenta + relcol 3 mul + dup 1 le { + dup 1 sub neg 0 3 2 roll } { + dup 2 le { + 1 sub dup 1 sub neg 0 3 1 roll } { + 2 sub dup 1 sub neg 0 3 0 roll } ifelse + } ifelse + 0 setcmykcolor + } def +/iCol3 { % i i_max | - : siemens + div /icnow x def + 165 1 icnow sub mul + 102 icnow mul + 33 120 icnow mul add setRGBcolor + } def +/iCol4 { % i i_max | - : red to blue (subsequence of old scheme iCol1) + relcol + 3 x sub 3 div 1 iCol1 + } def + + +%% One-dimensional color choice from given array: + +/iColA { % i i_max arr | - + /aCol x def + relcol + aCol length 1 sub mul % position within array + dup cvi dup 3 1 roll % idx pos idx + sub x % offset idx + 0 max aCol length 1 sub min % offset safe_idx + dup 1 add aCol length 1 sub min % offset i i+1 + aCol x get exec + 4 3 roll aCol x get exec colormix setRGBcolor + } def + + +%% Color arrays for non-linear one-dimensional choices: + +/aCol1 [ % red-blue + { 255 0 0 } % 1 + { 240 10 10 } % 2 + { 220 40 40 } % 3 + { 205 65 90 } % 4 + { 195 80 130 } % 5 + { 180 110 180 } % 6 + { 165 120 185 } % 7 + { 150 130 190 } % 8 + { 130 150 210 } % 9 + { 110 125 220 } % 10 + { 85 105 230 } % 11 + { 70 90 255 } % 12 + { 0 0 255 } % 13 + ] def +/aCol2 [ % orange-red-blue-darkblue + { 255 180 0 } % 1 + { 255 160 0 } % 1 + { 255 120 0 } % 2 + { 255 70 0 } % 3 + { 255 0 0 } % 4 + { 220 30 30 } % 5 + { 220 70 60 } % 6 + { 220 100 110 } % 7 + { 200 130 130 } % 8 + { 200 130 160 } % 9 + { 180 110 180 } % 10 + { 165 110 185 } % 11 + { 150 130 190 } % 12 + { 130 150 210 } % 13 + { 100 120 220 } % 14 + { 85 105 230 } % 15 + { 70 90 255 } % 16 + { 0 0 255 } % 17 + { 0 0 180 } % 18 + { 10 10 150 } % 19 + { 30 30 130 } % 20 + ] def +/aCol3 [ % [fixed size: 9] siemenscolors + { 165 0 33 } % siemensred + { 33 153 102 } % siemensgreen + { 0 102 153 } % siemensblue + { 0 51 102 } % siemenstext + { 255 153 0 } % siemensorange + { 102 102 102 } % siemensdark + { 255 221 0 } % siemensyellow + { 221 221 221 } % siemensgrey + { 221 102 102 } % siemenspink + ] def +/aCol4 [ % green-blue-brown + { 120 160 60 } + { 90 185 40 } + { 50 215 20 } + { 0 245 0 } + { 10 235 112 } + { 20 235 143 } + { 30 230 173 } + { 40 225 194 } + { 50 205 215 } + { 40 153 204 } + { 40 102 153 } + { 40 82 122 } + { 90 74 101 } + { 140 68 80 } + { 170 59 60 } + { 190 50 40 } + { 180 65 40 } + { 160 80 40 } + { 140 100 40 } + { 120 80 30 } + { 100 60 20 } + ] def +/aCol5 [ % [fixed size: 8] gnuplot default (see man gnuplot and rgb.txt) + { 255 0 0 } % red + { 0 255 0 } % green + { 0 0 255 } % blue + { 255 0 255 } % magenta + { 0 255 255 } % cyan + { 160 82 45 } % sienna + { 255 165 0 } % orange + { 255 127 80 } % coral + ] def + + +%% Specialized ifelse, depending on pcol / ccol - OBSOLETE since 11a: + +/ifpcol { % proc1 proc2 | - + pcol 0 eq { pop exec } { exec pop} ifelse % 3 1 roll ifelse + } def +/ifccol { % proc1 proc2 | - + ccol 0 eq { pop exec } { exec pop} ifelse % 3 1 roll ifelse + } def + + +%% old-style colors round the circle - OBSOLETE since 10a: + +% global preset +/pColSet { % col ncol | - + /npcol x def % # different colours + /pcol x def % colours off/on + } def +/cColSet { % col ncol | - + /nccol x def % # different colours + /ccol x def % colours off/on + } def +% default setting +0 3 pColSet % default setting +0 3 cColSet % default setting +% now defined locally in g3.ps +/ipCol { 100 iCol1 } def +/icCol { 100 iCol1 } def + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Fonts and Text Blocks %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% Prepare standard fonts: + +% extend font encoding +/ReEncode { % OldFont NewFont Encoding | - + /MyEncoding x def + x findfont % select OldFont + dup length dict begin + {def} forall + /Encoding MyEncoding def + currentdict + end + definefont % define as NewFont + } def + +% we assume that image scripts are Latin1 encoded +/Helvetica /MyFont ISOLatin1Encoding ReEncode +/Helvetica-Oblique /MyFont-Oblique ISOLatin1Encoding ReEncode +/Helvetica-Bold /MyFont-Bold ISOLatin1Encoding ReEncode +/Helvetica-BoldOblique /MyFont-BoldOblique ISOLatin1Encoding ReEncode + +/setPalatino { +/Palatino /MyFont ISOLatin1Encoding ReEncode +/Palatino-Italic /MyFont-Oblique ISOLatin1Encoding ReEncode +/Palatino-Bold /MyFont-Bold ISOLatin1Encoding ReEncode +/Palatino-BoldItalic /MyFont-BoldOblique ISOLatin1Encoding ReEncode +} def + +%% Preset standard styles: + +% scale and set font; define fontsize, fontheight +/setfontandsize { % font size | - + dup 0 le { pop 100 } if % fontsize <= 0 not allowed ! + /fontnonnil true def + pt fm dup /fontsize x def + x findfont + x scalefont + setfont + gsave % determine fontheight - from the cookbook : + np 0 0 mv (1) true charpath flattenpath + pathbbox % low_left_x, low_left_y, up_right_x, up_right_y + x pop x pop x pop + /fontheight x def + grestore + } def + +% standard settings for labelling axes +/setnum { /MyFont 24 setfontandsize } def +/setlab { /MyFont 24 setfontandsize } def + +% user commands (free choice of fontsize, but fixed font family) +/setown { /MyFont x setfontandsize } def +/setbol { /MyFont-Bold x setfontandsize } def +/setboq { /MyFont-BoldOblique x setfontandsize } def +/setobl { /MyFont-Oblique x setfontandsize } def + + +%% String treatment: + +/showif { % string | - : increment xwidth or plot string + prepare + { stringwidth pop xwidth add /xwidth x def } + { show } + ifelse + } def +/script { % matrix relpos_y | - + /yoffset x fontheight mul def + currentfont x makefont setfont + 0 yoffset rm + } def +/scred .71 def +/subsc { + showif + [scred 0 0 scred 0 0] -.2 script + } def +/supsc { + showif + [scred 0 0 scred 0 0] .6 script + } def +/endsc { + showif + regularfont setfont + 0 yoffset neg rm + } def +/grec { + showif + /Symbol findfont fontsize scalefont setfont + } def +/endgr { + showif + regularfont setfont + } def +/endall { + showif + regularfont setfont + } def +/build { % string xrel yrel obj | - : plot obj above/below string + /obj x def /yrelbui x def /xrelbui x def + dup showif + prepare + { pop } + { stringwidth pop xrelbui neg mul fontheight yrelbui mul % relpos for obj + currentpoint 4 2 roll % save position after string + rm obj pop % obj must end with () that will be pop'ed + mv % back to saved position + } + ifelse + } def +/gbuild { % string xrel yrel obj | - : plot obj above/below string + /obj x def /yrelbui x def /xrelbui x def + /Symbol findfont fontsize scalefont setfont + dup showif + prepare + { pop regularfont setfont } + { stringwidth pop xrelbui neg mul fontheight yrelbui mul % relpos for obj + currentpoint 4 2 roll % save position after string + regularfont setfont + rm obj pop % obj must end with () that will be pop'ed + mv % back to saved position + } + ifelse + } def +/hut { % ..) (<Char>) hut (.. %%% MISERABEL PROGRAMMIERT + x showif + 1.4 .6 {(\136) show ()} build + } def +/ghut { % ..) (<grec-Char>) ghut (.. %%% BREITE PASST NUR FUER Phi(t) + x showif + .8 .65 {(\136) show ()} gbuild + } def +/tilde { + x showif + 1. .6 {(~) show ()} build + } def +/gtilde { + x showif + 1. .6 {(~) show ()} gbuild + } def +/spce { % string n spce - ; insert n times ( ) + {showif ( )} repeat + } def + +% the following macros use the symbol/curve plotting mechanism +/pins { % string symins - ; symbol must be selected by pset + showif + ( ) showif ( ) .5 .5 { currentxy 0 p black ()} build ( ) showif + } def +/clenins { % string len clenins - ; curve must be selected by cset + x showif % I suppose that pins is preceeded by 8 spaces + dup ( ) stringwidth pop mul 2 add /xstrich x xmm div def + % length of inserted curve : + % -1 space : curve begins and ends in middle of ( ) + % +3 spaces: pins requires 3 times ( ) + ( ) 0 .5 { currentxy currentxy 0 ci x xstrich add x 0 cf () } build + 2 add {( ) showif} repeat + } def +/cins { % string symins - ; curve must be selected by cset + showif 8 % I suppose that pins is preceeded by 8 spaces + dup ( ) stringwidth pop mul 2 add /xstrich x xmm div 10 div def + % nov03, ohne zu verstehen, "10 div" eingefuegt + % length of inserted curve : + % -1 space : curve begins and ends in middle of ( ) + % +3 spaces: pins requires 3 times ( ) + ( ) 0 .5 { currentxy currentxy 0 ci x xstrich add x 0 cf () } build + 2 add {( ) showif} repeat + } def + +/block { % x y ob xrel yrel | - + /yrel x def /xrel x def /blabla x def + /ypos x ym def /xpos x xm def + /regularfont currentfont def /yoffset 0 def % initialize for security + /prepare true def /xwidth 0 def 0 0 mv % to prevent empty-path-error + blabla endall % first pass : determine xwidth + boxif { /boxwidth xwidth (M) stringwidth pop boxxr mul 2 mul add def + /boxheight fontheight 1 boxyr 2 mul add mul def + np xpos xwidth xrel mul sub boxwidth xwidth sub 2 div sub + ypos fontheight .5 boxyr add mul sub mv + boxwidth 0 rl 0 boxheight rl boxwidth neg 0 rl cp + boxproc + } if + xpos xwidth xrel mul sub ypos fontheight yrel mul sub mv + /prepare false def + blabla endall % second pass : plot + /boxif false def + } def +/rblock { % x y ang ob proc rblock - + 5 3 roll + gsave + xym translate + 3 2 roll rotate + 0 0 4 2 roll exec + grestore + } def + +/Box { % x y {exe} + /boxif true def + /boxproc x def /boxyr x def /boxxr x def + } def +/nBox { .6 .6 3 2 roll Box } def +/boxif false def +/textW { % obj | length : calculate only length. + /blabla x def + /regularfont currentfont def /yoffset 0 def % initialize for security + /prepare true def /xwidth 0 def 0 0 mv % to prevent empty-path-error + blabla endall + xwidth % has been determined + } def +/textw { % obj | y : dito, in 0..10-units + textW xmm div + } def + +% horizontal text: x y ob | - +/textLB { 0. 0. block } bind def +/textCB { .5 0. block } bind def +/textRB { 1. 0. block } bind def +/textLM { 0. .5 block } bind def +/textCM { .5 .5 block } bind def +/textRM { 1. .5 block } bind def +/textLT { 0. 1. block } bind def +/textCT { .5 1. block } bind def +/textRT { 1. 1. block } bind def + +% rotated text: x y ang ob | - +/rtextLB { {textLB} rblock } bind def +/rtextLM { {textLM} rblock } bind def +/rtextRB { {textRB} rblock } bind def +/rtextRM { {textRM} rblock } bind def +/rtextCM { {textCM} rblock } bind def + + +%% Language selection: + +% preset +/language { % choose_this of_so_many | - % select current language + /langMax x def + /langChc x def + } def +1 1 language % default +% choose text from sequence +/langSel { % text_1 .. text_M | text_C : choose text, M=langMax, C=langChc + langMax dup langChc sub 1 add roll + langMax 1 sub { pop } repeat + } def + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Coordinate Frame %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% Layout presets: + +/xyTicLen {0.10 fm} def +/xyTacLen {0.20 fm} def +/txllen {0.20 fm} def +/tyllen {0.20 fm} def +/linsetAxx {black 0.7 setline} def +/linsetTic {black 0.7 setline} def +/linsetTac {black 0.7 setline} def +/linsetGri {black 0.4 setline} def + +%% Start-up commands: + +/Resets { + /yNumLengthL 0 def /yNumLengthH 0 def + /xNumHeightL .3 def /xNumHeightH 0 def + /xNumHeightRel 2.4 def + /aMean 5 def + /xPlotFrame {} def + /yPlotFrame {} def + /zPlotFrame {} def + black + } def +/BoxBackground { + 0 0 10 10 boxit gsave setboxbackgroundcolor fill grestore +} def +/setboxbackgroundcolor { white } def + + +%% Some more presets for g3.ps: + +/iFrame 0 def + +/setnewpage { % xoff yoff + /yoffnewpage x def + /xoffnewpage x def +} def +/newpage { + goffsetA4 + xoffnewpage yoffnewpage offset +} def +/setpagegrid { % ncol nrow xoffnewframe yoffnewframe + /yoffnewframe x def + /xoffnewframe x def + /nrowpage x def + /ncolpage x def +} def +/nextFrame { + /iFrame iFrame 1 add def + iFrame nrowpage ncolpage mul mod 0 eq { + showpage gscale newpage + } { + iFrame ncolpage mod 0 eq { + xoffnewframe ncolpage 1 sub neg mul yoffnewframe offset + } { + xoffnewframe 0 offset + } ifelse + } ifelse +} def + + +/zValues { pop pop } def +/plotafter {} def +/whiteframe { 1 0 0 10 10 graybox } def +/plotframes { xPlotFrame yPlotFrame } def +/plotbefore { plotframes } def + +/abc {abclab setown abcx abcy 3 2 roll textCM} def % usage ((a)) abc +/abcset { % x y siz abcset - : preset for abc + /abclab x def /abcy x def /abcx x def + } def + + +%% Ticks: + +% set tick array - internal macros +/tiputs { % rel_pos_of_tick | pos_of_tick : innermost routine for /taproc + tastep mul taloop add + } def +/taproclin { % (#tick/tack) | - : define /taproc for use in SetVec + 1 x div /tistep x def + /taproc { 0 tistep .999 { tiputs } for } def + } def +/taproclog { % (#ticks/tacks) | - : define /taproc for use in SetVec + dup 3 gt { pop /taproc { 1 1 9 { log tiputs } for } def + }{ dup 1 gt { pop /taproc { 0 tiputs 2 log tiputs 5 log tiputs } def + }{ dup 0 gt { pop /taproc { 0 tiputs } def + }{ neg taproclin + } ifelse } ifelse } ifelse + } def +/SetVec { % tafro tatoo nta /vector | - : set /vector + 4 1 roll + /nta x def /tatoo x def /tafro x def + /tastep tatoo tafro sub nta 1 sub div def + [ + 0 1 nta { + tastep mul tafro add /taloop x def + taproc exec + } for + ] def + } def +% set tick array - user commands +/SetTicVecLin { taproclin /TicVec SetVec } def +/SetTicVecLog { taproclog /TicVec SetVec } def + +% set tack-and-number array +/SetTacVec { % [ pos {label} pos {label} ... ] | - + /TacVec x def + } def + +% define axes + % note on angles : 0 = x-axis, 90 = y-axis +/OneAxx { % fro to xpos ypos aang tang | - : presets for Axx, Tic, Tac, Num + % store arguments + /tAng x def /aAng x def + /yPos x def /xPos x def + /aTo x def /aFro x def + % set constants + /xTicLen tAng cos xyTicLen mul def /yTicLen tAng sin xyTicLen mul def + /xTacLen tAng cos xyTacLen mul def /yTacLen tAng sin xyTacLen mul def + /xAng aAng cos def /yAng aAng sin def + /aMean aFro aTo add 2 div def + /aArr false def + } def +/ArrAxx { % label <args of OneAxx> | - : axis with arrow + OneAxx + /aLab x def + /aArr true def + } def + +% draw axis (with parameters preset by OneAxx or ArrAxx) +/Axx { % - | - + linsetAxx + gsave + xPos yPos offset + mmscale + aAng rotate + % draw a line + aFro 0 np mv + aTo 0 li st + % draw an arrow and a label, if requested + aArr { + gsave + aTo 0 offset + aAng neg rotate + mmunscale + aAng rotate + 0 0 0 .3 pfeilspitze % draw an arrow + .3 0 offset + aAng neg rotate + setlab + aAng 45 le + { 0 -.8 xNumHeightL sub aLab textRT } + { 0 .2 aLab textCB } + ifelse + grestore + } if + grestore + } def + +% draw ticks (positions given by SetTicVec, parameters preset by OneAxx/..) +/Tic { % - | - : draw tick as defined in TicProc + linsetTic + TicVec { + dup dup aFro lt x aTo gt or {pop} {TicProc} ifelse + } forall + } def +/TicProc { % aPos | - : default procedure to plot one tick + np + xPos yPos xym mv + dup xAng mul x yAng mul xym rm % eat argument, go to start pos. + xTicLen yTicLen rl st + } def +/xGric { % yFro yTo | - : draw a grid line (instead of an x tick) + linsetGri + TicVec { + 3 copy dup 5 -1 roll aFro lt x aTo gt or {pop pop pop} { + dup % y1 y2 x x + 4 -1 roll xym np mv % y2 x + x xym li st + } ifelse + } forall + pop pop + } def +/yGric { % xFro xTo | - : draw a grid line (instead of an y tick) + linsetGri + TicVec { + 3 copy dup 5 -1 roll aFro lt x aTo gt or {pop pop pop} { + dup % x1 x2 y y + 4 -1 roll x xym np mv % x2 y + xym li st + } ifelse + } forall + pop pop + } def + +% draw tacks (positions given by SetTacVec, parameters preset by OneAxx/..) +/TacExe { % Proc | - % Execute Proc for all pairs of elements of TacVec + % (but only if inside aFro..aTo) + /TacProc x def + /ispair true def % toggle: take pos, take label, take pos, take label ... + TacVec { + ispair + { + /aPos x def + /ispair false def + } { + aPos dup aFro lt x aTo gt or + {pop} {TacProc} ifelse + /ispair true def + } ifelse + } forall + } def +/Tac { + linsetTac + { pop xPos yPos xym mv + aPos dup xAng mul x yAng mul xym rm + xTacLen yTacLen rl st + } TacExe + } def +% unnecessary optimisation by specialisation: OBSOLETE since 11a +/xTacL { Tac } def +/xTacH { Tac } def +/yTacL { Tac } def +/yTacH { Tac } def +% special tack routines, only for rectangular axes +/xTacC { % : centered tack on x axis + linsetTac + { pop aPos xm yPos ym txllen 2 div sub np mv 0 txllen rl st } TacExe + } def +/xGrid { % : rule instead of tack on x axis + linsetTac + { pop aPos xm np yPos ym mv 0 10 xym rl st } TacExe + } def +/yTacC { % : centered tack on y axis + linsetTac + { pop xPos xm tyllen 2 div sub aPos ym np mv tyllen 0 rl st } TacExe + } def +/yGrid { % : rule instead of tack on low y axis + linsetTac + { pop aPos ym np xPos xm x mv 10 0 xym rl st } TacExe + } def + +% draw numbers (pos-txt pairs given by SetTacVec) +/Num { % Generic but useless. Adjust for your application. + setnum + fontheight ymm div yDisRel mul tAng sin mul /yDist x def + { dup textW xDisRel mul tAng cos mul /xDist x def + xPos aPos xAng mul add xDist sub + yPos aPos yAng mul add yDist sub 3 2 roll textCM } TacExe + } def +/setnumDisRel { % xDisRel yDisRel | - : adjust just a little bit + /yDisRel x def /xDisRel x def + } def +1.2 1.2 setnumDisRel % default setting +% explicit Num routines for rectangular case +/xNumL { % : numbers on low x axis + setnum + { fontheight ymm div % conversion -> user_scale + dup /xNumHeightL x def + -.6 mul yPos add aPos x 3 2 roll textCT } TacExe + } def +/xNumH { % : numbers on high x axis + setnum + { fontheight ymm div % conversion -> user_scale + dup /xNumHeightH x def + .6 mul yPos add aPos x 3 2 roll textCB } TacExe + } def +/yNumL { % : numbers on low y axis + setnum + { fontsize -.3 mul xmm div xPos add aPos 3 2 roll textRM + xwidth dup yNumLengthL gt {/yNumLengthL x def} {pop} ifelse + } TacExe + } def +/yNumLD { % : calculate only yNumLength (used for adjustement) + setnum + { textW dup yNumLengthL gt {/yNumLengthL x def} {pop} ifelse + } TacExe + } def +/yDumL { % {(..)} yDumL : compare yNumLength with one arg (used for adjustement) + setnum + textW dup yNumLengthL gt {/yNumLengthL x def} {pop} ifelse + } def +/yNumH { % : numbers on high y axis + setnum + { fontsize .3 mul xmm div xPos add aPos 3 2 roll textLM + xwidth dup yNumLengthH gt {/yNumLengthH x def} {pop} ifelse + } TacExe + } def +/yNumHD { % : calculate only yNumLength (used for adjustement) + setnum + {textW dup yNumLengthH gt {/yNumLengthH x def} {pop} ifelse + } TacExe + } def +/yDumH { % {(..)} yDumH : compare yNumLength with one arg (used for adjustement) + setnum + textW dup yNumLengthH gt {/yNumLengthH x def} {pop} ifelse + } def + +% draw labels +/xCL { % xlabel | - ; plots coordinate name below the x-axis. + setlab + aMean xNumHeightL xNumHeightRel neg mul + 3 -1 roll textCT + } def +/xCH { % xlabel | - ; plots coordinate name above the x-axis. + setlab + aMean xNumHeightH xNumHeightRel mul 10 add + 3 -1 roll textCB + } def +/yCL { % ylabel | - ; plots coordinate name to the left of the y-axis. + gsave + setlab + yNumLengthL neg fontsize -.85 mul add % yNumLengthL calculated in yN + aMean ym translate + 0 0 mv + 90 rotate + 0 x 0 x textCB + grestore + } def +/yCH { % ylabel | - ; plots coordinate name to the right of the y-axis. + gsave + setlab + yNumLengthH fontsize .85 mul add 10 xm add + aMean ym translate + 0 0 mv + 90 rotate + 0 x 0 x textCT + grestore + } def +/yCF { % ylabel | - ; plots coordinate name *falling* right of the y-axis. + gsave + setlab + yNumLengthH fontsize .85 mul add 10 xm add + aMEan ym translate + 0 0 mv + -90 rotate + 0 x 0 x textCB + grestore + } def + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Data Plotting (Symbols and Curves) %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% Initializations: + +% asymmetric error bars? +/err_asy false def % overwrite this if data are quadruples x y d- d+ + + +%% Presets: + +% global preset [wups11a: exchanged rad<->lin to conform with pset] +/SymGSet { % sradglo slinglo serrglo | - + /serrglo x def % plot error bars? 0=never, 1=always, 2=as_given_in_pset + /slinglo x def % symbol linewidth multiplier + /sradglo x def % symbol size multiplier + } def + + +%% Retrieve presets from style array: + +/pstyle { pStyles setstyle } def +/cstyle { cStyles setstyle } def +/setstyle { % chosen_number array | - : set p or c as predefined in array. + dup length % i A n + 3 2 roll % A n i + dup 0 le { + pop pop pop ostyle % chosen_number<=0 means: don't plot + } { + 1 sub x % A i-1 n + mod get % A(i-1) + exec + } ifelse + } def + + +%% Set plot symbol: + +/pset { % styp sfill serr srad slin | - + % arg -> symbol linewidth + /slin x slinglo mul def + % arg -> symbol size + /srad x fm 0.16 mul sradglo mul def + % arg -> plot error bar? + 2 serrglo ne { pop serrglo } if % if (serrglo=2) use serr else use serrglo + /plot_errorbar x 1 eq { { errorbar } } { { pop pop pop pop } } ifelse def + % arg -> fill the symbol? (0=open, 1=full, 2=colored_with_black_border) + /sfill x def + % adjust srad: it's the _outer_ radius + % TROUBLE sfill 1 ne {/srad srad slin fm pt sub def} if + % arg -> symbol type + /ps {ps_nil} def % default: don't plot (maybe we only want an error bar) + dup 1 eq {/ps {ps_square} def} if + dup 2 eq {/ps {ps_diamond} def} if + dup 3 eq {/ps {ps_circle} def} if + dup 4 eq {/ps {ps_triangle} def} if + dup 5 eq {/ps {ps_cedez} def} if + dup 6 eq {/ps {ps_eieruhr} def} if + dup 7 eq {/ps {ps_valve} def} if + dup 8 eq {/ps {ps_tfwd} def} if + dup 9 eq {/ps {ps_tbwd} def} if + dup 10 eq {/ps {ps_pentagram} def} if + dup 11 eq {/ps {ps_plus} def} if + dup 12 eq {/ps {ps_cross} def} if + dup 13 eq {/ps {ps_star} def} if + dup 14 eq {/ps {ps_pentagon} def} if + dup 15 eq {/ps {ps_horiz} def} if + dup 16 eq {/ps {ps_verti} def} if + pop + % + /t { % x y d[- d+] | - : plot a symbol and eventually an error bar. + err_asy not { dup } if + 4 copy pop pop plot_symbol + plot_errorbar + } bind def + /ti { t } bind def + /tf { t black } bind def + } def + + +%% Set curve: + +/lset { % lwidth dashes | - + 0 setdash + dup 0 gt { + pt fm setlinewidth + % pop error bar and convert frame coord -> paper coord + /txy { err_asy { pop } if pop xym } def % x y d[- d+] | x' y' + % commands to plot points (can be overwritten by nopoints): + /ti { np txy mv } def % x y d[- d+] | - : start curve + /t { txy li } def % x y d[- d+] | - : continue curve + /tf { txy li st } def % x y d[- d+] | - : terminate and plot curve + } { + ostyle + } ifelse + } def + + +%% Plot nothing: + +/ostyle { % - | - + /ti { nopoint } def + /t { nopoint } def + /tf { nopoint } def +} def +/nopoint { % x y d[- d+] | - + pop pop pop err_asy { pop } if +} def + + +%% Plot an asymmetric vertical error bar: + +/errorbar { % x y d- d+ | - + gsave + slin setline + 3 copy pop pop + dup 0 gt x 10 lt and { + 4 copy + x pop add 10. 2 copy gt { x } if pop ym x xm x + 2 copy x .05 sub x np mv .1 0 rl st + np mv + pop sub 0. 2 copy lt { x } if pop ym x xm x + 2 copy lineto st + x .05 sub x np mv .1 0 rl st + } { + pop pop pop pop + } ifelse + grestore +} def + + +%% Plot a data symbol: + +/plot_symbol { % x y | - + gsave + offset + srad dup scale + slin srad div setline % factor 1/srad compensates "scale" + ps % the actual plot symbol, defined by 'pset' + grestore + } def + +/fill_symbol { + sfill dup + 0 eq { + pop st + } { + 1 eq { + fill + } { + gsave fill grestore + gsave black st grestore + } ifelse + } ifelse + } def + + +%% The different symbols, designed for unit area (no arguments): + +/ps_nil { + } bind def + +/ps_square { + .5 .5 np mv + 0 -1 rl + -1 0 rl + 0 1 rl cp fill_symbol + } bind def + +/ps_diamond { + gsave 45 rotate ps_square grestore + } bind def + +/ps_circle { + 0 0 np .564 0 360 arc cp fill_symbol + } bind def + +/ps_triangle { + .77 dup dup 90 pol2xy np mv + 210 pol2xy li + 330 pol2xy li cp fill_symbol + } bind def + +/ps_cedez { + gsave 180 rotate ps_triangle grestore + } bind def + +/ps_tfwd { + gsave 30 rotate ps_triangle grestore + } bind def + +/ps_tbwd { + gsave 210 rotate ps_triangle grestore + } bind def + +/ps_eieruhr { + -.7 -.7 np mv + .7 -.7 li + -.7 .7 li + .7 .7 li cp fill_symbol + } bind def + +/ps_valve { + gsave 90 rotate ps_eieruhr grestore + } bind def + +/ps_pentagram { + .8 dup dup dup dup + 90 pol2xy np mv + 234 pol2xy li + 18 pol2xy li + 162 pol2xy li + 306 pol2xy li cp fill_symbol + } bind def + +/ps_pentagon { + .8 dup dup dup dup + 18 pol2xy np mv + 90 pol2xy li + 162 pol2xy li + 234 pol2xy li + 306 pol2xy li cp fill_symbol + } bind def + +/ps_plus { + gsave 45 rotate ps_cross grestore + } bind def + +/ps_cross { + .5 .5 np mv + -1 -1 rl st + -.5 .5 np mv + 1 -1 rl st + } bind def + +/ps_star { + .7 dup 0 pol2xy np mv 180 pol2xy li st + .7 dup 120 pol2xy np mv 300 pol2xy li st + .7 dup 240 pol2xy np mv 60 pol2xy li st + } bind def + +/ps_horiz { + -.7 0 np mv + 1.4 0 rl st + } bind def + +/ps_verti { + 0 -.7 np mv + 0 1.4 rl st + } bind def + + +%% Set column plotting (use this instead of pset) - BROKEN in 11a or earlier + +/setcolumn{ % shift width exec | % + % usage: 0 .2 { gsave { .5 setgray fill } grestore cp } setcolumn + /colexec x def % what's this ? + /colwidth x def + /colshift x def + /t { % broken - may need rewrite + np x colshift add x xym 2 copy mv pop + colwidth xm 0 rl + colwidth xm add 0 wy ym li + colwidth neg xm 0 rl + cp colexec + } def + /ti { t } bind def + /tf { t black } bind def +} def + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% List %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +/NewList { % xins yins size advance NewList - + /nl_advance x def setown /nl_yins x def /nl_xins x def + /nl_xshift fontsize xmm div .9 mul def + /nl_xrline 0.33 def + /nl_ystep fontheight ymm div nl_advance mul def + /newline { + /nl_yins nl_yins nl_ystep sub def + } def + /fracline { % frac | - + fontheight ymm div nl_advance mul mul /nl_yins x nl_yins x sub def + } def + } def +/newlist { 1.65 NewList } def +/TxLine { % text TxLine - + nl_xins nl_yins 3 -1 roll textLM newline + } bind def +/TxCLine { % text TxLine - + nl_xins nl_yins 3 -1 roll textCM newline + } bind def +/infline{ % Obsolete since Frida2.1.5 + oooinfo 1 eq { TxLine } { pop } ifelse + } bind def +/PtTxLine { % pstyle text | - + x pstyle + nl_xins nl_xshift .5 mul add nl_yins 0 t + black nl_xins nl_xshift 1.5 mul add nl_yins 3 2 roll textLM + newline + } bind def +/PttttTxLine { % pstyle text | - %% chain of very small symbols + x pstyle + nl_xins nl_xshift .10 mul add nl_yins 0 t + nl_xins nl_xshift .26 mul add nl_yins 0 t + nl_xins nl_xshift .42 mul add nl_yins 0 t + nl_xins nl_xshift .58 mul add nl_yins 0 t + nl_xins nl_xshift .74 mul add nl_yins 0 t + nl_xins nl_xshift .90 mul add nl_yins 0 t + black nl_xins nl_xshift 1.5 mul add nl_yins 3 2 roll textLM + newline + } bind def +/PtPtCvTxLine { % pstyle pstyle cstyle text | - + 4 3 roll pstyle nl_xins nl_yins 0 t + 3 2 roll pstyle nl_xins nl_xshift add nl_yins 0 t + x cstyle + nl_xins nl_xshift 2 mul add + dup dup nl_xshift nl_xrline mul sub nl_yins 0 ti + nl_xshift nl_xrline mul add nl_yins 0 tf + nl_xshift add nl_yins 3 2 roll black textLM + newline + } bind def +/PtCvTxLine { % pstyle cstyle text | - + 3 2 roll pstyle nl_xins nl_yins 0 t + x cstyle + nl_xins nl_xshift 1 mul add + dup dup nl_xshift -.33 mul add nl_yins 0 ti + nl_xshift 0.33 mul add nl_yins 0 tf + nl_xshift add nl_yins 3 2 roll black textLM + newline + } bind def +/PtPtTxLine { % pstyle pstyle text | - + 3 2 roll pstyle nl_xins nl_yins 0 t + x pstyle nl_xins nl_xshift add nl_yins 0 t + black nl_xins nl_xshift 2 mul add nl_yins 3 2 roll textLM + newline + } bind def +/CvTxLine { % cstyle text | - + x cstyle + nl_xins fontsize xmm div nl_xrline mul 0 mul sub nl_yins 0 ti + nl_xins fontsize xmm div nl_xrline mul 3 mul add nl_yins 0 tf + black nl_xins nl_xshift 1.5 mul add nl_yins 3 2 roll textLM + newline + } bind def +/Cv2TxLine { % cstyle text | - + x cstyle + nl_xins fontsize xmm div nl_xrline mul sub nl_yins 0 ti + nl_xins fontsize xmm div nl_xrline mul add nl_xshift add nl_yins 0 tf + black nl_xins nl_xshift 2 mul add nl_yins 3 2 roll textLM + newline + } bind def +/PCTxLine { % pstyle(with plset) text | - + x pstyle + nl_xins fontsize xmm div nl_xrline 2 mul mul sub nl_yins 0 ci + nl_xins fontsize xmm div nl_xrline 2 mul mul add nl_yins 0 cf + nl_xins yins 0 t + black nl_xins + fontsize xmm div 1.9 mul % instead of xshift + add nl_yins 3 2 roll textLM + newline + } bind def +/showfilename { % xins yins size | - + setown + ooofnam 1 eq { filename textRB } { pop pop } ifelse + } def +/InfSet { % ooofnam oooinfo | - : set on(1) or off(0) + /oooinfo x def /ooofnam x def + } def +0 0 InfSet % default setting + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Macro Collection %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% gray areas (mainly applied with grayval=1 for blank areas) [longtime grey..] + +/execOval3 { % xl xh yl yh dr { proc } | - + gsave + 6 1 roll + fm /qqdr x def + ym /qqyh x def + ym /qqyl x def + xm /qqxh x def + xm /qqxl x def + qqxl qqyl qqdr add np mv + qqxl qqyh qqdr sub li + qqxl qqdr add qqyh qqdr sub qqdr 180 90 arcn + qqxh qqdr sub qqyh li + qqxh qqdr sub qqyh qqdr sub qqdr 90 0 arcn + qqxh qqyl qqdr add li + qqxh qqdr sub qqyl qqdr add qqdr 0 -90 arcn + qqxl qqdr add qqyl li + qqxl qqdr add qqyl qqdr add qqdr -90 -180 arcn + cp exec grestore + } def +/execRect3 { % xl xh yl yh {proc} | - + 5 1 roll + gsave + ym /qqyh x def + ym /qqyl x def + xm /qqxh x def + xm /qqxl x def + np + qqxl qqyl mv + qqxh qqyl li + qqxh qqyh li + qqxl qqyh li + cp exec grestore + } def +/execRectangle { % OBSOLETE + 5 1 roll + gsave + wy /qqyh x def + wy /qqyl x def + wx /qqxh x def + wx /qqxl x def + np + qqxl xm qqyl ym mv + qqxh xm qqyl ym li + qqxh xm qqyh ym li + qqxl xm qqyh ym li + cp exec grestore + } def +/execHexagon { % xl xh yl yh (all in user coords) {proc} | - + 5 1 roll + gsave + wy /qqyh x def + wy /qqyl x def + wx /qqxh x def + wx /qqxl x def + /qqdr qqyh qqyl sub 2 div def + np + qqxl qqdr add qqyl xym mv + qqxh qqdr sub qqyl xym li + qqxh qqyl qqdr add xym li + qqxh qqdr sub qqyh xym li + qqxl qqdr add qqyh xym li + qqxl qqyl qqdr add xym li + cp exec grestore + } def +/coordRectangle { % xl xh yl yh (all in plot coords) {proc} | - + 5 1 roll + gsave + /qqyh x def + /qqyl x def + /qqxh x def + /qqxl x def + np + qqxl xm qqyl ym mv + qqxh xm qqyl ym li + qqxh xm qqyh ym li + qqxl xm qqyh ym li + cp exec grestore + } def + + +%% special objects + +/pfeilangle 36.87 def +/pfeilspitze { % x[local] y[local] rot siz + % draw with current linestyle, as set e.g. by linsetAxx + x 4 2 roll % siz rot x y + gsave + xym translate 180 add rotate dup dup dup + [] 0 setdash + pfeilangle cos mul x pfeilangle sin mul np mv + 0 0 li pfeilangle cos mul x pfeilangle sin neg mul li st + grestore + } def +/pfeiL { % (arrow anchored at base) x y rot siz len + gsave + dup xm x ym mul sqrt % (scale len) + 5 3 roll + xym translate % (origin at base) rot siz len + 3 2 roll + rotate % (draw rightwards) siz len + dup 0 translate % (origin at head) siz len + x 0 0 0 4 3 roll pfeilspitze % len + 0 0 np mv neg 0 li st + grestore + } def +/Pfeil { % (arrow anchored at head) x y rot siz len + dup xm x ym mul sqrt 5 copy + pop pfeilspitze + x pop + x 4 2 roll % len rot x y + gsave + xym translate 180 add rotate + 0 0 np mv 0 li st + grestore + } def +/pfeil { % (OBSOLETE) x[local] y[local] rot siz len[global] + fm 5 copy % not working well + pop pfeilspitze + x pop + x 4 2 roll % len rot x y + gsave + xym translate 180 add rotate + 0 0 np mv 0 li st + grestore + } def +/pfeil_arcn { % x_cent y_cent radius ang_from ang_to siz + gsave + 6 -2 roll offset + 4 copy pop 0 0 5 2 roll + np arcn st + % radius ang_from ang_to siz + 4 1 roll + gsave + rotate + pop + % siz radius + 0 -90 4 3 roll + pfeilspitze + grestore + grestore +} def + +/knautschy { % x0 y0 y_knau y_tot knautschy - : insert an S in dived y-axis + % the total height of the generated object is y_tot + % of which y_knau(.le. y_tot) is for the real knautsch, + % the remainder is for vertical prolongations. + x ym 4 div dup /tmpy x def 5 sqrt mul /tmpx x def + /tmpa x ym tmpy 4 mul sub 2 div def + np ym x xm x mv 0 tmpa rl tmpx tmpy rl tmpx -2 mul tmpy 2 mul rl + tmpx tmpy rl 0 tmpa rl st + } def +/separy { % x0 y0 sep lng ang lin - : insert an // in dived y-axis + setline + /spang x def + /splng x def + /spsep x def + 2 copy spsep sub gsave offset spang rotate + splng -.5 mul fm 0 np mv splng fm 0 rl st grestore + spsep add gsave offset spang rotate + splng -.5 mul fm 0 np mv splng fm 0 rl st grestore + } def + +/bemasz { % x y L ang text | - %% precede by '24 setown 1 [] lset /pfeilangle 90 def' + gsave + 5 3 roll offset % consumes x and y + x rotate % consumes ang | L text + dup textw .5 mul fontheight .4 mul add /bmszDT x def % => half text width + 0 0 3 2 roll textCM % L + .5 mul /bmszDX x def % => half bemasz length + bmszDX 0 0 fontheight .67 mul bmszDX bmszDT sub Pfeil + bmszDX neg 0 180 fontheight .67 mul bmszDX bmszDT sub Pfeil + grestore + } def + + +%% Text composition shortcuts: + +/g { x grec endgr} bind def +/sb { x subsc endsc} bind def +/sp { x supsc endsc} bind def +/sbgr { x grec () subsc endsc () endgr} bind def +/spgr { x grec () supsc endsc () endgr} bind def + + +%% Text macros for neutron scattering: + +/hbar { + showif + (h) 1.2 .66 { + currentpoint fontheight .11 mul setline np mv + fontheight dup .8 mul x .3 mul rl + st () + } build + } bind def +/hbarw { hbar () grec (w) endgr } bind def +/wbar { grec (w) endgr ( / 2) grec (p) endgr } bind def +/taumean { () (\341t\361) g } bind def +/Sqw { showif (S\(q,) grec (w) endgr (\)) showif } bind def +/Sqn { showif (S\(q,) grec (n) endgr (\)) showif } bind def +/SQw { showif (S\(Q,) grec (w) endgr (\)) showif } bind def +/Sttw { showif (S\(2) grec (q) endgr (,) grec (w) endgr (\)) showif } bind def +/Sttn { showif (S\(2) grec (q) endgr (,) grec (n) endgr (\)) showif } bind def +/Xqw { grec (c) endgr (''\(q,) grec (w) endgr (\)) showif } bind def +/Xqn { grec (c) endgr (''\(q,) grec (n) endgr (\)) showif } bind def +/ueV{ grec (m) endgr (eV) showif} bind def +/inueV { showif (\() grec (m) endgr (eV\)) showif } bind def +/inmeVr { showif (\(meV) supsc (-1) endsc (\)) showif } bind def +/inueVr { showif (\() grec (m) endgr (eV) + supsc (-1) endsc (\)) showif } bind def +/inGHzr { showif (\(GHz) (-1) sp (\)) showif } def + +%% home-made Angstr is obsolete; use \305 (more reliable than Å) +/Angstr { + showif + (A) .5 1.23 { + currentpoint fontheight .1 mul setline np + fontheight .14 mul 0 360 arc st () + } build +} bind def +/Angr { showif (\305) supsc (-1) endsc } bind def +/inAngr { showif (\() Angr (\)) showif } bind def +/Angrr { showif (\305) supsc (-2) endsc } bind def +/inAngrr { showif (\() Angrr (\)) showif } bind def +/wmin {grec (w) endgr () subsc (min) endsc} def +/winpi { grec (w) endgr ( / 2) grec (p) endgr } def +/Celsius { showif (\26x)g(C) showif } bind def + + +%% More shortcuts for impatient users: + +/L { langSel } bind def +/G { gsave exec grestore } bind def +/gs { gsave } bind def +/gr { grestore } bind def + +end % WuGdict... + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Mark "ewu", the end of the wups.. macro definition file %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +WuGdict11a begin + +10 dup autolabel defsiz +1 dup stdred +2 -13 setnewpage newpage + +/darkgreen { 13 133 13 setRGBcolor } def +/litegreen {202 253 222 setRGBcolor } def +/darkblue { 13 13 133 setRGBcolor } def +/liteblue {202 202 255 setRGBcolor } def + +/boxcenter{ qqxl qqxh add 2 div qqyl qqyh add 2 div } def + +/greenbox{ + 5 1 roll + { { litegreen fill } G darkgreen 2 [] lset st } execRect3 + black boxcenter 3 2 roll textCM +} def + +/grisbox{ + 5 1 roll + { { .8 setgray fill } G .2 setgray 2 [] lset st } execRect3 + black boxcenter 3 2 roll textCM +} def + +/blueoval{ + 6 1 roll + { { liteblue fill } G darkblue 2 [] lset st } execOval3 + black boxcenter 3 2 roll textCM +} def +/greenoval{ + 6 1 roll + { { litegreen fill } G darkgreen 2 [] lset st } execOval3 + black boxcenter 3 2 roll textCM +} def + +21 setown + +1 [] lset black +/upline { 270 .5 2 Pfeil } def % (arrow anchored at base) x y rot siz len + 2.5 7 upline + 9 7 upline +15.5 7 upline + +0 18 5 7 {(libBornAgainCore)} greenbox + +gsave +0 4 1 3 {(libBornAgainFit)} greenbox + 2 3 upline +4.5 0 offset +0 3.8 1 3 {(libgsl)} grisbox + 1.9 3 upline +4.3 0 offset +0 3.8 1 3 {(libfftw3)} grisbox + 1.9 3 upline +4.3 0 offset +gsave +0 1 offset +1. .4 offset +3 { + 0 3.8 0 2 {(other libs)} grisbox + -.5 -.2 offset +} repeat +grestore + 2.4 3.4 270 .5 1.6 Pfeil +grestore + +0 5 9 11 .4 {(BornAgain GUI)} greenoval +21 setobl 6.5 11.5 9 11 .4 {(Python apps)} blueoval +21 setobl 8.5 11.5 8.5 9.5 .3 {(Examples)} greenoval +21 setown 13 18 9 11 .4 {(C++ apps)} blueoval +15 18 8.5 9.5 .3 {(Examples)} greenoval + +darkblue +3 [] lset +{ 5.75 10.1 offset + 0 0 np 1.5 225 315 arc st + 315 rotate 1.5 0 90 .4 0 Pfeil % (arrow anchored at head) x y rot siz lenoffset } G + } G +5.75 8.2 {(export)} textCM + +showpage +end % WuGdict... diff --git a/Doc/UserManual/fig/drawing/architecturePy.ps b/Doc/UserManual/fig/drawing/architecturePy.ps new file mode 100644 index 0000000000000000000000000000000000000000..97a3cc22e6cbc1f4d65cdfee5076362bfc6228a2 --- /dev/null +++ b/Doc/UserManual/fig/drawing/architecturePy.ps @@ -0,0 +1,1711 @@ +%!PS-Adobe-1.0 EPSF-1.0 +%%BoundingBox: 19 214 567 804 +%%Comment: Bounding box extracted by bboxx +%%+: A program by Dov Grobgeld 2003 + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% FRIDA: fast reliable interactive data analysis %% +%% wups11a.ps: graphic macros %% +%% (C) Joachim Wuttke 1990-2016 %% +%% http://www.messen-und-deuten.de/frida %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Sections: +% - Programming, Page Formatting, Coordinate Transforms +% - Colors +% - Fonts and Text Blocks +% - Coordinate Frame +% - Data Plotting (Symbols and Curves) +% - Lists +% - Macro Collection + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Programming, Page Formatting, Coordinate Transforms %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% Framework: + +% For interleaving applications, isolate what follows in a dictionary +/WuGdict11a 400 dict def +WuGdict11a begin + + +%% Shortcuts: + +/np { newpath } bind def +/mv { moveto } bind def +/rm { rmoveto } bind def +/rl { rlineto } bind def +/li { lineto } bind def +/cp { closepath } bind def +/st { stroke } bind def +/x { exch } bind def + +/black { 0 setgray } bind def +/white { 1 setgray } bind def + +/F false def +/T true def + + +%% Constants: + +/pt { .018567 mul} bind def % for line widths and font sizes, reason unclear +/cm {28.346456 mul} bind def % typographic_point -> cm + +/twopi { 6.2831853072 } def + + +%% Math operators: + +/rnd { rand cvr 1 30 bitshift div 2 div 0 max 1 min } def % -> between 0 and 1 + +/min { 2 copy gt { x } if pop } def +/max { 2 copy lt { x } if pop } def + +/tan { dup sin x cos div } def +/cot { dup cos x sin div } def +/pol2xy{ 2 copy cos mul 3 1 roll sin mul } def % r phi | x y + +/eexp { 2.71828 x exp } def % "exp" is x^y, eexp is e^x +/tanh { 2.71828 x 2 copy exp 3 1 roll neg exp + 2 copy sub 3 1 roll add div } def + + +%% Page layout and global figure size: + +% shift origin +% The PostScript coordinate system starts in the lower left corner +% of the page, whereas we want our figures to be justified in the +% upper left corner. Therefore we need a vertical translation, +% depending on the paper size. A4 is 210x297 mm^2. By this occasion, +% we also provide a border of 7 mm. +/cmtranslate { % x y cmtranslate | - + cm x cm x translate } bind def +/originUpperLeft_A4{ .7 28.3 cmtranslate } bind def +/goffsetA4 { ungscale originUpperLeft_A4 gscale } def +/EdgeLeftDIN{ originUpperLeft_A4 } bind def % OBSOLETE since 11a + +% set absolute global scale and relative symbol size +/defsiz { % size(cm) symbolsize(rel) | - + /ftot x def + /gsiz x cm 10 div def + gscale % within 'size', coordinates run from 0 to 10 + } def +/gscale { + gsiz dup scale +} def +/ungscale { + 1 gsiz div dup scale +} def + +% symbol (and label?) size as sublinear function of figure size +/autolabel { % size(cm) | symbolsize(rel) + dup 7 div 2 add 4 mul % the simplest sublinear increase + x div % anticipate overall rescaling + } def + + +%% Frame size and shape, frame coordinates: + +% aspect ratios +/gyld {0.447214 mul} bind def /Gyld {0.447214 div} bind def % sqrt(5) +/guld {0.547723 mul} bind def /Guld {0.547723 div} bind def % sqrt(3) +/gold {0.618034 mul} bind def /Gold {0.618034 div} bind def % goldener Schnitt +/gild {0.707107 mul} bind def /Gild {0.707107 div} bind def % sqrt(2) : DIN +/geld {0.759836 mul} bind def /Geld {0.759836 div} bind def % sqrt(sqrt(3)) +/gald {0.817765 mul} bind def /Gald {0.817765 div} bind def % sqrt sqrt sqrt 5 + +% define frame coordinates +/defred { % x_reduction y_reduction label_reduction | - + /fmm x ftot mul def + /ymm x def + /xmm x def + + % conversion frame_coordinate -> global_coord + /xm {xmm mul} bind def + /ym {ymm mul} bind def + /fm {fmm mul} bind def + /xym {ym x xm x} bind def + + % prefer rescaling over explicit conversion (make more use of this !) + /mmscale { xmm ymm scale } bind def + /mmunscale { 1 xmm div 1 ymm div scale } bind def + + % graphic commands in frame coordinates + /offset { xym translate } bind def + /currentxy { currentpoint ymm div x xmm div x } bind def + /setline { pt fm setlinewidth [] 0 setdash } bind def + } def + +/stdred { % x_reduction y_reduction | - + 2 copy mul sqrt defred + } def + +%% World (= user application) coordinates: + +% user must declare x and y range +/xSetCoord { % log min max | - + /wxmax x def + /wxmin x def + /wxlog x 0 eq not def + % prepare conversion world coord -> frame coord + /wxdel wxmax wxmin wxlog { div log } { sub } ifelse def + /wxd { % dx(world) | dx(frame) + wxlog { log } if wxdel div 10 mul + } bind def + /wx { % x(world) | x(frame) + wxmin wxlog { div } { sub } ifelse + wxd + } bind def + } def +/ySetCoord { % log min max | - + /wymax x def + /wymin x def + /wylog x 0 eq not def + /wydel wymax wymin wylog { div log } { sub } ifelse def + /wyd { % dy(world) | dy(frame) + wylog { log } if wydel div 10 mul + } bind def + /wy { % y(world) | y(frame) + wymin wylog { div } { sub } ifelse + wyd + } bind def + } def + +% pair conversion +/wxy { % x,y(world) -> x,y(frame) + wy x wx x + } def + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Colors %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% Color operators: + +/setRGBcolor { + 3 { 255 div 3 1 roll } repeat setrgbcolor + } def + +/colormix { % weight(0..1) col1(R|G|B) col2(R|G|B) | col(R|G|B) + 7 -1 roll dup /weightA x def /weightB x 1 x sub def + 4 -1 roll weightA mul x weightB mul add 5 1 roll + 3 -1 roll weightA mul x weightB mul add 4 1 roll + 2 -1 roll weightA mul x weightB mul add 3 1 roll + } def + +/relcol { % i_col n_col | rel(0..1) : for one-dimensional choices + 1 sub div 0 max 1 min + } def + + +%% Named colors: + +/siemensorange { 255 153 0 setRGBcolor } bind def +/siemensblue { 0 102 153 setRGBcolor } bind def +/siemenstext { 0 51 102 setRGBcolor } bind def +/siemensred { 165 0 33 setRGBcolor } bind def +/siemenspink { 221 102 102 setRGBcolor } bind def +/siemensgrey { 221 221 221 setRGBcolor } bind def +/siemensdark { 102 102 102 setRGBcolor } bind def +/siemensgreen { 33 153 102 setRGBcolor } bind def +/siemensyellow { 255 221 0 setRGBcolor } bind def + +/red { 255 0 0 setRGBcolor } bind def + + +%% One-dimensional linear color choices: + +/iCol1 { % i i_max | - : default -2010, round the circle, RGBR + relcol dup 1 x % rel 1 rel + 360 mul 255 add cos 1 add dup mul neg .053 mul 1 add % modulate saturation + sethsbcolor + } def +/iCol2 { % i i_max | - : cyan - yellow - magenta + relcol 3 mul + dup 1 le { + dup 1 sub neg 0 3 2 roll } { + dup 2 le { + 1 sub dup 1 sub neg 0 3 1 roll } { + 2 sub dup 1 sub neg 0 3 0 roll } ifelse + } ifelse + 0 setcmykcolor + } def +/iCol3 { % i i_max | - : siemens + div /icnow x def + 165 1 icnow sub mul + 102 icnow mul + 33 120 icnow mul add setRGBcolor + } def +/iCol4 { % i i_max | - : red to blue (subsequence of old scheme iCol1) + relcol + 3 x sub 3 div 1 iCol1 + } def + + +%% One-dimensional color choice from given array: + +/iColA { % i i_max arr | - + /aCol x def + relcol + aCol length 1 sub mul % position within array + dup cvi dup 3 1 roll % idx pos idx + sub x % offset idx + 0 max aCol length 1 sub min % offset safe_idx + dup 1 add aCol length 1 sub min % offset i i+1 + aCol x get exec + 4 3 roll aCol x get exec colormix setRGBcolor + } def + + +%% Color arrays for non-linear one-dimensional choices: + +/aCol1 [ % red-blue + { 255 0 0 } % 1 + { 240 10 10 } % 2 + { 220 40 40 } % 3 + { 205 65 90 } % 4 + { 195 80 130 } % 5 + { 180 110 180 } % 6 + { 165 120 185 } % 7 + { 150 130 190 } % 8 + { 130 150 210 } % 9 + { 110 125 220 } % 10 + { 85 105 230 } % 11 + { 70 90 255 } % 12 + { 0 0 255 } % 13 + ] def +/aCol2 [ % orange-red-blue-darkblue + { 255 180 0 } % 1 + { 255 160 0 } % 1 + { 255 120 0 } % 2 + { 255 70 0 } % 3 + { 255 0 0 } % 4 + { 220 30 30 } % 5 + { 220 70 60 } % 6 + { 220 100 110 } % 7 + { 200 130 130 } % 8 + { 200 130 160 } % 9 + { 180 110 180 } % 10 + { 165 110 185 } % 11 + { 150 130 190 } % 12 + { 130 150 210 } % 13 + { 100 120 220 } % 14 + { 85 105 230 } % 15 + { 70 90 255 } % 16 + { 0 0 255 } % 17 + { 0 0 180 } % 18 + { 10 10 150 } % 19 + { 30 30 130 } % 20 + ] def +/aCol3 [ % [fixed size: 9] siemenscolors + { 165 0 33 } % siemensred + { 33 153 102 } % siemensgreen + { 0 102 153 } % siemensblue + { 0 51 102 } % siemenstext + { 255 153 0 } % siemensorange + { 102 102 102 } % siemensdark + { 255 221 0 } % siemensyellow + { 221 221 221 } % siemensgrey + { 221 102 102 } % siemenspink + ] def +/aCol4 [ % green-blue-brown + { 120 160 60 } + { 90 185 40 } + { 50 215 20 } + { 0 245 0 } + { 10 235 112 } + { 20 235 143 } + { 30 230 173 } + { 40 225 194 } + { 50 205 215 } + { 40 153 204 } + { 40 102 153 } + { 40 82 122 } + { 90 74 101 } + { 140 68 80 } + { 170 59 60 } + { 190 50 40 } + { 180 65 40 } + { 160 80 40 } + { 140 100 40 } + { 120 80 30 } + { 100 60 20 } + ] def +/aCol5 [ % [fixed size: 8] gnuplot default (see man gnuplot and rgb.txt) + { 255 0 0 } % red + { 0 255 0 } % green + { 0 0 255 } % blue + { 255 0 255 } % magenta + { 0 255 255 } % cyan + { 160 82 45 } % sienna + { 255 165 0 } % orange + { 255 127 80 } % coral + ] def + + +%% Specialized ifelse, depending on pcol / ccol - OBSOLETE since 11a: + +/ifpcol { % proc1 proc2 | - + pcol 0 eq { pop exec } { exec pop} ifelse % 3 1 roll ifelse + } def +/ifccol { % proc1 proc2 | - + ccol 0 eq { pop exec } { exec pop} ifelse % 3 1 roll ifelse + } def + + +%% old-style colors round the circle - OBSOLETE since 10a: + +% global preset +/pColSet { % col ncol | - + /npcol x def % # different colours + /pcol x def % colours off/on + } def +/cColSet { % col ncol | - + /nccol x def % # different colours + /ccol x def % colours off/on + } def +% default setting +0 3 pColSet % default setting +0 3 cColSet % default setting +% now defined locally in g3.ps +/ipCol { 100 iCol1 } def +/icCol { 100 iCol1 } def + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Fonts and Text Blocks %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% Prepare standard fonts: + +% extend font encoding +/ReEncode { % OldFont NewFont Encoding | - + /MyEncoding x def + x findfont % select OldFont + dup length dict begin + {def} forall + /Encoding MyEncoding def + currentdict + end + definefont % define as NewFont + } def + +% we assume that image scripts are Latin1 encoded +/Helvetica /MyFont ISOLatin1Encoding ReEncode +/Helvetica-Oblique /MyFont-Oblique ISOLatin1Encoding ReEncode +/Helvetica-Bold /MyFont-Bold ISOLatin1Encoding ReEncode +/Helvetica-BoldOblique /MyFont-BoldOblique ISOLatin1Encoding ReEncode + +/setPalatino { +/Palatino /MyFont ISOLatin1Encoding ReEncode +/Palatino-Italic /MyFont-Oblique ISOLatin1Encoding ReEncode +/Palatino-Bold /MyFont-Bold ISOLatin1Encoding ReEncode +/Palatino-BoldItalic /MyFont-BoldOblique ISOLatin1Encoding ReEncode +} def + +%% Preset standard styles: + +% scale and set font; define fontsize, fontheight +/setfontandsize { % font size | - + dup 0 le { pop 100 } if % fontsize <= 0 not allowed ! + /fontnonnil true def + pt fm dup /fontsize x def + x findfont + x scalefont + setfont + gsave % determine fontheight - from the cookbook : + np 0 0 mv (1) true charpath flattenpath + pathbbox % low_left_x, low_left_y, up_right_x, up_right_y + x pop x pop x pop + /fontheight x def + grestore + } def + +% standard settings for labelling axes +/setnum { /MyFont 24 setfontandsize } def +/setlab { /MyFont 24 setfontandsize } def + +% user commands (free choice of fontsize, but fixed font family) +/setown { /MyFont x setfontandsize } def +/setbol { /MyFont-Bold x setfontandsize } def +/setboq { /MyFont-BoldOblique x setfontandsize } def +/setobl { /MyFont-Oblique x setfontandsize } def + + +%% String treatment: + +/showif { % string | - : increment xwidth or plot string + prepare + { stringwidth pop xwidth add /xwidth x def } + { show } + ifelse + } def +/script { % matrix relpos_y | - + /yoffset x fontheight mul def + currentfont x makefont setfont + 0 yoffset rm + } def +/scred .71 def +/subsc { + showif + [scred 0 0 scred 0 0] -.2 script + } def +/supsc { + showif + [scred 0 0 scred 0 0] .6 script + } def +/endsc { + showif + regularfont setfont + 0 yoffset neg rm + } def +/grec { + showif + /Symbol findfont fontsize scalefont setfont + } def +/endgr { + showif + regularfont setfont + } def +/endall { + showif + regularfont setfont + } def +/build { % string xrel yrel obj | - : plot obj above/below string + /obj x def /yrelbui x def /xrelbui x def + dup showif + prepare + { pop } + { stringwidth pop xrelbui neg mul fontheight yrelbui mul % relpos for obj + currentpoint 4 2 roll % save position after string + rm obj pop % obj must end with () that will be pop'ed + mv % back to saved position + } + ifelse + } def +/gbuild { % string xrel yrel obj | - : plot obj above/below string + /obj x def /yrelbui x def /xrelbui x def + /Symbol findfont fontsize scalefont setfont + dup showif + prepare + { pop regularfont setfont } + { stringwidth pop xrelbui neg mul fontheight yrelbui mul % relpos for obj + currentpoint 4 2 roll % save position after string + regularfont setfont + rm obj pop % obj must end with () that will be pop'ed + mv % back to saved position + } + ifelse + } def +/hut { % ..) (<Char>) hut (.. %%% MISERABEL PROGRAMMIERT + x showif + 1.4 .6 {(\136) show ()} build + } def +/ghut { % ..) (<grec-Char>) ghut (.. %%% BREITE PASST NUR FUER Phi(t) + x showif + .8 .65 {(\136) show ()} gbuild + } def +/tilde { + x showif + 1. .6 {(~) show ()} build + } def +/gtilde { + x showif + 1. .6 {(~) show ()} gbuild + } def +/spce { % string n spce - ; insert n times ( ) + {showif ( )} repeat + } def + +% the following macros use the symbol/curve plotting mechanism +/pins { % string symins - ; symbol must be selected by pset + showif + ( ) showif ( ) .5 .5 { currentxy 0 p black ()} build ( ) showif + } def +/clenins { % string len clenins - ; curve must be selected by cset + x showif % I suppose that pins is preceeded by 8 spaces + dup ( ) stringwidth pop mul 2 add /xstrich x xmm div def + % length of inserted curve : + % -1 space : curve begins and ends in middle of ( ) + % +3 spaces: pins requires 3 times ( ) + ( ) 0 .5 { currentxy currentxy 0 ci x xstrich add x 0 cf () } build + 2 add {( ) showif} repeat + } def +/cins { % string symins - ; curve must be selected by cset + showif 8 % I suppose that pins is preceeded by 8 spaces + dup ( ) stringwidth pop mul 2 add /xstrich x xmm div 10 div def + % nov03, ohne zu verstehen, "10 div" eingefuegt + % length of inserted curve : + % -1 space : curve begins and ends in middle of ( ) + % +3 spaces: pins requires 3 times ( ) + ( ) 0 .5 { currentxy currentxy 0 ci x xstrich add x 0 cf () } build + 2 add {( ) showif} repeat + } def + +/block { % x y ob xrel yrel | - + /yrel x def /xrel x def /blabla x def + /ypos x ym def /xpos x xm def + /regularfont currentfont def /yoffset 0 def % initialize for security + /prepare true def /xwidth 0 def 0 0 mv % to prevent empty-path-error + blabla endall % first pass : determine xwidth + boxif { /boxwidth xwidth (M) stringwidth pop boxxr mul 2 mul add def + /boxheight fontheight 1 boxyr 2 mul add mul def + np xpos xwidth xrel mul sub boxwidth xwidth sub 2 div sub + ypos fontheight .5 boxyr add mul sub mv + boxwidth 0 rl 0 boxheight rl boxwidth neg 0 rl cp + boxproc + } if + xpos xwidth xrel mul sub ypos fontheight yrel mul sub mv + /prepare false def + blabla endall % second pass : plot + /boxif false def + } def +/rblock { % x y ang ob proc rblock - + 5 3 roll + gsave + xym translate + 3 2 roll rotate + 0 0 4 2 roll exec + grestore + } def + +/Box { % x y {exe} + /boxif true def + /boxproc x def /boxyr x def /boxxr x def + } def +/nBox { .6 .6 3 2 roll Box } def +/boxif false def +/textW { % obj | length : calculate only length. + /blabla x def + /regularfont currentfont def /yoffset 0 def % initialize for security + /prepare true def /xwidth 0 def 0 0 mv % to prevent empty-path-error + blabla endall + xwidth % has been determined + } def +/textw { % obj | y : dito, in 0..10-units + textW xmm div + } def + +% horizontal text: x y ob | - +/textLB { 0. 0. block } bind def +/textCB { .5 0. block } bind def +/textRB { 1. 0. block } bind def +/textLM { 0. .5 block } bind def +/textCM { .5 .5 block } bind def +/textRM { 1. .5 block } bind def +/textLT { 0. 1. block } bind def +/textCT { .5 1. block } bind def +/textRT { 1. 1. block } bind def + +% rotated text: x y ang ob | - +/rtextLB { {textLB} rblock } bind def +/rtextLM { {textLM} rblock } bind def +/rtextRB { {textRB} rblock } bind def +/rtextRM { {textRM} rblock } bind def +/rtextCM { {textCM} rblock } bind def + + +%% Language selection: + +% preset +/language { % choose_this of_so_many | - % select current language + /langMax x def + /langChc x def + } def +1 1 language % default +% choose text from sequence +/langSel { % text_1 .. text_M | text_C : choose text, M=langMax, C=langChc + langMax dup langChc sub 1 add roll + langMax 1 sub { pop } repeat + } def + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Coordinate Frame %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% Layout presets: + +/xyTicLen {0.10 fm} def +/xyTacLen {0.20 fm} def +/txllen {0.20 fm} def +/tyllen {0.20 fm} def +/linsetAxx {black 0.7 setline} def +/linsetTic {black 0.7 setline} def +/linsetTac {black 0.7 setline} def +/linsetGri {black 0.4 setline} def + +%% Start-up commands: + +/Resets { + /yNumLengthL 0 def /yNumLengthH 0 def + /xNumHeightL .3 def /xNumHeightH 0 def + /xNumHeightRel 2.4 def + /aMean 5 def + /xPlotFrame {} def + /yPlotFrame {} def + /zPlotFrame {} def + black + } def +/BoxBackground { + 0 0 10 10 boxit gsave setboxbackgroundcolor fill grestore +} def +/setboxbackgroundcolor { white } def + + +%% Some more presets for g3.ps: + +/iFrame 0 def + +/setnewpage { % xoff yoff + /yoffnewpage x def + /xoffnewpage x def +} def +/newpage { + goffsetA4 + xoffnewpage yoffnewpage offset +} def +/setpagegrid { % ncol nrow xoffnewframe yoffnewframe + /yoffnewframe x def + /xoffnewframe x def + /nrowpage x def + /ncolpage x def +} def +/nextFrame { + /iFrame iFrame 1 add def + iFrame nrowpage ncolpage mul mod 0 eq { + showpage gscale newpage + } { + iFrame ncolpage mod 0 eq { + xoffnewframe ncolpage 1 sub neg mul yoffnewframe offset + } { + xoffnewframe 0 offset + } ifelse + } ifelse +} def + + +/zValues { pop pop } def +/plotafter {} def +/whiteframe { 1 0 0 10 10 graybox } def +/plotframes { xPlotFrame yPlotFrame } def +/plotbefore { plotframes } def + +/abc {abclab setown abcx abcy 3 2 roll textCM} def % usage ((a)) abc +/abcset { % x y siz abcset - : preset for abc + /abclab x def /abcy x def /abcx x def + } def + + +%% Ticks: + +% set tick array - internal macros +/tiputs { % rel_pos_of_tick | pos_of_tick : innermost routine for /taproc + tastep mul taloop add + } def +/taproclin { % (#tick/tack) | - : define /taproc for use in SetVec + 1 x div /tistep x def + /taproc { 0 tistep .999 { tiputs } for } def + } def +/taproclog { % (#ticks/tacks) | - : define /taproc for use in SetVec + dup 3 gt { pop /taproc { 1 1 9 { log tiputs } for } def + }{ dup 1 gt { pop /taproc { 0 tiputs 2 log tiputs 5 log tiputs } def + }{ dup 0 gt { pop /taproc { 0 tiputs } def + }{ neg taproclin + } ifelse } ifelse } ifelse + } def +/SetVec { % tafro tatoo nta /vector | - : set /vector + 4 1 roll + /nta x def /tatoo x def /tafro x def + /tastep tatoo tafro sub nta 1 sub div def + [ + 0 1 nta { + tastep mul tafro add /taloop x def + taproc exec + } for + ] def + } def +% set tick array - user commands +/SetTicVecLin { taproclin /TicVec SetVec } def +/SetTicVecLog { taproclog /TicVec SetVec } def + +% set tack-and-number array +/SetTacVec { % [ pos {label} pos {label} ... ] | - + /TacVec x def + } def + +% define axes + % note on angles : 0 = x-axis, 90 = y-axis +/OneAxx { % fro to xpos ypos aang tang | - : presets for Axx, Tic, Tac, Num + % store arguments + /tAng x def /aAng x def + /yPos x def /xPos x def + /aTo x def /aFro x def + % set constants + /xTicLen tAng cos xyTicLen mul def /yTicLen tAng sin xyTicLen mul def + /xTacLen tAng cos xyTacLen mul def /yTacLen tAng sin xyTacLen mul def + /xAng aAng cos def /yAng aAng sin def + /aMean aFro aTo add 2 div def + /aArr false def + } def +/ArrAxx { % label <args of OneAxx> | - : axis with arrow + OneAxx + /aLab x def + /aArr true def + } def + +% draw axis (with parameters preset by OneAxx or ArrAxx) +/Axx { % - | - + linsetAxx + gsave + xPos yPos offset + mmscale + aAng rotate + % draw a line + aFro 0 np mv + aTo 0 li st + % draw an arrow and a label, if requested + aArr { + gsave + aTo 0 offset + aAng neg rotate + mmunscale + aAng rotate + 0 0 0 .3 pfeilspitze % draw an arrow + .3 0 offset + aAng neg rotate + setlab + aAng 45 le + { 0 -.8 xNumHeightL sub aLab textRT } + { 0 .2 aLab textCB } + ifelse + grestore + } if + grestore + } def + +% draw ticks (positions given by SetTicVec, parameters preset by OneAxx/..) +/Tic { % - | - : draw tick as defined in TicProc + linsetTic + TicVec { + dup dup aFro lt x aTo gt or {pop} {TicProc} ifelse + } forall + } def +/TicProc { % aPos | - : default procedure to plot one tick + np + xPos yPos xym mv + dup xAng mul x yAng mul xym rm % eat argument, go to start pos. + xTicLen yTicLen rl st + } def +/xGric { % yFro yTo | - : draw a grid line (instead of an x tick) + linsetGri + TicVec { + 3 copy dup 5 -1 roll aFro lt x aTo gt or {pop pop pop} { + dup % y1 y2 x x + 4 -1 roll xym np mv % y2 x + x xym li st + } ifelse + } forall + pop pop + } def +/yGric { % xFro xTo | - : draw a grid line (instead of an y tick) + linsetGri + TicVec { + 3 copy dup 5 -1 roll aFro lt x aTo gt or {pop pop pop} { + dup % x1 x2 y y + 4 -1 roll x xym np mv % x2 y + xym li st + } ifelse + } forall + pop pop + } def + +% draw tacks (positions given by SetTacVec, parameters preset by OneAxx/..) +/TacExe { % Proc | - % Execute Proc for all pairs of elements of TacVec + % (but only if inside aFro..aTo) + /TacProc x def + /ispair true def % toggle: take pos, take label, take pos, take label ... + TacVec { + ispair + { + /aPos x def + /ispair false def + } { + aPos dup aFro lt x aTo gt or + {pop} {TacProc} ifelse + /ispair true def + } ifelse + } forall + } def +/Tac { + linsetTac + { pop xPos yPos xym mv + aPos dup xAng mul x yAng mul xym rm + xTacLen yTacLen rl st + } TacExe + } def +% unnecessary optimisation by specialisation: OBSOLETE since 11a +/xTacL { Tac } def +/xTacH { Tac } def +/yTacL { Tac } def +/yTacH { Tac } def +% special tack routines, only for rectangular axes +/xTacC { % : centered tack on x axis + linsetTac + { pop aPos xm yPos ym txllen 2 div sub np mv 0 txllen rl st } TacExe + } def +/xGrid { % : rule instead of tack on x axis + linsetTac + { pop aPos xm np yPos ym mv 0 10 xym rl st } TacExe + } def +/yTacC { % : centered tack on y axis + linsetTac + { pop xPos xm tyllen 2 div sub aPos ym np mv tyllen 0 rl st } TacExe + } def +/yGrid { % : rule instead of tack on low y axis + linsetTac + { pop aPos ym np xPos xm x mv 10 0 xym rl st } TacExe + } def + +% draw numbers (pos-txt pairs given by SetTacVec) +/Num { % Generic but useless. Adjust for your application. + setnum + fontheight ymm div yDisRel mul tAng sin mul /yDist x def + { dup textW xDisRel mul tAng cos mul /xDist x def + xPos aPos xAng mul add xDist sub + yPos aPos yAng mul add yDist sub 3 2 roll textCM } TacExe + } def +/setnumDisRel { % xDisRel yDisRel | - : adjust just a little bit + /yDisRel x def /xDisRel x def + } def +1.2 1.2 setnumDisRel % default setting +% explicit Num routines for rectangular case +/xNumL { % : numbers on low x axis + setnum + { fontheight ymm div % conversion -> user_scale + dup /xNumHeightL x def + -.6 mul yPos add aPos x 3 2 roll textCT } TacExe + } def +/xNumH { % : numbers on high x axis + setnum + { fontheight ymm div % conversion -> user_scale + dup /xNumHeightH x def + .6 mul yPos add aPos x 3 2 roll textCB } TacExe + } def +/yNumL { % : numbers on low y axis + setnum + { fontsize -.3 mul xmm div xPos add aPos 3 2 roll textRM + xwidth dup yNumLengthL gt {/yNumLengthL x def} {pop} ifelse + } TacExe + } def +/yNumLD { % : calculate only yNumLength (used for adjustement) + setnum + { textW dup yNumLengthL gt {/yNumLengthL x def} {pop} ifelse + } TacExe + } def +/yDumL { % {(..)} yDumL : compare yNumLength with one arg (used for adjustement) + setnum + textW dup yNumLengthL gt {/yNumLengthL x def} {pop} ifelse + } def +/yNumH { % : numbers on high y axis + setnum + { fontsize .3 mul xmm div xPos add aPos 3 2 roll textLM + xwidth dup yNumLengthH gt {/yNumLengthH x def} {pop} ifelse + } TacExe + } def +/yNumHD { % : calculate only yNumLength (used for adjustement) + setnum + {textW dup yNumLengthH gt {/yNumLengthH x def} {pop} ifelse + } TacExe + } def +/yDumH { % {(..)} yDumH : compare yNumLength with one arg (used for adjustement) + setnum + textW dup yNumLengthH gt {/yNumLengthH x def} {pop} ifelse + } def + +% draw labels +/xCL { % xlabel | - ; plots coordinate name below the x-axis. + setlab + aMean xNumHeightL xNumHeightRel neg mul + 3 -1 roll textCT + } def +/xCH { % xlabel | - ; plots coordinate name above the x-axis. + setlab + aMean xNumHeightH xNumHeightRel mul 10 add + 3 -1 roll textCB + } def +/yCL { % ylabel | - ; plots coordinate name to the left of the y-axis. + gsave + setlab + yNumLengthL neg fontsize -.85 mul add % yNumLengthL calculated in yN + aMean ym translate + 0 0 mv + 90 rotate + 0 x 0 x textCB + grestore + } def +/yCH { % ylabel | - ; plots coordinate name to the right of the y-axis. + gsave + setlab + yNumLengthH fontsize .85 mul add 10 xm add + aMean ym translate + 0 0 mv + 90 rotate + 0 x 0 x textCT + grestore + } def +/yCF { % ylabel | - ; plots coordinate name *falling* right of the y-axis. + gsave + setlab + yNumLengthH fontsize .85 mul add 10 xm add + aMEan ym translate + 0 0 mv + -90 rotate + 0 x 0 x textCB + grestore + } def + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Data Plotting (Symbols and Curves) %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% Initializations: + +% asymmetric error bars? +/err_asy false def % overwrite this if data are quadruples x y d- d+ + + +%% Presets: + +% global preset [wups11a: exchanged rad<->lin to conform with pset] +/SymGSet { % sradglo slinglo serrglo | - + /serrglo x def % plot error bars? 0=never, 1=always, 2=as_given_in_pset + /slinglo x def % symbol linewidth multiplier + /sradglo x def % symbol size multiplier + } def + + +%% Retrieve presets from style array: + +/pstyle { pStyles setstyle } def +/cstyle { cStyles setstyle } def +/setstyle { % chosen_number array | - : set p or c as predefined in array. + dup length % i A n + 3 2 roll % A n i + dup 0 le { + pop pop pop ostyle % chosen_number<=0 means: don't plot + } { + 1 sub x % A i-1 n + mod get % A(i-1) + exec + } ifelse + } def + + +%% Set plot symbol: + +/pset { % styp sfill serr srad slin | - + % arg -> symbol linewidth + /slin x slinglo mul def + % arg -> symbol size + /srad x fm 0.16 mul sradglo mul def + % arg -> plot error bar? + 2 serrglo ne { pop serrglo } if % if (serrglo=2) use serr else use serrglo + /plot_errorbar x 1 eq { { errorbar } } { { pop pop pop pop } } ifelse def + % arg -> fill the symbol? (0=open, 1=full, 2=colored_with_black_border) + /sfill x def + % adjust srad: it's the _outer_ radius + % TROUBLE sfill 1 ne {/srad srad slin fm pt sub def} if + % arg -> symbol type + /ps {ps_nil} def % default: don't plot (maybe we only want an error bar) + dup 1 eq {/ps {ps_square} def} if + dup 2 eq {/ps {ps_diamond} def} if + dup 3 eq {/ps {ps_circle} def} if + dup 4 eq {/ps {ps_triangle} def} if + dup 5 eq {/ps {ps_cedez} def} if + dup 6 eq {/ps {ps_eieruhr} def} if + dup 7 eq {/ps {ps_valve} def} if + dup 8 eq {/ps {ps_tfwd} def} if + dup 9 eq {/ps {ps_tbwd} def} if + dup 10 eq {/ps {ps_pentagram} def} if + dup 11 eq {/ps {ps_plus} def} if + dup 12 eq {/ps {ps_cross} def} if + dup 13 eq {/ps {ps_star} def} if + dup 14 eq {/ps {ps_pentagon} def} if + dup 15 eq {/ps {ps_horiz} def} if + dup 16 eq {/ps {ps_verti} def} if + pop + % + /t { % x y d[- d+] | - : plot a symbol and eventually an error bar. + err_asy not { dup } if + 4 copy pop pop plot_symbol + plot_errorbar + } bind def + /ti { t } bind def + /tf { t black } bind def + } def + + +%% Set curve: + +/lset { % lwidth dashes | - + 0 setdash + dup 0 gt { + pt fm setlinewidth + % pop error bar and convert frame coord -> paper coord + /txy { err_asy { pop } if pop xym } def % x y d[- d+] | x' y' + % commands to plot points (can be overwritten by nopoints): + /ti { np txy mv } def % x y d[- d+] | - : start curve + /t { txy li } def % x y d[- d+] | - : continue curve + /tf { txy li st } def % x y d[- d+] | - : terminate and plot curve + } { + ostyle + } ifelse + } def + + +%% Plot nothing: + +/ostyle { % - | - + /ti { nopoint } def + /t { nopoint } def + /tf { nopoint } def +} def +/nopoint { % x y d[- d+] | - + pop pop pop err_asy { pop } if +} def + + +%% Plot an asymmetric vertical error bar: + +/errorbar { % x y d- d+ | - + gsave + slin setline + 3 copy pop pop + dup 0 gt x 10 lt and { + 4 copy + x pop add 10. 2 copy gt { x } if pop ym x xm x + 2 copy x .05 sub x np mv .1 0 rl st + np mv + pop sub 0. 2 copy lt { x } if pop ym x xm x + 2 copy lineto st + x .05 sub x np mv .1 0 rl st + } { + pop pop pop pop + } ifelse + grestore +} def + + +%% Plot a data symbol: + +/plot_symbol { % x y | - + gsave + offset + srad dup scale + slin srad div setline % factor 1/srad compensates "scale" + ps % the actual plot symbol, defined by 'pset' + grestore + } def + +/fill_symbol { + sfill dup + 0 eq { + pop st + } { + 1 eq { + fill + } { + gsave fill grestore + gsave black st grestore + } ifelse + } ifelse + } def + + +%% The different symbols, designed for unit area (no arguments): + +/ps_nil { + } bind def + +/ps_square { + .5 .5 np mv + 0 -1 rl + -1 0 rl + 0 1 rl cp fill_symbol + } bind def + +/ps_diamond { + gsave 45 rotate ps_square grestore + } bind def + +/ps_circle { + 0 0 np .564 0 360 arc cp fill_symbol + } bind def + +/ps_triangle { + .77 dup dup 90 pol2xy np mv + 210 pol2xy li + 330 pol2xy li cp fill_symbol + } bind def + +/ps_cedez { + gsave 180 rotate ps_triangle grestore + } bind def + +/ps_tfwd { + gsave 30 rotate ps_triangle grestore + } bind def + +/ps_tbwd { + gsave 210 rotate ps_triangle grestore + } bind def + +/ps_eieruhr { + -.7 -.7 np mv + .7 -.7 li + -.7 .7 li + .7 .7 li cp fill_symbol + } bind def + +/ps_valve { + gsave 90 rotate ps_eieruhr grestore + } bind def + +/ps_pentagram { + .8 dup dup dup dup + 90 pol2xy np mv + 234 pol2xy li + 18 pol2xy li + 162 pol2xy li + 306 pol2xy li cp fill_symbol + } bind def + +/ps_pentagon { + .8 dup dup dup dup + 18 pol2xy np mv + 90 pol2xy li + 162 pol2xy li + 234 pol2xy li + 306 pol2xy li cp fill_symbol + } bind def + +/ps_plus { + gsave 45 rotate ps_cross grestore + } bind def + +/ps_cross { + .5 .5 np mv + -1 -1 rl st + -.5 .5 np mv + 1 -1 rl st + } bind def + +/ps_star { + .7 dup 0 pol2xy np mv 180 pol2xy li st + .7 dup 120 pol2xy np mv 300 pol2xy li st + .7 dup 240 pol2xy np mv 60 pol2xy li st + } bind def + +/ps_horiz { + -.7 0 np mv + 1.4 0 rl st + } bind def + +/ps_verti { + 0 -.7 np mv + 0 1.4 rl st + } bind def + + +%% Set column plotting (use this instead of pset) - BROKEN in 11a or earlier + +/setcolumn{ % shift width exec | % + % usage: 0 .2 { gsave { .5 setgray fill } grestore cp } setcolumn + /colexec x def % what's this ? + /colwidth x def + /colshift x def + /t { % broken - may need rewrite + np x colshift add x xym 2 copy mv pop + colwidth xm 0 rl + colwidth xm add 0 wy ym li + colwidth neg xm 0 rl + cp colexec + } def + /ti { t } bind def + /tf { t black } bind def +} def + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% List %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +/NewList { % xins yins size advance NewList - + /nl_advance x def setown /nl_yins x def /nl_xins x def + /nl_xshift fontsize xmm div .9 mul def + /nl_xrline 0.33 def + /nl_ystep fontheight ymm div nl_advance mul def + /newline { + /nl_yins nl_yins nl_ystep sub def + } def + /fracline { % frac | - + fontheight ymm div nl_advance mul mul /nl_yins x nl_yins x sub def + } def + } def +/newlist { 1.65 NewList } def +/TxLine { % text TxLine - + nl_xins nl_yins 3 -1 roll textLM newline + } bind def +/TxCLine { % text TxLine - + nl_xins nl_yins 3 -1 roll textCM newline + } bind def +/infline{ % Obsolete since Frida2.1.5 + oooinfo 1 eq { TxLine } { pop } ifelse + } bind def +/PtTxLine { % pstyle text | - + x pstyle + nl_xins nl_xshift .5 mul add nl_yins 0 t + black nl_xins nl_xshift 1.5 mul add nl_yins 3 2 roll textLM + newline + } bind def +/PttttTxLine { % pstyle text | - %% chain of very small symbols + x pstyle + nl_xins nl_xshift .10 mul add nl_yins 0 t + nl_xins nl_xshift .26 mul add nl_yins 0 t + nl_xins nl_xshift .42 mul add nl_yins 0 t + nl_xins nl_xshift .58 mul add nl_yins 0 t + nl_xins nl_xshift .74 mul add nl_yins 0 t + nl_xins nl_xshift .90 mul add nl_yins 0 t + black nl_xins nl_xshift 1.5 mul add nl_yins 3 2 roll textLM + newline + } bind def +/PtPtCvTxLine { % pstyle pstyle cstyle text | - + 4 3 roll pstyle nl_xins nl_yins 0 t + 3 2 roll pstyle nl_xins nl_xshift add nl_yins 0 t + x cstyle + nl_xins nl_xshift 2 mul add + dup dup nl_xshift nl_xrline mul sub nl_yins 0 ti + nl_xshift nl_xrline mul add nl_yins 0 tf + nl_xshift add nl_yins 3 2 roll black textLM + newline + } bind def +/PtCvTxLine { % pstyle cstyle text | - + 3 2 roll pstyle nl_xins nl_yins 0 t + x cstyle + nl_xins nl_xshift 1 mul add + dup dup nl_xshift -.33 mul add nl_yins 0 ti + nl_xshift 0.33 mul add nl_yins 0 tf + nl_xshift add nl_yins 3 2 roll black textLM + newline + } bind def +/PtPtTxLine { % pstyle pstyle text | - + 3 2 roll pstyle nl_xins nl_yins 0 t + x pstyle nl_xins nl_xshift add nl_yins 0 t + black nl_xins nl_xshift 2 mul add nl_yins 3 2 roll textLM + newline + } bind def +/CvTxLine { % cstyle text | - + x cstyle + nl_xins fontsize xmm div nl_xrline mul 0 mul sub nl_yins 0 ti + nl_xins fontsize xmm div nl_xrline mul 3 mul add nl_yins 0 tf + black nl_xins nl_xshift 1.5 mul add nl_yins 3 2 roll textLM + newline + } bind def +/Cv2TxLine { % cstyle text | - + x cstyle + nl_xins fontsize xmm div nl_xrline mul sub nl_yins 0 ti + nl_xins fontsize xmm div nl_xrline mul add nl_xshift add nl_yins 0 tf + black nl_xins nl_xshift 2 mul add nl_yins 3 2 roll textLM + newline + } bind def +/PCTxLine { % pstyle(with plset) text | - + x pstyle + nl_xins fontsize xmm div nl_xrline 2 mul mul sub nl_yins 0 ci + nl_xins fontsize xmm div nl_xrline 2 mul mul add nl_yins 0 cf + nl_xins yins 0 t + black nl_xins + fontsize xmm div 1.9 mul % instead of xshift + add nl_yins 3 2 roll textLM + newline + } bind def +/showfilename { % xins yins size | - + setown + ooofnam 1 eq { filename textRB } { pop pop } ifelse + } def +/InfSet { % ooofnam oooinfo | - : set on(1) or off(0) + /oooinfo x def /ooofnam x def + } def +0 0 InfSet % default setting + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Macro Collection %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% gray areas (mainly applied with grayval=1 for blank areas) [longtime grey..] + +/execOval3 { % xl xh yl yh dr { proc } | - + gsave + 6 1 roll + fm /qqdr x def + ym /qqyh x def + ym /qqyl x def + xm /qqxh x def + xm /qqxl x def + qqxl qqyl qqdr add np mv + qqxl qqyh qqdr sub li + qqxl qqdr add qqyh qqdr sub qqdr 180 90 arcn + qqxh qqdr sub qqyh li + qqxh qqdr sub qqyh qqdr sub qqdr 90 0 arcn + qqxh qqyl qqdr add li + qqxh qqdr sub qqyl qqdr add qqdr 0 -90 arcn + qqxl qqdr add qqyl li + qqxl qqdr add qqyl qqdr add qqdr -90 -180 arcn + cp exec grestore + } def +/execRect3 { % xl xh yl yh {proc} | - + 5 1 roll + gsave + ym /qqyh x def + ym /qqyl x def + xm /qqxh x def + xm /qqxl x def + np + qqxl qqyl mv + qqxh qqyl li + qqxh qqyh li + qqxl qqyh li + cp exec grestore + } def +/execRectangle { % OBSOLETE + 5 1 roll + gsave + wy /qqyh x def + wy /qqyl x def + wx /qqxh x def + wx /qqxl x def + np + qqxl xm qqyl ym mv + qqxh xm qqyl ym li + qqxh xm qqyh ym li + qqxl xm qqyh ym li + cp exec grestore + } def +/execHexagon { % xl xh yl yh (all in user coords) {proc} | - + 5 1 roll + gsave + wy /qqyh x def + wy /qqyl x def + wx /qqxh x def + wx /qqxl x def + /qqdr qqyh qqyl sub 2 div def + np + qqxl qqdr add qqyl xym mv + qqxh qqdr sub qqyl xym li + qqxh qqyl qqdr add xym li + qqxh qqdr sub qqyh xym li + qqxl qqdr add qqyh xym li + qqxl qqyl qqdr add xym li + cp exec grestore + } def +/coordRectangle { % xl xh yl yh (all in plot coords) {proc} | - + 5 1 roll + gsave + /qqyh x def + /qqyl x def + /qqxh x def + /qqxl x def + np + qqxl xm qqyl ym mv + qqxh xm qqyl ym li + qqxh xm qqyh ym li + qqxl xm qqyh ym li + cp exec grestore + } def + + +%% special objects + +/pfeilangle 36.87 def +/pfeilspitze { % x[local] y[local] rot siz + % draw with current linestyle, as set e.g. by linsetAxx + x 4 2 roll % siz rot x y + gsave + xym translate 180 add rotate dup dup dup + [] 0 setdash + pfeilangle cos mul x pfeilangle sin mul np mv + 0 0 li pfeilangle cos mul x pfeilangle sin neg mul li st + grestore + } def +/pfeiL { % (arrow anchored at base) x y rot siz len + gsave + dup xm x ym mul sqrt % (scale len) + 5 3 roll + xym translate % (origin at base) rot siz len + 3 2 roll + rotate % (draw rightwards) siz len + dup 0 translate % (origin at head) siz len + x 0 0 0 4 3 roll pfeilspitze % len + 0 0 np mv neg 0 li st + grestore + } def +/Pfeil { % (arrow anchored at head) x y rot siz len + dup xm x ym mul sqrt 5 copy + pop pfeilspitze + x pop + x 4 2 roll % len rot x y + gsave + xym translate 180 add rotate + 0 0 np mv 0 li st + grestore + } def +/pfeil { % (OBSOLETE) x[local] y[local] rot siz len[global] + fm 5 copy % not working well + pop pfeilspitze + x pop + x 4 2 roll % len rot x y + gsave + xym translate 180 add rotate + 0 0 np mv 0 li st + grestore + } def +/pfeil_arcn { % x_cent y_cent radius ang_from ang_to siz + gsave + 6 -2 roll offset + 4 copy pop 0 0 5 2 roll + np arcn st + % radius ang_from ang_to siz + 4 1 roll + gsave + rotate + pop + % siz radius + 0 -90 4 3 roll + pfeilspitze + grestore + grestore +} def + +/knautschy { % x0 y0 y_knau y_tot knautschy - : insert an S in dived y-axis + % the total height of the generated object is y_tot + % of which y_knau(.le. y_tot) is for the real knautsch, + % the remainder is for vertical prolongations. + x ym 4 div dup /tmpy x def 5 sqrt mul /tmpx x def + /tmpa x ym tmpy 4 mul sub 2 div def + np ym x xm x mv 0 tmpa rl tmpx tmpy rl tmpx -2 mul tmpy 2 mul rl + tmpx tmpy rl 0 tmpa rl st + } def +/separy { % x0 y0 sep lng ang lin - : insert an // in dived y-axis + setline + /spang x def + /splng x def + /spsep x def + 2 copy spsep sub gsave offset spang rotate + splng -.5 mul fm 0 np mv splng fm 0 rl st grestore + spsep add gsave offset spang rotate + splng -.5 mul fm 0 np mv splng fm 0 rl st grestore + } def + +/bemasz { % x y L ang text | - %% precede by '24 setown 1 [] lset /pfeilangle 90 def' + gsave + 5 3 roll offset % consumes x and y + x rotate % consumes ang | L text + dup textw .5 mul fontheight .4 mul add /bmszDT x def % => half text width + 0 0 3 2 roll textCM % L + .5 mul /bmszDX x def % => half bemasz length + bmszDX 0 0 fontheight .67 mul bmszDX bmszDT sub Pfeil + bmszDX neg 0 180 fontheight .67 mul bmszDX bmszDT sub Pfeil + grestore + } def + + +%% Text composition shortcuts: + +/g { x grec endgr} bind def +/sb { x subsc endsc} bind def +/sp { x supsc endsc} bind def +/sbgr { x grec () subsc endsc () endgr} bind def +/spgr { x grec () supsc endsc () endgr} bind def + + +%% Text macros for neutron scattering: + +/hbar { + showif + (h) 1.2 .66 { + currentpoint fontheight .11 mul setline np mv + fontheight dup .8 mul x .3 mul rl + st () + } build + } bind def +/hbarw { hbar () grec (w) endgr } bind def +/wbar { grec (w) endgr ( / 2) grec (p) endgr } bind def +/taumean { () (\341t\361) g } bind def +/Sqw { showif (S\(q,) grec (w) endgr (\)) showif } bind def +/Sqn { showif (S\(q,) grec (n) endgr (\)) showif } bind def +/SQw { showif (S\(Q,) grec (w) endgr (\)) showif } bind def +/Sttw { showif (S\(2) grec (q) endgr (,) grec (w) endgr (\)) showif } bind def +/Sttn { showif (S\(2) grec (q) endgr (,) grec (n) endgr (\)) showif } bind def +/Xqw { grec (c) endgr (''\(q,) grec (w) endgr (\)) showif } bind def +/Xqn { grec (c) endgr (''\(q,) grec (n) endgr (\)) showif } bind def +/ueV{ grec (m) endgr (eV) showif} bind def +/inueV { showif (\() grec (m) endgr (eV\)) showif } bind def +/inmeVr { showif (\(meV) supsc (-1) endsc (\)) showif } bind def +/inueVr { showif (\() grec (m) endgr (eV) + supsc (-1) endsc (\)) showif } bind def +/inGHzr { showif (\(GHz) (-1) sp (\)) showif } def + +%% home-made Angstr is obsolete; use \305 (more reliable than Å) +/Angstr { + showif + (A) .5 1.23 { + currentpoint fontheight .1 mul setline np + fontheight .14 mul 0 360 arc st () + } build +} bind def +/Angr { showif (\305) supsc (-1) endsc } bind def +/inAngr { showif (\() Angr (\)) showif } bind def +/Angrr { showif (\305) supsc (-2) endsc } bind def +/inAngrr { showif (\() Angrr (\)) showif } bind def +/wmin {grec (w) endgr () subsc (min) endsc} def +/winpi { grec (w) endgr ( / 2) grec (p) endgr } def +/Celsius { showif (\26x)g(C) showif } bind def + + +%% More shortcuts for impatient users: + +/L { langSel } bind def +/G { gsave exec grestore } bind def +/gs { gsave } bind def +/gr { grestore } bind def + +end % WuGdict... + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Mark "ewu", the end of the wups.. macro definition file %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +WuGdict11a begin + +9 dup autolabel defsiz +1 dup stdred +2 -21 setnewpage newpage + +/darkgreen { 13 133 13 setRGBcolor } def +/litegreen {202 253 222 setRGBcolor } def +/darkGreen { 1 33 1 setRGBcolor } def +/liteGreen {162 233 172 setRGBcolor } def +/darkblue { 13 13 133 setRGBcolor } def +/liteblue {202 202 255 setRGBcolor } def + +/boxcenter{ qqxl qqxh add 2 div qqyl qqyh add 2 div } def + +/greenbox{ + 5 1 roll + { { litegreen fill } G darkgreen 2 [] lset st } execRect3 + black boxcenter 3 2 roll textCM +} def + +/Greenbox{ + 5 1 roll + { { liteGreen fill } G darkgreen 3 [.27 .12] lset st } execRect3 + black boxcenter 3 2 roll textCM +} def + +/grisbox{ + 5 1 roll + { { .8 setgray fill } G .2 setgray 2 [] lset st } execRect3 + black boxcenter 3 2 roll textCM +} def + +/blueoval{ + 6 1 roll + { { liteblue fill } G darkblue 2 [] lset st } execOval3 + black boxcenter 3 2 roll textCM +} def +/greenoval{ + 6 1 roll + { { litegreen fill } G darkgreen 2 [] lset st } execOval3 + black boxcenter 3 2 roll textCM +} def +/Greenoval{ + 6 1 roll + { { liteGreen fill } G darkgreen 2 [] lset st } execOval3 + black boxcenter 3 2 roll textCM +} def + +21 setown + +1 [] lset black +/upline { 270 .5 2 Pfeil } def % (arrow anchored at base) x y rot siz len + +4 14 3.5 7.5 {()} greenbox +5 13 5 7 {()} Greenbox +9 4.25 {(libBornAgainCore (C++))} textCM +9 6 {(libBornAgainCore (exposed))} textCM + +gsave +9 -.5 offset +2.4 2.4 270 .5 1.6 Pfeil +1. .4 offset +3 { + 0 3.8 0 2 {(other libs)} grisbox + -.5 -.2 offset +} repeat +grestore + +gsave 0 1 offset +21 setobl +-2 18 8 16 {()} greenbox +5 13 11 13 .3 {(Core wrapper)} Greenoval +-1 7 8.5 10.5 .3 {(Fit wrapper)} Greenoval +11 17 13.5 15.5 .3 {(plot utils)} Greenoval +{ 4 [] lset 9 6 270 .5 5 Pfeil } G +9 16 270 .5 1.5 Pfeil +-1 15 {(bornagain Python module)} textLT +grestore + +gsave +21 setobl +15 19.4 5 7 {(matplotlib)} grisbox +16 7 270 .5 7.5 Pfeil +% Py -> matplotlib +{ 11.5 19.3 offset +0 0 np mv 5 0 rl +6 -1 1 90 0 arcn st +7 -12.3 270 .5 11.3 Pfeil +} G +grestore + +gsave +-6 -5.5 offset +12 7.5 270 .5 1.5 Pfeil +4 14 3.5 7.5 {()} greenbox +5 13 5 7 {()} Greenbox +9 4.25 {(libBornAgainFit (C++))} textCM +9 6 {(libBornAgainFit (exposed))} textCM +{ 4 [] lset 9 7 270 .5 8 Pfeil } G +grestore + +gsave +21 setobl +0 18 offset +6.5 11.5 1 3 .4 {(Python apps)} blueoval +8.5 12 0.5 1.5 .3 {(Examples)} greenoval +grestore + +showpage +end % WuGdict... diff --git a/Doc/UserManual/fig/icons/Weblink.png b/Doc/UserManual/fig/icons/Weblink.png new file mode 100644 index 0000000000000000000000000000000000000000..cfc7b6e33c068b3a288adf44ff9aa4ae836c473c Binary files /dev/null and b/Doc/UserManual/fig/icons/Weblink.png differ diff --git a/Wrap/python/__init__.py.in b/Wrap/python/__init__.py.in index 667e10d0b41de3571984b93ef41d708e4bd6d6b2..7d8c3655e9c14bc3755648d6344d3de5d5e44601 100644 --- a/Wrap/python/__init__.py.in +++ b/Wrap/python/__init__.py.in @@ -11,4 +11,3 @@ from libBornAgainFit import * sys.path.append(os.path.abspath(os.path.dirname(__file__))) from plot_utils import * -