Select Git revision
-
Xisco Jimenez Forteza authoredXisco Jimenez Forteza authored
DataFits.m 111.47 KiB
(* ::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. *)
(************************************************************************)
(* ::Code::Initialization:: *)
BeginPackage["DataFits`",{"NRLists`","ErrorBarPlots`"}];
(* ::Code::Initialization:: *)
\[Eta]::usage="\[Eta] for local usage";
S::usage="S for local usage";
\[Chi]1::usage="\[Chi]1 for local usage";
\[Chi]2::usage="\[Chi]2 for local usage";
\[Delta]\[Chi]::usage="\[Delta]\[Chi] for local usage";
a0::usage="a0 for local usage";
a1::usage="a1 for local usage";
a2::usage="a2 for local usage";
sTot::usage="";
sTot3::usage="";
\[Chi]Tot::usage="";
\[Chi]diffplus::usage="";
\[Chi]diffstan::usage="";
DataFitFunction::usage="DataFitFunction[data_?ListQ,ansatzList_?ListQ,OptionsPattern[]]";
DataFitFunctionAll::usage="DataFitFunctionAll[dataraw_?ListQ,OptionsPattern[]]";
DataFitFunctionAllNoWeights::usage="DataFitFunctionAllWeights[dataraw_?ListQ,OptionsPattern[]]";
AnsatzRestrictions::usage="AnsatzRestrictions[nsfit_, q1fit_, ansatzGen_]";
Plot2DFits::usage="Plot2DFits[data_?ListQ,fitlist_?ListQ,fitvars_?ListQ, OptionsPattern[]]";
myListPlot3D::usage="myListPlot3D[data_?ListQ,options]: Plot 3d data + interpolated function";
ColorGradient::usage="ColorGradient[data,colors,options]. Create a linear gradient of colors for the data";
CreateColors::usage="CreateColors[codes,colors]. Set different colors for each NR code";
CleanAnsatzParams::usage="cleanAnsatzParams[paramsGuess_, vars_]";
Generate1DPolynomialAnsatz::usage="Generate1DPolynomialAnsatz[CoefficientPrefixString_?StringQ,variable_,MinOrder_?IntegerQ,MaxOrder_?IntegerQ] creates a polynomial function ansatz.";
Residuals::usage="Residuals[data_,fit_,vars_] computes fit residuals.";
AtomsList::usage="Take the coefficients out";
GeneralizeFunction::usage="GeneralizeFunction[expr_,x_] insert free coefficient at all (non-exact) real numbers in a function";
GeneralizeFunction::usage="GeneralizeFunction[expr_,x_,coord_,orderNum,orderDenom_] insert polynomial with free coefficients at all (non-exact) real numbers in a function";
ExactPade::usage="ExactPade[ansatz_,coeffRules_,padeOptions_] get Pade approximant while keeping exact coefficients fixed.";
Generate1DPadeAnsatzList::usage="Generate1DPadeAnsatzList[ansatz_,\!\(\*
StyleBox[\"coeffRules_\", \"Code\"]\)\!\(\*
StyleBox[\",\", \"Code\"]\)\!\(\*
StyleBox[\"variable_\", \"Code\"]\)\!\(\*
StyleBox[\",\", \"Code\"]\)\!\(\*
StyleBox[\"paramName_\", \"Code\"]\)\!\(\*
StyleBox[\",\", \"Code\"]\)\!\(\*
StyleBox[\"minPadeTypeSum_\", \"Code\"]\)\!\(\*
StyleBox[\",\", \"Code\"]\)\!\(\*
StyleBox[\"maxPadeTypeSum_\", \"Code\"]\)] make a list of all Pade ansaetze with type (num+denom) summing up between [min,max].";
InvertRules::usage="InvertRules[rules_] invert a list of rules";
Get1dInverseRules::usage="Get1dInverseRules[ansatz_,coeffRules_] invert a set of 1d rules in eta or S, taking care of the Pade form";
Get1dInverseRulesS::usage="Get1dInverseRulesS[ansatz_,coeffRules_,productAnsatz_] invert the 1d rules in S, taking care of normalization and Pade form";
FitPredictionIntervalFunctionFinalOnly::usage="FitPredictionIntervalFunctionFinalOnly[fit_,ansatzRules_] return function for the fit uncertainty (prediction interval), final fit statistics only";
FitPredictionIntervalFunctionFinalOnlyq1::usage="FitPredictionIntervalFunctionFinalOnlyq1[fit_,ansatzRules_] return function for the fit uncertainty (prediction interval), in the limit of q=1, final fit statistics only";
FitPredictionIntervalFinalOnly::usage="FitPredictionIntervalFinalOnly[fit_,ansatzRules_,etain_,chi1in_,chi2in_] estimate the fit uncertainty (prediction interval) at a given point, final fit statistics only";
FitPredictionIntervalStderrSq::usage="FitPredictionIntervalStderrSq[\!\(\*
StyleBox[\"finalFit_\", \"Code\"]\)\!\(\*
StyleBox[\",\", \"Code\"]\)\!\(\*
StyleBox[\"finalAnsatzRules_\", \"Code\"]\)\!\(\*
StyleBox[\",\", \"Code\"]\)\!\(\*
StyleBox[\"fit2dParts_\", \"Code\"]\)\!\(\*
StyleBox[\",\", \"Code\"]\)\[Eta]0stuff_,extraCoeffRules_,productAnsatz_,q1_] evaluate the various stderrsq contributions for fit uncertainty intervals";
FitPredictionIntervalFunction::usage="FitPredictionIntervalFunction[finalFit_,finalAnsatzRules_,fit2dParts_,\[Eta]0stuff_,extraCoeffRules_,productAnsatz_] return function for the fit uncertainty (prediction interval)";
FitPredictionIntervalFunctionq1::usage="FitPredictionIntervalFunctionq1[finalFit_,finalAnsatzRules_,fit2dParts_,\[Eta]0stuff_,extraCoeffRules_,productAnsatz_] return function for the fit uncertainty (prediction interval), in the limit of q=1";
FitPredictionInterval::usage="FitPredictionInterval[finalFit_,finalAnsatzRules_,fit2dParts_,\[Eta]0fit_,extraCoeffRules_,productAnsatz_,etain_,chi1in_,chi2in_] estimate the fit uncertainty (prediction interval) at a given point";
TeXExportCoeffTable::usage="TeXExportCoeffTable[fit_,filename_] export a fit coefficient table into a nice TeX file.";
TeXExportCovarMatrixTable::usage="TeXExportCovarMatrixTable[fitCovar_,fitCoeffRules_,filename_] export fit covariance matrix into a nice TeX file.";
SubscriptRules::usage="SubscriptRules[rules_] make a subscript rule from a numeric coefficient rule.";
GetRawTwoDAnsatz::usage="GetRawTwoDAnsatz[finalfit_,fit2dParts_,productAnsatz_,constrained_] put together raw 2d ansatz equation.";
GetAllRules::usage="GetAllRules[finalfit_,fit2dParts_,twodrules_] collect all 1d, 2d and 3d coefficient rules";
TeXFormatAnsatz::usage="TeXFormatAnsatz[ansatz_,formattingRules_,coeffRules_] format an ansatz nicer in TeX";
TeXExportAnsatz::usage="TeXExportAnsatz[ansatz_,formattingRules_,coeffRules_,filename_] export a nicely formatted ansatz to TeX.";
TeXExportTwoDAnsatz::usage="TeXExportTwoDAnsatz[finalfit_,fit2dParts_,twodrules_,formattingRules_,productAnsatz_,constrained_,filename_] format the 2d part of the final ansatz.";
TeXExportChiDiffTerms::usage="TeXExportChiDiffTerms[chidiffAnsaetze_,formattingRules_,coeffRules_,filename_] concatenate and export to TeX the various chidiff ansatz terms.";
TeXExportFinalAnsatz::usage="TeXExportFinalAnsatz[finalfit_,fit2dParts_,twodrules_,chidiffAnsaetze_,formattingRules_,productAnsatz_,twodConstrained_,filename_] format the final ansatz nicely.";
TexExportCoeffTable::usage="TeXExportCoeffTable[coeffRules_,covar_,filename_] format a fit coefficient table without t-stat nor p-value.";
TeXExportTabularTable::usage="TeXExportTabularTable[datatable_,filename_,rowHeadings_,colHeadings_,padZeroes_] export a table with array->tabular and formatting fixes.";
PyExportFinalFit::usage="PyExportFinalFit[fit_,extraFormattingRules_,filename_] export the final fit (with numerical coefficients) for python LAL uise.";
PyExportFinalAnsatz::usage="PyExportFinalAnsatz[finalfit_,fit2dParts_,chidiffAnsaetze_,productAnsatz_,extraFormattingRules_,filename_] export the final ansatz (with symbolic coefficients) for python LAL uise.";
PyExportFinalFitCoeffs::usage="PyExportFinalFitCoeffs[finalfit_,fit2dParts_,\!\(\*
StyleBox[\"all2dconstraints_\", \"Code\"]\)\!\(\*
StyleBox[\",\", \"Code\"]\)filename_] export the numerical coefficients to be used together with the ansatz.";
SupplExportAllFitCoeffs::usage="SupplExportAllFitCoeffs[finalfit_,fit2dParts_,\!\(\*
StyleBox[\"all2dconstraints_\", \"Code\"]\)\!\(\*
StyleBox[\",\", \"Code\"]\)\!\(\*
StyleBox[\"eta0covar_\", \"Code\"]\)\!\(\*
StyleBox[\",\", \"Code\"]\)filename_] export the numerical coefficients to a plain ASCII table file.";
SupplExportCovarMatrix::usage="SupplExportCovarMatrix[covar_,coeffRules_,fileName_] export covariance matrices as simple ASCII table files.";
AIC::usage="AIC[data,fitname,variables,number of parameters]: Explicit computation of the AIC value given by NonlinearModelFit. In data [[#,-2]]: values, [[#,-1]]: weights. Fit is the fit name e.g FinalSpin0815. Does not work for RITFinalSpinNonPrec2014";
AICc::usage="AIC[data,fitname,variables,number of parameters]: Explicit computation of the AICc value given by NonlinearModelFit. In data [[#,-2]]: values, [[#,-1]]: weights. Fit is the fit name e.g FinalSpin0815. Does not work for RITFinalSpinNonPrec2014";
BIC::usage="AIC[data,fitname,variables,number of parameters]: Explicit computation of the BIC value given by NonlinearModelFit. In data [[#,-2]]: values, [[#,-1]]: weights. Fit is the fit name e.g FinalSpin0815. Does not work for RITFinalSpinNonPrec2014";
KullbagLeiblerDiv::usage="KullbagLeiblerDiv[p1_?ListQ,p2_?ListQ]: Computation of the KL criterion";
JensenShanonDiv::usage="JensenShanonDiv[p1_?ListQ,p2_?ListQ]: Computation of the JS criterion";
KL::usage="KL[p1_?ListQ,p2_?ListQ],lim: Computation of the KL criterion";
JS::usage="JS[p1_?ListQ,p2_?ListQ,lim]: Computation of the JS criterion";
CredibleRegion::usage="CredibleRegion[data_,level_]: Computation of the credible region";
ComputeEdges::usage="ComputeEdges[pts]";
CredibleInterval::usage="CredibleInterval[data_,level_]: Computation of the credible intervals";
(* ::Code::Initialization:: *)
Begin["`Private`"];
(* ::Code::Initialization:: *)
AtomsList[expr_]:=Union@Select[Level[expr,{0,Infinity}],AtomQ];
InterpolationDomain[fun_]:=Module[{min,max},{min,max}={fun[[1,1,1]],fun[[1,1,2]]}];
q\[Eta][\[Eta]_]:=-(1.-1/(2\[Eta]))+Sqrt[(1-1/(2\[Eta]))^2 -1]
\[Eta]q[q_]:=q/(1.+q)^2.
\[Chi]diffplus[\[Eta]_,xx_,yy_]:=Module[{s},s=(1/2(1+Sqrt[1-4 \[Eta]])xx - 1/2(1-Sqrt[1-4 \[Eta]])yy)]
\[Chi]diffstan[\[Eta]_,xx_,yy_]:=Module[{s},s=xx-yy]
myListPlot3D[list_,opt___]:=Module[{p1,p2},
p1=ListPlot3D[If[(Length@Dimensions@list)>1,list[[1]],list],InterpolationOrder-> 3];
p2=ListPointPlot3D[list,PlotStyle-> PointSize-> Large,opt];
Show[p1,p2]
];
myListPlot3D[list_,opt___]:=Module[{p1,p2},
p1=ListPlot3D[list,InterpolationOrder-> 3,opt];
p2=ListPointPlot3D[list,PlotStyle-> PointSize-> Large,opt];
Show[p1,p2]
];
\[Chi]Tot[\[Eta]_,\[Chi]1_,\[Chi]2_]:=Module[{m1,m2,s},
m1=1/2 (1+Sqrt[1-4 \[Eta]]);
m2=1/2 (1-Sqrt[1-4 \[Eta]]);
s=(m1 \[Chi]1 + m2 \[Chi]2)/(m1+ m2)
]
sTot[\[Eta]_,\[Chi]1_,\[Chi]2_]:=Module[{m1,m2},
m1=1/2 (1+Sqrt[1-4 \[Eta]]);
m2=1/2 (1-Sqrt[1-4 \[Eta]]);
(m1^2 \[Chi]1 + m2^2 \[Chi]2)
]
sTotR[\[Eta]_,\[Chi]1_,\[Chi]2_]:=Module[{m1,m2},
m1=1/2 (1+Sqrt[1-4 \[Eta]]);
m2=1/2 (1-Sqrt[1-4 \[Eta]]);
(m1^2 \[Chi]1 + m2^2 \[Chi]2)/(m1^2 + m2^2)
]
sTot3[\[Eta]_,\[Chi]1_,\[Chi]2_]:=Module[{m1,m2},
m1=1/2 (1+Sqrt[1-4 \[Eta]]);
m2=1/2 (1-Sqrt[1-4 \[Eta]]);
(m1^2 \[Chi]1 + m2^2 \[Chi]2)/(m1^2 + m2^2)
]
countSummands[expr_]:=If[Head[expr]===Plus,Length[expr],If[expr===0,0,1]]
GeneralizeFunction[expr_,x_]:=Module[{num,numTermsNum,numSymbolsFirstTerm,i,termsNum,termsDenom,iStart,rule0,rulesNum,rulesDenom,reals},
num=Numerator[expr];
numTermsNum = countSummands[num];
If[numTermsNum==1,
termsNum = {num};
numSymbolsFirstTerm=1;
,
termsNum = Level[num,{1,1}];
numSymbolsFirstTerm=Length[Cases[Level[termsNum[[1]],{1,Infinity}],y_Symbol]];
];
If[numSymbolsFirstTerm==0,
iStart=2;
reals=Cases[Tally[Select[Level[termsNum[[1]],{0,Infinity}],AtomQ]][[All,1]],y_Real];
If[Length[reals]>0,
rule0={termsNum[[1]]->termsNum[[1]] ToExpression[ToString@x<>"0"]};
,
rule0={};
];
,
iStart=1;
rule0={};
];
rulesNum=rule0;
For[i=iStart,i<=Length[termsNum],i++,
reals=Cases[Tally[Select[Level[termsNum[[i]],{0,Infinity}],AtomQ]][[All,1]],y_Real];
If[Length[reals]>0,
rulesNum=Join[rulesNum,{termsNum[[i]] -> termsNum[[i]] ToExpression[ToString@x<>ToString[i-iStart+1]]}];
];
];
(* currently assumes that denominator always has a -1 in front, can be easily generalized with countSummands as for numerator *)
termsDenom = Level[Denominator[expr],{1,1}];
rulesDenom = {};
For[i=1,i<=Length[termsDenom],i++,
reals=Cases[Tally[Select[Level[termsDenom[[i]],{0,Infinity}],AtomQ]][[All,1]],y_Real];
If[Length[reals]>0,
rulesDenom=Join[rulesDenom,{termsDenom[[i]] -> termsDenom[[i]] ToExpression[ToString@x<>ToString[Length[termsNum]-iStart+1+i]]}];
];
];
Return[(Numerator[expr]/.rulesNum)/(Denominator[expr]/.rulesDenom)]
]
GeneralizeFunction[expr_,x_,coord_,orderNum_,orderDenom_]:=Module[{num,numTermsNum,numSymbolsFirstTerm,i,termsNum,termsDenom,iStart,rule0,rulesNum,rulesDenom,reals},
num=Numerator[expr];
numTermsNum = countSummands[num];
If[numTermsNum==1,
termsNum = {num};
numSymbolsFirstTerm=1;
,
termsNum = Level[num,{1,1}];
numSymbolsFirstTerm=Length[Cases[Level[termsNum[[1]],{1,Infinity}],y_Symbol]];
];
If[numSymbolsFirstTerm==0,
iStart=2;
reals=Cases[Tally[Select[Level[termsNum[[1]],{0,Infinity}],AtomQ]][[All,1]],y_Real];
If[Length[reals]>0,
rule0={termsNum[[1]]->termsNum[[1]](Sum[coord^j ToExpression/@ToExpression@(ToString@x<>"0"<>ToString@j),{j,0,orderNum}])};
,
rule0={};
];
,
iStart=1;
rule0={};
];
rulesNum=rule0;
For[i=iStart,i<=Length[termsNum],i++,
reals=Cases[Tally[Select[Level[termsNum[[i]],{0,Infinity}],AtomQ]][[All,1]],y_Real];
If[Length[reals]>0,
rulesNum=Join[rulesNum,{termsNum[[i]] -> termsNum[[i]](Sum[coord^j ToExpression@(ToString@x<>ToString[i-iStart+1]<>ToString@j),{j,0,orderNum}])}];
];
];
(* currently assumes that denominator always has a -1 in front, can be easily generalized with countSummands as for numerator *)
termsDenom = Level[Denominator[expr],{1,1}];
rulesDenom = {};
For[i=1,i<=Length[termsDenom],i++,
reals=Cases[Tally[Select[Level[termsDenom[[i]],{0,Infinity}],AtomQ]][[All,1]],y_Real];
If[Length[reals]>0,
rulesDenom=Join[rulesDenom,{termsDenom[[i]] -> termsDenom[[i]](Sum[coord^j ToExpression/@ToExpression@(ToString@x<>ToString[Length[termsNum]-iStart+1+i]<>ToString@j),{j,0,orderDenom}])}];
];
];
(Numerator[expr]/.rulesNum)/(Denominator[expr]/.rulesDenom)
]
(*wrapper to Pade approximant that keeps exact coefficients like Sqrt[2] exact, so that GeneralizeFunction won't assign extra coefficients to them.*)
ExactPade[ansatz_,coeffRules_,padeOptions_]:=PadeApproximant[ansatz,padeOptions]/.coeffRules;
myRound[x_,d_] := Module[{mantExp,mant,exp},
mantExp = MantissaExponent[x];
mant = mantExp[[1]];
exp = mantExp[[2]];
If[mant<1.0,
mant = 10*mant;
exp = exp-1;
];
mant = Round[mant,0.1^d];
(*
If[exp<0,
mant = Round[mant,0.1^(d-1)];
,
mant = Round[mant,0.1^d];
];
*)
Return[mant*10^exp]
]
Generate1DPadeAnsatzList[ansatz_,coeffRules_,variable_,paramName_,minPadeTypeSum_,maxPadeTypeSum_]:=Module[{i,j,ansatzDegree,padeAnsatzList,padeType,exactPade,genPade,genPadeList,exactPadeReals,exactPadeRounding},
For[i=1,i<maxPadeTypeSum,i++,
j=Max[1,minPadeTypeSum-i];
While[(j<=i)&&(i+j<=maxPadeTypeSum),
ansatzDegree = Exponent[ansatz,variable];
If[(j==1)&&(i==ansatzDegree),
Print["Not generating Pade approximant for type ("<>ToString[i]<>","<>ToString[j]<>") with polynomial ansatz of order "<>ToString[ansatzDegree]<>", as it would just duplicate the polynomial."];
,
padeType = {i,j};
exactPade = ExactPade[ansatz,coeffRules,{variable,0,padeType}];
exactPadeReals=Cases[AtomsList[exactPade],y_Real];
exactPadeRounding=Table[exactPadeReals[[i]]->myRound[exactPadeReals[[i]],2],{i,1,Length@exactPadeReals}];
exactPade = exactPade /. exactPadeRounding;
genPade = GeneralizeFunction[exactPade,paramName];
If[!ValueQ[genPadeList],
genPadeList={{genPade,{variable}}};
,
AppendTo[genPadeList,{genPade,{variable}}];
]
];
j++;
];
];
Print["Generated these Pade approximants:"];
Print[genPadeList];
Return[genPadeList];
]
InvertRules[rules_]:=Module[{},
Table[rules[[i,2]]->rules[[i,1]],{i,Length@rules}]
]
Get1dInverseRules[ansatz_,coeffRules_]:=Module[{origCoeffs,inverseRules},
(* in case this is a Pade rational ansatz, disentangle it *)
origCoeffs = Cases[Select[Join[Level[Numerator[ansatz],{1,Infinity}],Level[Denominator[ansatz],{1,Infinity}]],AtomQ],y_Real];
If[Length[origCoeffs]>0,
inverseRules = Table[origCoeffs[[i]]*coeffRules[[i,2]] -> origCoeffs[[i]]*coeffRules[[i,1]], {i,Length@coeffRules}];
,
inverseRules = InvertRules[coeffRules];
];
Return[inverseRules];
]
Get1dInverseRulesS[ansatz_,coeffRules_,productAnsatz_]:=Module[{ansatzWithoutS0,inverseRules},
If[productAnsatz,
ansatzWithoutS0 = ansatz/(ansatz/.S->0)/.{1.->1};
,
ansatzWithoutS0 = ansatz-(ansatz/.S->0)/.{0.->0};
];
inverseRules = Get1dInverseRules[ansatzWithoutS0,coeffRules];
Return[inverseRules];
]
ColorGradient[data_,ColorList_,OptionsPattern[{"Weights"->"","Verbose"->False}]]:=Module[{min,max,weights,wc,blendtab,\[Delta]n,verbose},
weights=OptionValue["Weights"];
verbose=OptionValue["Verbose"];
min=Min[data];
max=Max[data];
\[Delta]n=(max-min)1./(Length@ColorList-1);
If[Not@ListQ@weights,weights=Table[min + \[Delta]n(i-1),{i,Length@ColorList}];,weights=weights Table[min + \[Delta]n(i-1),{i,Length@ColorList}];];
blendtab=Table[{weights[[i]],ColorList[[i]]},{i,Length@ColorList}];
If[verbose,Print["Weights: ",weights]];
Table[Blend[blendtab,data[[i]]],{i,Length@data}]
]
CreateColors[code_,colors_]:=Module[{},
Which[code=="BAM",colors[[1]],code=="SXS",colors[[2]],code=="GaTech",colors[[3]],code=="RIT",colors[[4]],True,colors[[5]]]]
FitPredictionIntervalFunctionFinalOnly[fit_,ansatzRules_]:=Module[{ansatz,coeffNames,coeffRules,Ncoeff,Ndata,EstVar,quant95,covarMatrix,coeffGrad,stderrsq},
ansatz = fit[[15]];
coeffRules = fit[[2]];
coeffNames = coeffRules[[All,1]];
Ncoeff = Length@coeffNames;
Ndata = Length@Last@fit; (* length of residuals vector *)
EstVar = fit[[16]]; (* would be = Total[resid^2]/(Ndata-Ncoeff) without weights *)
(* take gradient vector in the coefficients *)
coeffGrad = Table[D[ansatz/.ansatzRules,coeffNames[[i]]],{i,Ncoeff}] /. coeffRules;
(* estimate of fit error: multiply coefficient gradient with covariance matrix *)
covarMatrix = fit[[14]];
stderrsq = (coeffGrad.covarMatrix.coeffGrad);
(* report back the 95% student-t quantile (applied on both sides, this gives a 90% interval) *)
quant95 = Quantile[StudentTDistribution[Ndata-Ncoeff],0.95];
Return[quant95 * Sqrt[ EstVar + stderrsq ]];
]
FitPredictionIntervalFunctionFinalOnlyq1[fit_,ansatzRules_]:=Module[{ansatz,coeffNames,coeffRules,Ncoeff,Ndata,EstVar,quant95,covarMatrix,coeffGrad,stderrsq,chidiffcoeff,chidiff2coeff},
ansatz = fit[[15]];
coeffRules = fit[[2]];
coeffNames = coeffRules[[All,1]];
Ncoeff = Length@coeffNames;
Ndata = Length@Last@fit; (* length of residuals vector *)
EstVar = fit[[16]]; (* would be = Total[resid^2]/(Ndata-Ncoeff) without weights *)
(* take gradient vector in the coefficients *)
coeffGrad = Table[D[ansatz/.ansatzRules,coeffNames[[i]]],{i,Ncoeff}] /. coeffRules;
(* take care of issues in the q=1, eta=0.25 limit of the spin-diff terms *)
chidiffcoeff = Coefficient[coeffGrad,(\[Chi]1-\[Chi]2)];
chidiff2coeff = Coefficient[coeffGrad,(\[Chi]1-\[Chi]2)^2];
coeffGrad = coeffGrad - chidiffcoeff(\[Chi]1-\[Chi]2) + Limit[chidiffcoeff,\[Eta]->0.25](\[Chi]1-\[Chi]2) - chidiff2coeff (\[Chi]1-\[Chi]2)^2 + Limit[chidiff2coeff,\[Eta]->0.25](\[Chi]1-\[Chi]2)^2;
(* estimate of fit error: multiply coefficient gradient with covariance matrix *)
covarMatrix = fit[[14]];
stderrsq = (coeffGrad.covarMatrix.coeffGrad);
(* report back the 95% student-t quantile (applied on both sides, this gives a 90% interval) *)
quant95 = Quantile[StudentTDistribution[Ndata-Ncoeff],0.95];
Return[quant95 * Sqrt[ EstVar + stderrsq ]];
]
FitPredictionIntervalFinalOnly[fit_,ansatzRules_,etain_,chi1in_,chi2in_]:=Module[{fiterrFunc,fiterrFuncq1,fiterrs,i,eta,chi1,chi2},
(* so we can deal with both scalars and lists *)
If[Length[etain]==0,
eta = {etain};
chi1 = {chi1in};
chi2 = {chi2in};
,
eta = etain;
chi1 = chi1in;
chi2 = chi2in;
];
(* evaluate the general error estimate *)
fiterrFunc = FitPredictionIntervalFunctionFinalOnly[fit,ansatzRules];
(* avoid indeterminates at q=1, eta=0.25 *)
If[MemberQ[eta,0.25],
fiterrFuncq1 = FitPredictionIntervalFunctionFinalOnlyq1[fit,ansatzRules];
];
fiterrs = Table[fiterrFunc,{i,1,Length@eta}];
For[i=1,i<=Length@eta,i++,
If[eta[[i]]==0.25,
fiterrs[[i]]=fiterrFuncq1;
];
];
(* switch spin parametrization and insert user values *)
fiterrs = fiterrs/.{S->sTot3[\[Eta],\[Chi]1,\[Chi]2]};
Return[Table[fiterrs[[i]]/.{\[Eta]->eta[[i]],\[Chi]1->chi1[[i]],\[Chi]2->chi2[[i]]},{i,1,Length@eta}]];
]
FitPredictionIntervalStderrSq[finalFit_,finalAnsatzRules_,fit2dParts_,\[Eta]0stuff_,extraCoeffRules_,productAnsatz_,q1_]:=Module[{finalAnsatz,finalCoeffNames,finalCoeffRules,NfinalCoeffs,finalCovarMatrix,finalCoeffGrad,chidiffcoeff,chidiff2coeff,
etaCoeffRules,etaCoeffNames,NetaCoeffs,etaAnsatz,etaInverseRules,etaCoeffGrad,etaCovarMatrix,
SCoeffRules,SCoeffNames,NSCoeffs,SAnsatz,SInverseRules,SCoeffGrad,SCovarMatrix,
twodCoeffRules,ansatz2dRaw,zeroRules,
\[Eta]0fit,\[Eta]0Constraints,\[Eta]0CoeffRules,\[Eta]0CoeffNames,N\[Eta]0Coeffs,\[Eta]0CovarMatrix,\[Eta]0Coeffgrad,
finalStderrSq,etaStderrSq,SStderrSq,twodStderrSq,\[Eta]0StderrSq,
allStderrSq},
finalAnsatz = finalFit[[15]];
finalCoeffRules = finalFit[[2]];
finalCoeffNames = finalCoeffRules[[All,1]];
NfinalCoeffs = Length@finalCoeffNames;
(* take gradient vector in the coefficients *)
finalCoeffGrad = Table[D[finalAnsatz/.finalAnsatzRules,finalCoeffNames[[i]]],{i,NfinalCoeffs}] /. finalCoeffRules;
(* take care of issues in the q=1, eta=0.25 limit of the spin-diff terms *)
If[q1,
chidiffcoeff = Coefficient[finalCoeffGrad,(\[Chi]1-\[Chi]2)];
chidiff2coeff = Coefficient[finalCoeffGrad,(\[Chi]1-\[Chi]2)^2];
finalCoeffGrad = finalCoeffGrad - chidiffcoeff(\[Chi]1-\[Chi]2) + Limit[chidiffcoeff,\[Eta]->0.25](\[Chi]1-\[Chi]2) - chidiff2coeff (\[Chi]1-\[Chi]2)^2 + Limit[chidiff2coeff,\[Eta]->0.25](\[Chi]1-\[Chi]2)^2;
finalCoeffGrad = Limit[finalCoeffGrad,\[Eta]->0.25];
];
(* estimate of fit error: multiply coefficient gradient with covariance matrix *)
finalCovarMatrix = finalFit[[14]];
finalStderrSq = (finalCoeffGrad.finalCovarMatrix.finalCoeffGrad);
(* also get contributions from 1D eta and S fits *)
etaAnsatz = fit2dParts[[2]];
etaCoeffRules = fit2dParts[[3]];
etaCoeffNames = etaCoeffRules[[All,1]];
NetaCoeffs = Length@etaCoeffNames;
etaCovarMatrix = fit2dParts[[4]];
SAnsatz = fit2dParts[[5]];
SCoeffRules = fit2dParts[[6]];
SCoeffNames = SCoeffRules[[All,1]];
NSCoeffs = Length@SCoeffNames;
SCovarMatrix = fit2dParts[[7]];
(* construct raw 2D ansatz *)
etaInverseRules = Get1dInverseRules[etaAnsatz,etaCoeffRules];
SInverseRules = Get1dInverseRulesS[SAnsatz,SCoeffRules,productAnsatz];
twodCoeffRules = Join[fit2dParts[[8]],fit2dParts[[9]]];
If[Not@productAnsatz,
zeroRules = Table[ToExpression["f"<>ToString@i<>"0"]->0,{i,0,Exponent[Numerator[fit2dParts[[1]]],S]}];
twodCoeffRules = Join[twodCoeffRules/.zeroRules,zeroRules];
];
ansatz2dRaw = fit2dParts[[1]]/.etaInverseRules/.SInverseRules;
(* take gradient vectors of the final ansatz (only 2D part needed) in the previously-determined coefficients *)
etaCoeffGrad = Table[D[ansatz2dRaw, etaCoeffNames[[i]]], {i,NetaCoeffs}] /. Join[etaCoeffRules,SCoeffRules,twodCoeffRules];
SCoeffGrad = Table[D[ansatz2dRaw, SCoeffNames[[i]]], {i,NSCoeffs}] /. Join[etaCoeffRules,SCoeffRules,twodCoeffRules];
(* also get contribution from extreme-mass ratio limit fit *)
If[ListQ[\[Eta]0stuff]&&(Length[\[Eta]0stuff]==0),
\[Eta]0StderrSq=0;
etaCoeffGrad = etaCoeffGrad /. Join[finalCoeffRules,extraCoeffRules];
SCoeffGrad = SCoeffGrad /. Join[finalCoeffRules,extraCoeffRules];
,
If[ListQ[\[Eta]0stuff],
\[Eta]0fit = \[Eta]0stuff[[1]];
\[Eta]0Constraints = \[Eta]0stuff[[2]];
,
\[Eta]0fit = \[Eta]0stuff;
\[Eta]0Constraints = {};
];
\[Eta]0CoeffRules = \[Eta]0fit["BestFitParameters"];
\[Eta]0CoeffNames = \[Eta]0CoeffRules[[All,1]];
N\[Eta]0Coeffs = Length@\[Eta]0CoeffNames;
\[Eta]0CovarMatrix = \[Eta]0fit["CovarianceMatrix"];
\[Eta]0Coeffgrad = Table[D[ansatz2dRaw/.twodCoeffRules/.\[Eta]0Constraints, \[Eta]0CoeffNames[[i]]], {i,N\[Eta]0Coeffs}] /. Join[etaCoeffRules,SCoeffRules] /. Join[\[Eta]0CoeffRules,finalCoeffRules,extraCoeffRules];
If[q1,
\[Eta]0Coeffgrad = Limit[\[Eta]0Coeffgrad, \[Eta]->0.25];
];
\[Eta]0StderrSq = (\[Eta]0Coeffgrad.\[Eta]0CovarMatrix.\[Eta]0Coeffgrad);
etaCoeffGrad = etaCoeffGrad /. \[Eta]0Constraints /. Join[\[Eta]0CoeffRules,finalCoeffRules,extraCoeffRules];
SCoeffGrad = SCoeffGrad /. \[Eta]0Constraints /. Join[\[Eta]0CoeffRules,finalCoeffRules,extraCoeffRules];
];
(* dot gradient vectors together with the corresponding covar matrices *)
etaStderrSq = (etaCoeffGrad.etaCovarMatrix.etaCoeffGrad);
SStderrSq = (SCoeffGrad.SCovarMatrix.SCoeffGrad);
If[q1,
etaCoeffGrad = Limit[etaCoeffGrad, \[Eta]->0.25];
SCoeffGrad = Limit[SCoeffGrad, \[Eta]->0.25];
];
allStderrSq = {finalStderrSq,etaStderrSq,SStderrSq,\[Eta]0StderrSq};
Return[allStderrSq];
]
FitPredictionIntervalFunction[finalFit_,finalAnsatzRules_,fit2dParts_,\[Eta]0fit_,extraCoeffRules_,productAnsatz_]:=Module[{finalCoeffRules,finalCoeffNames,NfinalCoeffs,Ndata,EstVar,quant95,stderrsq,stderrSqContribs,q1},
finalCoeffRules = finalFit[[2]];
finalCoeffNames = finalCoeffRules[[All,1]];
NfinalCoeffs = Length@finalCoeffNames;
Ndata = Length@Last@finalFit; (* length of residuals vector *)
EstVar = finalFit[[16]]; (* would be = Total[resid^2]/(Ndata-Ncoeff) without weights *)
q1=False;
stderrSqContribs = FitPredictionIntervalStderrSq[finalFit,finalAnsatzRules,fit2dParts,\[Eta]0fit,extraCoeffRules,productAnsatz,q1];
(* add up all error contributions in quadrature *)
stderrsq = Total[stderrSqContribs];
(* report back the 95% student-t quantile (applied on both sides, this gives a 90% interval), adding up also the variance contribution for PREDICTION interval (not mean confidence) *)
quant95 = Quantile[StudentTDistribution[Ndata-NfinalCoeffs],0.95];
Return[quant95 * Sqrt[ EstVar + stderrsq ]];
]
FitPredictionIntervalFunctionq1[finalFit_,finalAnsatzRules_,fit2dParts_,\[Eta]0stuff_,extraCoeffRules_,productAnsatz_]:=Module[{finalCoeffRules,finalCoeffNames,NfinalCoeffs,Ndata,EstVar,quant95,stderrsq,stderrSqContribs,q1},
finalCoeffRules = finalFit[[2]];
finalCoeffNames = finalCoeffRules[[All,1]];
NfinalCoeffs = Length@finalCoeffNames;
Ndata = Length@Last@finalFit; (* length of residuals vector *)
EstVar = finalFit[[16]]; (* would be = Total[resid^2]/(Ndata-Ncoeff) without weights *)
q1=True;
stderrSqContribs = FitPredictionIntervalStderrSq[finalFit,finalAnsatzRules,fit2dParts,\[Eta]0stuff,extraCoeffRules,productAnsatz,q1];
(* add up all error contributions in quadrature *)
stderrsq = Total[stderrSqContribs];
(* report back the 95% student-t quantile (applied on both sides, this gives a 90% interval), adding up also the variance contribution for PREDICTION interval (not mean confidence) *)
quant95 = Quantile[StudentTDistribution[Ndata-NfinalCoeffs],0.95];
Return[quant95 * Sqrt[ EstVar + stderrsq ]];
]
FitPredictionInterval[finalFit_,finalAnsatzRules_,fit2dParts_,\[Eta]0stuff_,extraCoeffRules_,productAnsatz_,etain_,chi1in_,chi2in_]:=Module[{fiterrFunc,fiterrFuncq1,fiterrs,i,eta,chi1,chi2},
(* so we can deal with both scalars and lists *)
If[Length[etain]==0,
eta = {etain};
chi1 = {chi1in};
chi2 = {chi2in};
,
eta = etain;
chi1 = chi1in;
chi2 = chi2in;
];
(* evaluate the general error estimate *)
fiterrFunc = FitPredictionIntervalFunction[finalFit,finalAnsatzRules,fit2dParts,\[Eta]0stuff,extraCoeffRules,productAnsatz];
(* avoid indeterminates at q=1, eta=0.25 *)
If[MemberQ[eta,0.25],
fiterrFuncq1 = FitPredictionIntervalFunctionq1[finalFit,finalAnsatzRules,fit2dParts,\[Eta]0stuff,extraCoeffRules,productAnsatz];
];
fiterrs = Table[fiterrFunc,{i,1,Length@eta}];
For[i=1,i<=Length@eta,i++,
If[eta[[i]]==0.25,
fiterrs[[i]]=fiterrFuncq1;
];
];
(* switch spin parametrization and insert user values *)
fiterrs = fiterrs/.{S->sTot3[\[Eta],\[Chi]1,\[Chi]2]};
Return[Table[fiterrs[[i]]/.{\[Eta]->eta[[i]],\[Chi]1->chi1[[i]],\[Chi]2->chi2[[i]]},{i,1,Length@eta}]];
]
TeXExportCoeffTable[coeffTable_,filename_]:=Module[{texTable},
texTable = StringReplace[ToString[TeXForm[NumberForm[coeffTable,3]]],{"$\\grave{ }$*${}^{\\wedge}$"->"}\\cdot10^{"}];
Export[filename, texTable, "Text"];
]
TeXExportCovarMatrixTable[fitCovar_,fitCoeffRules_,filename_]:=Module[{covarMatrix,paramNames,fullMatrix,texTable},
covarMatrix = fitCovar;
paramNames = fitCoeffRules[[All,1]];
fullMatrix = Join[List/@Join[{""},paramNames],Join[{paramNames},covarMatrix,1],2];
texTable = StringReplace[ToString[TeXForm[NumberForm[fullMatrix,3]]],{"$\\grave{ }$*${}^{\\wedge}$"->"}\\cdot10^{"}];
Export[filename,texTable,"Text"];
(* then run on the resulting file: sed -i 's/{/[/g;s/}/],/g;s/*^/e/g' PeakLuminosityUIBCovMatrix_S5.txt *)
]
SubscriptRules[rules_]:=Module[{},
Return[Table[rules[[i,1]]->Subscript[ToExpression[StringTake[ToString@rules[[i,1]],1]],ToExpression[StringTake[ToString@rules[[i,1]],2;;]]],{i,1,Length@rules}]];
]
TeXFormatAnsatz[ansatz_,formattingRules_,coeffRules_]:=Module[{subscripts,formattedAnsatz,TeXansatz},
subscripts = SubscriptRules[coeffRules];
formattedAnsatz = ansatz/.formattingRules/.subscripts;
(*
ansatzReals=Cases[AtomsList[ansatzRaw],y_Real];
ansatzRounding=Table[ansatzReals[[i]]\[Rule]NumberForm[ansatzReals[[i]],{2,2}],{i,1,Length@ansatzReals}];
formattedAnsatz = formattedAnsatz ./ .ansatzRounding;
*)
TeXansatz = TeXForm[formattedAnsatz];
TeXansatz = StringReplace[ToString@TeXansatz," _"->"_"];
TeXansatz = StringReplace[TeXansatz,"{}"->""];
TeXansatz = StringReplace[TeXansatz,"\\overset{\\land }"->"\\widehat"];
TeXansatz = StringReplace[TeXansatz,"\\hat"->"\\widehat"];
Return[TeXansatz];
]
TeXExportAnsatz[ansatz_,formattingRules_,coeffRules_,filename_]:=Module[{TeXansatz},
TeXansatz = TeXFormatAnsatz[ansatz,formattingRules,coeffRules];
Export[filename, TeXansatz, "Text"];
]
GetRawTwoDAnsatz[finalfit_,fit2dParts_,productAnsatz_,constrained_]:=Module[{etaAnsatz,etaCoeffRules,etaInverseRules,SAnsatz,SCoeffRules,SInverseRules,ansatzRaw},
etaAnsatz = fit2dParts[[2]];
etaCoeffRules = fit2dParts[[3]];
etaInverseRules = Get1dInverseRules[etaAnsatz,etaCoeffRules];
SAnsatz = fit2dParts[[5]];
SCoeffRules = fit2dParts[[6]];
SInverseRules = Get1dInverseRulesS[SAnsatz,SCoeffRules,productAnsatz];
ansatzRaw = (fit2dParts[[1]]/.etaInverseRules/.SInverseRules);
If[constrained,
ansatzRaw = ansatzRaw /. fit2dParts[[8]] /. fit2dParts[[9]] /. {4.->4, 16.->16, 64.->64, 256.->256} /. {-4.->-4, -16.->-16, -64.->-64, -256.->-256};
];
Return[ansatzRaw];
]
GetAllRules[finalfit_,fit2dParts_,twodrules_]:=Module[{allRules},
allRules=Join[fit2dParts[[3]],fit2dParts[[6]],fit2dParts[[8]],fit2dParts[[9]],finalfit[[2]]]; (* etaCoeffRules, SCoeffRules, 2dconstraintsNumerator, 2dconstraintsDenominator, finalfitCoeffRules *)
If[ListQ@twodrules&&(Length@twodrules>0),
allRules=Join[allRules,twodrules];
];
Return[allRules];
]
TeXExportTwoDAnsatz[finalfit_,fit2dParts_,twodrules_,formattingRules_,productAnsatz_,constrained_,filename_]:=Module[{ansatzRaw,allRules,zeroRules},
ansatzRaw = GetRawTwoDAnsatz[finalfit,fit2dParts,productAnsatz,constrained];
allRules = GetAllRules[finalfit,fit2dParts,twodrules];
If[Not@productAnsatz,
zeroRules=Table[ToExpression["f"<>ToString@i<>"0"]->0,{i,0,Exponent[Numerator[fit2dParts[[1]]],S]}];
allRules=Join[allRules,zeroRules];
];
TeXExportAnsatz[ansatzRaw,formattingRules,allRules,filename];
]
TeXExportChiDiffTerms[chidiffAnsaetze_,formattingRules_,coeffRules_,filename_]:=Module[{fullTeX,numChiDiffTerms,thisTerm},
fullTeX = "";
numChiDiffTerms = Length@chidiffAnsaetze;
If[numChiDiffTerms>=1,
thisTerm = TeXFormatAnsatz[chidiffAnsaetze[[1]],formattingRules,coeffRules];
fullTeX = "A_1(\\eta)&="<>thisTerm;
];
If[numChiDiffTerms>=2,
thisTerm = TeXFormatAnsatz[chidiffAnsaetze[[2]],formattingRules,coeffRules];
fullTeX = fullTeX<>" \\\\\nA_2(\\eta)&="<>thisTerm;
];
If[numChiDiffTerms>=3,
thisTerm = TeXFormatAnsatz[chidiffAnsaetze[[3]],formattingRules,coeffRules];
fullTeX = fullTeX<>" \\\\\nA_3(\\eta)&="<>thisTerm;
];
Export[filename, fullTeX, "Text"];
]
TeXExportFinalAnsatz[finalfit_,fit2dParts_,twodrules_,chidiffAnsaetze_,formattingRules_,productAnsatz_,twodConstrained_,filename_]:=Module[{ansatzRaw,numChiDiffTerms,allRules},
ansatzRaw = GetRawTwoDAnsatz[finalfit,fit2dParts,productAnsatz,twodConstrained];
numChiDiffTerms = Length@chidiffAnsaetze;
If[numChiDiffTerms>=1,
ansatzRaw = ansatzRaw + chidiffAnsaetze[[1]] (\[Chi]1-\[Chi]2);
];
If[numChiDiffTerms>=2,
ansatzRaw = ansatzRaw + chidiffAnsaetze[[2]] (\[Chi]1-\[Chi]2)^2;
];
If[numChiDiffTerms>=3,
ansatzRaw = ansatzRaw + chidiffAnsaetze[[3]] S (\[Chi]1-\[Chi]2);
];
allRules = GetAllRules[finalfit,fit2dParts,twodrules];
TeXExportAnsatz[ansatzRaw,formattingRules,allRules,filename];
]
TeXExportCoeffTable[coeffRules_,covar_,filename_]:=Module[{coeffNames,coeffErrs,headerLine,coeffTable,texTable},
coeffNames = coeffRules[[All,1]]/.SubscriptRules[coeffRules];
coeffErrs = Sqrt[Diagonal[covar]];
headerLine = {"estimate","std.err.","rel.err.[%]"};
(*
coeffTable = TableForm[Table[{coeffRules[[i,2]],coeffErrs[[i]],Abs[100*coeffErrs[[i]]/coeffRules[[i,2]]]},{i,Length@coeffRules}],TableHeadings\[Rule]{coeffNames,headerLine}];
texTable = StringReplace[ToString[TeXForm[NumberForm[coeffTable,3]]],{"$\\grave{ }$*${}^{\\wedge}$"\[Rule]"}\\cdot10^{"}];
Export[filename,texTable, "Text"];
*)
(*
TeXExportTabularTable[Map[NumberForm[#,3]&,Table[{coeffRules[[i,2]],coeffErrs[[i]],Abs[100*coeffErrs[[i]]/coeffRules[[i,2]]]},{i,Length@coeffRules}],{2}], filename, coeffNames, headerLine]
*)
TeXExportTabularTable[Table[{NumberForm[coeffRules[[i,2]],3],NumberForm[coeffErrs[[i]],3],NumberForm[Abs[100*coeffErrs[[i]]/coeffRules[[i,2]]],{3,1}]},{i,Length@coeffRules}],
filename, coeffNames, headerLine, 0]
]
TeXExportTabularTable[datatable_,filename_,rowLabels_,colHeadings_,padZeroes_]:=Module[{nRows,tableFormatted,texTable,tableAtoms,maxDecDigits},
nRows = Length@datatable;
tableFormatted = TableForm[datatable, TableHeadings->{rowLabels,colHeadings}];
texTable = ToString[TeXForm[tableFormatted]];
texTable = StringReplace[texTable,{"array"->"tabular"}];
texTable = StringReplace[texTable,{"&"->"$&$"}]; (* close and open math mode at each field separator *)
texTable = StringReplace[texTable,{"$&$"->"&$"},1]; (* remove the extra open$ at first separator *)
texTable = StringReplace[texTable,{"$\$&$$"->"\&"},1];(* remove the extra elements when exporting & *)
texTable = StringReplace[texTable,{"\\\\"->"$\\\\"}]; (* close math mode at each line break *)
texTable = StringReplace[texTable,{"\\\\"->"\\\\$"},nRows]; (* reopen math mode after each line break, but only for numrows (not at last one) *)
texTable = StringReplace[texTable,{"\\\\"->"\\\\\\hline"},1]; (* add a horizontal line after the first (headers) line *)
texTable = StringReplace[texTable,{"{tabular}{c"->"{tabular}{l"}]; (* make row-headers column left-centered *)
texTable = StringReplace[texTable,{"cc}"->"cc}\\hline\\hline"}]; (* add initial double line *)
texTable = StringReplace[texTable,{"\\end{tabular}"->"\\hline\\hline\\end{tabular}"}]; (* final double lines at end of table *)
If[padZeroes==1, (* pad trailing zeroes *)
texTable = StringReplace[texTable,{".\\times"->".0\\times"}];
,
If[padZeroes==2,
texTable = StringReplace[texTable,{".\\times"->".00\\times"}];
texTable = StringReplace[texTable,Table["."<>ToString@i<>"\\times"->"."<>ToString@i<>"0\\times",{i,0,9}]];
,
If[padZeroes==3,
texTable = StringReplace[texTable,{".\\times"->".000\\times"}];
texTable = StringReplace[texTable,Table["."<>ToString@i<>"\\times"->"."<>ToString@i<>"00\\times",{i,0,9}]];
texTable = StringReplace[texTable,Flatten[Table[Table["."<>ToString@i<>ToString@j<>"\\times"->"."<>ToString@i<>ToString@j<>"0\\times",{i,0,9}],{j,0,9}]]];
];
];
];
Export[filename, texTable, "Text"];
]
PyExportFinalFit[fit_,extraFormattingRules_,filename_]:=Module[{fitCform,pyRules1,pyRules2,pyRules3,fitPyform},
fitCform = ToString@CForm[fit];
(* formatting hacks: greek letters, powers, Shat (FIXME: not yet variable wrt to effective-spin parameter choice!) *)
pyRules1 = {"\[Eta]"->"eta","\[Chi]"->"chi","Sqrt(2)"->"sqrt2","Sqrt(3)"->"sqrt3"};
pyRules2 = Join[{"(chi1 - chi2)"->"chidiff","Power(chi1 - chi2,2)"->"chidiff2"},
Table["Power(eta,"<>ToString@i<>")"->"eta"<>ToString@i,{i,2,9}],
Table["Power(S,"<>ToString@i<>")"->"S"<>ToString@i,{i,2,9}],
{"Power(1 - 4*eta,0.5)"->"sqrt1m4eta"}];
pyRules3 = {"S"->"Shat","1 "->"1. ","0 "->"0. "};
fitPyform = StringReplace[StringReplace[StringReplace[StringReplace[fitCform,pyRules1],pyRules2],pyRules3],extraFormattingRules];
fitPyform = fitPyform<>"\n";
Export[filename, fitPyform, "Text"];
]
PyExportFinalAnsatz[finalfit_,fit2dParts_,chidiffAnsaetze_,keepfi0_,extraFormattingRules_,filename_]:=Module[{ansatzRaw,numChiDiffTerms,zeroRules,ansatzCform,
pyRules1,pyRules2,pyRules3,ansatzPyform,sqrti,sqrtRules,fracs,fracStrings,fracReals,fracRules,twodConstrained},
twodConstrained = True;
ansatzRaw = GetRawTwoDAnsatz[finalfit,fit2dParts,productAnsatz,twodConstrained];
numChiDiffTerms = Length@chidiffAnsaetze;
If[numChiDiffTerms>=1,
ansatzRaw = ansatzRaw + chidiffAnsaetze[[1]] (\[Chi]1-\[Chi]2);
];
If[numChiDiffTerms>=2,
ansatzRaw = ansatzRaw + chidiffAnsaetze[[2]] (\[Chi]1-\[Chi]2)^2;
];
If[numChiDiffTerms>=3,
ansatzRaw = ansatzRaw + chidiffAnsaetze[[3]] S (\[Chi]1-\[Chi]2);
];
If[Not@keepfi0,
zeroRules = Table[ToExpression["f"<>ToString@i<>"0"]->0,{i,0,Exponent[Numerator[fit2dParts[[1]]],S]}];
ansatzRaw = ansatzRaw/.zeroRules;
];
(* hack to avoid rounding of square-roots *)
sqrti = {2,3,5,6,7};
sqrtRules = Table[Sqrt[sqrti[[i]]]->ToExpression["sqrt"<>ToString@sqrti[[i]]<>""],{i,Length@sqrti}];
(* hack to avoid rounding of fractions, first part: replace by named string before ToString@CForm[SetPrecision[...]] *)
fracs = {1/3,2/3,4/3,5/3};
fracs = Join[fracs,-fracs];
fracStrings = Table[ToExpression["frac"<>StringReplace[ToString@Numerator@fracs[[i]],{"-"->"m"}]<>ToString@Denominator@fracs[[i]]],{i,Length@fracs}];
fracRules = Table[fracs[[i]]->fracStrings[[i]],{i,Length@fracs}];
ansatzCform = ToString@CForm[SetPrecision[ansatzRaw/.sqrtRules/.fracRules,3]];
(* hack to avoid rounding of fractions, second part: replace named string back to real number fractions *)
fracReals = Table[ToString@SetPrecision[Numerator@fracs[[i]],2]<>"/"<>ToString@SetPrecision[Denominator@fracs[[i]],2],{i,Length@fracs}];
fracRules = Table[ToString@fracStrings[[i]]->fracReals[[i]],{i,Length@fracs}];
ansatzCform = StringReplace[ansatzCform,fracRules];
(* more formatting hacks: greek letters, powers, Shat (FIXME: not yet variable wrt to effective-spin parameter choice!) *)
pyRules1 = {"\[Eta]"->"eta","\[Chi]"->"chi"};
pyRules2 = Join[{"(chi1 - 1.*chi2)"->"chidiff","Power(chi1 - 1.*chi2,2)"->"chidiff2"},
Table["Power(eta,"<>ToString@i<>")"->"eta"<>ToString@i,{i,2,9}],
Table["Power(S,"<>ToString@i<>")"->"S"<>ToString@i,{i,2,9}],
{"Power(1. - 4.*eta,0.5)"->"sqrt1m4eta"},{"Sqrt(1. - 4.*eta)"->"sqrt1m4eta"}];
pyRules3 = {"S"->"Shat"};
ansatzPyform = StringReplace[StringReplace[StringReplace[StringReplace[ansatzCform,pyRules1],pyRules2],pyRules3],extraFormattingRules];
ansatzPyform = ansatzPyform<>"\n";
Export[filename, ansatzPyform, "Text"];
]
PyExportFinalFitCoeffs[finalfit_,fit2dParts_,all2dconstraints_,filename_]:=Module[{pyCoeffsList,pyCoeffsString},
pyCoeffsList = Join[Table[ToString@fit2dParts[[3,i,1]]<>" = "<>ToString@CForm@fit2dParts[[3,i,2]],{i,Length@fit2dParts[[3]]}],
Table[ToString@fit2dParts[[6,i,1]]<>" = "<>ToString@CForm@fit2dParts[[6,i,2]],{i,Length@fit2dParts[[6]]}],
Table[ToString@all2dconstraints[[i,1]]<>" = "<>ToString@CForm[all2dconstraints[[i,2]]/.{1->1.,0->0.}],{i,Length@all2dconstraints}],
(*{ToString@\[Eta]0derconstv3[[1,1]]<>" = "<>ToString@CForm[\[Eta]0derconstv3[[1,2]]]}, *)
Table[ToString@finalfit[[2,i,1]]<>" = "<>ToString@CForm@finalfit[[2,i,2]],{i,Length@finalfit[[2]]}]
];
pyCoeffsString = "";
For[i=1, i <= Length@pyCoeffsList, i++,
pyCoeffsString = pyCoeffsString<>" "<>pyCoeffsList[[i]]<>"\n"];
Export[filename, pyCoeffsString, "Text"];
]
SupplExportAllFitCoeffs[finalfit_,fit2dParts_,all2dconstraints_,eta0covar_,filename_]:=Module[{coeffsList,coeffsString,stdErrsEta,stdErrsS,stdErrs2D,stdErrsFinal},
stdErrsEta = Sqrt[Diagonal[fit2dParts[[4]]]];
stdErrsS = Sqrt[Diagonal[fit2dParts[[7]]]];
stdErrs2D = Join[Sqrt[Diagonal[eta0covar]],ConstantArray[0.0,Length[all2dconstraints]-Length[eta0covar]]];
stdErrsFinal = Sqrt[Diagonal[finalfit[[14]]]];
coeffsList = Join[Table[ToString@fit2dParts[[3,i,1]]<>" "<>ToString@CForm@fit2dParts[[3,i,2]]<>" "<>ToString@CForm@stdErrsEta[[i]],{i,Length@fit2dParts[[3]]}],
Table[ToString@fit2dParts[[6,i,1]]<>" "<>ToString@CForm@fit2dParts[[6,i,2]]<>" "<>ToString@CForm@stdErrsS[[i]],{i,Length@fit2dParts[[6]]}],
Table[ToString@all2dconstraints[[i,1]]<>" "<>ToString@CForm[all2dconstraints[[i,2]]/.{1->1.,0->0.}]<>" "<>ToString@CForm@stdErrs2D[[i]],{i,Length@all2dconstraints}],
(*{ToString@\[Eta]0derconstv3[[1,1]]<>" "<>ToString@CForm[\[Eta]0derconstv3[[1,2]]]}, *)
Table[ToString@finalfit[[2,i,1]]<>" "<>ToString@CForm@finalfit[[2,i,2]]<>" "<>ToString@CForm@stdErrsFinal[[i]],{i,Length@finalfit[[2]]}]
];
coeffsString = "# coeff estimate stderr\n";
For[i=1, i <= Length@coeffsList, i++,
coeffsString = coeffsString<>coeffsList[[i]]<>"\n"];
coeffsString = StringReplace[coeffsString,{". "->".0 ",".\n"->".0\n"}];
Export[filename, coeffsString, "Text"];
]
SupplExportCovarMatrix[covar_,coeffRules_,fileName_]:=Module[{coeffNames,fullMatrix,covarString},
coeffNames = coeffRules[[All,1]];
covarString = "# coeffs:";
For[i=1, i <= Length@coeffRules, i++,
covarString = covarString<>" "<>ToString@coeffRules[[i,1]];
];
covarString = covarString<>"\n";
For[i=1, i <= Length@covar, i++,
For[j=1, j <= Length@covar, j++,
covarString = covarString<>" "<>ToString@NumberForm[covar[[i,j]], {16, 16}, ExponentFunction -> (If[-10 < # < 10, Null, #] &)];
];
covarString = covarString<>"\n";
];
Export[fileName, covarString, "Text"];
]
Options[AIC]={"Weights"->False};
AIC[data_,fit_,fitvars_,OptionsPattern[]]:=Module[{bracketedvars,coeff,datapnts,err,n,res,ress,weigths},
n=Length@data;
coeff=Length@fitvars;
weigths=OptionValue["Weights"];
If[weigths,err=data[[All,-1]];datapnts=data[[All,-2]];,err=1;datapnts=data[[All,-1]];];
res=Table[data[[i,-2]]-(fit/.Table[fitvars[[j]]->data[[i,j]],{j,Length@fitvars}]),{i,Length@data}];
ress=Total[err (res)^2];
n + n Log[2\[Pi]]+n Log[ress/n]+2(coeff+1)
]
Options[AICc]=Options[AIC];
AICc[data_,fit_,fitvars_,OptionsPattern[]]:=Module[{coeff,n,res,newfit,bracketedvars,ress,weigths},
weigths=OptionValue["Weights"];
n=Length@data;
coeff=Length@fitvars;
AIC[data,fit,fitvars,"Weights"->weigths]+(2*coeff(coeff+1) )/(n - coeff -1)
]
BIC[data_,fit_,fitvars_,coeff_]:=Module[{n,res,newfit,bracketedvars,ress},
n=Length@data;
bracketedvars=StringReplace[StringReplace[ToString@fitvars,"{"->"["],"}"->"]"];
newfit=ToExpression[ToString@fit<>bracketedvars];
res=Table[data[[i,-2]]-(newfit/.Table[fitvars[[j]]->data[[i,j]],{j,Length@fitvars}]),{i,Length@data}];
ress=Total[data[[All,-1]](res)^2];
n + n Log[2\[Pi]]+n Log[ress/n]+Log[n](coeff+1)
]
Residuals[data_,fit_,vars_,OptionsPattern[{"Verbose"->False,"Relative"->False}]]:=Module[{datvals,relative,fitvals,res,verbose},
verbose=OptionValue["Verbose"];
relative=OptionValue["Relative"];
If[verbose,Print["variables -> ",vars]];
datvals=TakeColumn[data,-1];
fitvals=fit/.Table[(vars[[j]]->data[[All,j]]),{j,Length@vars}];
If[relative,res=1-fitvals/datvals,res=datvals-fitvals]
]
KullbagLeiblerDiv[p1_?ListQ,p2_?ListQ]:=Module[{fun},
fun=1.Function[{p,q},Limit[p*Log[(p+\[Epsilon])/(q+\[Epsilon])],\[Epsilon]->0]][p2,p1];
Total[fun]
]
KL[data1_,data2_,lim_]:=Module[{n,res},
n=Length@data1;
NIntegrate[PDF[data1,x] Log[PDF[data1,x]/PDF[data2,x]], {x,-lim,lim}]
]
JensenShanonDiv[p1_?ListQ,p2_?ListQ]:=Module[{m,fun},
m=0.5 (p1+p2);
fun=Function[{p,q,m},Limit[p*Log[(p+\[Epsilon])/(m+\[Epsilon])]+ q*Log[(q+ \[Epsilon])/(m+\[Epsilon])],\[Epsilon]->0]][p1,p2,m];
Total[fun]
]
JS[data1_,data2_,lim_]:=Module[{n,res},
n=Length@data1;
1/2 NIntegrate[PDF[data1,x] Log[PDF[data1,x]/(PDF[data2,x]+ PDF[data1,x])], {x,-lim,lim}] + 1/2 NIntegrate[PDF[data2,x] Log[PDF[data2,x]/(PDF[data2,x]+PDF[data1,x])] , {x,-lim,lim}]
]
ComputeEdges[pts_]:=Module[{ptsx,auxvar,auxvar2,nears,i},
ptsx=SortBy[pts,First];
auxvar={};
i=1;
AppendTo[auxvar,{ptsx[[i]]}];
While[i<= Length@ptsx-1,
If[ptsx[[i+1,1]]==ptsx[[i,1]],i=i+1,AppendTo[auxvar,{ptsx[[i]]}];i=i+1]
];
AppendTo[auxvar,{ptsx[[i]]}];
auxvar=Flatten[auxvar,1];
i=Length@ptsx-1;
While[i> 1,
If[ptsx[[i+1,1]]==ptsx[[i,1]],i=i-1,AppendTo[auxvar,ptsx[[i+1]]];i=i-1]
];
AppendTo[auxvar,ptsx[[i]]];
Do[auxvar=AppendTo[auxvar,0.5auxvar[[1]]+0.5auxvar[[-1]]],{i,3}];
auxvar
]
CredibleRegion[data_,level_]:=Module[{datasrt,prob,cumprob,pbound},
(* Last column must be the PDF *)
datasrt=SortBy[data,Last];
prob=TakeColumn[datasrt,-1];
cumprob=Accumulate[prob]/Total[prob];
pbound=Quiet@Position[cumprob,_?(#>= (1-level) cumprob[[-1]]& ),1][[1,1]];
ComputeEdges[datasrt[[pbound-1;;-1]]][[All,1;;-2]]
]
CredibleInterval[data_,level_]:=Module[{datasrt,prob,cumprob,pbound},
(* Last column must be the PDF *)
datasrt=SortBy[data,Last];
prob=TakeColumn[datasrt,-1];
cumprob=Accumulate[prob]/Total[prob];
pbound=Quiet@Position[cumprob,_?(#>= (1-level) cumprob[[-1]]& ),1][[1,1]];
datasrt[[pbound;;-1]]
]
Generate1DPolynomialAnsatz[CoefficientPrefixString_?StringQ,variable_,MinOrder_?IntegerQ,MaxOrder_?IntegerQ]:=Module[{ansatz,i,j},
ansatz = Total/@Table[ToExpression[CoefficientPrefixString<>ToString@i] * variable^i,{j,MinOrder,MaxOrder},{i,0,j}];
Transpose[{ansatz,Table[{variable},{i,Length@ansatz}]}]
]
CleanAnsatzParams[paramsGuess_, vars_]:=Module[{pos,params,varsStr,paramsStr,tmp},
params = DeleteDuplicates@Flatten@paramsGuess;
tmp=Select[params, Not@NumberQ@#& ];
varsStr = ToString/@vars;
paramsStr= ToString/@tmp;
(* Clean the variables from the parameters and identify variables *)
pos = Flatten[Position[paramsStr,#]&/@varsStr,1];
params=Delete[tmp,pos];
params
];
(* ::Code::Initialization:: *)
Options[DataFitFunction]={
"FitAll" -> True,
"AxesTag" -> "Amplitude",
"Verbose" -> 1,
"StatisticalTest" -> "AIC",
"Sorted" -> True,
"Weights" -> {},
"PlotRange" -> All,
"ToolTipTags" -> "",
"Domain" -> {0,1},
"GetIntervals" -> False
};
DataFitFunction[dataRAW_?ListQ,ansatzList_?ListQ,OptionsPattern[]]:=Module[{ansatz,ansatzaparams,ansatzvars,cleartrue,fit,stats,verbose,
ansatzparamsStr,ansatzvarsStr,outparams,fittab,plot1,plot2,datasorted,plotdomain,myvar,plotdomain1,axestag,aic,aicc,bic,rsquared,rmse,
statisticaltest,stattoplot,sortfield,residuals,minexp,maxexp,minexp2,maxexp2,sorted,paramerrors,residualsplot,weights,plotrange,print,
ansatzaparamsGuess,paramTStat,overview,data,dimWeights,tooltiptags,inner,confidenceinttable,userPlotDomain,vcov,
estvar,confbands,predbands,getintervals,loglikelihood},
verbose = OptionValue["Verbose"];
axestag = OptionValue["AxesTag"];
statisticaltest = OptionValue["StatisticalTest"];
sorted = OptionValue["Sorted"];
weights = OptionValue["Weights"];
plotrange = OptionValue["PlotRange"];
tooltiptags = OptionValue["ToolTipTags"];
userPlotDomain = OptionValue["Domain"];
getintervals = OptionValue["GetIntervals"];
If[TrueQ@weights,
dimWeights = Last@Dimensions@dataRAW;
weights = TakeColumn[dataRAW,dimWeights];
data = TakeColumn[dataRAW, Range[dimWeights-1]],
data = dataRAW[[All,1;;Length@dataRAW[[1]]]];
If[verbose,Print["Raw data with no weights on the lists!"]];
];
If[verbose>=2,
print[x___]:=Print[x],
print[x___]:={}
];
ansatz = Chop/@ (ansatzList[[All,1]]);
ansatzvars = ansatzList[[All,2]];
ansatzaparamsGuess = N/@AtomsList/@ansatz;
ansatzaparams = Table[CleanAnsatzParams[ansatzaparamsGuess[[i]], ansatzvars[[i]]],{i,Length@ansatzvars}];
(*
print["Ans\[ADoubleDot]tze -> ", ansatz//TableForm];
print["#\[NonBreakingSpace]data points -> ", Length@data];
print["#\[NonBreakingSpace]data points -> ", Length@Union[data, SameTest->(Abs[#1[[1]]-#2[[1]]] < 0.01 &)], " identifying x-values deviating < 0.01"];
*)
(*Print["Weights: ", If[Length@weights>0,weights,Automatic]];*)
fittab=Table[
If[Length@ansatzaparams[[i]]>=1,
fit = NonlinearModelFit[data,ansatz[[i]],ansatzaparams[[i]],ansatzvars[[i]],MaxIterations->1000,Weights->If[Length@weights>0,weights,Automatic]];
outparams = fit["BestFitParameters"];
stats = fit["ParameterTable"];
paramerrors = fit["ParameterErrors"];
paramTStat = fit["ParameterTStatistics"];
residuals = fit["FitResiduals"];
aic = fit["AIC"];
aicc = aic + (2*Length@outparams(Length@outparams+1) )/(Length@data - Length@outparams -1);
bic = fit["BIC"];
rsquared = fit["RSquared"];
rmse = Sqrt@Mean[residuals^2];
confidenceinttable = fit["ParameterConfidenceIntervalTable"];
vcov = fit["CovarianceMatrix"];
estvar = fit["EstimatedVariance"];
If[getintervals,
confbands = fit["MeanPredictionBands",ConfidenceLevel->0.9];
predbands = fit["SinglePredictionBands",ConfidenceLevel->0.9];
,
confbands = {};
predbands = {};
];
(* 1 2 3 4 5 6 7 8 9 *)
{Normal@fit, outparams, stats, aic, aicc, bic, rsquared, ScientificForm@rmse, paramerrors,
(* 10 11 12 13 14 15 *)
Sort[CombineColumns[ansatzaparams[[i]],paramTStat],Abs@#1[[2]]<Abs@#2[[2]]&], Length@ansatzaparams[[i]], rmse, confidenceinttable, vcov, ansatz[[i]],
(* 16 17 18 19 *)
estvar, confbands, predbands, residuals },
{ansatz[[i]],"dummy","dummy","dummy","dummy","dummy","dummy","dummy","dummy","dummy"}]
,{i,Length@ansatzList}];
Which[statisticaltest=="AIC",
stattoplot=aic;
sortfield=4;
,
statisticaltest=="AICc",
stattoplot=aicc;
sortfield=5;
,
statisticaltest=="BIC",
stattoplot=bic;
sortfield=6;
,
statisticaltest=="RSquared",
stattoplot=rsquared;
sortfield=7;
,
statisticaltest=="RMSE",
stattoplot=rmse;
sortfield=12;
];
If[sorted, fittab = SortBy[fittab,#[[sortfield]]& ]];
overview = TakeColumn[fittab,{1,11,7,8,5,6,3}]; (* fit eqn, numParams, Rsquared, RSME, AICc, BIC, coefficient table *)
residuals = fittab[[All,19]];
(*
resVSaic = TakeColumn[fittab, {4,7}];
resVSaicc = TakeColumn[fittab, {5,7}];
resVSbic = TakeColumn[fittab, {6,7}];
Print[ListLogPlot[{resVSaic,resVSaicc,resVSbic},PlotRange\[Rule]All,PlotStyle\[Rule]{Red,Blue,Green},PlotLegends\[Rule] {"AIC","AICc","BIC"},
Frame\[Rule] True,FrameLabel\[Rule] {"*IC*","RMSE"}]];
*)
If[verbose>=1,
Print[overview//TableForm];
];
If[verbose>=2,
Which[Length@ansatzvars[[1]]==1,
(* {minexp,maxexp}={Min[Exponent[#,ansatzvars]&/@ansatz],Max[Exponent[#,ansatzvars]&/@ansatz]}; *)
{minexp,maxexp}={Min[Table[Length[fittab[[i,2]]],{i,Length@ansatzList}]],Max[Table[Length[fittab[[i,2]]],{i,Length@ansatzList}]]};
datasorted=SortBy[data,First];
plotdomain={Min[First@First@datasorted,First@userPlotDomain],Max[First@Last@datasorted,Last@userPlotDomain]};
(*plot1=Plot[Evaluate[Table[fittab[[i,1]]/.ansatzvars[[i,1]]\[Rule]x,{i,Length@ansatzList}]],{x,First@plotdomain,Last@plotdomain},
Epilog\[Rule]{Point[Table[Tooltip[#,If[ListQ@tooltiptags,tooltiptags[[i]],ToString[data[[i]]]]],{i,Length@data}]&/@data]},
PlotRange\[Rule]plotrange,Frame\[Rule]True,PlotStyle\[Rule]Red,FrameLabel\[Rule]{Style[ToString@ansatzvars[[1,1]],14],Style["f("<>ToString@ansatzvars[[1,1]]<>")",14]}];*)
plot1=Plot[Evaluate[Table[fittab[[i,1]]/.ansatzvars[[i,1]]->x,{i,Length@ansatzList}]],{x,First@plotdomain,Last@plotdomain},PlotLegends->Evaluate[Table[fittab[[i,1]],{i,Length@ansatzList}]]];
plot2=ListPlot[Table[Tooltip[data[[i]],If[ListQ@tooltiptags,tooltiptags[[i]],ToString[data[[i]]]]],{i,Length@data}], PlotStyle->Red];
stattoplot=Transpose[{Table[Length[fittab[[i,2]]],{i,Length@ansatzList}],TakeColumn[fittab,sortfield]}];
inner=(Inner[List,data[[All,1]],#,List]&/@residuals);
Print@{Show[plot1, plot2, ImageSize->450, Frame->True, FrameLabel->{Style[ToString@ansatzvars[[1,1]],14],Style["f("<>ToString@ansatzvars[[1,1]]<>")",14]}],
ListPlot[Partition[stattoplot,1],Frame->True,FrameLabel->{Style["\!\(\*SubscriptBox[\(N\), \(coeff\)]\)",14],Style[statisticaltest,14]},ImageSize->450,PlotRange->{{minexp-1,maxexp+1},All},
PlotLegends->Table[fittab[[i,1]],{i,Length@ansatzList}]],
ListPlot[Table[Tooltip[#[[i]],If[ListQ@tooltiptags,tooltiptags[[i]],ToString[data[[i]]]]],{i,Length@data}]&/@inner,PlotRange->{plotdomain,All},
ImageSize->450,Frame->True,FrameLabel->{Style[ToString@ansatzvars[[1,1]],14],Style["data-fit",14]}]
};
,
Length@ansatzvars[[1]]==2,
(*
{minexp,maxexp} ={Min[Exponent[#,ansatzvars[[1,1]]]&/@ansatz],Max[Exponent[#,ansatzvars[[1,1]]]&/@ansatz]};
{minexp2,maxexp2}={Min[Exponent[#,ansatzvars[[1,2]]]&/@ansatz],Max[Exponent[#,ansatzvars[[1,2]]]&/@ansatz]};
*)
plot2=ListPointPlot3D[data,PlotRange->plotrange,PlotStyle->PointSize[0.02],PlotLegends->{"data"}];
plot1=Plot3D[Evaluate[Table[fittab[[i,1]]/.ansatzvars[[i,1]]->x/.ansatzvars[[1,2]]->y,{i,Length@ansatzList}]],
{x,First@First@userPlotDomain,Last@First@userPlotDomain}, {y,First@Last@userPlotDomain,Last@Last@userPlotDomain}, PlotRange->plotrange,
AxesLabel->{Style[ToString@ansatzvars[[1,1]],14],Style[ToString@ansatzvars[[1,2]],14],Style["f("<>ToString@ansatzvars[[1,1]]<>","<>ToString@ansatzvars[[1,2]]<>")",14]},
PlotLegends->(*Evaluate[Table[fittab[[i,1]],{i,Length@ansatzList}]]*)Table["Ansatz "<>ToString[i],{i,Length@ansatzList}]];
stattoplot=Table[{Exponent[fittab[[i,1]], ansatzvars[[i,1]]],Exponent[fittab[[i,1]], ansatzvars[[i,2]]],fittab[[i,4]]},{i,Length@ansatzList}];
residualsplot=Table[Transpose[{data[[All,1]],data[[All,2]],residuals[[i]]}],{i,Length@ansatzList}];
Print@{Show[plot1,plot2,ImageSize->450],
(* ListPointPlot3D[stattoplot,PlotStyle\[Rule]Red,AxesLabel\[Rule]{"order "<>ToString@ansatzvars[[1,1]],"order "<>ToString@ansatzvars[[1,2]],statisticaltest},ImageSize\[Rule]450,PlotRange\[Rule]{{minexp-0.2,maxexp+0.2},{minexp2-0.2,maxexp2+0.2},Automatic}],*)
(*myListPlot3D[residualsplot,AxesLabel\[Rule]{Style[ToString@ansatzvars[[1,1]],14],Style[ToString@ansatzvars[[1,2]],14],""},PlotLabel->Style["Residuals",14],ImageSize\[Rule]450],*)
myListPlot3D[residualsplot,AxesLabel->{Style[ToString@ansatzvars[[1,1]],14],Style[ToString@ansatzvars[[1,2]],14],Style["data-fit",14]},ImageSize->450,PlotRange->plotrange]};
Print[];
,True,
Print["More than 2 variables can not be plotted :) "];
];
];
Return[fittab];
]
Options[DataFitFunctionAll]={
"NSFitindex" -> 1, (* which fit to pick *)
"q1Fitindex" -> 1,
"FitCase" -> 1, (* 1: 1D fits, 2: 1D+2D fits, return 2D only: 3: 1D+2D fits, return both; 4: 1D+2D+3D fits, return only 2D+3D; 5: 1D+2D+3D fits, return all, but with reduced verbosity *)
"MassRatioUnequalFits" -> {1,1.5,2.,3.,4.,8.,18.},
"NonSpinningAnsatzList" -> {{a1 \[Eta]+a2 \[Eta]^2+a3 \[Eta]^3,{\[Eta]}},{a1 \[Eta]+a2 \[Eta]^2+a3 \[Eta]^3+a4 \[Eta]^4,{\[Eta]}},{a1 \[Eta]+a2 \[Eta]^2+a3 \[Eta]^3+a4 \[Eta]^4+a5 \[Eta]^5,{\[Eta]}}},
"EqualBHAnsatzList" -> {{b1 S+b2 S^2+b3 S^3,{S}},{b1 S+b2 S^2+b3 S^3+b4 S^4,{S}},{b1 S+b2 S^2+b3 S^3+b4 S^4+b5 S^5,{S}},{b1 S+b2 S^2+b3 S^3+b4 S^4+b5 S^5+b6 S^6,{S}},{b1 S+b2 S^2+b3 S^3+b4 S^4+b5 S^5+b6 S^6+b7 S^7,{S}},
{b1 S+b2 S^2+b3 S^3+b4 S^4+b5 S^5+b6 S^6+b7 S^7+b8 S^8,{S}}},
"Addq1Ansatz" -> {},
"AddNSAnsatz" -> {},
"AddGenAnsatz" -> {},
"StatisticalTest" -> "BIC",
"AnsatzTestCombinations" -> {{1},{1}},
"PlotRange" -> All,
"RationalFunctions" -> True,
"ProductAnsatz" -> False,
"GeneralAnsatzRules" -> {},
"ToolTipTags" -> "",
"ProductGeneralizeOrder" -> 2,
"ProductGeneralizeOrderDenom" -> -1,
"ProductGeneralizeMinPowerNum" -> -1,
"TwoDSpinAnsatzOrderNum" -> -1,
"TwoDSpinAnsatzOrderDenom" -> -1,
"SpinDiffWeights" -> True,
"Weights" -> True,
"AddSpinDiffLinAnsatz" -> {},
"AddSpinDiffQuadAnsatz" -> {},
"AddSpinDiffMixAnsatz" -> {},
"SpinDifferenceRules" -> {},
"\[Eta]LimitEqualSpin" -> 0,
"GetIntervals" -> False,
"SpinParameter" -> sTot3,
"SpinDiffParameter" -> \[Chi]diffstan(*(\[Chi]1-\[Chi]2)*),
"FastAnalysis" -> False,
"Addf00ToAnsatz" -> False
};
DataFitFunctionAll[data_?ListQ,OptionsPattern[]]:=Module[{datans,nsfits,nsansatz,ansatzvars,dataq1,dataq1sorted,ansatzq1,nsfitindex,q1fit,ansatz,nsfit,sys,solNS,coeffs,ansatzS,solq1,ansatzFinal,
ansatzFinal\[Delta]\[Chi],allData,fitEq,allDataEqS,dataeqs,my\[Eta],myd\[Eta],dataq1Sym,pos,massratioplots,myfit,tabfits,uneqfits,massratiounequalfits,
uneqfit2,uneqfit,uneqfit3,q1fitopt,q1fitindex,expans,expns,mydq,thisq,oneDverbosity,perqVerbosity,
ansatzFinal\[Delta]\[Chi]1,ansatzFinal\[Delta]\[Chi]2,lplot,lqplotl,lqplotq,lmplotl,lmplotm,lmqplotl,lmqplotm,lmqplotq,
addnsansatz,addq1ansatz,\[Eta]sfit,statisticaltest,nsdegree,q1degree,addgenansatz,genansatzindex,ansatzchidifflinear,ansatzchidiffquadratic,plot1,plot2,plot3,plot4,plot4a,plot4b,plot4mirror,
testansatzcomb,myfit2,q1fits,ansatzAll,fitcase,alldataeqfit,alldataeqfitv2,eqdatafit,linearpar,linearparerr,linearpar2,linearpar2err,quadpar,quadparerr,
linearfit1,quadfit,ansatz\[Eta]1,ansatz\[Eta]2,linearfit2,plotrange,uneqredunfit,uneqredunfit2,ansatzFinalS\[Delta]\[Chi],spindiffterm,
spindiffterm2,ansatz\[Eta]3,ansatz\[Eta]4,spindiffterm21,spindiffterm22,generalAnsatzRules,weights,num,denom,zeroRules,spinAnsatz,q1fitS0,fitabc,tooltiptags,dataq1tag,mysel,dataq1pos,tooltiptagsaux,
\[Eta]0Ansatz,spinpart,spindifferencerules,spindiffweights,datauneqs,dataeqs2,addspindifflinansatz,addspindiffquadansatz,addspindiffmixansatz,ansatzchidiffmix,
tooltiptagsns,tooltiptagseq,dataq1mixterm,myfitmixterm,linearpar3,linearpar3err,mixpar,mixparerr,linearfit3,mixfit,spindiffterm31,spindiffterm32,ansatzS\[Delta]\[Chi]raw,ansatzFinalS\[Delta]\[Chi]\[Chi]2,
ansatzS\[Delta]\[Chi]\[Chi]2raw,myfitmixquadterm,dataq1mixquadterm,linearpar4err,linearpar4,linearfit4,mixparerr2,mixpar2,quadparerr2,quadpar2,mixfit2,quadfit2,spindiffterm41,spindiffterm42,
spindiffterm43,unphysical,numRestrictions,denomRestrictions,extraStuff,ansatzRaw,spinAnsatzRaw,etaAnsatz,etaCoeffRules,etaCovar,SAnsatz,SCoeffRules,SCovar,getintervals,data\[Eta]S\[Chi]diff,
spinparameter,avgerrperq,avgwgthperq,extrawght,dataeqsunmass,allDataEqSv2,eqdatafitv2,dataunconstr,allDataUnconstr,spindiffparameter,
productAnsatz,productGeneralizeOrderNum,productGeneralizeOrderDenom,productGeneralizeMinPowerNum,twoDSpinAnsatzOrderNum,twoDSpinAnsatzOrderDenom,
q1fitS0orderNum,q1fitS0orderDenom,spinAnsatzToGeneralize,spinAnsatzNum,spinAnsatzDenom,q1AnsatzRaw,q1AnsatzRawS0,spinAnsatzRawNum,spinAnsatzRawDenom,spinAnsatzRawToGeneralize,
dfitspindiffterm,dfitspindiffterm21,dfitspindiffterm22,dfitspindiffterm31,dfitspindiffterm32,dfitspindiffterm41,dfitspindiffterm42,dfitspindiffterm43,fastanalysis,plot3a,dataq1a},
(* Input field "data" is expected in the form {\[Eta], \[Chi]1, \[Chi]2, value}, convention: m1 \[GreaterEqual] m2 !!!!CHECK!!!! *)
nsfitindex = OptionValue["NSFitindex"];
q1fitindex = OptionValue["q1Fitindex"];
addnsansatz = OptionValue["AddNSAnsatz"];
addq1ansatz = OptionValue["Addq1Ansatz"];
fitcase = OptionValue["FitCase"];
statisticaltest= OptionValue["StatisticalTest"];
addgenansatz = OptionValue["AddGenAnsatz"];
testansatzcomb = OptionValue["AnsatzTestCombinations"];
plotrange = OptionValue["PlotRange"];
generalAnsatzRules = OptionValue["GeneralAnsatzRules"];
tooltiptags=OptionValue["ToolTipTags"];
spindifferencerules=OptionValue["SpinDifferenceRules"];
spindiffweights=OptionValue["SpinDiffWeights"];
weights=OptionValue["Weights"];
massratiounequalfits=\[Eta]q[OptionValue["MassRatioUnequalFits"]];
addf00toansatz=OptionValue["Addf00ToAnsatz"];
addspindifflinansatz=OptionValue["AddSpinDiffLinAnsatz"];
addspindiffquadansatz=OptionValue["AddSpinDiffQuadAnsatz"];
addspindiffmixansatz=OptionValue["AddSpinDiffMixAnsatz"];
getintervals=OptionValue["GetIntervals"];
spinparameter=OptionValue["SpinParameter"];
spindiffparameter=OptionValue["SpinDiffParameter"];
productAnsatz = OptionValue["ProductAnsatz"];
productGeneralizeOrderNum = OptionValue["ProductGeneralizeOrder"];
productGeneralizeOrderDenom = OptionValue["ProductGeneralizeOrderDenom"];
productGeneralizeMinPowerNum = OptionValue["ProductGeneralizeMinPowerNum"];
If[productGeneralizeOrderDenom<0, productGeneralizeOrderDenom = productGeneralizeOrderNum;];
If[productGeneralizeMinPowerNum<0, productGeneralizeMinPowerNum = If[productAnsatz,0,1];]; (* by default, set the fi0 terms to zero in a sum ansatz, but keep them in a product ansatz; can be user-overriden *)
twoDSpinAnsatzOrderNum = OptionValue["TwoDSpinAnsatzOrderNum"];
twoDSpinAnsatzOrderDenom = OptionValue["TwoDSpinAnsatzOrderDenom"];
fastanalysis = OptionValue["FastAnalysis"];
nsansatz = OptionValue["NonSpinningAnsatzList"];
If[Length@addnsansatz>0,Do[nsansatz=Append[nsansatz,addnsansatz[[i]]];,{i,Length@addnsansatz}]];
unphysical = Select[data,#1[[1]] > 0.25 &];
Print["data points with \[Eta] > 0.25: ", unphysical];
datans = Select[data, #1[[2]]^2+#1[[3]]^2 < 0.01 &]; (* zero spin, for 1d fit *)
dataeqs = Select[data, (Abs[#1[[2]]-#1[[3]]] < 0.01)||(#1[[1]]< OptionValue["\[Eta]LimitEqualSpin"]) &]; (* all equal spins, including zero *)
datauneqs = Complement[data,dataeqs]; (* all unequal spins *)
dataq1 = Select[dataeqs, (Abs[#1[[1]]-0.25] < 0.0001) && (#1[[2]]^2+#1[[3]]^2 >= 0.01) &]; (* equal nonzero spins, equal mass, for 1d fit *)
dataeqsunmass = Select[dataeqs, (Abs[#1[[1]]-0.25] > 0.0001) && (#1[[2]]^2+#1[[3]]^2 >= 0.01) &]; (* equal nonzero spins, unequal mass, for 2d fit *)
dataunconstr = Complement[data,Join[datans,dataq1]]; (* not 1D constrained: unequal-spin equal-mass or nonzero-spin unequal-mass, for 3d fit *)
If[ListQ@tooltiptags,
pos = Flatten[Position[data,#]&/@datans];
tooltiptagsns = tooltiptags[[pos]];
];
Print["#\[NonBreakingSpace]of data points: ", Length@data];
Print["#\[NonBreakingSpace]of non-spinning data points: ", Length@datans];
Print["#\[NonBreakingSpace]of equal-spin equal-mass data points: ", Length@dataq1];
Print["#\[NonBreakingSpace]of equal-spin unequal-mass data points: ", Length@dataeqsunmass];
Print["#\[NonBreakingSpace]of unequal-spin data points: ", Length@datauneqs];
Print["# of non-zero-spin unequal-mass data points: ", Length@dataunconstr];
Print["Sums of subspaces: S=0 + q=1 + equal-spin + unequal-spin cases: ", Length@datans + Length@dataq1 + Length@dataeqsunmass + Length@datauneqs];
Print[" S=0 + q=1 + others: ", Length@datans + Length@dataq1 + Length@dataunconstr];
Print["Eff. spin parameter: ",spinparameter];
Print["Spin-diff parameter: ",spindiffparameter];
(*
Print["Rules for General Anzatze : ", generalAnsatzRules];
Print["Rules for Spin Difference Anzatze : ", spindifferencerules];
*)
allData = TakeColumn[data, {1,2,3,4,5}]/. {\[Eta]\[Eta]_,c1_,c2_,res_,ww_}->{\[Eta]\[Eta],spinparameter[\[Eta]\[Eta],c1,c2],res,ww};
allDataEqS = TakeColumn[dataeqs, {1,2,3,4,5}]/. {\[Eta]\[Eta]_,c1_,c2_,res_,ww_}->{\[Eta]\[Eta],spinparameter[\[Eta]\[Eta],c1,c2],res,ww};
allDataEqSv2 = TakeColumn[dataeqsunmass, {1,2,3,4,5}]/. {\[Eta]\[Eta]_,c1_,c2_,res_,ww_}->{\[Eta]\[Eta],spinparameter[\[Eta]\[Eta],c1,c2],res,ww};
allDataUnconstr = TakeColumn[dataunconstr, {1,2,3,4,5}]/. {\[Eta]\[Eta]_,c1_,c2_,res_,ww_}->{\[Eta]\[Eta],spinparameter[\[Eta]\[Eta],c1,c2],res,ww};
If[(fitcase==3)||(fitcase>=5),
oneDverbosity = 0;
,
oneDverbosity = 2;
];
(* non-spinning fit *)
Print[Style["Non-Spinning Fit",Blue]];
nsfits = DataFitFunction[TakeColumn[datans,{1,4,5}], nsansatz, "Domain"->{0,0.25}, "PlotRange"->plotrange, "StatisticalTest"->statisticaltest, "Verbose"->oneDverbosity, "Weights"->weights,
"ToolTipTags"->tooltiptagsns, "GetIntervals"->getintervals&&(fitcase==1)];
Print["---------------------"];
Print["Select \[Chi]1=\[Chi]2=0 Fit with nsfitindex = ", nsfitindex, " -> ", nsfit = nsfits[[nsfitindex,1]] ];
Print["---------------------"];
(* equal mass/equal spin fit *)
Print[Style["q=1, \[Chi]1=\[Chi]2 Fit",Blue]];
dataq1sorted = Sort[TakeColumn[dataq1,{2,3,4,5}]]/. {xx_?NumberQ,yy_,zz_,ww_}->{spinparameter[0.25,xx,yy],zz,ww};
If[ListQ@tooltiptags,
pos = Flatten[Position[data,#]&/@dataq1sorted];
tooltiptagseq = tooltiptags[[pos]];
];
Clear[b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,S];
(* ansatzq1 = Total/@Table[ToExpression["b"<>ToString@i] * S^i,{j,3,8},{i,1,j}];
ansatzq1 = Transpose[{ansatzq1,Table[{S},{i,Length@ansatzq1}]}]; *)
ansatzq1 = OptionValue["EqualBHAnsatzList"];
If[Length@addq1ansatz>0,Do[ansatzq1=Append[ansatzq1,addq1ansatz[[i]]];,{i,Length@addq1ansatz}]];
If[productAnsatz,
ansatzq1[[All,1]]=(nsfit/. \[Eta]->0.25) * ansatzq1[[All,1]];
,
ansatzq1[[All,1]]=(nsfit/. \[Eta]->0.25) + ansatzq1[[All,1]];
];
If[ListQ@tooltiptags,
pos = Flatten[Position[TakeColumn[data,{2,3,4,5}]/. {xx_?NumberQ,yy_,zz_,ww_}->{spinparameter[0.25,xx,yy],zz,ww},#]&/@dataq1sorted];
tooltiptagseq = tooltiptags[[pos]];
];
q1fits = DataFitFunction[dataq1sorted, ansatzq1, "Domain"-> {-1,1}, "PlotRange"->plotrange, "StatisticalTest"->statisticaltest, "Verbose"->oneDverbosity, "Weights"->weights,
"ToolTipTags"->tooltiptagseq, "GetIntervals"->getintervals&&(fitcase==1)];
If[fitcase==1, Return[{nsfits,q1fits}]];
etaAnsatz = nsfits[[nsfitindex,15]];
etaCoeffRules = nsfits[[nsfitindex,2]];
etaCovar = nsfits[[nsfitindex,14]];
SAnsatz = q1fits[[q1fitindex,15]];
SCoeffRules = q1fits[[q1fitindex,2]];
SCovar = q1fits[[q1fitindex,14]];
q1fit = q1fits[[q1fitindex,1]];
Print["---------------------"];
Print["Select q=1 Fit with q1fitindex = ", q1fitindex, " -> ", q1fit];
Print["---------------------"];
Print[Style["{\[Eta],S} Fit",Blue]];
nsdegree = Exponent[nsfit,\[Eta],List];
q1degree = Exponent[q1fit,S,List];
ansatz={Flatten[Total@Table[Total@Table[ToExpression["f"<>ToString@i<>ToString@j] *S^j,{j,q1degree}]*\[Eta]^i,{i,nsdegree}]],{\[Eta],S}};
If[productAnsatz,
ansatz=Collect[nsfit * Flatten[Total@Table[Total@Table[ToExpression["f"<>ToString@i<>ToString@j] * S^j, {j,4}]*\[Eta]^i, {i,4}]], S];
,
ansatz=Collect[nsfit + Flatten[Total@Table[Total@Table[ToExpression["f"<>ToString@i<>ToString@j] * S^j, {j,4}]*\[Eta]^i, {i,4}]], S];
];
(*If[Length@addgenansatz>0,ansatz=addgenansatz[[1]];];*)
(*ansatzFinal=Table[AnsatzRestrictions[ansatzAll[[i,1]],ansatzAll[[i,2]],ansatzAll[[i,3]]],{i,Length@ansatzAll}];*)
If[fitcase<=4,
Print["\[InvisibleSpace]using nsfit: ", nsfit];
Print["\[InvisibleSpace]using q1fit: ", q1fit];
];
If[Length@addgenansatz>0
,
ansatzFinal=addgenansatz[[1]];
Print[Style["Selecting ansatz from AddGenAnsatz",Blue]];
,
If[OptionValue["RationalFunctions"],
Print[];
If[productAnsatz,
q1fitS0 = q1fit/(q1fit/. S-> 0);
,
q1fitS0 = q1fit-(q1fit/. S-> 0);
];
q1fitS0 = Chop[q1fitS0]/.{1.->1};
q1fitS0orderNum = Exponent[Numerator[q1fitS0],S];
q1fitS0orderDenom = Exponent[Denominator[q1fitS0],S];
If[twoDSpinAnsatzOrderNum<0, twoDSpinAnsatzOrderNum = q1fitS0orderNum];
If[twoDSpinAnsatzOrderDenom<0, twoDSpinAnsatzOrderDenom = q1fitS0orderDenom];
If[(twoDSpinAnsatzOrderNum>q1fitS0orderNum)||(twoDSpinAnsatzOrderDenom>q1fitS0orderDenom),
spinAnsatzNum = Numerator[q1fitS0] + Sum[1.0*S^i,{i,q1fitS0orderNum+1,twoDSpinAnsatzOrderNum}];
spinAnsatzDenom = Denominator[q1fitS0] + Sum[1.0*S^i,{i,q1fitS0orderDenom+1,twoDSpinAnsatzOrderDenom}];
spinAnsatzToGeneralize = spinAnsatzNum/spinAnsatzDenom;
,
spinAnsatzToGeneralize = q1fitS0;
];
spinAnsatz = GeneralizeFunction[spinAnsatzToGeneralize, "f", \[Eta], productGeneralizeOrderNum, productGeneralizeOrderDenom];
Print["spinAnsatz before boundary conditions = ", spinAnsatz];
(* spinAnsatzRaw = spinAnsatz /. InvertRules[SCoeffRules]; *)
q1AnsatzRaw = q1fits[[q1fitindex,15]];
If[productAnsatz,
q1AnsatzRawS0 = q1AnsatzRaw/(q1AnsatzRaw/.S->0);
,
q1AnsatzRawS0 = q1AnsatzRaw-(q1AnsatzRaw/.S->0);
];
q1AnsatzRawS0 = Chop[q1AnsatzRawS0]/.{1.->1};
If[(twoDSpinAnsatzOrderNum>q1fitS0orderNum)||(twoDSpinAnsatzOrderDenom>q1fitS0orderDenom),
spinAnsatzRawNum = Numerator[q1AnsatzRawS0] + Sum[1.0*S^i,{i,q1fitS0orderNum+1,twoDSpinAnsatzOrderNum}];
spinAnsatzRawDenom = Denominator[q1AnsatzRawS0] + Sum[1.0*S^i,{i,q1fitS0orderDenom+1,twoDSpinAnsatzOrderDenom}];
spinAnsatzRawToGeneralize = spinAnsatzRawNum/spinAnsatzRawDenom;
,
spinAnsatzRawToGeneralize = q1AnsatzRawS0;
];
spinAnsatzRaw = GeneralizeFunction[spinAnsatzRawToGeneralize, "f", \[Eta], productGeneralizeOrderNum, productGeneralizeOrderDenom];
numRestrictions = AnsatzRestrictions[Numerator[q1fitS0],Numerator[spinAnsatz],"Parameters"->True];
denomRestrictions = AnsatzRestrictions[Denominator[q1fitS0],Denominator[spinAnsatz],"Parameters"->True];
num = Collect[Numerator[spinAnsatz]/.numRestrictions,{S,\[Eta]}];
If[productGeneralizeMinPowerNum>0,
zeroRules = Flatten@Table[ToExpression["f"<>ToString@i<>ToString@j]->0,{i,0,Exponent[num,S]},{j,0,productGeneralizeMinPowerNum-1}];
Print["setting the following coefficients to zero:"];
Print[zeroRules];
num = num/.zeroRules;
];
denom = Collect[Denominator[spinAnsatz]/.denomRestrictions,{S,\[Eta]}];
spinpart = num/denom;
Print["spinAnsatz after equal mass boundary conditions = ",spinpart];
Print["applying user-set generalAnsatzRules:"];
Print[generalAnsatzRules];
If[productAnsatz,
ansatzFinal = (nsfit * spinpart) /. generalAnsatzRules;
(* \[Eta]0Ansatz =Limit[(spinAnsatz/\[Eta]), \[Eta]\[Rule] 0]//Chop//Simplify; *)
ansatzRaw = nsfit * spinAnsatzRaw;
,
ansatzFinal = (nsfit + spinpart) /. generalAnsatzRules;
(* \[Eta]0Ansatz =Limit[(spinpart/\[Eta]), \[Eta]\[Rule] 0]//Chop//Simplify; *)
ansatzRaw = nsfit + spinAnsatzRaw;
];
Print[];
(* 1 2 3 4 5 6 7 8 9 *)
extraStuff = {ansatzRaw, etaAnsatz, etaCoeffRules, etaCovar, SAnsatz, SCoeffRules, SCovar, numRestrictions, denomRestrictions};
,
(* Constrain the ansatz to non spinning and q=1 cases *)
(*ansatzFinal=AnsatzRestrictions[nsfit,q1fit,ansatz] /. generalAnsatzRules;*)
ansatzFinal=AnsatzRestrictions[ nsfit,q1fit,ansatz];
];
];
Print["\[InvisibleSpace]ansatzFinal: ", ansatzFinal];
Print[];
(*
(* this is redundant and should only differ from 'v2' in uncertainty interval widths *)
If[fitcase\[LessEqual]4,
Print[Style["eqS fit to all "<>ToString@Length@allData<>" data points:",Blue]];
alldataeqfit = DataFitFunction[allData, {{ansatzFinal,{\[Eta],S}}}, "PlotRange"\[Rule]{{0,0.25},{-1,1},All}, "Domain"\[Rule]{{0,0.25},{-1,1}},
"Verbose"\[Rule]2, "Weights"\[Rule]weights,"StatisticalTest"\[Rule]statisticaltest, "GetIntervals"\[Rule]getintervals];
];
*)
Print[Style["eqS fit to all "<>ToString@Length@allDataUnconstr<>" data points without 1D regions:",Blue]];
alldataeqfitv2 = DataFitFunction[allDataUnconstr, {{ansatzFinal,{\[Eta],S}}}, "PlotRange"->{{0,0.25},{-1,1},All}, "Domain"->{{0,0.25},{-1,1}},
"Verbose"->2, "Weights"->weights,"StatisticalTest"->statisticaltest, "GetIntervals"->getintervals];
(*
(* this is redundant and should only differ from 'v2' in uncertainty interval widths *)
If[fitcase\[LessEqual]4,
Print[Style["eqS fit to "<>ToString@Length@allDataEqS<>" equal-spin data points:",Blue]];
eqdatafit = DataFitFunction[allDataEqS, {{ansatzFinal,{\[Eta],S}}}, "PlotRange"\[Rule]{{0,0.25},{-1,1},All}, "Domain"\[Rule]{{0,0.25},{-1,1}},
"Verbose"\[Rule]2, "Weights"\[Rule]weights,"StatisticalTest"\[Rule]statisticaltest, "GetIntervals"\[Rule]getintervals];
];
*)
Print[Style["eqS fit to "<>ToString@Length@allDataEqSv2<>" equal-spin data points without 1D regions:",Blue]];
eqdatafitv2 = DataFitFunction[allDataEqSv2, {{ansatzFinal,{\[Eta],S}}}, "PlotRange"->{{0,0.25},{-1,1},All}, "Domain"->{{0,0.25},{-1,1}},
"Verbose"->2, "Weights"->weights,"StatisticalTest"->statisticaltest, "GetIntervals"->getintervals];
(* 2DeqS 2Dall 3D placeholders 1D2Dparts 1Deta 1DS 2DSansatz *)
If[fitcase<=3, Return[{eqdatafitv2, alldataeqfitv2, {}, {}, {}, {}, extraStuff, nsfits, q1fits, spinpart}];];
Print[Style["(fit to allData) - (fit to allDataEqS):",Blue]];
Print[Plot3D[alldataeqfitv2[[1,1]]-eqdatafitv2[[1,1]],{\[Eta],0,0.25`},{S,-1,1},AxesLabel->{Style["\[Eta]",Black,14],Style["S",Black,14],Style["diff",14]}]];
Clear[a0,a1,a2,a3,\[Chi]diff,q];
(* Fit the spin difference terms *)
Print["----------------"];
Print[Style["{\[Eta],S,\[Chi]diff}",Blue]];
mydq=0.005;
tabfits=Table[
Print[Style["MassRatio -> ",Blue],q\[Eta][i]];
my\[Eta]=i;
thisq=q\[Eta][i];
If[ thisq < 2,
myd\[Eta] = Abs[0.0001+mydq (-2 thisq/(1+thisq)^3 + 1./(1+thisq)^2) ];,
myd\[Eta] = 0.001;
];
Print["myd\[Eta] = ", myd\[Eta] ];
mysel = Select[data,my\[Eta]-myd\[Eta]<#1[[1]]<my\[Eta]+myd\[Eta]&];
dataq1 = TakeColumn[mysel,{2,3,4,5}]/. {xx_?NumberQ,yy_,zz_,ww_}->{xx,yy,eqdatafitv2[[1,1]]/. \[Eta]->my\[Eta]/. S->spinparameter[my\[Eta],xx,yy],ww};
avgwgthperq = Mean[dataq1[[All,-1]]];
If[fitcase>=5,
perqVerbosity = 0; (* for higher fit cases, still do the per-q analysis, but suppress the plots *)
,
perqVerbosity = 1;
If[ListQ@tooltiptags,
dataq1pos = Flatten[Position[data,#]&/@mysel];
tooltiptagsaux = tooltiptags[[dataq1pos]];
];
If[0.25 -myd\[Eta]<my\[Eta]<0.25 +myd\[Eta],
dataq1Sym = dataq1/. {xx_?NumberQ,yy_,zz_,ww_}->{yy,xx,zz,ww};
dataq1 = Join[dataq1,dataq1Sym];
];
plot1 = myListPlot3D[dataq1[[All,1;;3]], AxesLabel->{Style["\[Chi]1",14],Style["\[Chi]2",14],""}, PlotRange->{{-1,1},{-1,1},All}, PlotLabel->Style["data(\[Chi]1,\[Chi]2)",14], ImageSize->250];
dataq1 = TakeColumn[mysel,{2,3,4,5}]/. {xx_?NumberQ,yy_,zz_,ww_}->{xx,yy,zz-(eqdatafitv2[[1,1]]/. \[Eta]->my\[Eta]/. S->spinparameter[my\[Eta],xx,yy]),ww};
If[0.25 -myd\[Eta]<my\[Eta]<0.25 +myd\[Eta],
dataq1Sym=dataq1/. {xx_?NumberQ,yy_,zz_,ww_}->{yy,xx,zz,ww};
dataq1=Join[dataq1,dataq1Sym];
];
plot2 = myListPlot3D[dataq1[[All,1;;3]], AxesLabel->{Style["\[Chi]1",14],Style["\[Chi]2",14],""}, PlotRange->{{-1,1},{-1,1},All}, PlotLabel->Style["data(\[Chi]1,\[Chi]2) - fit(S)",14], ImageSize->250];
dataq1 = TakeColumn[mysel,{2,3,4,5}]/. {xx_?NumberQ,yy_,zz_,ww_}->{spinparameter[my\[Eta],xx,yy],xx-yy,zz-(eqdatafitv2[[1,1]]/. \[Eta]->my\[Eta]/. S->spinparameter[my\[Eta],xx,yy]),ww};
If[0.25 -myd\[Eta]<my\[Eta]<0.25+myd\[Eta],
dataq1Sym=dataq1/. {xx_?NumberQ,yy_,zz_,ww_}->{xx,-yy,zz,ww};
dataq1=Join[dataq1,dataq1Sym];
];
plot3 = myListPlot3D[dataq1[[All,1;;3]], PlotStyle->Directive[RGBColor[0.880722, 0.611041, 0.142051],Opacity[0.7]], Lighting->{{"Ambient",RGBColor[0.880722, 0.611041, 0.142051]}},
AxesLabel->{Style["S",14],Style["\!\(\*SubscriptBox[\(\[Chi]\), \(diff\)]\)",14],""}, PlotRange->{{-1,1},{-2,2},All}, PlotLabel->Style["data(S,\!\(\*SubscriptBox[\(\[Chi]\), \(diff\)]\)) - fit(S)",14], ImageSize->250];
];
Clear[a,b,c,\[Chi]1,\[Chi]2,\[Delta]\[Chi]];
dataq1a= TakeColumn[dataq1,{1,2,3}];
dataq1 = TakeColumn[mysel,{2,3,4,5}]/. {xx_?NumberQ,yy_,zz_,ww_}->{spindiffparameter[my\[Eta],xx,yy],zz-(eqdatafitv2[[1,1]]/. \[Eta]->my\[Eta]/. S->spinparameter[my\[Eta],xx,yy]),ww};
(*dataq1 = TakeColumn[mysel,{2,3,4,5}]/.\[VeryThinSpace]{xx_?NumberQ,yy_,zz_,ww_}\[Rule]{(xx-yy),zz-(eqdatafitv2[[1,1]]/.\[VeryThinSpace]\[Eta]\[Rule]my\[Eta]/.\[VeryThinSpace]S\[Rule]spinparameter[my\[Eta],xx,yy]),ww}*)
Print["data dimensionality: ",Length@dataq1];
If[0.25 -myd\[Eta]<my\[Eta]<0.25+myd\[Eta],
dataq1Sym = dataq1/. {xx_?NumberQ,zz_,ww_}->{-xx,zz,ww};
dataq1 = Join[dataq1,dataq1Sym];
If[perqVerbosity>0, tooltiptagsaux = Join[tooltiptagsaux,tooltiptagsaux];];
Print["data dimensionality (including symmetric duplicates): ",Length@dataq1];
];
(*dataq1mixterm = TakeColumn[mysel,{2,3,4,5}]/.\[VeryThinSpace]{xx_?NumberQ,yy_,zz_,ww_}\[Rule]{xx-yy,spinparameter[my\[Eta],xx,yy]*(xx-yy),zz-(eqdatafitv2[[1,1]]/.\[VeryThinSpace]\[Eta]\[Rule]my\[Eta]/.\[VeryThinSpace]S\[Rule]spinparameter[my\[Eta],xx,yy]),ww};*)
dataq1mixterm = TakeColumn[mysel,{2,3,4,5}]/. {xx_?NumberQ,yy_,zz_,ww_}->{spindiffparameter[my\[Eta],xx,yy],spinparameter[my\[Eta],xx,yy]*spindiffparameter[my\[Eta],xx,yy],zz-(eqdatafitv2[[1,1]]/. \[Eta]->my\[Eta]/. S->spinparameter[my\[Eta],xx,yy]),ww};
myfit = DataFitFunction[dataq1, {{a \[Delta]\[Chi], {\[Delta]\[Chi]}}, {a \[Delta]\[Chi] + b \[Delta]\[Chi]^2,{\[Delta]\[Chi]}}}, "Verbose"->perqVerbosity, "AxesTag"->"Amplitude",
"StatisticalTest"->statisticaltest, "Sorted"->False, "Weights"->weights, "GetIntervals"->False];
myfitmixterm = DataFitFunction[dataq1mixterm, {{a \[Delta]\[Chi] + c y, {\[Delta]\[Chi],y}}, {a \[Delta]\[Chi] + c y +b \[Delta]\[Chi]^2,{\[Delta]\[Chi],y}}}, "Verbose"->perqVerbosity, "AxesTag"->"Amplitude",
"StatisticalTest"->statisticaltest, "Sorted"->False, "Weights"->weights, "GetIntervals"->False];
myfit = Join[myfit,myfitmixterm,{avgwgthperq}];
(* do NOT show mix-term fits here, as they tend to blow the scale, and are only projected down anyway *)
(* plot4=Show[Plot[{myfit[[1,1]],myfit[[2,1]]},{\[Delta]\[Chi],-0.1,0.1},PlotRange\[Rule]All,ImageSize\[Rule]250,
Frame\[Rule]True,FrameLabel\[Rule]{"Subscript[\[Chi], diff]","\[CapitalDelta](Subscript[\[Chi], diff])"},PlotLegends\[Rule]{"linear","lin+quad"}],
ListPlot[Table[Tooltip[dataq1[[i,1;;2]],If[ListQ@tooltiptags,tooltiptagsaux[[i]],ToString[{dataq1[[i,1]],dataq1[[i,2]]}]]],{i,Length@dataq1}],PlotStyle\[Rule]PointSize[Medium],PlotRange\[Rule]All,Frame->True]];
*)
dataq1a= Transpose[{dataq1a[[All,1]],dataq1a[[All,2]],dataq1a[[All,3]]-(myfit[[1,1]]/.\[Delta]\[Chi]->dataq1[[All,1]])}];
plot3a = myListPlot3D[dataq1a, PlotStyle->Directive[RGBColor[0.880722, 0.611041, 0.142051],Opacity[0.7]], Lighting->{{"Ambient",RGBColor[0.880722, 0.611041, 0.142051]}},
AxesLabel->{Style["S",14],Style["\!\(\*SubscriptBox[\(\[Chi]\), \(diff\)]\)",14],""}, PlotRange->{{-1,1},{-2,2},All}, PlotLabel->Style["data(S,\!\(\*SubscriptBox[\(\[Chi]\), \(diff\)]\)) - (fit(S) + f(\[Eta])\!\(\*SubscriptBox[\(\[Chi]\), \(diff\)]\))",14], ImageSize->250];
If[fitcase==4,
plot4a = ListPlot[Table[Tooltip[dataq1[[i,1;;2]],If[ListQ@tooltiptags,tooltiptagsaux[[i]],ToString[{dataq1[[i,1]],dataq1[[i,2]]}]]],{i,Length@dataq1}],
PlotStyle->PointSize[Medium], PlotRange->{{-2.,2.},All}, PlotLegends->{"NR data"}];
plot4b = Plot[{myfit[[1,1]],myfit[[2,1]]},{\[Delta]\[Chi],-2.,2.}, PlotLegends->{"linear","lin+quad"}, PlotRange->{{-2.,2.},All}];
If[0.25 -myd\[Eta]<my\[Eta]<0.25+myd\[Eta],
plot4mirror = ListPlot[Table[{dataq1[[i,1]],dataq1[[i,2]]},{i,Length@dataq1}], PlotStyle->{Gray,PointSize[Medium]}, PlotMarkers->\!\(\*
StyleBox["\"\<\[FilledSquare]\>\"",
StripOnInput->False,
FontSize->8]\), PlotLegends->{"mirror NR data"}];
plot4 = Show[{plot4b,plot4a}, Frame->True, FrameLabel->{"\!\(\*SubscriptBox[\(\[Chi]\), \(diff\)]\)","\[CapitalDelta](\!\(\*SubscriptBox[\(\[Chi]\), \(diff\)]\))"}, ImageSize->250];
,
plot4 = Show[{plot4b,plot4a}, Frame->True, FrameLabel->{"\!\(\*SubscriptBox[\(\[Chi]\), \(diff\)]\)","\[CapitalDelta](\!\(\*SubscriptBox[\(\[Chi]\), \(diff\)]\))"}, ImageSize->250];
];
Print[{plot1,plot2,plot3,plot3a,plot4}];
];
myfit, {i,massratiounequalfits}]; (* this line finishes the tabfits list *)
(*Print[tabfits[[All,-1]]];*)
Print["-----------"];
Print[Style["\[Eta] dependence of \!\(\*SubscriptBox[\(\[Chi]\), \(diff\)]\) terms",Blue]];
extrawght=Join[tabfits[[All,-1]],{1.}];
If[fastanalysis,
If[Length@addspindifflinansatz>0,
ansatzchidifflinear = addspindifflinansatz[[1,1]];
,
ansatzchidifflinear = (ToExpression["a10"] \[Eta]^Abs[ToExpression["a11"]] Sqrt[1-4 \[Eta]]^Abs[ToExpression["a12"]] ) /. spindifferencerules;
];
If[Length@addspindiffquadansatz>0,
ansatzchidiffquadratic = addspindiffquadansatz[[1,1]];
,
ansatzchidiffquadratic = ((ToExpression["a20"] \[Eta]^Abs[ToExpression["a21"]] Sqrt[1-4 \[Eta]]^Abs[ToExpression["a22"]] )) /. spindifferencerules;
];
ansatzFinal\[Delta]\[Chi]2 = (ansatzFinal /. S->spinparameter[\[Eta],\[Chi]1,\[Chi]2]) + ansatzchidifflinear spindiffparameter[\[Eta],\[Chi]1,\[Chi]2] + ansatzchidiffquadratic spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]^2;
If[Length@addspindiffmixansatz>0,
ansatzchidiffmix = addspindiffmixansatz[[1,1]];
,
ansatzchidiffmix = ((ToExpression["a30"] \[Eta]^Abs[ToExpression["a31"]] Sqrt[1-4 \[Eta]]^Abs[ToExpression["a32"]] )) /. spindifferencerules;
];
ansatzS\[Delta]\[Chi]\[Chi]2raw = ansatzchidifflinear spindiffparameter[\[Eta],\[Chi]1,\[Chi]2] + ansatzchidiffmix S spindiffparameter[\[Eta],\[Chi]1,\[Chi]2] + ansatzchidiffquadratic spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]^2; (* needed to extract the coefficients later on *)
ansatzFinalS\[Delta]\[Chi]\[Chi]2 = ( ansatzFinal + ansatzS\[Delta]\[Chi]\[Chi]2raw )/.S->spinparameter[\[Eta],\[Chi]1,\[Chi]2]; (* this is the form passed to DataFitFunction[] *)
Print[Style["full 3D fit to all "<>ToString@Length@dataunconstr<>" data points without 1D regions... (see results at the end after plots)",Blue]];
uneqfit2 = DataFitFunction[dataunconstr, {{ansatzFinalS\[Delta]\[Chi]\[Chi]2,{\[Eta],\[Chi]1,\[Chi]2}}},
"Verbose"->0, "AxesTag"->"Amplitude", "StatisticalTest"->statisticaltest, "Sorted"->False, "Weights"->weights, "GetIntervals"->getintervals];
Print["Done"];
Return[{uneqfit2 ,extraStuff, nsfits, q1fits, spinpart}];
,
linearparerr=Flatten@TakeColumn[tabfits,1][[All,9,1]];
linearparerr=Join[linearparerr,{10^-9}];
linearpar=Transpose[{Join[massratiounequalfits,{0}],Join[a/.TakeColumn[tabfits,1][[All,2]],{0}],extrawght/linearparerr^2}];
linearpar[[1]]={0.25,0,extrawght[[1]]/(10^(-9))^2};
linearparerr[[1]]={10^-9};
linearpar2err=Flatten@TakeColumn[tabfits,2][[All,9,1]];
linearpar2err=Join[linearpar2err,{10^-9}];
linearpar2=Transpose[{Join[massratiounequalfits,{0}],Join[a/.TakeColumn[tabfits,2][[All,2]],{0}],extrawght/linearpar2err^2}];
linearpar2[[1]]={0.25,0,extrawght[[1]]/(10^(-9))^2};
linearpar2err[[1]]={10^-9};
quadparerr=Flatten@TakeColumn[tabfits,2][[All,9,2]];
quadparerr=Join[quadparerr,{10^-9}];
quadpar=Transpose[{Join[massratiounequalfits,{0}],Join[b/.TakeColumn[tabfits,2][[All,2]],{0}],extrawght/quadparerr^2}];
linearpar3err=Flatten@TakeColumn[tabfits,3][[All,9,1]];
linearpar3err=Join[linearpar3err,{10^-9}];
linearpar3=Transpose[{Join[massratiounequalfits,{0}],Join[a/.TakeColumn[tabfits,3][[All,2]],{0}],extrawght/linearpar2err^2}];
linearpar3[[1]]={0.25,0,extrawght[[1]]/(10^(-9))^2};
linearpar3err[[1]]={10^-9};
mixparerr=Flatten@TakeColumn[tabfits,3][[All,9,2]];
mixparerr=Join[mixparerr,{10^-9}];
mixpar=Transpose[{Join[massratiounequalfits,{0}],Join[c/.TakeColumn[tabfits,3][[All,2]],{0}],extrawght/mixparerr^2}];
mixpar[[1]]={0.25,0,extrawght[[1]]/(10^(-9))^2};
mixparerr[[1]]={10^-9};
linearpar4err=Flatten@TakeColumn[tabfits,4][[All,9,1]];
linearpar4err=Join[linearpar4err,{10^-9}];
linearpar4=Transpose[{Join[massratiounequalfits,{0}],Join[a/.TakeColumn[tabfits,4][[All,2]],{0}],extrawght/linearpar4err^2}];
linearpar4[[1]]={0.25,0,extrawght[[1]]/(10^(-9))^2};
linearpar4err[[1]]={10^-9};
mixparerr2=Flatten@TakeColumn[tabfits,4][[All,9,2]];
mixparerr2=Join[mixparerr2,{10^-9}];
mixpar2=Transpose[{Join[massratiounequalfits,{0}],Join[c/.TakeColumn[tabfits,4][[All,2]],{0}],extrawght/mixparerr2^2}];
mixpar2[[1]]={0.25,0,extrawght[[1]]/(10^(-9))^2};
mixparerr2[[1]]={10^-9};
quadparerr2=Flatten@TakeColumn[tabfits,4][[All,9,2]];
quadparerr2=Join[quadparerr2,{10^-9}];
quadpar2=Transpose[{Join[massratiounequalfits,{0}],Join[b/.TakeColumn[tabfits,4][[All,2]],{0}],extrawght/quadparerr2^2}];
(*ansatz\[Eta]1=a0 \[Eta]^Abs[a1] N[1-4 \[Eta]]^0.7;*)
(*ansatz\[Eta]1=a0 \[Eta]^Abs[a1] N[1-4 \[Eta]]^Abs[a2];*)
(*ansatz\[Eta]1=a0 \[Eta] N[1-4 \[Eta]]^Abs[a2];*)
If[Length@addspindifflinansatz>0,
ansatzchidifflinear = addspindifflinansatz[[1,1]];
,
ansatzchidifflinear = (ToExpression["a10"] \[Eta]^Abs[ToExpression["a11"]] Sqrt[1-4 \[Eta]]^Abs[ToExpression["a12"]] ) /. spindifferencerules;
];
(*ansatzFinal\[Delta]\[Chi]=(ansatzFinal/. S\[Rule] spinparameter[\[Eta],\[Chi]1,\[Chi]2])+ansatzchidifflinear (\[Chi]1-\[Chi]2);*)
ansatzFinal\[Delta]\[Chi] = (ansatzFinal /. S->spinparameter[\[Eta],\[Chi]1,\[Chi]2]) + ansatzchidifflinear spindiffparameter[\[Eta],\[Chi]1,\[Chi]2];
If[Length@addspindiffquadansatz>0,
ansatzchidiffquadratic = addspindiffquadansatz[[1,1]];
,
ansatzchidiffquadratic = ((ToExpression["a20"] \[Eta]^Abs[ToExpression["a21"]] Sqrt[1-4 \[Eta]]^Abs[ToExpression["a22"]] )) /. spindifferencerules;
];
ansatzFinal\[Delta]\[Chi]2 = (ansatzFinal /. S->spinparameter[\[Eta],\[Chi]1,\[Chi]2]) + ansatzchidifflinear spindiffparameter[\[Eta],\[Chi]1,\[Chi]2] + ansatzchidiffquadratic spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]^2;
If[Length@addspindiffmixansatz>0,
ansatzchidiffmix = addspindiffmixansatz[[1,1]];
,
ansatzchidiffmix = ((ToExpression["a30"] \[Eta]^Abs[ToExpression["a31"]] Sqrt[1-4 \[Eta]]^Abs[ToExpression["a32"]] )) /. spindifferencerules;
];
ansatzS\[Delta]\[Chi]raw = ansatzchidifflinear spindiffparameter[\[Eta],\[Chi]1,\[Chi]2] + ansatzchidiffmix S spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]; (* needed to extract the coefficients later on *)
ansatzFinalS\[Delta]\[Chi] = ( ansatzFinal + ansatzS\[Delta]\[Chi]raw ) /. S->spinparameter[\[Eta],\[Chi]1,\[Chi]2]; (* this is the form passed to DataFitFunction[] *)
ansatzS\[Delta]\[Chi]\[Chi]2raw = ansatzchidifflinear spindiffparameter[\[Eta],\[Chi]1,\[Chi]2] + ansatzchidiffmix S spindiffparameter[\[Eta],\[Chi]1,\[Chi]2] + ansatzchidiffquadratic spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]^2; (* needed to extract the coefficients later on *)
ansatzFinalS\[Delta]\[Chi]\[Chi]2 = ( ansatzFinal + ansatzS\[Delta]\[Chi]\[Chi]2raw ) /. S->spinparameter[\[Eta],\[Chi]1,\[Chi]2]; (* this is the form passed to DataFitFunction[] *)
Print["Fitting ansaetze to per-q slopes, linear only:"];
linearfit1 = DataFitFunction[linearpar, {{ansatzchidifflinear,{\[Eta]}}}, "Verbose"->1, "Weights"->weights];
Print["linear+quadratic:"];
linearfit2 = DataFitFunction[linearpar2, {{ansatzchidifflinear,{\[Eta]}}}, "Verbose"->1, "Weights"->weights];
quadfit = DataFitFunction[quadpar, {{ansatzchidiffquadratic,{\[Eta]}}}, "Verbose"->1, "Weights"->weights];
Print["linear+mixture:"];
linearfit3 = DataFitFunction[linearpar3, {{ansatzchidifflinear,{\[Eta]}}}, "Verbose"->1, "Weights"->weights];
mixfit = DataFitFunction[mixpar, {{ansatzchidiffmix,{\[Eta]}}}, "Verbose"->1, "Weights"->weights];
Print["linear+mixture+quadratic:"];
linearfit4 = DataFitFunction[linearpar4, {{ansatzchidifflinear,{\[Eta]}}}, "Verbose"->1, "Weights"->weights];
mixfit2 = DataFitFunction[mixpar2, {{ansatzchidiffmix,{\[Eta]}}}, "Verbose"->1, "Weights"->weights];
quadfit2 = DataFitFunction[quadpar2, {{ansatzchidiffquadratic,{\[Eta]}}}, "Verbose"->1, "Weights"->weights];
Clear[a10,a11,a12,a20,a21,a22,a30,a31,a32,a1,a2,a0];
(*If[Length@addgenansatz>0,ansatz=addgenansatz[[1]];];*)
(*ansatzFinal=Table[AnsatzRestrictions[ansatzAll[[i,1]],ansatzAll[[i,2]],ansatzAll[[i,3]]],{i,Length@ansatzAll}];*)
(* this will only differ from uneqfit2 in the width of the error bars, not in the results, and is not needed anymore, but let's keep it here commented-out to have it handy for sanity checks *)
(*
Print[Style["full 3D fit to all "<>ToString@Length@data<>" data points...",Blue]];
uneqfit = DataFitFunction[data, {{ansatzFinal\[Delta]\[Chi],{\[Eta],\[Chi]1,\[Chi]2}},{ansatzFinal\[Delta]\[Chi]2,{\[Eta],\[Chi]1,\[Chi]2}},{ansatzFinalS\[Delta]\[Chi],{\[Eta],\[Chi]1,\[Chi]2}},{ansatzFinalS\[Delta]\[Chi]\[Chi]2,{\[Eta],\[Chi]1,\[Chi]2}}},
"Verbose"\[Rule]0, "AxesTag"\[Rule]"Amplitude", "StatisticalTest"\[Rule]statisticaltest, "Sorted"\[Rule]False, "Weights"\[Rule] weights, "GetIntervals"\[Rule]getintervals];
*)
Print[Style["full 3D fit to all "<>ToString@Length@dataunconstr<>" data points without 1D regions... (see results at the end after plots)",Blue]];
uneqfit2 = DataFitFunction[dataunconstr, {{ansatzFinal\[Delta]\[Chi],{\[Eta],\[Chi]1,\[Chi]2}},{ansatzFinal\[Delta]\[Chi]2,{\[Eta],\[Chi]1,\[Chi]2}},{ansatzFinalS\[Delta]\[Chi],{\[Eta],\[Chi]1,\[Chi]2}},{ansatzFinalS\[Delta]\[Chi]\[Chi]2,{\[Eta],\[Chi]1,\[Chi]2}}},
"Verbose"->0, "AxesTag"->"Amplitude", "StatisticalTest"->statisticaltest, "Sorted"->False, "Weights"->weights, "GetIntervals"->getintervals];
Print[Style["spin-diff fit to "<>ToString@Length@datauneqs<>" unequal-spin data points...",Blue]];
uneqfit3 = DataFitFunction[TakeColumn[datauneqs,{1,2,3,4,5}]/. {\[Eta]\[Eta]_,c1_,c2_,res_,ww_}->{\[Eta]\[Eta],c1,c2,res-(eqdatafitv2[[1,1]]/. \[Eta]->\[Eta]\[Eta]/. S->spinparameter[\[Eta]\[Eta],c1,c2]),ww},
{{ansatzchidifflinear spindiffparameter[\[Eta],\[Chi]1,\[Chi]2], {\[Eta],\[Chi]1,\[Chi]2}},
{ansatzchidifflinear spindiffparameter[\[Eta],\[Chi]1,\[Chi]2] + ansatzchidiffquadratic spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]^2, {\[Eta],\[Chi]1,\[Chi]2}},
{ansatzchidifflinear spindiffparameter[\[Eta],\[Chi]1,\[Chi]2] + ansatzchidiffmix spinparameter[\[Eta],\[Chi]1,\[Chi]2] spindiffparameter[\[Eta],\[Chi]1,\[Chi]2], {\[Eta],\[Chi]1,\[Chi]2}},
{ansatzchidifflinear spindiffparameter[\[Eta],\[Chi]1,\[Chi]2] + ansatzchidiffmix spinparameter[\[Eta],\[Chi]1,\[Chi]2] spindiffparameter[\[Eta],\[Chi]1,\[Chi]2] + ansatzchidiffquadratic spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]^2, {\[Eta],\[Chi]1,\[Chi]2}}},
"Verbose"->1, "AxesTag"->"Amplitude", "StatisticalTest"->statisticaltest, "Sorted"->False, "Weights"->weights, "GetIntervals"->getintervals];
(*
Print[Style["full 3D fit to "<>ToString@Length@datauneqs<>" unequal-spin data points...",Blue]];
uneqfit3 = DataFitFunction[datauneqs, {{ansatzFinal\[Delta]\[Chi],{\[Eta],\[Chi]1,\[Chi]2}},{ansatzFinal\[Delta]\[Chi]2,{\[Eta],\[Chi]1,\[Chi]2}},{ansatzFinalS\[Delta]\[Chi],{\[Eta],\[Chi]1,\[Chi]2}},{ansatzFinalS\[Delta]\[Chi]\[Chi]2,{\[Eta],\[Chi]1,\[Chi]2}}},
"Verbose"\[Rule]0, "AxesTag"\[Rule]"Amplitude", "StatisticalTest"\[Rule]statisticaltest, "Sorted"\[Rule]False, "Weights"\[Rule] weights, "GetIntervals"\[Rule]getintervals];
*)
(* eta-dependence for direct 3D fit over all non-1D data *)
spindiffterm = CoefficientList[uneqfit2[[1,1]]/.spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->\[Chi]diff,\[Chi]diff][[2]];
spindiffterm21 = CoefficientList[uneqfit2[[2,1]]/.spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->\[Chi]diff,\[Chi]diff][[2]];
spindiffterm22 = CoefficientList[uneqfit2[[2,1]]/.spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->\[Chi]diff,\[Chi]diff][[3]];
spindiffterm31 = CoefficientList[ansatzS\[Delta]\[Chi]raw/.uneqfit2[[3,2]]/.S->0/.spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->\[Chi]diff,\[Chi]diff][[2]];
spindiffterm32 = CoefficientList[ansatzS\[Delta]\[Chi]raw/.uneqfit2[[3,2]]/.S*spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->y,y][[2]];
spindiffterm41 = CoefficientList[ansatzS\[Delta]\[Chi]\[Chi]2raw/.uneqfit2[[4,2]]/.S->0/.spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->\[Chi]diff,\[Chi]diff][[2]];
spindiffterm42 = CoefficientList[ansatzS\[Delta]\[Chi]\[Chi]2raw/.uneqfit2[[4,2]]/.S spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->y,y][[2]];
spindiffterm43 = CoefficientList[ansatzS\[Delta]\[Chi]\[Chi]2raw/.uneqfit2[[4,2]]/.S->0/.spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->\[Chi]diff,\[Chi]diff][[3]];
(* eta-dependence for residuals-only spin-diff fit over all uneqS data *)
dfitspindiffterm = CoefficientList[uneqfit3[[1,1]]/.spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->\[Chi]diff,\[Chi]diff][[2]];
dfitspindiffterm21 = CoefficientList[uneqfit3[[2,1]]/.spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->\[Chi]diff,\[Chi]diff][[2]];
dfitspindiffterm22 = CoefficientList[uneqfit3[[2,1]]/.spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->\[Chi]diff,\[Chi]diff][[3]];
dfitspindiffterm31 = CoefficientList[ansatzS\[Delta]\[Chi]raw/.uneqfit3[[3,2]]/.S->0/.spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->\[Chi]diff,\[Chi]diff][[2]];
dfitspindiffterm32 = CoefficientList[ansatzS\[Delta]\[Chi]raw/.uneqfit3[[3,2]]/.S*spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->y,y][[2]];
dfitspindiffterm41 = CoefficientList[ansatzS\[Delta]\[Chi]\[Chi]2raw/.uneqfit3[[4,2]]/.S->0/.spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->\[Chi]diff,\[Chi]diff][[2]];
dfitspindiffterm42 = CoefficientList[ansatzS\[Delta]\[Chi]\[Chi]2raw/.uneqfit3[[4,2]]/.S spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->y,y][[2]];
dfitspindiffterm43 = CoefficientList[ansatzS\[Delta]\[Chi]\[Chi]2raw/.uneqfit3[[4,2]]/.S->0/.spindiffparameter[\[Eta],\[Chi]1,\[Chi]2]->\[Chi]diff,\[Chi]diff][[3]];
lplot=Show[{Plot[{spindiffterm,dfitspindiffterm,linearfit1[[1,1]]}, {\[Eta],0,0.25}, PlotLegends->{"direct 3D fit","fit to residuals","per-q res. fits"}, PlotStyle->{{Orange},{Magenta,Dotted},{Blue,Dashed}}],
ErrorListPlot[Table[{linearpar[[i,1;;2]], ErrorBar[1/Sqrt[linearpar[[i,-1]]]]}, {i,Length@linearparerr}], PlotStyle->Red],
ErrorListPlot[Table[{linearpar[[i,1;;2]], ErrorBar[linearparerr[[i]]]}, {i,Length@linearparerr}], PlotLegends->{"per-q fit results"}]},
PlotRange->{{0,0.25},{Min@linearpar[[All,2]]-0.001,Max@linearpar[[All,2]]+0.001}}, ImageSize->330, Frame->True, FrameLabel->{Style["\[Eta]",14],Style["\!\(\*SubscriptBox[\(f\), \(a\)]\)(\[Eta])",14]}, PlotLabel->{"linear fit, \!\(\*SubscriptBox[\(f\), \(a\)]\)(\[Eta])="{ansatzchidifflinear}}];
lqplotl=Show[{Plot[{spindiffterm21,dfitspindiffterm21,linearfit2[[1,1]]}, {\[Eta],0,0.25}, PlotLegends->{"direct 3D fit","fit to residuals","per-q res. fits"}, PlotStyle->{{Orange},{Magenta,Dotted},{Blue,Dashed}}],
ErrorListPlot[Table[{linearpar2[[i,1;;2]], ErrorBar[1/Sqrt[linearpar2[[i,-1]]]]}, {i,Length@linearpar2err}], PlotStyle->Red],
ErrorListPlot[Table[{linearpar2[[i,1;;2]], ErrorBar[linearpar2err[[i]]]}, {i,Length@linearpar2err}], PlotLegends->{"per-q fit results"}]},
PlotRange->{{0,0.25},{Min@linearpar2[[All,2]]-0.001,Max@linearpar2[[All,2]]+0.001}}, ImageSize->330, Frame->True, FrameLabel->{Style["\[Eta]",14],Style["\!\(\*SubscriptBox[\(f\), \(a\)]\)(\[Eta])",14]}, PlotLabel->{"lin+quad fit, lin term, \!\(\*SubscriptBox[\(f\), \(a\)]\)(\[Eta])="{ansatzchidifflinear}}];
lqplotq=Show[{Plot[{spindiffterm22,dfitspindiffterm22,quadfit[[1,1]]}, {\[Eta],0,0.25}, PlotLegends->{"direct 3D fit","fit to residuals","per-q res. fits"}, PlotStyle->{{Orange},{Magenta,Dotted},{Blue,Dashed}}],
ErrorListPlot[Table[{quadpar[[i,1;;2]],ErrorBar[1/Sqrt[quadpar[[i,-1]]]]},{i,Length@quadparerr}], PlotStyle->Red],
ErrorListPlot[Table[{quadpar[[i,1;;2]],ErrorBar[quadparerr[[i]]]},{i,Length@quadparerr}], PlotLegends->{"per-q fit results"}]},
PlotRange->{{0,0.25},{Min@quadpar[[All,2]]-0.001,Max@quadpar[[All,2]]+0.001}}, ImageSize->330, Frame->True, FrameLabel->{Style["\[Eta]",14],Style["\!\(\*SubscriptBox[\(f\), \(b\)]\)(\[Eta])",14]}, PlotLabel->{"lin+quad fit, quad term, \!\(\*SubscriptBox[\(f\), \(b\)]\)(\[Eta])="{ansatzchidiffquadratic}}];
lmplotl=Show[{Plot[{spindiffterm31,dfitspindiffterm31,linearfit3[[1,1]]},{\[Eta],0,0.25},PlotLegends->{"direct 3D fit","fit to residuals","per-q res. fits"}, PlotStyle->{{Orange},{Magenta,Dotted},{Blue,Dashed}}],
ErrorListPlot[Table[{linearpar3[[i,1;;2]],ErrorBar[1/Sqrt[linearpar3[[i,-1]]]]},{i,Length@linearpar3err}], PlotStyle->Red],
ErrorListPlot[Table[{linearpar3[[i,1;;2]],ErrorBar[linearpar3err[[i]]]},{i,Length@linearpar3err}], PlotLegends->{"per-q fit results"}]},
PlotRange->{{0,0.25},{Min@linearpar3[[All,2]]-0.001,Max@linearpar3[[All,2]]+0.001}}, ImageSize->330, Frame->True, FrameLabel->{Style["\[Eta]",14],Style["\!\(\*SubscriptBox[\(f\), \(a\)]\)(\[Eta])",14]}, PlotLabel->{"lin+mix fit, lin term, \!\(\*SubscriptBox[\(f\), \(a\)]\)(\[Eta])="{ansatzchidifflinear}}];
lmplotm=Show[{Plot[{spindiffterm32,dfitspindiffterm32,mixfit[[1,1]]},{\[Eta],0,0.25},PlotLegends->{"direct 3D fit","fit to residuals","per-q res. fits"}, PlotStyle->{{Orange},{Magenta,Dotted},{Blue,Dashed}}],
ErrorListPlot[Table[{mixpar[[i,1;;2]],ErrorBar[1/Sqrt[mixpar[[i,-1]]]]},{i,Length@mixparerr}], PlotStyle->Red],
ErrorListPlot[Table[{mixpar[[i,1;;2]],ErrorBar[mixparerr[[i]]]},{i,Length@mixparerr}], PlotLegends->{"per-q fit results"}]},
PlotRange->{{0,0.25},{Min@mixpar[[All,2]]-0.001,Max@mixpar[[All,2]]+0.001}}, ImageSize->330, Frame->True, FrameLabel->{Style["\[Eta]",14],Style["\!\(\*SubscriptBox[\(f\), \(c\)]\)(\[Eta])",14]}, PlotLabel->{"lin+mix fit, mix term, \!\(\*SubscriptBox[\(f\), \(c\)]\)(\[Eta])="{ansatzchidiffmix}}];
lmqplotl=Show[{Plot[{spindiffterm41,dfitspindiffterm41,linearfit4[[1,1]]},{\[Eta],0,0.25},PlotLegends->{"direct 3D fit","fit to residuals","per-q res. fits"}, PlotStyle->{{Orange},{Magenta,Dotted},{Blue,Dashed}}],
ErrorListPlot[Table[{linearpar4[[i,1;;2]],ErrorBar[1/Sqrt[linearpar4[[i,-1]]]]},{i,Length@linearpar4err}], PlotStyle->Red],
ErrorListPlot[Table[{linearpar4[[i,1;;2]],ErrorBar[linearpar4err[[i]]]},{i,Length@linearpar4err}], PlotLegends->{"per-q fit results"}]},
PlotRange->{{0,0.25},{Min@linearpar4[[All,2]]-0.001,Max@linearpar4[[All,2]]+0.001}}, ImageSize->330, Frame->True, FrameLabel->{Style["\[Eta]",14],Style["\!\(\*SubscriptBox[\(f\), \(a\)]\)(\[Eta])",14]}, PlotLabel->{"lin+mix+quad fit, lin term, \!\(\*SubscriptBox[\(f\), \(a\)]\)(\[Eta])="{ansatzchidifflinear}}];
lmqplotq=Show[{Plot[{spindiffterm43,dfitspindiffterm43,quadfit2[[1,1]]},{\[Eta],0,0.25},PlotLegends->{"direct 3D fit","fit to residuals","per-q res. fits"}, PlotStyle->{{Orange},{Magenta,Dotted},{Blue,Dashed}}],
ErrorListPlot[Table[{quadpar2[[i,1;;2]],ErrorBar[1/Sqrt[quadpar2[[i,-1]]]]},{i,Length@quadparerr2}], PlotStyle->Red],
ErrorListPlot[Table[{quadpar2[[i,1;;2]],ErrorBar[quadparerr2[[i]]]},{i,Length@quadparerr2}], PlotLegends->{"per-q fit results"}]},
PlotRange->{{0,0.25},{Min@quadpar2[[All,2]]-0.001,Max@quadpar2[[All,2]]+0.001}}, ImageSize->330, Frame->True, FrameLabel->{Style["\[Eta]",14],Style["\!\(\*SubscriptBox[\(f\), \(b\)]\)(\[Eta])",14]}, PlotLabel->{"lin+mix+quad fit, quad term, \!\(\*SubscriptBox[\(f\), \(b\)]\)(\[Eta])="{ansatzchidiffquadratic}}];
lmqplotm=Show[{Plot[{spindiffterm42,dfitspindiffterm42,mixfit2[[1,1]]},{\[Eta],0,0.25},PlotLegends->{"direct 3D fit","fit to residuals","per-q res. fits"}, PlotStyle->{{Orange},{Magenta,Dotted},{Blue,Dashed}}],
ErrorListPlot[Table[{mixpar2[[i,1;;2]],ErrorBar[1/Sqrt[mixpar2[[i,-1]]]]},{i,Length@mixparerr2}], PlotStyle->Red],
ErrorListPlot[Table[{mixpar2[[i,1;;2]],ErrorBar[mixparerr2[[i]]]},{i,Length@mixparerr2}], PlotLegends->{"per-q fit results"}]},
PlotRange->{{0,0.25},{Min@mixpar2[[All,2]]-0.001,Max@mixpar2[[All,2]]+0.001}}, ImageSize->330, Frame->True, FrameLabel->{Style["\[Eta]",14],Style["\!\(\*SubscriptBox[\(f\), \(c\)]\)(\[Eta])",14]}, PlotLabel->{"lin+mix+quad fit, mix term, \!\(\*SubscriptBox[\(f\), \(c\)]\)(\[Eta])="{ansatzchidifflinear}}];
Print[{lplot,lqplotl}]
Print[{lmplotl,lmqplotl}];
Print[{lqplotq,lmqplotq,Show[lmqplotq,PlotRange->{{0.0,0.25},Automatic}]}];
Print[{lmplotm,lmqplotm,Show[lmqplotm,PlotRange->{{0.0,0.25},Automatic}]}];
(* rewrite fit and ansatz output in terms of (\[Eta],S.\[Chi]1,\[Chi]2) and not as the expanded (\[Eta],\[Chi]1,\[Chi]2) version processed by DataFitFunction *)
uneqfit2[[1,1]] = ( ansatzFinal + ansatzchidifflinear (\[Chi]1-\[Chi]2) )/.uneqfit2[[1,2]];
uneqfit2[[1,15]] = ansatzFinal + ansatzchidifflinear (\[Chi]1-\[Chi]2);
uneqfit2[[2,1]] = ( ansatzFinal + ansatzchidifflinear (\[Chi]1-\[Chi]2) + ansatzchidiffquadratic (\[Chi]1-\[Chi]2)^2 )/.uneqfit2[[2,2]];
uneqfit2[[2,15]] = ansatzFinal + ansatzchidifflinear (\[Chi]1-\[Chi]2) + ansatzchidiffquadratic (\[Chi]1-\[Chi]2)^2;
uneqfit2[[3,1]] = ( ansatzFinal + ansatzchidifflinear (\[Chi]1-\[Chi]2) + ansatzchidiffmix S (\[Chi]1-\[Chi]2) )/.uneqfit2[[3,2]];
uneqfit2[[3,15]] = ansatzFinal + ansatzchidifflinear (\[Chi]1-\[Chi]2) + ansatzchidiffmix S (\[Chi]1-\[Chi]2);
uneqfit2[[4,1]] = ( ansatzFinal + ansatzchidifflinear (\[Chi]1-\[Chi]2) + ansatzchidiffmix S (\[Chi]1-\[Chi]2) + ansatzchidiffquadratic (\[Chi]1-\[Chi]2)^2 )/.uneqfit2[[4,2]];
uneqfit2[[4,15]] = ansatzFinal + ansatzchidifflinear (\[Chi]1-\[Chi]2) + ansatzchidiffmix S (\[Chi]1-\[Chi]2) + ansatzchidiffquadratic (\[Chi]1-\[Chi]2)^2;
Print[Style["total fit (linear in spindiff) to all data:",Blue]];
Print[uneqfit2[[1,1;;8]]];
Print[Style["total fit (linear+ quadratic in spindiff) to all data:",Blue]];
Print[uneqfit2[[2,1;;8]]];
Print[Style["total fit (linear in spindiff + spineff*spindiff) to all data:",Blue]];
Print[uneqfit2[[3,1;;8]]];
Print[Style["total fit (linear+quadratic in spindiff + spineff*spindiff) to all data:",Blue]];
Print[uneqfit2[[4,1;;8]]];
Print[Style["----------------", Blue]];
(* 2DeqS 2Dall 3Dlin 3Dlinquad 3Dlinmix 3Dlinquadmix 1D2Dparts 1Deta 1DS 2DSansatz *)
Return[{eqdatafitv2, alldataeqfitv2, uneqfit2[[1;;1]], uneqfit2[[2;;2]], uneqfit2[[3;;3]], uneqfit2[[4;;4]], extraStuff, nsfits, q1fits, spinpart}];];
]
AnsatzRestrictions[q1fit_,ansatzGen_,var_,varval_,OptionsPattern[{"Parameters"->False}]]:=Module[{ansatz,nsdegree,q1degree,expans,coeffs1,coeffs2,q1var,coeff\[Eta],expns,coeffS,sys,
coeffs,solveVars,solNS,ansatzS,solq1,ansatzFinal,parameters},
parameters=OptionValue["Parameters"];
ansatz=ansatzGen;
q1var=Variables[q1fit][[1]];
expans= Exponent[ansatz,q1var];
expns = Exponent[q1fit, q1var];
coeffs1= CoefficientList[Collect[ansatz,S],q1var];
solveVars= CoefficientList[#,var]&/@ coeffs1;
solveVars = Last/@\[NonBreakingSpace]Select[solveVars, Length@# > 0 &];
solveVars =Select[AtomsList[solveVars],!NumberQ[#1]&];
Print["solveVars: ", solveVars];
Print["q1fit: ", q1fit];
coeffs1=Select[CoefficientList[Collect[ansatz,S],q1var]/. var->varval,Not@NumberQ@#&];
coeffs2 = Drop[CoefficientList[q1fit,q1var],1]; (* this won't always work *)
(*
Print["coeffs1: ", coeffs1];
Print["coeffs2: ", coeffs2];
*)
sys=Table[coeffs1[[i]]==coeffs2[[i]],{i,Min[Length@coeffs1,Length@coeffs2]}];
(*
Print["sys: ",sys];
*)
coeffs=Drop[Select[AtomsList[ansatz/.var-> varval],!NumberQ[#1]&],-1];
(*
Print["coeffs:", coeffs[[1;;Min[expans+1,expns+1]]]];
*)
solq1=Simplify@First[Solve[sys,solveVars]];
ansatzFinal=ansatz/. solq1;
Print["Applying q=1 restriction : ",solq1 ];
(*Print["Applying q=1 restriction : ",solq1//TableForm ];*)
If[parameters,solq1,ansatzFinal]
];
AnsatzRestrictions[q1fit_,ansatzGen_,OptionsPattern[{"Parameters"->False}]]:=Module[{ansatz,nsdegree,q1degree,expans,coeffs1,coeffs2,q1var,coeff\[Eta],expns,coeffS,sys,coeffs,solveVars,
solNS,ansatzS,solq1,ansatzFinal,parameters},
parameters=OptionValue["Parameters"];
ansatz=ansatzGen;
q1var=Variables[q1fit][[1]];
expans= Exponent[ansatz,q1var];
expns = Exponent[q1fit, q1var];
coeffs1= CoefficientList[Collect[ansatz,S],q1var];
solveVars= CoefficientList[#,\[Eta]]&/@ coeffs1;
solveVars = Last/@\[NonBreakingSpace]Select[solveVars, Length@# > 0 &];
solveVars =Select[AtomsList[solveVars],!NumberQ[#1]&];
Print["solveVars: ", solveVars];
Print["q1fit: ", q1fit];
coeffs1 = Select[CoefficientList[Collect[ansatz,S],q1var],Not@NumberQ@#&]/. \[Eta]->0.25;
(* coeffs2 = Take[CoefficientList[q1fit,q1var],-Length@coeffs1] (* won't always work *); *)
coeffs2 = Coefficient[q1fit,q1var^Sort@Select[Exponent[MonomialList[ansatz,q1var],q1var],#>0& ] ]; (* this should work more generally, unless maybe for non-exact S-independent constant coefficients...? *)
Print["coeffs1: ", coeffs1];
Print["coeffs2: ", coeffs2];
sys=Table[coeffs1[[i]]==coeffs2[[i]],{i,Min[Length@coeffs1,Length@coeffs2]}];
Print["sys: ",sys];
coeffs=Drop[Select[AtomsList[ansatz/. \[Eta]->0.25],!NumberQ[#1]&],-1];
(*
Print["coeffs:", coeffs[[1;;Min[expans+1,expns+1]]]];
*)
solq1=Simplify@First[Solve[sys,solveVars]];
ansatzFinal=ansatz/. solq1;
Print["Applying q=1 restriction : ",solq1//TableForm ];
If[parameters,solq1,ansatzFinal]
];
AnsatzRestrictions[nsfit_,q1fit_,ansatzGen_,OptionsPattern[{"Parameters"->False}]]:=Module[{ansatz,nsdegree,q1degree,expans,expns,nsvar,q1var,coeff\[Eta],coeffS,sys,coeffs,solNS,ansatzS,
solq1,ansatzFinal,parameters},
parameters=OptionValue["Parameters"];
ansatz=ansatzGen;
nsvar=Variables[nsfit][[1]];
q1var=Variables[q1fit][[1]];
Print["nsvar: ", nsvar];
Print["q1var: ", q1var];
expans= Exponent[ansatz,nsvar];
expns = Exponent[nsfit, nsvar];
Print["expans: ", expans];
Print["expns: ", expns];
sys=Table[CoefficientList[Collect[ansatz/. q1var->0,nsvar],nsvar][[i]]==CoefficientList[nsfit,nsvar][[i]],{i,Min[expans+1,expns+1]}];
Print["sys: ",sys];
If[Length@Select[sys,Not@TrueQ]==0,
ansatzS=ansatz,
Print[Style["Something is wrong with the restrictions",Red]]
];
Print["Applying non-spinning restriction : ", ansatz//TableForm ];
expans= Exponent[ansatz,q1var];
expns = Exponent[q1fit, q1var];
Print["expans: ", expans];
Print["expns: ", expns];
sys=Table[CoefficientList[Collect[ansatzS/. nsvar->0.25,S],q1var][[i]]==CoefficientList[q1fit,q1var][[i]],{i,Min[expans+1,expns+1]}];
Print["sys: ",sys];
coeffs=Drop[Select[AtomsList[ansatzS/. nsvar->0.25],!NumberQ[#1]&],-1];
Print["coeffs: ",coeffs];
solq1=First[Solve[sys,coeffs[[1;;Min[expans+1,expns+1]]]]];
ansatzFinal=ansatzS/. solq1;
Print["Applying q=1 restriction : ",solq1//TableForm ];
If[parameters,solq1,ansatzFinal]
];
Plot2DFits[data_?ListQ,fitlist_?ListQ,fitvars_?ListQ,OptionsPattern[{"PlotRange"->Automatic,"ShowLegend"->True,"zLabel"->"","ToolTipTags"->"","Outliers"->0.005}]]:=Module[{myfitlist,fitdata,myresidual,styles,plotrange,pos,myvar1,myvar2,
myminvar1,mymaxvar2,mymaxvar1,myminvar2,myfitlistfunc,plot1,plot2,plot3,plottab,showlegend,zlabel,tooltiptags,myresidualhist,posoutliers,outliers,mylegend},
plotrange=OptionValue["PlotRange"];
showlegend=OptionValue["ShowLegend"];
zlabel=OptionValue["zLabel"];
tooltiptags=OptionValue["ToolTipTags"];
outliers=OptionValue["Outliers"];
myfitlist=Flatten[TakeColumn[#,1]&/@fitlist,1];
myvar1=Evaluate@Symbol@ToString@fitvars[[1]];
myvar2=Evaluate@Symbol@ToString@fitvars[[2]];
If[ListQ@plotrange,
myminvar1=plotrange[[1,1]];
mymaxvar1=plotrange[[1,2]];
myminvar2=plotrange[[2,1]];
mymaxvar2=plotrange[[2,2]];
,
myminvar1=Min[data[[All,1]]];
mymaxvar1=Max[data[[All,1]]];
myminvar2=Min[data[[All,2]]];
mymaxvar2=Max[data[[All,2]]];
];
myfitlist=(#/.myvar1->x/.myvar2->y)&/@myfitlist;
Print[Length[data]," data points, variables plotted -> ",{myvar1, myvar2}];
If[showlegend,
mylegend=(myfitlist/.x->myvar1/.y->myvar2);
Print[plot1=Show[{Plot3D[myfitlist,{x,myminvar1,mymaxvar1},{y,myminvar2,mymaxvar2},PlotStyle->Drop[ColorData[3,"ColorList"],1],PlotLabel->Style[ToString[zlabel],14,Black],PlotLegends->mylegend,Lighting->Automatic,PlotRange->plotrange,
AxesLabel->{Style[ToString@myvar1,14,Black],Style[ToString@myvar2,14,Black],""}],ListPointPlot3D[data,PlotStyle->PointSize[0.025]]}]],
Print[plot1=Show[{Plot3D[myfitlist,{x,myminvar1,mymaxvar1},{y,myminvar2,mymaxvar2},PlotStyle->Drop[ColorData[3,"ColorList"],1],PlotLabel->Style[ToString[zlabel],14,Black],Lighting->Automatic,PlotRange->plotrange,
AxesLabel->{Style[ToString@myvar1,14,Black],Style[ToString@myvar2,14,Black],""}],ListPointPlot3D[data,PlotStyle->PointSize[0.025]]}]]
];
plottab=Table[
Print[myfitlist[[j]]/.x->myvar1/.y->myvar2];
fitdata=Transpose[{data[[All,1]],data[[All,2]],Table[myfitlist[[j]]/.x->data[[i,1]]/.y->data[[i,2]],{i,Length@data}]}];
myresidual=Transpose[{data[[All,1]],data[[All,2]],fitdata[[All,3]]-data[[All,3]]}];
myresidualhist=myresidual[[All,3]]/fitdata[[All,3]];
Print[{plot2=Show[ListPointPlot3D[data,PlotStyle->PointSize[0.025],PlotRange->All],
Plot3D[myfitlist[[j]],{x,myminvar1,mymaxvar1},{y,myminvar2,mymaxvar2},PlotLabel->Style[ToString[zlabel],14,Black],
AxesLabel->{Style[ToString@myvar1,14,Black],Style[ToString@myvar2,14,Black],""},ImageSize->350,
PlotStyle->Drop[ColorData[3,"ColorList"],1][[j]],Lighting->Automatic,PlotRange->plotrange],AxesLabel->{Style[ToString@myvar1,14,Black],
Style[ToString@myvar2,14,Black],""}],
plot3=myListPlot3D[myresidual,PlotLabel->Style[ToString["residual"],14,Black],PlotRange->plotrange,ImageSize->350,AxesLabel->{Style[ToString@myvar1,14,Black],
Style[ToString@myvar2,14,Black],""},PlotStyle->Drop[ColorData[3,"ColorList"],1][[j]]],
If[Length@fitlist[[j,1]]==1,"No stats. available",fitlist[[j,1,3]]],Show[Histogram[myresidualhist,100],Frame->True,FrameLabel -> {"1-data/fit", "#"}],
ListPlot[Table[Tooltip[myresidualhist[[i]],If[ListQ@tooltiptags,tooltiptags[[i]],ToString[{data[[i,1]],data[[i,2]]}]]],{i,Length@myresidualhist}],PlotRange->All,Frame->True,FrameLabel -> {"#","1-data/fit"}],
Sqrt@Mean[myresidual[[All,3]]^2],
Select[(Reverse@SortBy[Transpose[{Abs@myresidualhist,If[ListQ@tooltiptags,tooltiptags,data[[All,1;;2]]]}],First]),#[[1]]>outliers&][[All,2]]//TableForm
}];
{plot2,plot3}
,{j,Length@myfitlist}];
Return[{plot1,plottab}]
]
(* ::Code::Initialization:: *)
End[];
EndPackage[];