From 500c5234cfd1e4b8cf2209e00cd332d8033efb2e Mon Sep 17 00:00:00 2001 From: ppetrak Date: Fri, 16 Dec 2022 18:55:43 +0100 Subject: [PATCH] clean-up --- examples/example_combined_fit.ipynb | 216 ++++++++++------------------ pyerrors/combined_fits.py | 216 ---------------------------- pyerrors/fits.py | 18 +-- 3 files changed, 81 insertions(+), 369 deletions(-) delete mode 100644 pyerrors/combined_fits.py diff --git a/examples/example_combined_fit.ipynb b/examples/example_combined_fit.ipynb index 811ee84c..e658e7da 100644 --- a/examples/example_combined_fit.ipynb +++ b/examples/example_combined_fit.ipynb @@ -55,19 +55,19 @@ "Fit with 3 parameters\n", "Method: migrad\n", "Optimization terminated successfully.\n", - "chisquare/d.o.f.: 1.1407448193242595\n", - "fit parameters [0.98418071 0.95797691 1.52431702]\n", - "chisquare/expected_chisquare: 1.1485431097238927\n" + "chisquare/d.o.f.: 0.3395164548834892\n", + "fit parameters [0.98791658 1.00784727 1.56875359]\n", + "chisquare/expected_chisquare: 0.339844373345418\n" ] } ], "source": [ - "output_test = pe.fits.least_squares(x_test,y_test,funcs_test,method='migrad',expected_chisquare=True)" + "output_test = pe.fits.least_squares(x_test,y_test,funcs_test,expected_chisquare=True)" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "id": "technological-rolling", "metadata": {}, "outputs": [], @@ -77,7 +77,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "id": "persistent-mathematics", "metadata": {}, "outputs": [ @@ -86,13 +86,13 @@ "output_type": "stream", "text": [ "Goodness of fit:\n", - "χ²/d.o.f. = 1.140745\n", - "χ²/χ²exp = 1.148543\n", - "p-value = 0.3293\n", + "χ²/d.o.f. = 0.339516\n", + "χ²/χ²exp = 0.339844\n", + "p-value = 0.9620\n", "Fit parameters:\n", - "0\t 0.984(33)\n", - "1\t 0.958(32)\n", - "2\t 1.524(42)\n", + "0\t 0.988(35)\n", + "1\t 1.008(32)\n", + "2\t 1.569(42)\n", "\n" ] } @@ -103,13 +103,13 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "id": "wooden-potential", "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWoAAAD4CAYAAADFAawfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAyDUlEQVR4nO3de3zO9f/H8cfboc2wSqgtQipzFityGiqVJOVUpvhKtuUcETnMIVH4McYMkUjO1EKpWM7MzPmQ0xxymNOQbTbX+/fH2ynH4br2uXZdr/vtdt1yXbv2uV7z/Xp6eX/eB6W1RgghhPPKYnUBQggh7kyCWgghnJwEtRBCODkJaiGEcHIS1EII4eSyOeKiefPm1YULF3bEpYUQwiWtX7/+hNY6362+5pCgLly4MDExMY64tBBCuCSlVPztviZDH0II4eQkqIUQwslJUAshhJNzyBj1raSmpnLo0CGSk5Mz6iOdmqenJwUKFCB79uxWlyKEcHIZFtSHDh0id+7cFC5cGKVURn2sU9Jac/LkSQ4dOkSRIkWsLkcI4eQybOgjOTmZxx57zO1DGkApxWOPPSb/uhBCpEuGjlFLSF8jvxdCiPSSm4lCCOHkJKiFEOIBhIaGopS66REaGmq3z3CroA4LC6N48eIEBgZaXYoQwkWEhoaitSYgIICAgAC01mit7RrUGTbrwxmMHj2a33//nQIFClhdihBCpJs1Qd2xI8TF2fea5crB8OG3/XJwcDB79+7ljTfe4MCBA/Tq1YsuXboAUKpUKaKiogB44403qFq1KitXruTJJ59k/vz55MiRg927dxMcHExCQgJZs2Zl5syZFC1a9KbPOX/+PG+//TanT58mNTWVAQMG8Pbbb9v3ZxVCuBW3GfqIiIjA19eXJUuW0KlTp9u+7++//6ZNmzZs3bqVRx55hNmzZwMQGBhImzZt2LhxIytXrsTHx+eW3+/p6cncuXOJjY1lyZIldO7cGTmXUgjxIKzpqO/Q+VqtSJEilCtXDoAKFSqwf/9+zp07x+HDh3nnnXcAE8a3o7WmR48e/PXXX2TJkoXDhw9z7NgxnnjiiYwoXwjhgtxqjPqKbNmyYbPZrj6/fuGJh4fH1V9nzZqVpKSke7r21KlTSUhIYP369WTPnp3ChQvLwhYh3MClS5f4999/HXJttxn6uF7hwoWJjY0FIDY2ln379t3x/blz56ZAgQLMmzcPgJSUFC5cuHDL9yYmJpI/f36yZ8/OkiVLiI+/7RazQggXMW/ePNauXcuGDRvYu3ev3a/vlkHdoEEDTp06RcmSJRk1ahTPPffcXb/n+++/JywsjDJlylC5cmWOHj16y/cFBgYSExND6dKlmTx5Mn5+fvYuXwjhJA4cOMDbb7/NO++8c/Vf6UOGDLH75yhH3Ojy9/fXN57wsn37dooXL273z8rM5PdEiMwpNTWVESNG0KdPn9v+69rT0/Oehk6VUuu11v63+ppbdtRCCHG/Vq9ejb+/P5999hm1atVizZo1NG3alCxZTJx6eXkRGBh41yHVe+GWNxPtYfPmzXzwwQf/ec3Dw4M1a9ZYVJEQwpFOnz5Njx49GDt2LL6+vsyePZt33nkHpRTe3t7YbDayZMlCcnIy3t7edp3pJUF9n0qXLk2cvRftCCGcjtaaadOm0alTJ06cOEH79u3p378/uXPnvvqeY8eO4evri4+PDxUrVuTIkSN2rUGCWgghbmP37t2EhITw+++/4+/vz8KFCylfvvxN75szZw41atQAIDw83O51yBi1EELcICUlhf79+1OqVCnWrFnDyJEjWb169S1DOiNIRy2EENdZsmQJISEh7Ny5k8aNG/N///d/+Pr6WlqTdNRCCAEkJCTQvHlzatWqxcWLF1m4cCHTp0+3PKTBzYI6I/ajXrp0KXXr1nXY9YUQ9mWz2Rg/fjzFihVj2rRp9OjRgy1btvD6669bXdpVbjX0IftRCyGut2XLFoKDg1mxYgXVqlUjIiKCEiVKWF3WTSwJ6o4dO9p9alu5cuUY7gT7UQOcPXuWN998k927d1OzZk1Gjx59dTK8EMJ6Fy5coF+/fgwdOhRvb28mTJhAixYtnPbPqXNW5QAZtR81wNq1axk5ciTbtm1jz549zJkzx+4/jxDi/ixYsICSJUsyePBgmjVrxs6dO2nZsuV9h/SVMxOjo6OJjo52yJmJlnTUd+p8rfag+1EDvPjiizz99NMAvP/++yxfvpyGDRs6tG4hxJ0dPnyYjh07MmvWLPz8/Fi6dCkBAQEPfN3Q0FC7hvKtuE1Hfb172Y86LS3tnq+vlLrjcyFExrl06dLViQRRUVEMGDCAuLg4u4R0RnHLoHbkftRghj727duHzWZj+vTpVK1a1W61CyHSLyYmhooVK9KhQwdeeukltmzZwhdffPGfhiwzSFdQK6U6KaW2KqW2KKWmKaXu/G9/J+fI/agBXnjhBdq2bUvx4sUpUqTI1SETIUTGOHv2LO3bt6dixYocPnyYH3/8kUWLFt12AoCzu+t+1EqpJ4HlQAmtdZJSagawQGs96XbfI/tRp4/8nghhX1prZs+eTYcOHThy5AghISF8+eWXPPLII1aXdlf22I86G5BDKZUN8AL+sVdxQghhD/v27aNu3bo0atSI/Pnzs3r1asLDwzNFSN/NXWd9aK0PK6WGAAeAJOA3rfVvDq/Mycl+1EI4h9TUVIYOHUq/fv3IkiULw4YNo127dmTL5jrr+e76kyilHgXeBooAZ4CZSqlmWuspN7yvNdAa4KmnnrJ/pU5G9qMWwnrLly8nODiYrVu3Ur9+fcLCwihYsKDVZdldeoY+XgH2aa0TtNapwByg8o1v0lpHaq39tdb++fLls3edQghx1cmTJ2nVqhXVqlXj3LlzzJ8/n7lz57pkSEP6gvoAUEkp5aXMhOCXge2OLUsIIW6mtWby5Mn4+fkxadIkunTpwtatW6lXr57VpTnUXYNaa70GmAXEApsvf0+kQ6sKDQWlbn44ePWPEMJ57dixg1q1atG8eXOeeeYZYmNj+eabb8iVK5fVpTlcumZ9aK37aK39tNaltNYfaK1THFpVaChoDQEB5qG1eUhQC+F2kpOT6d27N2XLliUuLo6IiAhWrFhBmTJlrC4twzj3bdGUFNi+HY4eBTue6CuEyBwWL17MJ598wu7duwkMDGTo0KE8/vjjVpeV4Zx7CXl8PCQmQr9+drlc/fr1qVChAiVLliQy0rGjN0KI+3f06FGaNm1K7dq1ARPYU6ZMccuQBmcN6hw5zJj0lSPXx4wxz3PkeKDLfvvtt6xfv56YmBjCwsI4efKkHYoVQlxxZcvPGx/p3V3OZrMRERGBn58fs2fPpnfv3mzevJlXXnnFsYU7OecM6r17oWlTuLI/rJcXBAbCXTZPupuwsDDKli1LpUqVOHjwIH///bcdihVCXBEaGorWmoCAAAICAtBao7VOV1Bv3LiRypUrExISQvny5dm0aRN9+/a967bC7sA5g9rHB7y9wWYzYZ2cbJ4/wDj10qVL+f3331m1ahUbN27k+eef/8/2pkIIa5w/f54uXbpQoUIF9u7dy+TJk/njjz8oVqyY1aU5Dee9mXjsGPj6mtCuWPHaMMh9SkxM5NFHH8XLy4sdO3awevVqOxUqhLhf8+fPp127dhw8eJCPP/6YQYMGkSdPHqvLcjrO2VEDzJkDzz4LuXJBeLh5/gBef/110tLSKF68OJ9//jmVKlWyU6FCiBulpKQQFxd32+2ADx48SP369alfvz4PP/wwy5cvJzIyUkL6Npy3o7YzDw8PFi5caHUZQriF+Ph4EhMT6devH6NHj776elpaGmFhYfTu3RubzcbgwYPp1KkT2bNnt7Ba5+ecHfWVlYnR0eYhKxOFyBRy5MiBUoojl4cqx4wZg1KKHDlysGbNGvz9/encuTM1atRg27ZtdO3aVUI6HZw3qK+sRrz+IUEthFPbu3cvTZs2vXqit5eXF40aNaJJkya89NJLJCQkMGvWLH7++WcKFy5sbbGZiNsMfQghHM/Hxwdvb29sNhtZsmQhKSmJqKgoUlJSaN++Pf369cPb29vqMjMdCWohhF0dO3aM/Pnzk5SUxLlz5/Dw8GDZsmVUqFDB6tIyLecc+hBCZEopKSmUL1+ehIQELly4QFhYGCdOnJCQfkBOGdQPugxVCJHxli5dSrly5ejVqxd58+blhRdeoF27dmTNmtXq0jI9pw3q+12Gejv79++nVKlS9itSCAFAQkICLVq0oGbNmqSkpLBgwQJKlCiBh4eH1aW5DKcM6ivuNmleCGEdm83GhAkT8PPzY+rUqXTv3p0tW7bwxhtvWF2ay3HqoL5+0rw9pKWlERgYSPHixWnYsCEXLlywy3WFcDdbt24lICCAVq1aUbJkSeLi4hg4cCBeXl5Wl+aSnDKo7zRp/kHs3LmTTz75hO3bt+Pt7f2fFVNCiLu7cOEC3bt3p1y5cmzbto0JEyawdOlSSpYsCVy7vxQdHU10dLTcX7ITpwzqW02aDwwMZN8DbnNasGBBqlSpAkCzZs1Yvnz5A9cqhLtYuHAhpUqVYtCgQQQGBrJjxw5atmx59c8pXLu/dONDgvrBOGVQ3zhpPjk5GW9vb554wOO4zCHqt38uhLjZP//8Q+PGjalTpw4eHh4sWbKESZMmkS9fPqtLcxtOGdRgJs37+vry/PPPExwcbJcbigcOHGDVqlUA/PDDD1StWvWBrymEq7p06RIjR47Ez8+Pn376if79+xMXF0eNGjWsLs3tOO3KxDlz5lz9P0R4eLhdrlmsWDHCw8Np2bIlJUqUICQkxC7XFcLVxMbGEhQURExMDLVr1yY8PJxnnnnG6rLcltMGtb0VLlyYHTt2WF2GEE7t7Nmz9OrVi1GjRpEvXz6mTZtGkyZNZJjQYk459CF3joXIWFprZs+eTfHixRk5ciTBwcHs2LGD9957T0LaCThlRx0aGiqhLEQG2b9/P23atGHBggWUK1eOOXPmULFiRavLEtfJ0I5aa52RH+fU5PdCWC01NZXBgwdTokQJoqOjGTZsGOvWrZOQdkIZ1lF7enpy8uRJHnvsMbf/p5TWmpMnT+Lp6Wl1KcJNrVixgqCgILZu3Ur9+vUJCwujYMGCVpclbiPDgrpAgQIcOnSIhISEjPpIp+bp6UmBAgWsLkO4mVOnTtGtWzfGjx/PU089xfz586lXr57VZYm7yLCgzp49O0WKFMmojxNCXEdrzZQpU+jcuTOnTp2iS5cu9OnTh1y5clldmkgHp7yZKISwn507dxISEsKSJUuoVKkSixcvpmzZslaXJe6BU07PE0I8uOTkZPr06UOZMmXYsGEDERERrFixQkI6E5KOWggX9PvvvxMSEsLu3btp2rQpw4YN4/HHH7e6LHGfpKMWwoUcO3aMwMBAXn31VQAWL17M1KlTJaQzOQlqIVyAzWZj7NixFCtWjFmzZtG7d282b97MK6+8YnVpwg5k6EOITG7Tpk0EBQWxevVqatasyZgxYyhWrJjVZQk7ko5aiEzq33//5bPPPqN8+fLs2bOHyZMn88cff0hIuyDpqIXIhH766SfatWvHgQMH+Pjjjxk0aBB58uSxuizhIBLUQmQiBw8epH379sybN49SpUqxfPnyq8fLCdclQx9CZAJpaWkMGzaM4sWL8+uvvzJo0CBiY2MlpJ1BaCgodfPDjjuAKkfs4ubv769jYmLsfl0h3NHatWsJCgoiLi6OOnXqMGrUKNmOwRldOaJs6dL7+nal1Hqttf+tvpaujlop9YhSapZSaodSartS6qX7qkQIkW6JiYm0adOGSpUqcfz4cWbNmkVUVJSEtBtK7xj1CGCR1rqhUuohwMuBNQnh1rTWTJ8+nU6dOnH8+HHat29Pv3798Pb2tro0cTv79plHUpJDLn/Xjlop9TBQHZgAoLW+qLU+45BqhHBze/bs4fXXX+f999+nQIECrF27luHDh0tIO6PUVJg9G157DZ5+Gg4cgNOnIT7e7h+VnqGPIkACMFEptUEpNV4plfPGNymlWiulYpRSMbLntBD3JiUlhQEDBlCqVClWrVrFyJEjWb16NRUqVLC6NHGjPXuge3coWBAaNoRt28yNw/z5IS0NBg+2/2dqre/4APyBNKDi5ecjgP53+p4KFSpoIdxdnz59NHDTo0+fPv9539KlS7Wfn58GdKNGjfThw4etKVjcXkqK1jNmaP3KK1qD1lmyaF2vntZRUVp7eprXbnx4et7TRwAx+nY5fLsv6GtB/QSw/7rn1YBf7vQ9EtRCXBMQEKADAgJuej0hIUE3b95cA7pIkSJ6wYIFGV+cuLNdu7Tu2lXrfPlMXD71lNb9+ml96NC19/zzj9ZNm5rwBq29vLQODNT6yJF7+qg7BfVdbyZqrY8qpQ4qpYpprXcCLwPb7NnVC+FObDYbkyZN4rPPPuPs2bN0796dnj174uUl9+idQkoKzJsHkZHw55+QNSu89Ra0bg21a5vn1/PxAW9vsNkgSxZITjbPn3jCbiWld9ZHO2Dq5Rkfe4H/2a0CIVxcSkoK27dv5+jRo5w8eZKQkBCWLVtGtWrVGDNmDCVLlrS6RAGwaxeMGweTJsGJE1C4MAwYAP/7H/j63vl7jx0z7/HxgYoV4cgRu5aWrqDWWsdhxqqFEPcoPj6exMRE6tSpw+bNm/H29mbChAm0aNGCLFlkcbClkpNh7lzTPS9dCtmyQb16pnt+9VXTIafHnDnXFryEh9u9TNnrQwgHyZEjB8nJyVefb9iwATC73rVs2dKqsgTAjh2me/7uOzh50kyvGzgQWrQwXbGTkb/OhXCQlStX8tRTT1197uHhQWBgIPv377euKHeWnAxTp0L16lC8OISFQc2a8Ntv8PffZsqdE4Y0SEcthN1dunSJMWPG8MUXX3D+/HkAlFKkpqbi7e3NE3a8ySTSYdu2a93z6dNQtCgMGmS650xyRJkEtRB2FBsbS1BQEDExMdSuXRutNVu3bsXHx4eKFStyxM43mcRtJCXBrFkwdiysWAHZs8O775qx5xo10j/2nB6hodC377XnSpn/9uljtx30ZPc8Iezg3Llz9OrVi5EjR5IvXz6GDx9OkyZNUEpR4/JNpqX3uauauAdbtpjuefJkOHMGnn3WhHPz5pAvn9XV3dGdds+TjlqIB6C1Zu7cubRv355//vmHkJAQvvzySx555BGrS3MfFy7AjBlm5saqVfDQQ9CggQnogIBrHW4mJkEtxH3av38/7dq1IyoqinLlyjF79mwqVqxodVnuY9MmE85TpkBiIhQrBkOHwocfQt68VldnVzLrQ4h7lJqaytdff03JkiVZsmQJQ4cOZd26dTeFdGhoKEopoqOjiY6ORimFUopQO5784Xb+/Re+/RYqVYKyZWH8eKhbF6KjYft2+PRTlwtpkDFqIe7JypUrCQoKYsuWLdSvX58RI0b8ZwqecJC4ONM9T50KZ8+a6XWtW8MHH8Bjj1ldnV3IGLUQD+jUqVN8/vnnjBs3joIFCzJ//nzq1atndVmu7fx5+PFHE9Dr1oGHBzRubAK6ShWXGHtOLwlqIe5Aa82UKVPo3Lkzp06dokuXLvTp04dcuXJZXZrrio291j2fPw8lSsCIEdCsGeTJY3V1lpCgFuI2du3aRUhICH/++SeVKlVi8eLFlC1b1uqyXNO5czBtmgno9evB0xOaNDHd80svuVX3fCsS1ELcIDk5mUGDBvHVV1/h5eVFREQEH3/8sWygZG9am1COjIQffjA3CkuVgpEjITAQHn3U6gqdhvw/T4jr/PHHH5QpU4a+ffvSsGFDduzYQVBQkIR0eoWGmu73xsf1M13OnoWICKhQAV54wUyva9zYzIHetAnatpWQvoF01EIAx44do3PnzkydOpVnnnmG3377jVdffdXqsjKf0FDzuLLl55XVmFrD2rWme542zSxSKVPGbAkaGAgPP2xNvZmEBLVwazabjfHjx9OtWzcuXLhA79696d69O56enlaX5hoSE81NwchI2LgRvLzg/ffN2PMLL7j92HN6SVALt7Vp0yaCg4NZtWoVNWrUYMyYMfj5+VldVuantdnjeedOs21oUhKUKwdjxkDTpuaYKnFPZOBNuJ1///2Xrl27Ur58ef7++28mT57Mn3/+KSH9oM6cgVGjzIrBLVsgNdUcZ7VunZlyFxwsIX2fpKMWbiUqKoq2bdsSHx9Pq1atGDx4MHncdG6uXWhtbgJGRpqNkZKS/vv17dvNEIen581fE+kmHbVwC4cOHeLdd9/lrbfeIleuXCxbtoxx48ZJSN+v06fNCSmlS5tVgrNnm82QFi0ywxtXZsl4eZmbhfv2WVtvJidBLVxaWloaw4cPp3jx4ixatIhBgwYRGxtL1apVrS4t89Eali83gezrCx06QM6cZmOkI0fMlLvXXjPDGzabCevkZPNcTrV5IDL0IVzW2rVrCQ4OZsOGDdSpU4dRo0ZRpEgRq8vKfE6ehO+/N8Mb27eb4G3ZEj7+2NwkvNGxYybIfXygYkUT4uKBSFALl5OYmMgXX3zB6NGj8fHxYebMmTRo0AAlU8HST2tYtsyE86xZkJJithb99luzOCVnztt/75w51+ZRh4dnSLmuToJauAytNTNmzKBjx44cP36cdu3a0b9/f7xlpkH6nThhjrGKjDTT6x5+2HTOH39sFqgIS0hQC5ewd+9e2rRpw6JFi6hQoQJRUVFUqFDB6rIyB63NxvuRkeam4MWLULkyTJoEjRqZG4LCUnIzUWRqFy9eZODAgZQsWZIVK1YQFhbGmjVrJKTTIyEBhgwxR1jVrAkLF5q5zps3m5O7mze/95C+stdHdLR53GqvD3HP5IQXkWn99ddfBAcHs337dho2bMjw4cN58sknrS7LudlsZv+NyEgzlpyaClWrmiXdDRtCjhxWV+i25IQX4VJOnDhB165dmThxIoULF+aXX36hTp06Vpfl3I4fN0MZ48bB7t1md7o2bczYc4kSVlcn7kKCWmQaWmsmTZrEZ599RmJiIp9//jm9evXCS8ZQb81mgz/+MN3z/Pmme65e3QxDNGhgVguKTEGCWmQK27ZtIyQkhL/++osqVaoQERFBqVKlrC7LOR09ChMnmu553z5z+Gu7dqZ7lv1MMiUJauHUkpKSGDBgAN988w25c+dm/Pjx/O9//5ON/G9ks8HixaZ7/uknSEszc5m//BLeeUe650xOglo4rV9//ZVPPvmEvXv38uGHHzJkyBDy5ctndVnO5Z9/TPc8fjzs3w9580KnTtCqFTz3nNXVCTuRoBZO58iRI3Tq1Inp06dTrFgx/vzzT2rWrGl1Wc7j0iX47TfTPf/8s3n+8ssweDC8/TZ4eFhdobAzCWrhNC5dukRERAQ9evQgJSWFfv360bVrVzwkeIzDh80S7vHj4cAByJ8funQx3fMzz1hdnXAgCWrhFDZs2EBQUBDr1q3jlVdeYfTo0Tz77LNWl2W9S5fM1qGRkRAVZcaiX30Vhg6FevXgoYesrlBkAAlqYalz587Ru3dvwsLCyJcvHz/88APvvfeebKB08KDpnidMML9+/HHo1g0++giKFrW6OpHBJKiFJbTWzJs3j/bt23P48GGCg4MZOHAgjzzyiNWlWSctzSzjjoyEBQvMHhy1a8Pw4fDWW5A9u9UVCotIUIsMFx8fT7t27fj5558pU6YMM2fOpFKlSlaXZZ0DB0znPGGCGYd+4gno3t10z7J/tkCCWmSgXr16MWDAgP+8tmnTJhYtWuR+QZ2WBr/8YrrnhQvNa6+/bg6HffNN6Z7Ff6Q7qJVSWYEY4LDWuq7jShKuaNWqVcyfPx+ARx99lLS0NHbt2sUTrnxEU2go9O178+vVqsGePWYOtK8v9OxpuudChTK8RJE53Mvyrg7AdkcVIlzT6dOnCQoKonLlypw5c4Z58+bh6enJuXPn6Nevn9XlOVZoqBlnrljRbBdas6bZ8nPFCihf3uy/ER8P/fpJSIs7SldQK6UKAG8C4x1bjnAVWmumTp2Kn58fEyZM4NNPP+X48ePUr1+fI5fP0BszZgxKKXK46taa+/bBF1/AunVw4QKsXQu9e5sVhD//bKbXZZPRR3F36e2ohwNdAdvt3qCUaq2UilFKxSQkJNijNpFJ7dq1i1dffZVmzZpRpEgRYmJiGDp0KPv27aNp06ZX9+nw8vIiMDCQffv2WVyxHaWmmlNSXnsNnn4aBg40c58B/v3XDIXI0m5xj+4a1EqpusBxrfX6O71Pax2ptfbXWvvLfgzuKSUlhb59+1K6dGliYmIYPXo0K1asoNzlk6p9fHzw9vbGZrORJUsWkpOT8fb2do1x6j17zEyNggXNBvw7dsBnn0H9+nBlAykvLwgMNJ22EPcgPf/uqgLUU0rVATwBb6XUFK11M8eWJjKTP//8k5CQEHbt2sX777/PsGHDbhnAx44dw9fXFx8fHypWrHh1GCRTunjRjDNHRsLvv0PWrGa+c+vWZv5z1qwQEmI66ixZIDkZvL3N9Dsh7sFdg1pr3R3oDqCUqgF0kZAWVxw/fpzOnTszZcoUihYtyq+//krt2rVv+/45c+ZQo0YNAMLDwzOoSjv7+2+z38bEiebcwUKFYMAA+N//zCyO6x07Zl7z8TE3FTPzX0zCMnInQ9wXm83GhAkT6NatG+fPn6dnz5706NHDdW8MpqTAvHmme/7zT9Mtv/226Z5fecU8v5U5c8y+0ACZ9S8mYbl72n1da71U5lCLzZs3U61aNVq3bk2ZMmXYtGkT/fv3v2tIh4aGopQiOjqa6OholFIopQh15hOqd+0yY80FCsB775nx5YEDzf4bV24a3i6khbAXrbXdHxUqVNDC9Zw/f1537dpVZ8uWTefNm1dPmjRJ22w2q8uyv6QkrX/4QeuAAK1B62zZtG7YUOvfftP60qX0X6dPH/P9Nz769HFQ4SIzA2L0bTJVma/bl7+/v46JibH7dYV1oqKiaNu2LfHx8Xz00UcMHjyYxx57zOqy7GvHDnPO4HffwcmTZnpd69bQooXZvU4IB1JKrdda+9/qazJGLe7o0KFDdOjQgTlz5lCiRAn++usvqlWrZnVZ9pOcbIYwxo6FZcvMHhvvvGMCumbNa1PrhLCQBLW4pbS0NMLDw+nZsydpaWkMHDiQzp0785CrbFS/bdu17vn0aXNCytdfQ/Pm5uQUIZyIBLW4ybp16wgODiY2NpY33niDUaNG8fTTT1td1oNLSoKZM83MjRUrTPfcoIHpngMCpHsWTkuCWlyVmJhIz549CQ8P54knnmDGjBk0bNgw85+2smWLCefvv4czZ8wS7iFD4MMPQVbRikxAglqgtWbmzJl07NiRo0eP0rZtWwYMGIC3t7fVpd2/CxdgxgwT0KtWmbMFGzY03XP16mYXOyEyCQlqN7d3717atGnDokWLKF++PD/99BP+/re88Zw5bNpkwnnKFEhMBD8/GDYMPvgA8ua1ujoh7osEtZu6ePEiQ4YMoX///mTLlo3hw4fTpk0bsmXGbTf//RemTzcBvWYNeHhAo0ame65aVbpnkellwj+V4kEtW7aM4OBgtm3bRoMGDRgxYgRPPvmk1WXdu7g4E85Tp8LZs1CihDkI9oMPIE8eq6sTwm4kqN3IyZMn6dq1K99++y2FChUiKiqKN9980+qy7s358/Djjyag160DT09o3Nh0z5UrS/csXJLMR3IDWmsmTZpEsWLFmDx5Mt26dWPr1q0ZH9KhoSZIb3ykZ6+P2FgIDja70H38sZlqFxZmzh387juoUkVCWrgsWULu4rZv305ISAjR0dFUrlyZiIgISpcubW1RL70E27ebJdt32pv53DmYNs10z+vXQ44c0KSJ6Z4rVZJgFi7lTkvIpaN2UUlJSfTs2ZOyZcuyadMmxo0bx7Jly6wPaTAHuiYmmkNdb6Q1xMSYMPbxgaAgs0H/qFGme5440QS9hLRwIzJG7YJ+++03PvnkE/bs2cMHH3zAkCFDyO8My6Jz5DB7a1wxZox5eHqaDfZ/+MF0zxs2mGOr3nvPBPaLL0owC7cmQe1Cjhw5QqdOnZg+fTrPPfccf/zxB7Vq1bK6rGv27oUuXczNQJvNhHG1amaGho+PWaRSrhyMHg1Nm8LDD1tdsRBOQYLaBVy6dImxY8fSvXv3qwfMduvWDQ8PD6tL+y8fH3NmoM1mOuQLF+DXXyFnThPMrVuDv790z0LcQII6k4uLiyMoKIi1a9fy8ssvM2bMGJ599lmry7qZ1mYxyoIF157nzWtOTomONgEuhLgluZmYSZ0/f55PP/2UChUqsH//fqZOncrixYudL6TPnDE3AsuWNTcBDxy49rUTJ8yilWHDrKpOiExBOupMaN68ebRr145Dhw4RFBTEV199xaOPPmp1WddobTZCiow0GyMlJZkhjchIc4Mwd26rKxQiU5GgzkTi4+Np3749P/30E6VLl2bGjBm89NJLVpd1zalTZjOkyEjYutUEcosWZoHK889bXZ0QmZYEdSaQmprKiBEj6NOnDwDffPMNHTp0IHv27BZXhumeV6ww4Txzppl+9+KLMGGCWdqdK5fVFQqR6UlQO7lVq1YRHBzMpk2beOuttxg5ciSFChWyuixz+Ov335uA3r7d3Az86CPTPZcta3V1QrgUuZlosSNHjhAQEMDRo0f/8/rp06cJDg6mSpUqnDp1irlz5zJ//nxrQ1prM0MjMBCefBI6dTJznSdONKsGr9w0FELYlXTUFgkNDaVv375Xn/v4+ADQu3dvihUrRqdOnThx4gQdO3akb9++5LbyBtyJE2bjo3HjYOdOE86tW5vu2RmWpAvh4mRTJovkyJGD5OuXU1+WJUsWbDYbL774IhERETxv1U04rWHpUjO0MWeO2W+jShUT0A0bmlWFQgi7kU2ZnNDevXtp2rQpWS6ffJ09e3ayZMmCl5cX4eHhrFy50pqQPn4cvvkGihWDWrVg0SIICTEHxC5fbg6ElZAWIkPJ0IdFfHx88Pb2xmazAWZmR9GiRVm2bNnVYZAMY7PBkiWme547F1JTzR4cvXtDgwZmMyUhhGUkqC1y/PhxfvnlFwAeeughateuTfbs2TM2pI8dg0mTzNjznj1mc6S2bc3Yc/HiGVeHEOKOZOgjg9lsNsaNG0ehQoU4ePAgYA6ajYqKYu7cuYSm57STBysAFi82h78WKACff27+O3UqHD5slnNLSAvhVKSjzkBbtmwhODiYFStWUL16dSIiIiieUaF49KiZRjduHOzbB489Bh06QKtW4OeXMTUIIe6LBHUGuHDhAv369WPo0KE8/PDDTJw4kebNm6McvZ3nle45MhJ++gnS0qBmTRg4EN55B5xtG1QhxC1JUDvYL7/8Qtu2bdm/fz8tW7Zk8ODB5M2b17Ef+s8/8O23MH68OfYqb16zOKVVK3juOcd+thDC7iSoHeTw4cN06NCB2bNnU7x4caKjo6levbrjPvDSJbMJf2QkREWZ5y+/DF9/DW+/Ld2zEJmYBLWdXbp0iVGjRtGzZ0/S0tL48ssv6dKlCw899JBjPvDQIdM9T5hg9nrOn98cd9WqFTzzjGM+UwiRoSSo7SgmJoagoCBiY2N57bXXCA8Pp2jRovb/oEuXYOFC0z3/8osZi371VRg6FOrVA0f9pSCEsIQEtR0kJibSs2dPwsPDefzxx5k+fTqNGjWy/83CgwdN5zxhgumkH38cunUz3fPTT9v3s4QQTkOC+gForZk1axYdOnTg6NGjtGnThgEDBvCwPU/PTksz5wxGRpouWmuoXRtGjIC33gJn2JNaCOFQsuDlPu3bt48333yTxo0b88QTT7BmzRpGjhyZ/pAODTWnbd/4uLLgJT7eLOEuVMjcDFy/Hrp3NysIFy2Cd9+VkBbCTdw1qJVSBZVSS5RS25RSW5VSHTKiMGd18eJFBg0aRMmSJVm2bBnDhw9n7dq1vPDCC/d2odBQ0x1fWTIeEmJ2qCtXDurUgSJFYMAAs7/z3LnmRuGAAeZ1IYRbues2p0opH8BHax2rlMoNrAfqa6233e57XHWb0+XLlxMcHMzWrVt59913GTFiBAUKFLi/i+XIYY6tuhVfX3NaykcfmY5aCOHyHmibU631Ea117OVfnwO2A0/at0TndvLkSVq1akW1atU4d+4cP//8M7Nnz77/kAazAX+1av99zdfXbJIUHw/9+klICyGAexyjVkoVBp4H1tzia62VUjFKqZiEhAQ7lWctrTXfffcdfn5+TJo0ia5du7Jt2zbq1q17/xfduxd69DAHwC5bdu11pcxYdPPmkE3u8Qohrkl3UCulcgGzgY5a67M3fl1rHam19tda++fLl8+eNVpix44d1KpVixYtWvDss8+yYcMGBg8eTM6cOe/9YhcvwqxZZrZG0aIweLA5zup6WsOYMdduJgohxGXpat2UUtkxIT1Vaz3HsSVZKykpia+++opBgwaRM2dOIiMj+eijj66exHJPdu82+21MnGhOTilYEPr2hZYtzdaiQgiRDncNamVWbUwAtmuthzm+JOssXryYkJAQ9uzZQ7NmzRg6dCj58+e/t4ukpMC8eWY70T/+gKxZoW5dc9bga6+Z50IIcQ/S01FXAT4ANiul4i6/1kNrvcBhVWWwo0eP8umnnzJt2jSeffZZfv/9d15++eV7u8iuXSacJ00yp3YXKgT9+5vu2dfXIXULIdzDXYNaa70ccPDGydaw2WyMHTuW7t27k5SURGhoKN26dcPT0zN9F0hJMSd0jxtnzhzMmtXstdG6tdl7Q7pnIYQduO30gri4OIKDg1mzZg21atVizJgxPJfevZp37jRLur/7Dk6eNItQBg6EFi2uLWARQgg7cbugPn/+PH369GHEiBHkyZOH77//nsDAwLtvoJScDLNnm+45OtpMoatf33TPL78M93OzUQgh0sGtgnr+/Pm0a9eOgwcP0rp1awYNGsSjjz5652/ats2E8+TJcOqU2aVu0CDTPT/+eIbULYRwb24R1AcOHKB9+/bMnz+f0qVL8+OPP1K5cuXbf0NSkpn3HBkJy5ebzY/eecd0zzVrSvcshMhQLh3UaWlpjBgxgj59+qC15uuvv6Zjx45kv92uc1u3mnCePBnOnDEnpHz9tVkteK/T9IQQwk5cNqhXr15NcHAwGzdupG7duowaNYpCt9o748IFmDnTBPTKlaZ7btDAdM8BAdI9CyEs53JBfebMGbp3787YsWPx9fVlzpw51K9f/+abhZs3m3D+/ntITDSncw8ZAh9+CC6wBF4I4TpcJqi11vz444906tSJhIQEOnbsSN++fcmdO/e1N/37L8yYYQJ69WpztmDDhqZ7rl7dbIwkhBBOxiWCevfu3XzyyScsXryYF154gYULF/L8889fe8PGjSacp0yBs2fBzw+GDYMPPoC8ea0rXAgh0iFTB3VKSgpff/01X375JR4eHowaNYrg4GCyZs0K58/D9OkmoNeuBQ8PaNTIdM9Vq0r3LITINDJtUC9dupTg4GB27txJkyZNGDZsGL6+vrBhgwnnqVPh3DkoUQKGDzfdc548VpcthBD3LNMFdUJCAl26dGHy5Mk8/fTTLFy4kNerVIEffzQBHRMDnp7QuLHpnitXlu5ZCJGpZZqgttlsTJw4ka5du3Lu3Dm++OILvnjjDXJMnmyGNM6fh1KlICwMmjWDu604FEKITCJTBPXWrVsJDg5m+fLlVK9ShTEvv0yJqCj48ktzSGyTJqZ7rlRJumchhMtx6qC+cOEC/fv3Z8iQITycMyffVq9Oi5gY1IoVULo0jBoFgYHwyCNWlyqEEA7jtEG9cOFC2oSEsC8+nv/lycPXp06RNyYG3nvPdM8vvijdsxDCLThVUB+Ji6Nx9eo85efHD+vWUVwplgIBTz0FAwZA06Y3HworhBAuzimCOrRGDfpGR1MNWAmodesAaJA/PwE//wz+/tI9CyHcltJa2/2i/v7+OiYmJt3vz6EUybd43RNIckB9QgjhbJRS67XW/rf6mlNsDbd3wwaaFipEjsvPvYDAwoXZt3GjlWUJIYRTcIqgHtuxIwfj40nBdNHJwIH9+4lo397iyoQQwnpOEdShS5eS18eH4JIlWT19OsElS5LXx4fQpUutLk0IISznFDcTAeb888/VX4c3bmxhJUII4VycoqMWQghxexLUQgjh5CSohRDCyUlQCyGEk5OgFkIIJydBLYQQTk6CWgghnJxD9vpQSiUA8ff57XmBE3YsJzOQn9n1udvPC/Iz36tCWut8t/qCQ4L6QSilYm63MYmrkp/Z9bnbzwvyM9uTDH0IIYSTk6AWQggn54xBHWl1ARaQn9n1udvPC/Iz243TjVELIYT4L2fsqIUQQlxHgloIIZyc0wS1Uup1pdROpdRupdTnVteTEZRS3yqljiultlhdS0ZQShVUSi1RSm1TSm1VSnWwuiZHU0p5KqXWKqU2Xv6Z+1pdU0ZRSmVVSm1QSkVZXUtGUErtV0ptVkrFKaXSf2hseq7tDGPUSqmswC7gVeAQsA54X2u9zdLCHEwpVR04D0zWWpeyuh5HU0r5AD5a61ilVG5gPVDflf93VkopIKfW+rxSKjuwHOigtV5tcWkOp5T6FPAHvLXWda2ux9GUUvsBf6213Rf5OEtH/SKwW2u9V2t9EfgReNvimhxOa/0XcMrqOjKK1vqI1jr28q/PAduBJ62tyrG0cf7y0+yXH9Z3Rw6mlCoAvAmMt7oWV+AsQf0kcPC654dw8T/A7k4pVRh4HlhjcSkOd3kIIA44DizWWrv8zwwMB7oCNovryEga+E0ptV4p1dqeF3aWoBZuRCmVC5gNdNRan7W6HkfTWl/SWpcDCgAvKqVcephLKVUXOK61Xm91LRmsqta6PPAG0Oby0KZdOEtQHwYKXve8wOXXhIu5PE47G5iqtZ5jdT0ZSWt9BlgCvG5xKY5WBah3ecz2R6CWUmqKtSU5ntb68OX/HgfmYoZ07cJZgnod8KxSqohS6iHgPeAni2sSdnb5xtoEYLvWepjV9WQEpVQ+pdQjl3+dA3PDfIelRTmY1rq71rqA1row5s/yn1rrZhaX5VBKqZyXb5CjlMoJ1AbsNpvLKYJaa50GtAV+xdxgmqG13mptVY6nlJoGrAKKKaUOKaU+sromB6sCfIDpsOIuP+pYXZSD+QBLlFKbMA3JYq21W0xXczOPA8uVUhuBtcAvWutF9rq4U0zPE0IIcXtO0VELIYS4PQlqIYRwchLUQgjh5CSohRDCyUlQCyGEk5OgFkIIJydBLYQQTu7/AW36geljb9VpAAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] @@ -132,12 +132,12 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "id": "3b82d1c6", "metadata": {}, "outputs": [], "source": [ - "x_const = {'c':list(np.arange(0,10)),'d':list(np.arange(10,20))}\n", + "x_const = {'c':[0,1,2,3,4,5,6,7,8,9],'d':list(np.arange(10,20))}\n", "y_const = {'c':[pe.Obs([np.random.normal(1, val, 1000)],['ensemble1']) \n", " for val in [0.25,0.3,0.01,0.2,0.5,1.3,0.26,0.4,0.1,1.0]],\n", " 'd':[pe.Obs([np.random.normal(1, val, 1000)],['ensemble1'])\n", @@ -148,20 +148,22 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 9, "id": "7c1f7950", "metadata": {}, "outputs": [], "source": [ - "def func_const(a, x):\n", - " return a[0]\n", + "#needs to be vectorized for expected chi2 to work (jacobian matrix incorrect dim. otherwise)\n", + "#@anp.vectorize\n", + "def func_const(a,x):\n", + " return a[0]#*anp.ones(len(x))\n", "\n", "funcs_const = {\"c\": func_const,\"d\": func_const}" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 10, "id": "82e0cdb6", "metadata": {}, "outputs": [ @@ -172,39 +174,18 @@ "Fit with 1 parameter\n", "Method: migrad\n", "Optimization terminated successfully.\n", - "chisquare/d.o.f.: 0.7268201670950173\n", - "fit parameters [0.99968989]\n" + "chisquare/d.o.f.: 1.444161495357013\n", + "fit parameters [0.9997047]\n" ] } ], "source": [ - "output_const = pe.combined_fits.combined_fit(x_const,y_const,funcs_const,method='migrad')" + "output_const = pe.fits.least_squares(x_const,y_const,funcs_const,method='migrad')" ] }, { "cell_type": "code", - "execution_count": 12, - "id": "53021f73", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "13.80958317480533" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "output_const.chisquare" - ] - }, - { - "cell_type": "code", - "execution_count": 13, + "execution_count": 11, "id": "ab5c5bef", "metadata": {}, "outputs": [], @@ -214,25 +195,25 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 12, "id": "d6abfe4f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - " chisquare: 13.80958317480533\n", - " chisquare_by_dof: 0.7268201670950173\n", + " chisquare: 27.439068411783246\n", + " chisquare_by_dof: 1.444161495357013\n", " dof: 19\n", - " fit_function: {'c': , 'd': }\n", - " fit_parameters: [Obs[0.99969(22)]]\n", + " fit_function: {'c': , 'd': }\n", + " fit_parameters: [Obs[0.99970(22)]]\n", " iterations: 15\n", " message: 'Optimization terminated successfully.'\n", " method: 'migrad'\n", - " p_value: 0.7946762502119166" + " p_value: 0.09483431965197764" ] }, - "execution_count": 14, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -243,7 +224,31 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 13, + "id": "50e3de50", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fit with 1 parameter\n", + "Method: migrad\n", + "Optimization terminated successfully.\n", + "chisquare/d.o.f.: 1.444161495357013\n", + "fit parameters [0.9997047]\n" + ] + } + ], + "source": [ + "output_const = pe.fits.least_squares(x_const,y_const,funcs_const,method='migrad')" + ] + }, + { + "cell_type": "code", + "execution_count": 14, "id": "efd3d4d0", "metadata": {}, "outputs": [], @@ -256,7 +261,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "id": "57d65824", "metadata": {}, "outputs": [ @@ -264,7 +269,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "[Obs[0.9905(78)], Obs[1.0090(96)], Obs[0.99960(32)], Obs[1.0032(62)], Obs[1.018(18)], Obs[0.988(49)], Obs[1.0084(83)], Obs[1.000(13)], Obs[0.9960(32)], Obs[1.009(34)], Obs[0.990(16)], Obs[0.970(35)], Obs[0.9865(91)], Obs[0.9981(80)], Obs[1.0065(97)], Obs[0.99983(31)], Obs[0.9985(61)], Obs[1.040(32)], Obs[1.011(12)], Obs[0.9966(31)]]\n" + "[Obs[1.0101(80)], Obs[0.9908(97)], Obs[0.99919(32)], Obs[0.9962(64)], Obs[0.965(17)], Obs[1.004(42)], Obs[1.0094(82)], Obs[1.004(13)], Obs[0.9974(31)], Obs[0.954(34)], Obs[1.004(16)], Obs[1.058(37)], Obs[0.9893(84)], Obs[0.9895(85)], Obs[0.9914(96)], Obs[1.00028(33)], Obs[1.0005(62)], Obs[0.957(32)], Obs[0.988(13)], Obs[1.0040(32)]]\n" ] } ], @@ -274,7 +279,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 16, "id": "731552bc", "metadata": {}, "outputs": [ @@ -285,7 +290,7 @@ "Fit with 1 parameter\n", "Method: Levenberg-Marquardt\n", "`ftol` termination condition is satisfied.\n", - "chisquare/d.o.f.: 0.7268201670947627\n" + "chisquare/d.o.f.: 1.4441614953561615\n" ] } ], @@ -295,7 +300,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 17, "id": "019583b5", "metadata": {}, "outputs": [], @@ -305,25 +310,25 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 18, "id": "f28a3478", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - " chisquare: 13.809583174800492\n", - " chisquare_by_dof: 0.7268201670947627\n", + " chisquare: 27.439068411767067\n", + " chisquare_by_dof: 1.4441614953561615\n", " dof: 19\n", - " fit_function: \n", - " fit_parameters: [Obs[0.99969(22)]]\n", + " fit_function: \n", + " fit_parameters: [Obs[0.99970(22)]]\n", " iterations: 7\n", " message: '`ftol` termination condition is satisfied.'\n", " method: 'Levenberg-Marquardt'\n", - " p_value: 0.7946762502121925" + " p_value: 0.0948343196523247" ] }, - "execution_count": 19, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -334,13 +339,13 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 19, "id": "466cd303", "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYAAAAD5CAYAAAAuneICAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAnYklEQVR4nO3de3wU9b3/8deHmwliRAxqAFtoD20xCAEj2FYNRY9FT4vCzwsXFbSWg1bb09b+1HKElUqPPcfWWqVRRERaK96i0pYebYtEqUoJNqKAF4ygoREoKl64iOVz/pgJLrluspvdTeb9fDzmkZ3vd76zn53d7Gdnvt+ZMXdHRESip1OmAxARkcxQAhARiSglABGRiFICEBGJKCUAEZGIUgIQEYmoLs0tYGYLgK8BW919cAP1XwDuAoYDM9z9xri6McDNQGdgvrvfEJYPABYDhwOrgQvc/aPmYsnPz/f+/fsn8LJERKTW6tWr/+HuveuWW3PnAZjZycAHwKJGEsARwKeBs4B3ahOAmXUGXgH+FagGVgET3X2dmd0PlLn7YjO7DXje3UubexHFxcVeUVHR3GIiIhLHzFa7e3Hd8mYPAbn7k8DbTdRvdfdVwN46VSOADe5eFf66XwycaWYGjAYeDJe7myB5iIhIGrVlH0Bf4M24+eqw7HDgXXf/uE65iIikUdZ3ApvZNDOrMLOKbdu2ZTocEZEOo9lO4CRsBo6Om+8Xlm0HeppZl3AvoLa8Qe4+D5gHQR9A24UrIq21d+9eqqur2b17d6ZDibScnBz69etH165dE1q+LRPAKmBgOOJnMzABmOTubmZPAGcT9AtMAR5twzhEpI1VV1dzyCGH0L9/f4JuPkk3d2f79u1UV1czYMCAhNokMgz0XmAUkG9m1cAsoGv4hLeZ2VFABZAH7DOz/wCOcff3zOxy4DGCYaAL3H1tuNqrgMVmdj3wN+DOxF+miGSb3bt368s/w8yMww8/nJYcKm82Abj7xGbq3yI4jNNQ3VJgaQPlVQSjhESkg9CXf+a19D3I+k5gERFpG0oAIlkqFothZvWmWCyW6dAio0ePHg2Wz5w5kz/96U8peY5Ro0bR0AmuTz31FIWFhRQVFbF582bOPvtsACorK1m6tN6BlVZRAhDJUrFYDHenpKSEkpIS3B13VwLIArNnz+bUU09t0+e45557uOaaa6isrKRv3748+GBw7qwSgIhIHYsWLWLIkCEMHTqUCy64AICNGzcyevRohgwZwimnnMIbb7wBwNSpU7n00ks54YQT+MxnPsPy5cu5+OKLGTRoEFOnTj1gvd/97ncpLCzklFNO2d/BOnXq1P1fyP3792fWrFkMHz6cY489lpdeegmADz/8kIsvvpgRI0YwbNgwHn00GOy4a9cuJkyYwKBBgxg3bhy7du2q91rmz5/P/fffz7XXXsvkyZPZuHEjgwcP5qOPPmLmzJncd999FBUVcd999yW1zdpyGKiIRNDzW3ewY/fHzS/YAofmdGHoEYc2Wr927Vquv/56nn76afLz83n77eDqNVdccQVTpkxhypQpLFiwgG9/+9s88sgjALzzzjs888wzLFmyhLFjx/KXv/yF+fPnc/zxx1NZWUlRUREffvghxcXF3HTTTcyePZvrrruOW2+9td7z5+fn89xzz/HLX/6SG2+8kfnz5zNnzhxGjx7NggULePfddxkxYgSnnnoqt99+O927d2f9+vWsWbOG4cOH11vfJZdcwooVK/ja177G2WefzcaNGwHo1q0bs2fPpqKiosE4Wkp7ACLS7i1btoxzzjmH/Px8AHr16gXAM888w6RJkwC44IILWLFixf42X//61zEzjj32WI488kiOPfZYOnXqRGFh4f4v3E6dOnHeeecBcP755x/QPt748eMBOO644/a3ffzxx7nhhhsoKipi1KhR7N69mzfeeIMnn3yS888/H4AhQ4YwZMiQ1G6MFtAegIikVFO/1LPJQQcdBARf8rWPa+c//rjhPZjGhlnWtu/cufP+tu7OQw89xOc///lUhp1S2gMQkXZv9OjRPPDAA2zfvh1g/yGgL33pSyxevBgIOlVPOumkFq133759+4/1/+Y3v+HEE09MuO1Xv/pVbrnlFmovuf+3v/0NgJNPPpnf/OY3ALz44ousWbOmRTEdcsghvP/++y1q0xglABFp9woLC5kxYwYlJSUMHTqU733vewDccsst3HXXXQwZMoRf/epX3HzzzS1a78EHH8xf//pXBg8ezLJly5g5c2bCba+99lr27t3LkCFDKCws5NprrwXg0ksv5YMPPmDQoEHMnDmT4447rkUxfeUrX2HdunUp6QRu9oYw2UQ3hJEoGjVqFADLly/PaBxNWb9+PYMGDcp0GELD70WrbwgjIiIdkxKAiEhE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\n", "text/plain": [ "
" ] @@ -364,83 +369,6 @@ "plt.legend()\n", "plt.show()" ] - }, - { - "cell_type": "code", - "execution_count": 21, - "id": "dd14c5dc", - "metadata": {}, - "outputs": [], - "source": [ - "def func_const_wrong():\n", - " a=x" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "id": "d4e8adbc", - "metadata": {}, - "outputs": [], - "source": [ - "funcs_const_wrong = {\"c\": 4,\"d\": func_const_wrong}" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "id": "27f8d77c", - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "func (key=c) is not a function.", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_55611/20019894.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0moutput_const2_wrong\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpe\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcombined_fits\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcombined_fit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx_const\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0my_const\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mfuncs_const_wrong\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'migrad'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m~/phd/develop_pyerrors/piapyerrors/pyerrors/combined_fits.py\u001b[0m in \u001b[0;36mcombined_fit\u001b[0;34m(x, y, funcs, silent, **kwargs)\u001b[0m\n\u001b[1;32m 71\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mfuncs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 72\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mcallable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfuncs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 73\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'func (key='\u001b[0m\u001b[0;34m+\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m') is not a function.'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 74\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 75\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'x and y input (key='\u001b[0m\u001b[0;34m+\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m') do not have the same length'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mTypeError\u001b[0m: func (key=c) is not a function." - ] - } - ], - "source": [ - "output_const2_wrong = pe.combined_fits.combined_fit(x_const,y_const,funcs_const_wrong,method='migrad')" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "id": "e7110837", - "metadata": {}, - "outputs": [], - "source": [ - "x_const_wrong = {'c':list(np.arange(0,11)),'d':list(np.arange(10,20))}" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "2dae0db9", - "metadata": {}, - "outputs": [ - { - "ename": "Exception", - "evalue": "x and y input (key=c) do not have the same length", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/tmp/ipykernel_55611/2795677260.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mpe\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcombined_fits\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcombined_fit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx_const_wrong\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0my_const\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mfuncs_const\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mmethod\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'migrad'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m~/phd/develop_pyerrors/piapyerrors/pyerrors/combined_fits.py\u001b[0m in \u001b[0;36mcombined_fit\u001b[0;34m(x, y, funcs, silent, **kwargs)\u001b[0m\n\u001b[1;32m 73\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'func (key='\u001b[0m\u001b[0;34m+\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m') is not a function.'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 74\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 75\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'x and y input (key='\u001b[0m\u001b[0;34m+\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m') do not have the same length'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 76\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m42\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 77\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mException\u001b[0m: x and y input (key=c) do not have the same length" - ] - } - ], - "source": [ - "pe.combined_fits.combined_fit(x_const_wrong,y_const,funcs_const,method='migrad')" - ] } ], "metadata": { diff --git a/pyerrors/combined_fits.py b/pyerrors/combined_fits.py deleted file mode 100644 index 1099305e..00000000 --- a/pyerrors/combined_fits.py +++ /dev/null @@ -1,216 +0,0 @@ -import iminuit -import autograd.numpy as anp -from autograd import jacobian -from pyerrors.fits import Fit_result -import numpy as np -import pyerrors as pe -from autograd import jacobian as auto_jacobian -from autograd import hessian as auto_hessian -from autograd import elementwise_grad as egrad -from numdifftools import Jacobian as num_jacobian -from numdifftools import Hessian as num_hessian -import scipy.optimize -import scipy.stats - -def combined_fit(x,y,funcs,silent=False,**kwargs): - r'''Performs a combined non-linear fit. - Parameters - ---------- - x : ordered dict - dict of lists. - y : ordered dict - dict of lists of Obs. - funcs : ordered dict - dict of objects - fit functions have to be of the form (here a[0] is the common fit parameter) - ```python - import autograd.numpy as anp - funcs = {"a": func_a, - "b": func_b} - - def func_a(a, x): - return a[1] * anp.exp(-a[0] * x) - - def func_b(a, x): - return a[2] * anp.exp(-a[0] * x) - ``` - It is important that all numpy functions refer to autograd.numpy, otherwise the differentiation - will not work. - silent : bool, optional - If true all output to the console is omitted (default False). - initial_guess : list - can provide an initial guess for the input parameters. Relevant for - non-linear fits with many parameters. - num_grad : bool - Use numerical differentation instead of automatic differentiation to perform the error propagation (default False). - ''' - - output = Fit_result() - output.fit_function = funcs - - if kwargs.get('num_grad') is True: - jacobian = num_jacobian - hessian = num_hessian - else: - jacobian = auto_jacobian - hessian = auto_hessian - - x_all = [] - y_all = [] - for key in x.keys(): - x_all+=x[key] - y_all+=y[key] - - x_all = np.asarray(x_all) - - if len(x_all.shape) > 2: - raise Exception('Unknown format for x values') - - # number of fit parameters - n_parms_ls = [] - for key in funcs.keys(): - if not callable(funcs[key]): - raise TypeError('func (key='+ key + ') is not a function.') - if len(x[key]) != len(y[key]): - raise Exception('x and y input (key='+ key + ') do not have the same length') - for i in range(42): - try: - funcs[key](np.arange(i), x_all.T[0]) - except TypeError: - continue - except IndexError: - continue - else: - break - else: - raise RuntimeError("Fit function (key="+ key + ") is not valid.") - n_parms = i - n_parms_ls.append(n_parms) - n_parms = max(n_parms_ls) - if not silent: - print('Fit with', n_parms, 'parameter' + 's' * (n_parms > 1)) - - if 'initial_guess' in kwargs: - x0 = kwargs.get('initial_guess') - if len(x0) != n_parms: - raise Exception('Initial guess does not have the correct length: %d vs. %d' % (len(x0), n_parms)) - else: - x0 = [0.1] * n_parms - - def chisqfunc(p): - chisq = 0.0 - for key in funcs.keys(): - x_array = np.asarray(x[key]) - model = anp.array(funcs[key](p,x_array)) - y_obs = y[key] - y_f = [o.value for o in y_obs] - dy_f = [o.dvalue for o in y_obs] - C_inv = np.diag(np.diag(np.ones((len(x_array),len(x_array)))))/dy_f/dy_f - chisq += anp.sum((y_f - model)@ C_inv @(y_f - model)) - return chisq - - output.method = kwargs.get('method', 'Levenberg-Marquardt') - if not silent: - print('Method:', output.method) - - if output.method == 'migrad': - tolerance = 1e-4 - if 'tol' in kwargs: - tolerance = kwargs.get('tol') - fit_result = iminuit.minimize(chisqfunc, x0, tol=tolerance) # Stopping criterion 0.002 * tol * errordef - output.iterations = fit_result.nfev - else: - tolerance = 1e-12 - if 'tol' in kwargs: - tolerance = kwargs.get('tol') - fit_result = scipy.optimize.minimize(chisqfunc, x0, method=kwargs.get('method'), tol=tolerance) - output.iterations = fit_result.nit - - chisquare = fit_result.fun - output.message = fit_result.message - - if not fit_result.success: - raise Exception('The minimization procedure did not converge.') - - if x_all.shape[-1] - n_parms > 0: - output.chisquare = chisqfunc(fit_result.x) - output.dof = x_all.shape[-1] - n_parms - output.chisquare_by_dof = output.chisquare/output.dof - output.p_value = 1 - scipy.stats.chi2.cdf(output.chisquare, output.dof) - else: - output.chisquare_by_dof = float('nan') - - if not silent: - print(fit_result.message) - print('chisquare/d.o.f.:', output.chisquare_by_dof ) - print('fit parameters',fit_result.x) - - # use ordered dicts so the data and fit parameters can be mapped correctly - def chisqfunc_compact(d): - chisq = 0.0 - list_tmp = [] - c1 = 0 - c2 = 0 - for key in funcs.keys(): - x_array = np.asarray(x[key]) - c2+=len(x_array) - model = anp.array(funcs[key](d[:n_parms],x_array)) - y_obs = y[key] - y_f = [o.value for o in y_obs] - dy_f = [o.dvalue for o in y_obs] - C_inv = np.diag(np.diag(np.ones((len(x_array),len(x_array)))))/dy_f/dy_f - list_tmp.append(anp.sum((d[n_parms+c1:n_parms+c2]- model)@ C_inv @(d[n_parms+c1:n_parms+c2]- model))) - c1+=len(x_array) - chisq = anp.sum(list_tmp) - return chisq - - def prepare_hat_matrix(): # should be cross-checked again - hat_vector = [] - for key in funcs.keys(): - x_array = np.asarray(x[key]) - if (len(x_array)!= 0): - hat_vector.append(anp.array(jacobian(funcs[key])(fit_result.x, x_array))) - hat_vector = [item for sublist in hat_vector for item in sublist] - return hat_vector - - fitp = fit_result.x - y_f = [o.value for o in y_all] # y_f is constructed based on the ordered dictionary if the order is changed then the y values are not allocated to the the correct x and func values in the hessian - dy_f = [o.dvalue for o in y_all] # the same goes for dy_f - - if np.any(np.asarray(dy_f) <= 0.0): - raise Exception('No y errors available, run the gamma method first.') - - try: - hess = hessian(chisqfunc)(fitp) - except TypeError: - raise Exception("It is required to use autograd.numpy instead of numpy within fit functions, see the documentation for details.") from None - - jac_jac_y = hessian(chisqfunc_compact)(np.concatenate((fitp, y_f))) - - # Compute hess^{-1} @ jac_jac_y[:n_parms + m, n_parms + m:] using LAPACK dgesv - try: - deriv_y = -scipy.linalg.solve(hess, jac_jac_y[:n_parms, n_parms:]) - except np.linalg.LinAlgError: - raise Exception("Cannot invert hessian matrix.") - - - if kwargs.get('expected_chisquare') is True: - if kwargs.get('correlated_fit') is not True: - W = np.diag(1 / np.asarray(dy_f)) - cov = covariance(y_all) - hat_vector = prepare_hat_matrix() - A = W @ hat_vector #hat_vector = 'jacobian(func)(fit_result.x, x)' - P_phi = A @ np.linalg.pinv(A.T @ A) @ A.T - expected_chisquare = np.trace((np.identity(x.shape[-1]) - P_phi) @ W @ cov @ W) - output.chisquare_by_expected_chisquare = chisquare / expected_chisquare - if not silent: - print('chisquare/expected_chisquare:', output.chisquare_by_expected_chisquare) - - - result = [] - for i in range(n_parms): - result.append(pe.derived_observable(lambda x_all, **kwargs: (x_all[0] + np.finfo(np.float64).eps) / (y_all[0].value + np.finfo(np.float64).eps) * fitp[i], list(y_all), man_grad=list(deriv_y[i]))) - - output.fit_parameters = result - - return output \ No newline at end of file diff --git a/pyerrors/fits.py b/pyerrors/fits.py index e2998b25..180cc440 100644 --- a/pyerrors/fits.py +++ b/pyerrors/fits.py @@ -106,11 +106,11 @@ def least_squares(x, y, func, priors=None, silent=False, **kwargs): Do not need to use ordered dictionaries: python version >= 3.7: Dictionary order is guaranteed to be insertion order. (https://docs.python.org/3/library/stdtypes.html#dict-views) Ensures that x, y and func values are mapped correctly. - x : ordered dict + x : dict dict of lists. - y : ordered dict + y : dict dict of lists of Obs. - funcs : ordered dict + funcs : dict dict of objects fit functions have to be of the form (here a[0] is the common fit parameter) ```python @@ -141,7 +141,7 @@ def least_squares(x, y, func, priors=None, silent=False, **kwargs): can be used to choose an alternative method for the minimization of chisquare. The possible methods are the ones which can be used for scipy.optimize.minimize and migrad of iminuit. If no method is specified, Levenberg-Marquard is used. - Reliable alternatives are migrad, Powell and Nelder-Mead. + Reliable alternatives are migrad (default for combined fit), Powell and Nelder-Mead. correlated_fit : bool If True, use the full inverse covariance matrix in the definition of the chisquare cost function. For details about how the covariance matrix is estimated see `pyerrors.obs.covariance`. @@ -744,6 +744,10 @@ def _combined_fit(x,y,func,silent=False,**kwargs): raise Exception('Initial guess does not have the correct length: %d vs. %d' % (len(x0), n_parms)) else: x0 = [0.1] * n_parms + + output.method = kwargs.get('method', 'migrad') + if not silent: + print('Method:', output.method) def chisqfunc(p): chisq = 0.0 @@ -756,10 +760,6 @@ def _combined_fit(x,y,func,silent=False,**kwargs): C_inv = np.diag(np.diag(np.ones((len(x_array),len(x_array)))))/dy_f/dy_f chisq += anp.sum((y_f - model)@ C_inv @(y_f - model)) return chisq - - output.method = kwargs.get('method', 'Levenberg-Marquardt') - if not silent: - print('Method:', output.method) if output.method == 'migrad': tolerance = 1e-4 @@ -816,7 +816,7 @@ def _combined_fit(x,y,func,silent=False,**kwargs): for key in func.keys(): x_array = np.asarray(x[key]) if (len(x_array)!= 0): - hat_vector.append(anp.array(jacobian(func[key])(fit_result.x, x_array))) + hat_vector.append(jacobian(func[key])(fit_result.x, x_array)) hat_vector = [item for sublist in hat_vector for item in sublist] return hat_vector