(* ::Package:: *)

(************************************************************************)
(* This file was generated automatically by the Mathematica front end.  *)
(* It contains Initialization cells from a Notebook file, which         *)
(* typically will have the same name as this file except ending in      *)
(* ".nb" instead of ".m".                                               *)
(*                                                                      *)
(* This file is intended to be loaded into the Mathematica kernel using *)
(* the package loading commands Get or Needs.  Doing so is equivalent   *)
(* to using the Evaluate Initialization Cells menu command in the front *)
(* end.                                                                 *)
(*                                                                      *)
(* DO NOT EDIT THIS FILE.  This entire file is regenerated              *)
(* automatically each time the parent Notebook file is saved in the     *)
(* Mathematica front end.  Any changes you make to this file will be    *)
(* overwritten.                                                         *)
(************************************************************************)



(* :Title: FigScheme *)
(* :Context: SciDraw` *)
(* :Summary: Level scheme drawing *)
(* :Author: Mark A. Caprio, Department of Physics, University of Notre Dame *)
(* :Copyright: Copyright FIGYEAR, Mark A. Caprio *)
(* :Package Version: FIGVERSION *)
(* :Mathematica Version: MATHVERSION *)
(* :Discussion: FIGDISCUSSION *)
(* :History: See package information file. *)


BeginPackage["SciDraw`",SciDraw`Private`$ExternalContexts];


Unprotect[Evaluate[$Context<>"*"]];


Lev::usage="FIGURE OBJECT: Lev[c1,c2,E] generates an energy level.";
ExtensionLine::usage="FIGURE OBJECT: ExtensionLine[level,side,extension] generates an extension line attached to an energy level.";
Connector::usage="FIGURE OBJECT: Connector[level1,level2] generates a connectingline between levels.";BandLabel::usage="FIGURE OBJECT: BandLabel[level,text] attaches a label to a level at the Bottom position.";
Trans::usage="FIGURE OBJECT: Trans[level1,level2] generates a transition arrow.";


LastLevel::usage="LastLevel[] refers to the last Lev object drawn, or None if none have been drawn.";
LevelEnergyLabel::usage="LevelEnergyLabel[level] refers to the default energy label text for the level lev.";
AutoLevelInit::usage="AutoLevelInit[position,space,bigspace] initializes the positioning parameters for automatic decay scheme generation."; 
AutoLevel::usage="AutoLevel[level1] selects a new starting level for transitions."; 
AutoTrans::usage="AutoTrans[level2] draws a transition to the designated ending level, in automatic decay scheme generation.  Any options taken by Trans may be given to AutoTrans."; 


Margin::usage="Option name for use with figure objects.";
VerticalShift::usage="Option name for use with figure objects.";
EnergyLabelFunction::usage="Option name for use with figure objects.";
WingHeight::usage="Option name for use with figure objects.";
WingSlopeWidth::usage="Option name for use with figure objects.";
WingTipWidth::usage="Option name for use with figure objects.";
MakeWing::usage="Option name for use with figure objects.";


IntermediatePoints::usage="Option name for use with figure objects.";
EndPositions::usage="Option name for use with figure objects.";
ToWing::usage="Option name for use with figure objects.";


Begin["`Private`"];





DeclareFigClass[
Lev,
{"NominalPoints","BasePoints","Points","UserXWidth","UserMargins","EnergyLabel"},
{},
{Center,Left,Right,Bottom,Top}
];
DefineFigClassOptions[
Lev,
{
(* line geometry*)
Margin->0.1,
VerticalShift->None,

(* automatic energy label  *)
EnergyLabelFunction->Automatic,
DecimalDigits->Automatic,

(* gull wings *)
WingHeight->0,
WingSlopeWidth->10,
WingTipWidth->40,
MakeWing->True
}
];


Lev::xorder="Level has zero or negative length, originally given coordinates `1`, and ultimately having endpoints `2` after applying margins.";


Constructor[Class:Lev,Self_Object][x1_?NumericQ,x2_?NumericQ,EnergyStr:(_?NumericQ|_String),Opts___?OptionQ]:=FigObjectWrapper[Class,Self,{Opts},
Module[
{
CanvasPoints,NominalCanvasPoints,BaseCanvasPoints,Energy,UsedVerticalShift,NudgeShift,x1m,x2m,p1m,p2m,
UsedMargin,UsedWingHeight,UsedWingSlopeWidth,UsedWingTipWidth,UsedMakeWing,
DerivedEnergyLabelFunction,DerivedEnergyLabel,LabelName,Side
},

(* validate extra options *)
FigCheckOption[Self,Margin,IntervalParametersPattern,FigOptions];
FigCheckOption[Self,VerticalShift,ScalarParameterPattern,FigOptions];
FigCheckOption[Self,EnergyLabelFunction,_,FigOptions];
FigCheckOption[Self,DecimalDigits,Automatic|((_Integer)?NonNegative)|{((_Integer)?NonNegative),((_Integer)?NonNegative)},FigOptions];
FigCheckOption[Self,WingHeight,IntervalParametersPattern,FigOptions];
FigCheckOption[Self,WingSlopeWidth,IntervalParametersPattern,FigOptions];
FigCheckOption[Self,WingTipWidth,IntervalParametersPattern,FigOptions];
FigCheckOption[Self,MakeWing,LogicalPattern|{LogicalPattern,LogicalPattern},FigOptions];
If[x2<x1,FigMessage[]];

(* option expansion *)
UsedMargin=UpgradePairEqual[(Margin/.FigOptions)];
UsedVerticalShift=UpgradeScalar[(VerticalShift/.FigOptions)];
UsedWingHeight=UpgradePairEqual[(WingHeight/.FigOptions)];
UsedWingSlopeWidth=UpgradePairEqual[(WingSlopeWidth/.FigOptions)];
UsedWingTipWidth=UpgradePairEqual[(WingTipWidth/.FigOptions)];
UsedMakeWing=UpgradePair[(MakeWing/.FigOptions)];  (* not numeric, so use UpgradePair *)

(* prerequisite calculations *)
Energy=Switch[EnergyStr,
_?NumericQ,EnergyStr,
_String,ToExpression[EnergyStr]
];

(* nominal canvas points -- those for marginless level *)
NudgeShift={{0,UsedVerticalShift},{0,UsedVerticalShift}};
NominalCanvasPoints=FigResolvePoint/@{{x1,Energy},{x2,Energy}}+NudgeShift;
Self@SetNominalPoints[NominalCanvasPoints];
Self@SetUserXWidth[x2-x1];

(* base canvas points -- those for wingless level *)
{x1m,x2m}=ExtendInterval[{x1,x2},-UsedMargin,Absolute];
If[
x1m>=x2m,
FigError[Self,"xorder",{x1,x2},{x1m,x2m}]
];
BaseCanvasPoints={p1m,p2m}=FigResolvePoint/@{{x1m,Energy},{x2m,Energy}}+NudgeShift;
Self@SetBasePoints[BaseCanvasPoints];
Self@SetUserMargins[UsedMargin];

(* true canvas points -- with possible wings *)
CanvasPoints=Join[
If[
(UsedWingHeight[[1]]==0)||(!UsedMakeWing[[1]]),
{p1m},
{p1m+{0,UsedWingHeight[[1]]},p1m+{UsedWingTipWidth[[1]],UsedWingHeight[[1]]},p1m+{UsedWingTipWidth[[1]]+UsedWingSlopeWidth[[1]],0}}
],
Reverse@If[
(UsedWingHeight[[2]]==0)||(!UsedMakeWing[[2]]),
{p2m},
{p2m+{0,UsedWingHeight[[1]]},p2m+{-UsedWingTipWidth[[1]],UsedWingHeight[[1]]},p2m+{-UsedWingTipWidth[[1]]-UsedWingSlopeWidth[[1]],0}}
]
];
Self@SetPoints[CanvasPoints];

(* make graphics elements *)
FigLineElement[
{Line[CanvasPoints]},
FigOptions
];

(* define energy label text *)
(* energy label priority: (1) string, (2) specified function, (3) specified decimal digits, (4) simple pass through of number*)
DerivedEnergyLabelFunction=If[
(EnergyLabelFunction/.FigOptions)===Automatic,
If[
(DecimalDigits/.FigOptions)===Automatic,
Identity,
(FixedPointForm[#,(DecimalDigits/.FigOptions)]&)
],
(EnergyLabelFunction/.FigOptions)
];
DerivedEnergyLabel=Switch[
EnergyStr,
_String,EnergyStr,
_?NumericQ,(DerivedEnergyLabelFunction/.FigOptions)@EnergyStr
];
Self@SetEnergyLabel[DerivedEnergyLabel];

(* push energy label text in place of Automatic label values *) 
FigOptions=Join[
Table[
LabelName=SidifyOptionName[Side][Label];
LabelName->ResolveOption[LabelName,{Automatic->DerivedEnergyLabel},FigOptions],
{Side,$FigClassAttachedLabels[ObjectClass[Self]]}
],
FigOptions
];

(* record self as last level *)
$LastLevel=Self;
]
];


MakeAnchor[Class:Lev,Self_Object][Name:Left,Arg:None]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigAnchor[Canvas[First[Self@GetPoints[]]],Right]
];
MakeAnchor[Class:Lev,Self_Object][Name:Right,Arg:None]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigAnchor[Canvas[Last[Self@GetPoints[]]],Left]
];
MakeAnchor[Class:Lev,Self_Object][Name:Bottom,Arg:None]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigAnchor[CentroidPoint[Canvas/@(Self@GetBasePoints[])],Top]
];
MakeAnchor[Class:Lev,Self_Object][Name:Top,Arg:None]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigAnchor[CentroidPoint[Canvas/@(Self@GetBasePoints[])],Bottom]
];
MakeAnchor[Class:Lev,Self_Object][Name:Center,Arg:None]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigAnchor[CentroidPoint[Canvas/@(Self@GetBasePoints[])]]
];


MakeAnchor[Class:Lev,Self_Object][Name:Level,Arg:(x_?NumericQ)]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
Module[
{u=x/(Self@GetUserXWidth[])},
FigAnchor[Canvas[InterpolateSegment[Self@GetNominalPoints[],Tail,u]]]
]
];
MakeAnchor[Class:Lev,Self_Object][Name:Level,Arg:{Side:(Left|Right),(x_?NumericQ)}]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
Module[
{u=x/(Self@GetUserXWidth[])},
FigAnchor[Canvas[{
First[InterpolateSegment[Self@GetNominalPoints[],Tail,u]],
Last[(Self@GetPoints[])[[Switch[Side,Left,1,Right,-1]]]]
}]]
]
];


MakeBoundingBox[Class:Lev,Self_Object][]:=FigCurveBoundingBox[Self@GetPoints[]];


LastLevel[]:=$LastLevel;
DeclareFigFallThroughError[LastLevel];


DeclareFigClass[
ExtensionLine,
{"Points"},
{},
{Left,Right}
];
DefineFigClassOptions[
ExtensionLine,
{
(* geometry *)
ToWing->True
}
];


Constructor[Class:ExtensionLine,Self_Object][
Object[LevelName:ObjectNamePattern[Lev]]|(LevelName:ObjectNamePattern[Lev]),
Side:(Left|Right),
(x_?NonNegative),
Opts___?OptionQ]:=FigObjectWrapper[Class,Self,{Opts},
Module[
{CanvasPoints,x1,x2,Arg1,Arg2,UsedMargin},

(* validate extra options *)
FigCheckOption[Self,ToWing,LogicalPattern,FigOptions];

(* construct full curve specification *)
UsedMargin=(Object[LevelName]@GetUserMargins[]);
{x1,x2}=Switch[Side,
Left,
{UsedMargin[[1]]-x,UsedMargin[[1]]},
Right,
(Object[LevelName]@GetUserXWidth[])+
{-UsedMargin[[2]],-UsedMargin[[2]]+x}
];
{Arg1,Arg2}=If[
(ToWing/.FigOptions),
{Side,#}&/@{x1,x2},
{x1,x2}
];
CanvasPoints=FigResolvePoint/@{FigAnchor[LevelName,Level,Arg1],FigAnchor[LevelName,Level,Arg2]};
Self@SetPoints[CanvasPoints];

(* make graphics elements *)
FigLineElement[
{Line[CanvasPoints]},
FigOptions
];


]
];


MakeAnchor[Class:ExtensionLine,Self_Object][Name:Left,None]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigCurveAnchorFromPoints[Self@GetPoints[],Tail,None]
];
MakeAnchor[Class:ExtensionLine,Self_Object][Name:Right,None]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigCurveAnchorFromPoints[Self@GetPoints[],Head,None]
];


MakeBoundingBox[Class:ExtensionLine,Self_Object][]:=FigCurveBoundingBox[Self@GetPoints[]];


DeclareFigClass[
Connector,
{"Points"},
{},
{Bottom,Center,Top}
];
DefineFigClassOptions[
Connector,
{
}
];


Constructor[Class:Connector,Self_Object][
Object[LevelName1:ObjectNamePattern[Lev]]|(LevelName1:ObjectNamePattern[Lev]),
Object[LevelName2:ObjectNamePattern[Lev]]|(LevelName2:ObjectNamePattern[Lev]),
Opts___?OptionQ]:=FigObjectWrapper[Class,Self,{Opts},
Module[
{CanvasPoints},

CanvasPoints=FigResolvePoint/@{FigAnchor[LevelName1,Right],FigAnchor[LevelName2,Left]};
Self@SetPoints[CanvasPoints];

(* make graphics elements *)
FigLineElement[
{Line[CanvasPoints]},
FigOptions
];


]
];


MakeAnchor[Class:Connector,Self_Object][Name:Bottom,Arg_]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigCurveAnchorFromPoints[Self@GetPoints[],Right,Arg]
];
MakeAnchor[Class:Connector,Self_Object][Name:Center,Arg_]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigCurveAnchorFromPoints[Self@GetPoints[],Center,Arg]
];
MakeAnchor[Class:Connector,Self_Object][Name:Top,Arg_]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigCurveAnchorFromPoints[Self@GetPoints[],Left,Arg]
];


MakeBoundingBox[Class:Connector,Self_Object][]:=FigCurveBoundingBox[Self@GetPoints[]];


DeclareFigClass[
BandLabel,
{"Anchor","TextElement"},
{},
{}
];
DefineFigClassOptions[
BandLabel,
{
VerticalShift->-3
}
];


Constructor[Class:BandLabel,Self_Object][
Object[LevelName:ObjectNamePattern[Lev]]|(LevelName:ObjectNamePattern[Lev]),
TextArt_,
Opts___?OptionQ
]:=FigObjectWrapper[Class,Self,{Opts},
Module[
{
GivenPoint,Anchor,TextElement,
CanvasCenter,CanvasPivot,CanvasRadius,RotationAngle,UsedVerticalShift
},

(* validate options *)
FigCheckOption[Self,VerticalShift,ScalarParameterPattern,FigOptions];

(* generate point *)
UsedVerticalShift=UpgradeScalar[(VerticalShift/.FigOptions)];
Anchor=RelativeTo[
FigAnchor[LevelName,Bottom],
Canvas[{0,UsedVerticalShift}]
];

(* make text *)
TextElement=FigTextElement[
Anchor,
TextArt,
FigOptions
];

(* save references to spawned objects *)
Self@SetAnchor[Anchor];
Self@SetTextElement[TextElement];

]
];


MakeAnchor[Class:BandLabel,Self_Object][Name_,Arg_]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigRectangleAnchor[
(Self@GetTextElement[])@GetCenter[],(Self@GetTextElement[])@GetRadius[],(Self@GetTextElement[])@GetPivot[],(Self@GetTextElement[])@GetRotation[],
Name,Arg
]
];
MakeBoundingBox[Class:BandLabel,Self_Object][]:=FigRectangleBoundingBox[
(Self@GetTextElement[])@GetCenter[],(Self@GetTextElement[])@GetRadius[],(Self@GetTextElement[])@GetPivot[],(Self@GetTextElement[])@GetRotation[]
];


DeclareFigClass[
Trans,
FigArrow,
{"Points","LeftPoints","RightPoints"},
{},
{Center,Left,Right,Tail,Head}
];
DefineFigClassOptions[
Trans,
{TailFlush->True,HeadFlush->True},
{
(* geometry *)
IntermediatePoints->None,
EndPositions->0.5
}
];


Trans::twoautos="You cannot specify both initial and final horizontal positions as Automatic.";
RealizeTransEndpoints[Self_Object,LevelName1_,LevelName2_,EndPositions:{x1_,x2_}]:=Module[
{p1,p2},

(* check for circularity *)
If[
(x1===Automatic)&&(x2===Automatic),
FigError[Self,"twoautos"]
];

(* resolve independently-resolvable points *)
If[
(x1=!=Automatic),
p1=FigAnchor[LevelName1,Level,x1]
];
If[
(x2=!=Automatic),
p2=FigAnchor[LevelName2,Level,x2]
];

(* resolve automatic specifications *)
(* use "x" from other endpoint, and "y" from Center anchor of present endpoint's level *)
If[
(x1===Automatic),
p1=Canvas[{First[FigResolvePoint[p2]],Last[FigResolvePoint[FigAnchor[LevelName1,Center]]]}]
];
If[
(x2===Automatic),
p2=Canvas[{First[FigResolvePoint[p1]],Last[FigResolvePoint[FigAnchor[LevelName2,Center]]]}];
];

(* return result *)
{p1,p2}
];


UpgradePairEqualAutomatic[None]:={0,0};
UpgradePairEqualAutomatic[x:(_?NumericQ|Automatic)]:={x,x};
UpgradePairEqualAutomatic[{x:(_?NumericQ|Automatic),y:(_?NumericQ|Automatic)}]:={x,y};


Constructor[Class:Trans,Self_Object][
Object[LevelName1:ObjectNamePattern[Lev]]|(LevelName1:ObjectNamePattern[Lev]),
Object[LevelName2:ObjectNamePattern[Lev]]|(LevelName2:ObjectNamePattern[Lev]),
Opts___?OptionQ]:=FigObjectWrapper[Class,Self,{Opts},
Module[
{UsedEndPositions,CanvasPoints,LeftCanvasPoints,RightCanvasPoints,UsedWidth,p1,p2,Curve,UsedIntermediatePoints},

(* validate extra options *)
FigCheckOption[Self,IntermediatePoints,None|{FigCurvePointPattern...},FigOptions];
FigCheckOption[Self,EndPositions,((_?NumericQ)|Automatic)|{((_?NumericQ)|Automatic),((_?NumericQ)|Automatic)},FigOptions];

(* construct full curve specification *)
UsedEndPositions=UpgradePairEqualAutomatic[(EndPositions/.FigOptions)];
{p1,p2}=RealizeTransEndpoints[Self,LevelName1,LevelName2,UsedEndPositions];
UsedIntermediatePoints=ResolveOption[IntermediatePoints,{None->{}},FigOptions];
Curve=Join[{p1},UsedIntermediatePoints,{p2}];

(* invoke basic arrow constructor code *)
BasicArrow[Self][Curve];

]
];


Constructor[Class:Trans,Self_Object][
Object[LevelName1:ObjectNamePattern[Lev]]|(LevelName1:ObjectNamePattern[Lev]),
x1:((_?NumericQ)|Automatic),
Object[LevelName2:ObjectNamePattern[Lev]]|(LevelName2:ObjectNamePattern[Lev]),
x2:((_?NumericQ)|Automatic),
Opts___?OptionQ]:=FigObjectWrapper[Class,Self,{Opts},
Module[
{UsedEndPositions,CanvasPoints,LeftCanvasPoints,RightCanvasPoints,UsedWidth,p1,p2,Curve,UsedIntermediatePoints},

(* validate extra options *)
FigCheckOption[Self,IntermediatePoints,None|{FigCurvePointPattern...},FigOptions];
FigCheckOption[Self,EndPositions,((_?NumericQ)|Automatic)|{((_?NumericQ)|Automatic),((_?NumericQ)|Automatic)},FigOptions];

(* construct full curve specification *)
UsedEndPositions={x1,x2};
UsedIntermediatePoints=ResolveOption[IntermediatePoints,{None->{}},FigOptions];
{p1,p2}=RealizeTransEndpoints[Self,LevelName1,LevelName2,UsedEndPositions];
Curve=Join[{p1},UsedIntermediatePoints,{p2}];

(* invoke basic arrow constructor code *)
BasicArrow[Self][Curve];

]
];


MakeAnchor[Class:Trans,Self_Object][Name:(Head|Tail|Center),Arg_]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigCurveAnchorFromPoints[Self@GetPoints[],Name,Arg]
];
MakeAnchor[Class:Trans,Self_Object][Name:Left,Arg_]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigCurveAnchorFromPoints[Self@GetLeftPoints[],Name,Arg]
];
MakeAnchor[Class:Trans,Self_Object][Name:Right,Arg_]:=FigMakeAnchorWrapper[Class,Self,Name,Arg,
FigCurveAnchorFromPoints[Self@GetRightPoints[],Name,Arg]
];


MakeBoundingBox[Class:Trans,Self_Object][]:=FigCurveBoundingBox[Self@GetPoints[]];


AutoLevelInit[Position_?NumericQ,Space_?NumericQ,BigSpace_?NumericQ]  :=Module[
{},
AutoLevelCurrentLevel = Null;
AutoLevelCurrentPosition = Position;
AutoLevelSpace = Space;
AutoLevelBigSpace = BigSpace;
];
DeclareFigFallThroughError[AutoLevelInit];


AutoLevel[Object[LevelName1:ObjectNamePattern[Lev]]|(LevelName1:ObjectNamePattern[Lev])]:=Module[
{},
AutoLevelCurrentPosition+=If[
(AutoLevelCurrentLevel === Null),
 0,
AutoLevelBigSpace-AutoLevelSpace
];
AutoLevelCurrentLevel =LevelName1;
];
DeclareFigFallThroughError[AutoLevel];


AutoTrans[Object[LevelName2:ObjectNamePattern[Lev]]|(LevelName2:ObjectNamePattern[Lev]),Opts___?OptionQ]:=Module[
{},
Trans[AutoLevelCurrentLevel ,AutoLevelCurrentPosition,LevelName2,Automatic,Opts];
AutoLevelCurrentPosition+=AutoLevelSpace; 
];
DeclareFigFallThroughError[AutoTrans];


End[];


Protect[Evaluate[$Context<>"*"]];
Unprotect[Evaluate[$Context<>"$*"]];
EndPackage[];
