diff --git a/.gitignore b/.gitignore index e1b4611..f2ff886 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ spike *.sqlite build data +.vscode/ \ No newline at end of file diff --git a/aimmdb/_tests/__init__.py b/aimmdb/_tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/aimmdb/_tests/conftest.py b/aimmdb/_tests/conftest.py deleted file mode 100644 index 655042d..0000000 --- a/aimmdb/_tests/conftest.py +++ /dev/null @@ -1,23 +0,0 @@ -import contextlib -import getpass - -import pytest - - -@pytest.fixture -def enter_password(monkeypatch): - """ - Return a context manager that overrides getpass, used like: - - >>> with enter_password(...): - ... # Run code that calls getpass.getpass(). - """ - - @contextlib.contextmanager - def f(password): - original = getpass.getpass - monkeypatch.setattr("getpass.getpass", lambda: password) - yield - monkeypatch.setattr("getpass.getpass", original) - - return f diff --git a/aimmdb/_tests/eli_test_file.dat b/aimmdb/_tests/eli_test_file.dat deleted file mode 100755 index dff0b96..0000000 --- a/aimmdb/_tests/eli_test_file.dat +++ /dev/null @@ -1,683 +0,0 @@ -# Beamline.name: ISS (8-ID) - (08ID) Inner Shell Spectroscopy -# Beamline.x-ray_source: NSLS-II damping wiggler -# Beamline.collimation: ISS dual mirror system -# Beamline.focusing: ISS toroid mirror -# Beamline.harmonic_rejection: undefined -# Detector.I0: 17 cm, He: 62.0%, N2: 38.0% -# Detector.I1: 30 cm, He: 62.0%, N2: 38.0% -# Detector.I2: 17 cm, He: 62.0%, N2: 38.0% -# Detector.IF: PIPS -# Detector.I0_volt: -1700.0 -# Detector.I1_volt: -1700.0 -# Detector.I2_volt: -1700.0 -# Detector.I0_amp_gain: 5 -# Detector.I1_amp_gain: 5 -# Detector.I2_amp_gain: 6 -# Detector.IF_amp_gain: 6 -# Detector.aux: -# Element.symbol: Co -# Element.edge: K -# Facility.name: NSLS-II -# Facility.mode: Beam available -# Facility.energy: 3 GeV -# Facility.current: 399.56639748426807 -# Facility.GUP: 300010 -# Facility.SAF: 300010 -# Facility.cycle: 2022-1 -# Mono.name: Si(111) -# Mono.d_spacing: 3.1354951 -# Mono.encoder_resolution: 48.0 nrad -# Mono.angle_offset: -# Mono.scan_mode: pseudo-channel cut -# Mono.scan_type: -# Mono.trajectory_name: -# Mono.direction: -# Sample.name: 1-1 712 3 10 D C (pos 001) Co-K 0001 -# Sample.comment: -# Sample.stage: ISS.giant_xy stage -# ISS.sample_x_position: -336.0437703865 -# ISS.sample_y_position: -66.067285211 -# Scan.experimenters: Eli Stavitski -# Scan.edge_energy: 7709.0 -# Scan.start_time: 04/08/2022 08:37:45 -# Scan.end_time: 04/08/2022 08:38:20 -# Scan.duration: 00:34 -# Scan.transient_id: 226033 -# Scan.uid: d66dda13-d69c-4ca6-8fb7-76290ad71073 -# Scan.plot_hint: $5/$1 -# Column.1: energy eV -# Column.2: i0 -# Column.3: it -# Column.4: ir -# Column.5: if -# energy i0 it ir iff aux1 aux2 aux3 aux4 - 7509.000000 -1.428249e-05 -1.442278e-06 -2.325116e-07 -1.696860e-06 -7.383540e-06 1.686795e-05 -1.540353e-05 -1.990895e-06 - 7514.000000 -2.109614e-05 -2.140138e-06 -3.457031e-07 -2.507401e-06 -1.078244e-05 2.313060e-05 -1.311947e-05 1.096863e-05 - 7519.000000 -2.117449e-05 -2.161506e-06 -3.499174e-07 -2.520564e-06 -1.233055e-05 1.263222e-05 -8.352555e-06 2.941343e-06 - 7524.000000 -2.118350e-05 -2.177219e-06 -3.531900e-07 -2.526606e-06 -1.985960e-05 1.608047e-05 -2.154518e-05 -9.275274e-06 - 7529.000000 -2.125343e-05 -2.193307e-06 -3.566828e-07 -2.542888e-06 -2.564526e-05 1.617073e-05 -4.011363e-05 -1.479089e-05 - 7534.000000 -2.127577e-05 -2.208577e-06 -3.599024e-07 -2.550882e-06 -2.169648e-05 1.124580e-05 -2.583097e-05 -7.104161e-06 - 7539.000000 -2.131097e-05 -2.224139e-06 -3.632521e-07 -2.560908e-06 -2.242837e-05 2.422290e-05 -1.720725e-05 -6.384566e-06 - 7544.000000 -2.135681e-05 -2.240518e-06 -3.667892e-07 -2.572205e-06 -1.615860e-05 1.978539e-05 -1.580050e-05 -7.186035e-06 - 7549.000000 -2.136583e-05 -2.255104e-06 -3.699457e-07 -2.579175e-06 -7.440556e-06 2.668688e-05 -9.898860e-06 2.502418e-06 - 7554.000000 -2.139551e-05 -2.271771e-06 -3.733269e-07 -2.588298e-06 -4.100266e-06 1.933526e-05 -1.195002e-05 2.760708e-06 - 7559.000000 -2.145502e-05 -2.288179e-06 -3.768651e-07 -2.603254e-06 -1.182721e-05 1.875990e-05 -1.018805e-05 3.762703e-06 - 7564.000000 -2.115920e-05 -2.272881e-06 -3.748957e-07 -2.571850e-06 -1.265903e-05 2.480779e-05 -8.637734e-06 1.908036e-06 - 7569.000000 -2.125393e-05 -2.296385e-06 -3.796861e-07 -2.588136e-06 -1.990735e-05 2.910599e-05 2.927119e-06 7.552138e-07 - 7574.000000 -2.158994e-05 -2.339927e-06 -3.878981e-07 -2.638024e-06 -1.791158e-05 3.329068e-05 -4.137144e-06 7.496088e-06 - 7579.000000 -2.162434e-05 -2.355805e-06 -3.913250e-07 -2.648746e-06 -2.085102e-05 2.594044e-05 7.162398e-06 3.502133e-06 - 7584.000000 -2.164231e-05 -2.371780e-06 -3.948531e-07 -2.656006e-06 -1.607979e-05 2.548407e-05 6.118586e-06 2.137479e-06 - 7589.000000 -2.171881e-05 -2.390728e-06 -3.989260e-07 -2.672506e-06 -1.268741e-05 2.291652e-05 6.349209e-06 4.442873e-06 - 7594.000000 -2.172392e-05 -2.406470e-06 -4.022610e-07 -2.678005e-06 -1.333977e-05 3.119192e-05 1.090444e-05 2.429532e-06 - 7599.000000 -2.169383e-05 -2.420007e-06 -4.052139e-07 -2.678852e-06 -1.839577e-05 3.344500e-05 1.260542e-05 1.048020e-06 - 7604.000000 -2.168814e-05 -2.432916e-06 -4.081065e-07 -2.684408e-06 -1.078103e-05 2.513076e-05 2.776903e-06 -1.735183e-06 - 7609.000000 -2.180831e-05 -2.455940e-06 -4.130340e-07 -2.707455e-06 -7.025069e-06 1.899528e-05 -8.887740e-06 -8.924842e-06 - 7614.000000 -2.186445e-05 -2.474250e-06 -4.168995e-07 -2.721629e-06 -6.727752e-06 1.908296e-05 -1.778432e-05 -1.374160e-05 - 7619.000000 -2.190068e-05 -2.492749e-06 -4.208966e-07 -2.731838e-06 -1.246841e-05 1.874585e-05 -2.004627e-05 -9.371417e-06 - 7624.000000 -2.194289e-05 -2.511159e-06 -4.247433e-07 -2.743571e-06 -6.559018e-06 1.800399e-05 -7.829282e-06 -8.823298e-06 - 7629.000000 -2.193918e-05 -2.526843e-06 -4.281489e-07 -2.748458e-06 -2.720530e-06 2.231235e-05 -9.968202e-06 -8.764075e-06 - 7634.000000 -2.198332e-05 -2.544583e-06 -4.320767e-07 -2.760814e-06 -2.017881e-06 3.442291e-05 -3.678914e-06 -4.910219e-06 - 7639.000000 -2.206417e-05 -2.565269e-06 -4.364794e-07 -2.778325e-06 -4.145226e-06 3.162906e-05 -6.831739e-06 -7.471027e-06 - 7644.000000 -2.209312e-05 -2.582655e-06 -4.402141e-07 -2.788110e-06 -4.875863e-06 3.484327e-05 -2.041819e-05 -1.277677e-05 - 7649.000000 -2.210307e-05 -2.597481e-06 -4.435004e-07 -2.796806e-06 -3.855001e-06 2.922510e-05 -1.317681e-05 -4.237619e-06 - 7654.000000 -2.207974e-05 -2.607230e-06 -4.459164e-07 -2.802453e-06 -1.307325e-05 2.824124e-05 -1.548968e-05 -7.946061e-07 - 7659.000000 -2.215799e-05 -2.630639e-06 -4.506383e-07 -2.820019e-06 -2.216856e-05 2.784872e-05 -2.355868e-05 -7.477843e-06 - 7664.000000 -2.220618e-05 -2.649206e-06 -4.545453e-07 -2.834801e-06 -1.853799e-05 2.432133e-05 -1.314903e-05 -7.013495e-06 - 7669.000000 -2.224992e-05 -2.667726e-06 -4.583842e-07 -2.848611e-06 -1.710951e-05 2.286564e-05 2.607261e-06 -1.335362e-06 - 7674.000000 -2.227286e-05 -2.684128e-06 -4.618722e-07 -2.858944e-06 -1.382511e-05 2.743894e-05 4.775235e-06 1.152164e-05 - 7679.000000 -2.227220e-05 -2.699032e-06 -4.650783e-07 -2.864223e-06 -1.266842e-05 2.487302e-05 -1.022096e-05 7.566702e-06 - 7683.000000 -2.226425e-05 -2.711491e-06 -4.675381e-07 -2.867249e-06 -2.065598e-05 2.327048e-05 -1.127430e-05 4.556961e-06 - 7686.000000 -2.228986e-05 -2.720664e-06 -4.693568e-07 -2.877273e-06 -2.314819e-05 2.716545e-05 -8.304974e-06 8.873396e-07 - 7688.000000 -2.232942e-05 -2.729359e-06 -4.709878e-07 -2.887363e-06 -3.182207e-05 2.643494e-05 7.145518e-07 -1.774554e-06 - 7689.000000 -2.230945e-05 -2.731778e-06 -4.713761e-07 -2.884794e-06 -3.610620e-05 3.007875e-05 -2.949373e-06 -3.759813e-06 - 7689.200000 -2.227242e-05 -2.730122e-06 -4.709685e-07 -2.878800e-06 -3.443218e-05 3.305098e-05 -8.309904e-06 -5.199915e-06 - 7689.400000 -2.231164e-05 -2.732479e-06 -4.714144e-07 -2.884815e-06 -3.414132e-05 2.448610e-05 -1.293413e-06 -2.777683e-06 - 7689.600000 -2.227807e-05 -2.731099e-06 -4.711357e-07 -2.879247e-06 -3.144676e-05 1.673749e-05 -1.322889e-05 -9.567843e-06 - 7689.800000 -2.228719e-05 -2.732407e-06 -4.712758e-07 -2.881957e-06 -3.148138e-05 1.726935e-05 -1.207815e-05 -1.162527e-05 - 7690.000000 -2.232864e-05 -2.734835e-06 -4.717352e-07 -2.892718e-06 -2.353677e-05 2.289649e-05 -2.077035e-05 -5.227520e-06 - 7690.200000 -2.230604e-05 -2.736331e-06 -4.720412e-07 -2.884962e-06 -2.226875e-05 1.684230e-05 -1.516275e-05 -9.904576e-07 - 7690.400000 -2.235277e-05 -2.740060e-06 -4.729789e-07 -2.892058e-06 -2.390563e-05 2.022658e-05 -8.306833e-06 -1.096273e-06 - 7690.600000 -2.238420e-05 -2.742457e-06 -4.733579e-07 -2.898958e-06 -3.292068e-05 1.725520e-05 -1.183723e-05 -1.612001e-06 - 7690.800000 -2.239470e-05 -2.743488e-06 -4.736107e-07 -2.899722e-06 -3.530015e-05 2.455285e-05 -1.344917e-05 3.602199e-06 - 7691.000000 -2.236345e-05 -2.740964e-06 -4.730443e-07 -2.898327e-06 -3.479824e-05 1.343167e-05 -1.336646e-05 -1.308396e-06 - 7691.200000 -2.240085e-05 -2.745118e-06 -4.737886e-07 -2.902448e-06 -3.279115e-05 1.389538e-05 -1.003337e-05 3.166618e-07 - 7691.400000 -2.237832e-05 -2.743865e-06 -4.734714e-07 -2.899464e-06 -2.638277e-05 1.218899e-05 -1.367967e-05 -8.676154e-06 - 7691.600000 -2.238182e-05 -2.746658e-06 -4.739687e-07 -2.897956e-06 -2.274059e-05 2.044256e-05 -1.684558e-05 -6.534446e-06 - 7691.800000 -2.236625e-05 -2.748389e-06 -4.742769e-07 -2.893301e-06 -2.368791e-05 2.345262e-05 -2.129891e-05 1.810017e-06 - 7692.000000 -2.235092e-05 -2.745336e-06 -4.734848e-07 -2.896417e-06 -2.734829e-05 2.499799e-05 -1.254162e-05 -3.395434e-07 - 7692.200000 -2.234375e-05 -2.746567e-06 -4.736811e-07 -2.894138e-06 -2.139878e-05 2.854053e-05 -1.659328e-05 -2.098750e-06 - 7692.400000 -2.231615e-05 -2.742671e-06 -4.729742e-07 -2.892660e-06 -2.035139e-05 2.611299e-05 -1.136594e-05 2.034404e-06 - 7692.600000 -2.226457e-05 -2.739143e-06 -4.722155e-07 -2.884346e-06 -2.034033e-05 2.284302e-05 -1.278009e-05 5.193262e-06 - 7692.800000 -2.228064e-05 -2.741179e-06 -4.725976e-07 -2.887862e-06 -1.532546e-05 1.297342e-05 -7.972528e-06 -5.257704e-06 - 7693.000000 -2.230097e-05 -2.745280e-06 -4.734334e-07 -2.888811e-06 -1.380731e-05 2.230025e-05 -1.225451e-05 -1.701557e-05 - 7693.200000 -2.237301e-05 -2.751718e-06 -4.745912e-07 -2.900494e-06 -2.121406e-05 2.796266e-05 -1.125773e-05 -1.193366e-05 - 7693.400000 -2.238410e-05 -2.752262e-06 -4.745671e-07 -2.904700e-06 -1.899137e-05 2.823171e-05 -8.794999e-06 -1.363547e-05 - 7693.600000 -2.238614e-05 -2.754302e-06 -4.751038e-07 -2.902853e-06 -1.762297e-05 2.745804e-05 -1.277193e-05 -1.062331e-05 - 7693.800000 -2.242712e-05 -2.755670e-06 -4.754560e-07 -2.911384e-06 -2.142638e-05 3.171059e-05 -1.960857e-05 -1.160345e-05 - 7694.000000 -2.244000e-05 -2.756414e-06 -4.756260e-07 -2.913638e-06 -8.578814e-06 2.586911e-05 -2.782209e-06 -1.069174e-05 - 7694.200000 -2.243295e-05 -2.756346e-06 -4.755005e-07 -2.912109e-06 -3.557469e-06 1.867160e-05 -4.316521e-06 -4.200332e-06 - 7694.400000 -2.234880e-05 -2.754787e-06 -4.750793e-07 -2.895956e-06 -1.883196e-05 1.986170e-05 -1.613660e-06 2.742278e-06 - 7694.600000 -2.233461e-05 -2.756735e-06 -4.756418e-07 -2.892152e-06 -1.980426e-05 2.598536e-05 -1.013859e-05 -5.232248e-07 - 7694.800000 -2.229366e-05 -2.756387e-06 -4.753660e-07 -2.884470e-06 -1.889268e-05 2.480477e-05 -1.542787e-05 -2.670083e-06 - 7695.000000 -2.229310e-05 -2.752843e-06 -4.744921e-07 -2.889688e-06 -2.058684e-05 2.995803e-05 -1.648757e-06 -5.390901e-06 - 7695.200000 -2.228114e-05 -2.749226e-06 -4.737032e-07 -2.890245e-06 -2.141499e-05 2.411082e-05 -7.197079e-06 -6.641326e-06 - 7695.400000 -2.228488e-05 -2.752097e-06 -4.741674e-07 -2.889665e-06 -2.077044e-05 2.803537e-05 -5.735789e-06 -2.547027e-07 - 7695.600000 -2.231979e-05 -2.756592e-06 -4.749682e-07 -2.894219e-06 -1.714108e-05 2.195708e-05 -1.709252e-05 -7.318954e-06 - 7695.800000 -2.237575e-05 -2.759808e-06 -4.757189e-07 -2.906206e-06 -1.234958e-05 2.107191e-05 -8.580750e-06 -7.900860e-06 - 7696.000000 -2.238420e-05 -2.761575e-06 -4.761015e-07 -2.907352e-06 -1.402476e-05 3.032072e-05 -7.101320e-06 -1.104434e-05 - 7696.200000 -2.237468e-05 -2.761884e-06 -4.758929e-07 -2.906516e-06 -2.624090e-05 2.752539e-05 -1.189749e-05 -2.157549e-05 - 7696.400000 -2.232310e-05 -2.758704e-06 -4.751073e-07 -2.900125e-06 -3.285161e-05 2.823330e-05 -9.413545e-06 -1.327072e-05 - 7696.600000 -2.228949e-05 -2.755859e-06 -4.745420e-07 -2.895124e-06 -2.582918e-05 4.161294e-05 -8.481807e-06 -1.538219e-05 - 7696.800000 -2.228479e-05 -2.755597e-06 -4.745942e-07 -2.894263e-06 -2.716109e-05 4.030744e-05 -3.844837e-06 -2.715215e-05 - 7697.000000 -2.224612e-05 -2.751810e-06 -4.739663e-07 -2.888441e-06 -2.377299e-05 3.597992e-05 -1.678146e-05 -2.471750e-05 - 7697.200000 -2.224449e-05 -2.752869e-06 -4.741312e-07 -2.888468e-06 -2.250560e-05 3.600975e-05 -1.840382e-05 -1.252696e-05 - 7697.400000 -2.230395e-05 -2.757592e-06 -4.747308e-07 -2.899375e-06 -1.995889e-05 3.551743e-05 -9.005679e-06 -1.009015e-05 - 7697.600000 -2.231145e-05 -2.757266e-06 -4.747712e-07 -2.900792e-06 -1.713231e-05 2.938399e-05 9.101754e-08 -7.680369e-06 - 7697.800000 -2.227918e-05 -2.751609e-06 -4.739477e-07 -2.899750e-06 -2.262629e-05 2.538923e-05 -9.655748e-06 -9.687617e-06 - 7698.000000 -2.223175e-05 -2.747421e-06 -4.731908e-07 -2.891783e-06 -2.255303e-05 3.030497e-05 -9.327978e-06 -1.372474e-05 - 7698.200000 -2.225931e-05 -2.748838e-06 -4.733136e-07 -2.897583e-06 -2.230184e-05 3.660151e-05 -1.553532e-05 1.867246e-07 - 7698.400000 -2.220401e-05 -2.745541e-06 -4.724137e-07 -2.889393e-06 -2.139434e-05 3.785035e-05 -7.998436e-06 -3.951814e-07 - 7698.600000 -2.228493e-05 -2.752513e-06 -4.737930e-07 -2.902670e-06 -2.747571e-05 3.400849e-05 2.426052e-06 -2.976596e-06 - 7698.800000 -2.232843e-05 -2.758276e-06 -4.748998e-07 -2.909562e-06 -1.162278e-05 2.499513e-05 -6.348630e-06 1.143294e-05 - 7699.000000 -2.235331e-05 -2.761584e-06 -4.755581e-07 -2.913692e-06 -9.074983e-06 2.231736e-05 -1.658273e-05 6.673585e-06 - 7699.200000 -2.237304e-05 -2.764017e-06 -4.756488e-07 -2.915951e-06 -1.254002e-05 2.443719e-05 -1.405939e-05 4.526282e-06 - 7699.400000 -2.237105e-05 -2.765120e-06 -4.755123e-07 -2.914699e-06 -1.450590e-05 3.018713e-05 -1.336760e-05 -5.467038e-07 - 7699.600000 -2.231947e-05 -2.762085e-06 -4.749722e-07 -2.906231e-06 -1.055105e-05 3.560902e-05 4.582543e-06 8.533784e-06 - 7699.800000 -2.219953e-05 -2.750649e-06 -4.728588e-07 -2.889257e-06 -5.917634e-06 4.190010e-05 1.174570e-05 -1.356604e-06 - 7700.000000 -2.207136e-05 -2.741857e-06 -4.713567e-07 -2.866187e-06 -8.050389e-06 4.343597e-05 -8.398959e-07 -8.226644e-06 - 7700.200000 -2.208083e-05 -2.737794e-06 -4.707360e-07 -2.870936e-06 -2.466279e-05 4.120676e-05 7.516058e-06 -1.290430e-06 - 7700.400000 -2.213046e-05 -2.740379e-06 -4.708589e-07 -2.882871e-06 -2.315414e-05 4.600128e-05 6.251585e-06 -7.363009e-06 - 7700.600000 -2.212225e-05 -2.739987e-06 -4.706191e-07 -2.883227e-06 -1.557642e-05 3.987304e-05 2.383838e-06 -8.207347e-06 - 7700.800000 -2.207112e-05 -2.738771e-06 -4.703382e-07 -2.873187e-06 -1.586100e-05 3.846460e-05 3.598161e-06 -5.391892e-06 - 7701.000000 -2.210098e-05 -2.742538e-06 -4.711110e-07 -2.876861e-06 -7.883498e-06 4.540312e-05 4.018527e-06 -3.838095e-06 - 7701.200000 -2.210591e-05 -2.743476e-06 -4.710650e-07 -2.879247e-06 -8.166441e-06 4.813633e-05 1.003869e-05 8.757800e-07 - 7701.400000 -2.214385e-05 -2.746786e-06 -4.714129e-07 -2.886167e-06 -2.797746e-06 4.371413e-05 1.771800e-05 8.840481e-06 - 7701.600000 -2.216108e-05 -2.748952e-06 -4.716241e-07 -2.889970e-06 -5.248847e-06 3.802898e-05 1.453274e-05 -3.684823e-06 - 7701.800000 -2.220917e-05 -2.751531e-06 -4.718794e-07 -2.899955e-06 -1.596542e-05 4.296619e-05 -1.167737e-06 -1.445046e-05 - 7702.000000 -2.220771e-05 -2.753596e-06 -4.721509e-07 -2.899854e-06 -2.078374e-05 3.993229e-05 7.751685e-06 -7.127320e-06 - 7702.200000 -2.222663e-05 -2.758615e-06 -4.730116e-07 -2.901635e-06 -1.284459e-05 4.043780e-05 6.072018e-06 -7.793959e-06 - 7702.400000 -2.227913e-05 -2.764845e-06 -4.739017e-07 -2.908976e-06 -1.816912e-05 4.631070e-05 7.992253e-06 -9.523663e-06 - 7702.600000 -2.235065e-05 -2.771706e-06 -4.748837e-07 -2.922020e-06 -1.044727e-05 3.291215e-05 1.828577e-05 -8.673635e-06 - 7702.800000 -2.238193e-05 -2.776790e-06 -4.755313e-07 -2.925547e-06 -1.713730e-05 3.636022e-05 -1.733824e-06 -8.987112e-06 - 7703.000000 -2.244887e-05 -2.783712e-06 -4.767184e-07 -2.936012e-06 -1.676117e-05 3.535712e-05 3.038352e-06 5.235990e-07 - 7703.200000 -2.246748e-05 -2.785460e-06 -4.767008e-07 -2.942219e-06 -1.303733e-05 3.766217e-05 7.438024e-06 -4.208414e-06 - 7703.400000 -2.245575e-05 -2.786357e-06 -4.765507e-07 -2.939649e-06 -1.219246e-05 3.463897e-05 -1.269043e-07 -5.991075e-06 - 7703.600000 -2.242948e-05 -2.785379e-06 -4.758232e-07 -2.935715e-06 -1.550459e-05 3.044048e-05 9.556100e-06 -7.063761e-06 - 7703.800000 -2.246737e-05 -2.788595e-06 -4.761209e-07 -2.941563e-06 -2.010392e-05 2.543384e-05 -1.073666e-06 -1.181522e-05 - 7704.000000 -2.241202e-05 -2.785443e-06 -4.753810e-07 -2.933706e-06 -2.091841e-05 4.403107e-05 1.096408e-06 -1.091977e-05 - 7704.200000 -2.243533e-05 -2.787598e-06 -4.754326e-07 -2.940176e-06 -1.232376e-05 4.338565e-05 -2.554097e-06 -7.410944e-06 - 7704.400000 -2.246664e-05 -2.791118e-06 -4.758493e-07 -2.944456e-06 -1.526012e-05 5.160606e-05 1.489934e-05 -5.075175e-06 - 7704.600000 -2.248021e-05 -2.791476e-06 -4.755804e-07 -2.948062e-06 -1.948745e-05 4.464447e-05 6.659139e-06 1.758292e-07 - 7704.800000 -2.247000e-05 -2.791201e-06 -4.747990e-07 -2.948207e-06 -2.050586e-05 3.717251e-05 -5.378384e-06 -7.886604e-06 - 7705.000000 -2.251453e-05 -2.794492e-06 -4.751517e-07 -2.955757e-06 -1.298144e-05 4.172485e-05 1.941439e-06 -1.101596e-05 - 7705.200000 -2.251889e-05 -2.794480e-06 -4.747546e-07 -2.958109e-06 -2.324406e-05 3.272304e-05 -2.719912e-06 -2.037126e-05 - 7705.400000 -2.252498e-05 -2.796999e-06 -4.750227e-07 -2.957603e-06 -1.602981e-05 3.855320e-05 -8.348547e-06 -7.572215e-06 - 7705.600000 -2.251694e-05 -2.797069e-06 -4.745667e-07 -2.957447e-06 -3.055336e-06 4.213047e-05 1.850610e-05 -6.740859e-06 - 7705.800000 -2.251164e-05 -2.796657e-06 -4.736675e-07 -2.958277e-06 -4.558054e-06 4.694902e-05 8.693642e-06 -5.931396e-06 - 7706.000000 -2.251834e-05 -2.796870e-06 -4.729826e-07 -2.961311e-06 -6.933135e-06 3.649158e-05 7.163086e-06 -2.065123e-05 - 7706.200000 -2.252189e-05 -2.797166e-06 -4.724291e-07 -2.963567e-06 -2.341863e-06 3.000525e-05 2.658560e-05 -1.456926e-05 - 7706.400000 -2.251395e-05 -2.797541e-06 -4.717486e-07 -2.963138e-06 -6.551940e-06 3.788164e-05 2.577083e-05 -3.089764e-06 - 7706.600000 -2.252368e-05 -2.798036e-06 -4.711548e-07 -2.965689e-06 -1.236651e-05 4.386906e-05 4.818212e-06 -7.435150e-06 - 7706.800000 -2.252581e-05 -2.799611e-06 -4.702077e-07 -2.966501e-06 -1.488163e-05 5.064172e-05 1.640315e-06 -8.926209e-06 - 7707.000000 -2.250610e-05 -2.797847e-06 -4.686141e-07 -2.965462e-06 -1.562566e-05 4.310344e-05 1.690639e-05 -1.280876e-07 - 7707.200000 -2.252036e-05 -2.798363e-06 -4.676040e-07 -2.969709e-06 -1.355463e-05 5.159146e-05 7.055250e-06 -5.484629e-06 - 7707.400000 -2.251194e-05 -2.799054e-06 -4.664722e-07 -2.968514e-06 -1.194167e-05 4.931975e-05 1.155083e-05 -9.440114e-06 - 7707.600000 -2.249271e-05 -2.797166e-06 -4.645368e-07 -2.967684e-06 -1.417608e-05 5.373981e-05 1.523150e-05 -6.139788e-06 - 7707.800000 -2.248246e-05 -2.798797e-06 -4.625952e-07 -2.965741e-06 -1.295034e-05 4.465318e-05 4.631944e-07 -2.776443e-05 - 7708.000000 -2.249086e-05 -2.797741e-06 -4.599528e-07 -2.971317e-06 -1.140384e-05 4.916372e-05 -3.499344e-06 -2.057587e-05 - 7708.200000 -2.246548e-05 -2.796161e-06 -4.567552e-07 -2.969495e-06 -1.267563e-05 5.541888e-05 -6.796901e-06 -1.729162e-05 - 7708.400000 -2.248436e-05 -2.797485e-06 -4.535953e-07 -2.975891e-06 -1.842435e-05 5.397620e-05 -9.610425e-06 -2.178994e-05 - 7708.600000 -2.242891e-05 -2.793422e-06 -4.482257e-07 -2.970418e-06 -1.880976e-05 4.664038e-05 -1.620820e-06 -1.618486e-05 - 7708.800000 -2.240356e-05 -2.791473e-06 -4.420120e-07 -2.967896e-06 -1.494953e-05 4.798009e-05 -1.946710e-06 -1.290086e-05 - 7709.000000 -2.237920e-05 -2.788922e-06 -4.342049e-07 -2.968898e-06 -1.257874e-05 4.511179e-05 -1.424785e-05 -1.961250e-05 - 7709.200000 -2.244638e-05 -2.792418e-06 -4.263509e-07 -2.988563e-06 -6.881392e-06 4.291368e-05 -1.425212e-05 -2.682671e-05 - 7709.400000 -2.248515e-05 -2.794040e-06 -4.167574e-07 -3.003710e-06 -1.577698e-05 4.008400e-05 -2.557495e-05 -1.818801e-05 - 7709.600000 -2.255015e-05 -2.794598e-06 -4.064530e-07 -3.025609e-06 -1.261469e-05 3.785460e-05 -1.133505e-05 -2.075182e-05 - 7709.800000 -2.255650e-05 -2.792983e-06 -3.951781e-07 -3.038522e-06 -1.121623e-05 4.167494e-05 -4.694380e-06 -2.592223e-05 - 7710.000000 -2.255691e-05 -2.789774e-06 -3.833661e-07 -3.054288e-06 -2.900115e-06 3.655560e-05 -1.946795e-06 -2.436266e-05 - 7710.200000 -2.256399e-05 -2.787321e-06 -3.721017e-07 -3.069030e-06 -1.228215e-05 2.770877e-05 -1.308388e-05 -1.282199e-05 - 7710.400000 -2.253856e-05 -2.782604e-06 -3.614289e-07 -3.079434e-06 -1.864610e-05 2.701784e-05 -2.976650e-05 -2.026984e-05 - 7710.600000 -2.252623e-05 -2.780435e-06 -3.520221e-07 -3.086924e-06 -1.411723e-05 2.487001e-05 -2.210105e-05 -1.414693e-05 - 7710.800000 -2.253680e-05 -2.779853e-06 -3.434654e-07 -3.094096e-06 -1.741597e-05 3.294736e-05 -2.829892e-05 -8.930985e-06 - 7711.000000 -2.254384e-05 -2.779316e-06 -3.353047e-07 -3.097082e-06 -2.504015e-05 2.539335e-05 -2.693307e-05 -5.286168e-06 - 7711.200000 -2.254514e-05 -2.783223e-06 -3.284769e-07 -3.091235e-06 -3.225859e-05 2.967216e-05 -2.263699e-05 -1.591610e-05 - 7711.400000 -2.252124e-05 -2.782137e-06 -3.216707e-07 -3.082067e-06 -2.516847e-05 2.873037e-05 -2.049575e-05 -1.728128e-05 - 7711.600000 -2.248532e-05 -2.782954e-06 -3.154253e-07 -3.068145e-06 -2.903020e-05 3.104172e-05 -2.281636e-05 -2.259888e-05 - 7711.800000 -2.252796e-05 -2.788365e-06 -3.103410e-07 -3.068645e-06 -1.852299e-05 2.776502e-05 -1.963194e-05 -2.200990e-05 - 7712.000000 -2.253059e-05 -2.790279e-06 -3.052795e-07 -3.063870e-06 -1.390731e-05 3.537602e-05 -2.416086e-05 -5.436724e-06 - 7712.200000 -2.250891e-05 -2.791658e-06 -3.007151e-07 -3.056459e-06 -1.882147e-05 4.037954e-05 -2.717986e-05 -1.053901e-05 - 7712.400000 -2.246762e-05 -2.788251e-06 -2.961208e-07 -3.049895e-06 -1.851467e-05 3.508608e-05 -2.824864e-05 -5.716442e-06 - 7712.600000 -2.246414e-05 -2.791307e-06 -2.928280e-07 -3.047173e-06 -1.061611e-05 3.508897e-05 -2.166352e-05 -7.098072e-06 - 7712.800000 -2.247135e-05 -2.792897e-06 -2.898643e-07 -3.047831e-06 -9.478108e-06 3.779201e-05 -2.529592e-05 -1.680850e-05 - 7713.000000 -2.252017e-05 -2.795656e-06 -2.874767e-07 -3.055849e-06 -2.023766e-05 4.231590e-05 -2.728068e-05 -9.117358e-06 - 7713.200000 -2.250130e-05 -2.794804e-06 -2.852718e-07 -3.052974e-06 -1.802163e-05 4.011951e-05 -3.265922e-05 -2.580628e-06 - 7713.400000 -2.249958e-05 -2.795111e-06 -2.836277e-07 -3.052564e-06 -1.683507e-05 4.344685e-05 -1.261620e-05 -5.987505e-06 - 7713.600000 -2.245329e-05 -2.791027e-06 -2.818325e-07 -3.048605e-06 -2.044158e-05 4.212682e-05 -1.468717e-05 -7.892874e-06 - 7713.800000 -2.234475e-05 -2.782471e-06 -2.799807e-07 -3.031556e-06 -2.323554e-05 3.121993e-05 -1.003455e-05 -1.412707e-06 - 7714.000000 -2.236103e-05 -2.783516e-06 -2.795579e-07 -3.038220e-06 -1.114065e-05 4.361885e-05 -1.279480e-05 1.780236e-06 - 7714.200000 -2.235259e-05 -2.784452e-06 -2.793311e-07 -3.037743e-06 -6.230894e-06 3.808921e-05 -4.396011e-06 2.650068e-06 - 7714.400000 -2.237522e-05 -2.786843e-06 -2.791327e-07 -3.048854e-06 -1.340381e-05 3.935794e-05 -1.701249e-05 -3.461199e-06 - 7714.600000 -2.236466e-05 -2.787796e-06 -2.791203e-07 -3.051629e-06 -2.323849e-05 2.992610e-05 -1.534709e-05 -5.601732e-06 - 7714.800000 -2.241251e-05 -2.791370e-06 -2.792903e-07 -3.064547e-06 -2.774498e-05 3.157560e-05 -1.868636e-05 -6.381088e-06 - 7715.000000 -2.241730e-05 -2.788475e-06 -2.786033e-07 -3.070229e-06 -1.391740e-05 3.911794e-05 -8.631044e-06 2.961507e-06 - 7715.200000 -2.249662e-05 -2.792181e-06 -2.783880e-07 -3.089773e-06 -1.592247e-05 4.045931e-05 -4.995088e-06 -5.281318e-07 - 7715.400000 -2.253229e-05 -2.791838e-06 -2.772397e-07 -3.105302e-06 -1.348177e-05 3.939667e-05 -8.135839e-06 -1.504694e-05 - 7715.600000 -2.255861e-05 -2.793199e-06 -2.759564e-07 -3.115752e-06 -7.165257e-06 4.212838e-05 -1.608094e-05 -1.823087e-05 - 7715.800000 -2.253532e-05 -2.790510e-06 -2.733242e-07 -3.120376e-06 -7.620119e-06 2.826269e-05 -1.847878e-05 -1.177232e-05 - 7716.000000 -2.254714e-05 -2.789841e-06 -2.707534e-07 -3.130507e-06 -1.204147e-06 2.920724e-05 -8.235697e-06 -1.417893e-05 - 7716.200000 -2.255606e-05 -2.788942e-06 -2.672429e-07 -3.143000e-06 -1.231204e-05 3.193013e-05 -3.028013e-06 -7.676164e-06 - 7716.400000 -2.252056e-05 -2.784559e-06 -2.633551e-07 -3.148093e-06 -1.868613e-05 2.948362e-05 -2.163522e-06 -1.245250e-05 - 7716.600000 -2.254025e-05 -2.781903e-06 -2.592239e-07 -3.166232e-06 -8.315797e-06 2.762762e-05 1.966474e-06 -9.122107e-06 - 7716.800000 -2.251163e-05 -2.777971e-06 -2.546028e-07 -3.175489e-06 -5.658291e-06 2.411990e-05 5.542649e-07 -5.313148e-06 - 7717.000000 -2.255500e-05 -2.775845e-06 -2.501688e-07 -3.202213e-06 -1.001183e-05 2.231225e-05 4.584577e-07 -1.063930e-05 - 7717.200000 -2.257877e-05 -2.771717e-06 -2.454714e-07 -3.227601e-06 -6.704069e-06 2.550025e-05 8.905165e-06 -1.326930e-05 - 7717.400000 -2.256439e-05 -2.764365e-06 -2.405461e-07 -3.249150e-06 -1.223101e-05 3.800709e-05 -2.818145e-06 -2.314942e-05 - 7717.600000 -2.249414e-05 -2.753313e-06 -2.351612e-07 -3.264941e-06 -1.955224e-05 4.142139e-05 -5.098383e-06 -2.125589e-05 - 7717.800000 -2.251968e-05 -2.747428e-06 -2.305567e-07 -3.299576e-06 -1.177692e-05 3.505256e-05 4.461829e-06 -1.669636e-05 - 7718.000000 -2.246755e-05 -2.734272e-06 -2.250470e-07 -3.328931e-06 -1.146571e-05 2.773825e-05 -8.328209e-06 -1.190021e-05 - 7718.200000 -2.250637e-05 -2.726526e-06 -2.203026e-07 -3.376571e-06 -1.150077e-05 3.039535e-05 -4.563684e-06 -9.738591e-06 - 7718.400000 -2.240486e-05 -2.710342e-06 -2.146757e-07 -3.402139e-06 -2.543279e-06 3.468158e-05 -8.832012e-06 -1.716696e-05 - 7718.600000 -2.246731e-05 -2.700938e-06 -2.099258e-07 -3.466990e-06 -2.890269e-06 3.084896e-05 -1.416075e-05 -2.946394e-05 - 7718.800000 -2.236875e-05 -2.682538e-06 -2.043317e-07 -3.501914e-06 -1.182629e-05 4.122998e-05 -8.898079e-06 -2.146294e-05 - 7719.000000 -2.244283e-05 -2.671873e-06 -1.996704e-07 -3.568051e-06 -2.909892e-06 3.983298e-05 -1.691566e-05 -2.311366e-05 - 7719.200000 -2.242485e-05 -2.656280e-06 -1.945232e-07 -3.609785e-06 -1.106702e-06 4.094355e-05 -1.617605e-05 -2.472414e-05 - 7719.400000 -2.249055e-05 -2.650726e-06 -1.904745e-07 -3.651918e-06 -2.594024e-06 4.703680e-05 -1.056964e-05 -1.519894e-05 - 7719.600000 -2.247355e-05 -2.638414e-06 -1.858237e-07 -3.663979e-06 -6.586945e-06 2.811173e-05 -2.881080e-06 -1.344002e-05 - 7719.800000 -2.249852e-05 -2.634802e-06 -1.822687e-07 -3.667466e-06 -8.203228e-06 3.168015e-05 -7.365092e-06 -1.613489e-05 - 7720.000000 -2.249535e-05 -2.625563e-06 -1.784603e-07 -3.663310e-06 -1.267037e-05 3.483170e-05 -6.410757e-06 -6.900035e-06 - 7720.200000 -2.251968e-05 -2.620139e-06 -1.748264e-07 -3.662811e-06 -1.431558e-05 2.756354e-05 -4.764250e-06 -1.624353e-05 - 7720.400000 -2.255102e-05 -2.614848e-06 -1.717089e-07 -3.664255e-06 -1.161528e-05 2.418145e-05 1.772414e-06 -2.074048e-05 - 7720.600000 -2.255982e-05 -2.609252e-06 -1.686605e-07 -3.657687e-06 -1.173693e-05 2.473530e-05 1.211194e-05 -2.269313e-05 - 7720.800000 -2.255538e-05 -2.603560e-06 -1.658553e-07 -3.650551e-06 -1.702097e-05 3.333982e-05 1.248288e-06 -2.406264e-05 - 7721.000000 -2.255028e-05 -2.596821e-06 -1.631329e-07 -3.642422e-06 -1.760010e-05 2.904515e-05 -4.079073e-06 -2.646507e-05 - 7721.200000 -2.256637e-05 -2.590108e-06 -1.604813e-07 -3.632455e-06 -1.825792e-05 2.805628e-05 -5.724899e-06 -2.143160e-05 - 7721.400000 -2.250658e-05 -2.579681e-06 -1.577237e-07 -3.635069e-06 -1.795583e-05 2.517885e-05 -1.391441e-05 -2.175515e-05 - 7721.600000 -2.257063e-05 -2.573807e-06 -1.553446e-07 -3.635909e-06 -2.040181e-05 2.704884e-05 -1.323809e-05 -1.370447e-05 - 7721.800000 -2.253736e-05 -2.563573e-06 -1.528664e-07 -3.650325e-06 -2.646623e-05 3.809145e-05 -1.589910e-05 -2.092352e-05 - 7722.000000 -2.253037e-05 -2.554084e-06 -1.503176e-07 -3.657921e-06 -1.609479e-05 3.638938e-05 -7.214412e-06 -1.702714e-05 - 7722.200000 -2.249969e-05 -2.543248e-06 -1.477392e-07 -3.672836e-06 -1.775927e-05 2.940768e-05 -1.150646e-05 -6.974953e-06 - 7722.400000 -2.253340e-05 -2.532855e-06 -1.450010e-07 -3.696594e-06 -2.249809e-05 3.160023e-05 -6.158031e-06 -3.687094e-06 - 7722.600000 -2.255724e-05 -2.521956e-06 -1.423629e-07 -3.717275e-06 -2.206843e-05 2.714009e-05 2.226680e-06 -9.124504e-06 - 7722.800000 -2.258872e-05 -2.511166e-06 -1.395908e-07 -3.736177e-06 -2.598492e-05 2.732939e-05 -2.353807e-06 -1.236305e-05 - 7723.000000 -2.255285e-05 -2.496030e-06 -1.366394e-07 -3.746490e-06 -2.542968e-05 2.957409e-05 -2.386927e-05 -2.209991e-05 - 7723.200000 -2.256537e-05 -2.484379e-06 -1.338207e-07 -3.759056e-06 -2.976188e-05 3.105946e-05 -2.985693e-05 -2.855104e-05 - 7723.400000 -2.255704e-05 -2.470572e-06 -1.309227e-07 -3.767881e-06 -3.140864e-05 2.461205e-05 -2.185313e-05 -3.227429e-05 - 7723.600000 -2.257071e-05 -2.460406e-06 -1.281000e-07 -3.776007e-06 -2.142246e-05 2.752137e-05 -1.524017e-05 -2.265241e-05 - 7723.800000 -2.258156e-05 -2.447350e-06 -1.253219e-07 -3.783466e-06 -1.428843e-05 2.588633e-05 -3.041965e-05 -2.410077e-05 - 7724.000000 -2.257180e-05 -2.433071e-06 -1.225610e-07 -3.788437e-06 -1.486393e-05 2.056311e-05 -3.264887e-05 -2.162707e-05 - 7724.200000 -2.259142e-05 -2.420889e-06 -1.200049e-07 -3.794254e-06 -5.824786e-06 2.116629e-05 -3.218678e-05 -1.890899e-05 - 7724.400000 -2.259656e-05 -2.405314e-06 -1.171370e-07 -3.797376e-06 -1.202785e-05 2.312285e-05 -2.727814e-05 -2.446704e-05 - 7724.600000 -2.256268e-05 -2.391526e-06 -1.146705e-07 -3.798459e-06 -2.041056e-05 2.367938e-05 -3.800222e-05 -3.178523e-05 - 7724.800000 -2.254911e-05 -2.375413e-06 -1.122007e-07 -3.799084e-06 -1.131923e-05 2.255993e-05 -3.041846e-05 -2.473263e-05 - 7725.000000 -2.257957e-05 -2.358608e-06 -1.097799e-07 -3.799474e-06 -8.859609e-06 3.675898e-05 -2.544943e-05 -1.233643e-05 - 7725.200000 -2.256923e-05 -2.337879e-06 -1.073113e-07 -3.799579e-06 -1.311707e-05 3.852970e-05 -3.477777e-05 -2.545326e-05 - 7725.400000 -2.256741e-05 -2.315556e-06 -1.049252e-07 -3.799777e-06 -1.593088e-05 4.010532e-05 -4.176759e-05 -1.989259e-05 - 7725.600000 -2.258153e-05 -2.290185e-06 -1.027240e-07 -3.799784e-06 -1.320598e-05 3.200283e-05 -4.258802e-05 -1.440353e-05 - 7725.800000 -2.257035e-05 -2.261479e-06 -1.002653e-07 -3.799381e-06 1.828286e-06 3.054535e-05 -3.847975e-05 -1.502270e-05 - 7726.000000 -2.260648e-05 -2.234766e-06 -9.815243e-08 -3.799976e-06 6.209073e-08 2.383893e-05 -3.061798e-05 -1.765632e-05 - 7726.200000 -2.261051e-05 -2.202617e-06 -9.593544e-08 -3.799447e-06 -4.967447e-06 3.176422e-05 -3.175480e-05 -1.432808e-05 - 7726.400000 -2.260630e-05 -2.169365e-06 -9.384448e-08 -3.799377e-06 -7.035119e-06 3.013933e-05 -4.172514e-05 -1.812471e-05 - 7726.600000 -2.260191e-05 -2.134742e-06 -9.165533e-08 -3.799811e-06 -1.569615e-05 2.415202e-05 -4.870550e-05 -1.706774e-05 - 7726.800000 -2.258451e-05 -2.098072e-06 -8.947544e-08 -3.799573e-06 -1.836335e-05 1.840364e-05 -4.383945e-05 -2.220120e-05 - 7727.000000 -2.257467e-05 -2.062471e-06 -8.747488e-08 -3.799337e-06 -1.565657e-05 2.210639e-05 -3.999724e-05 -6.305301e-06 - 7727.200000 -2.258417e-05 -2.026785e-06 -8.532331e-08 -3.799663e-06 -1.279131e-05 2.409273e-05 -4.532375e-05 -1.296514e-05 - 7727.400000 -2.255264e-05 -1.994775e-06 -8.350164e-08 -3.800114e-06 -5.998222e-06 2.157424e-05 -3.293305e-05 -1.212073e-05 - 7727.600000 -2.251121e-05 -1.962923e-06 -8.178089e-08 -3.799473e-06 -3.102082e-06 2.739352e-05 -3.090555e-05 -2.033140e-05 - 7727.800000 -2.255736e-05 -1.935854e-06 -8.027054e-08 -3.799890e-06 -7.746344e-06 1.455367e-05 -2.920319e-05 -9.572123e-06 - 7728.000000 -2.257054e-05 -1.912065e-06 -7.899889e-08 -3.799834e-06 -7.899140e-06 1.779379e-05 -3.679583e-05 -3.679881e-06 - 7728.200000 -2.255008e-05 -1.890087e-06 -7.781301e-08 -3.799855e-06 -5.563021e-06 3.105164e-05 -4.046037e-05 -1.020970e-05 - 7728.400000 -2.258241e-05 -1.872527e-06 -7.672639e-08 -3.799822e-06 -2.802860e-06 2.751735e-05 -3.680751e-05 -1.149608e-05 - 7728.600000 -2.257807e-05 -1.858660e-06 -7.597685e-08 -3.799686e-06 -5.891467e-06 3.351093e-05 -3.516634e-05 -2.168993e-05 - 7728.800000 -2.258182e-05 -1.849997e-06 -7.544274e-08 -3.799904e-06 -1.033582e-05 3.011039e-05 -3.418606e-05 -1.879636e-05 - 7729.000000 -2.255889e-05 -1.842446e-06 -7.494023e-08 -3.799693e-06 -1.317653e-05 3.190325e-05 -3.797360e-05 -1.651874e-05 - 7729.200000 -2.253098e-05 -1.836571e-06 -7.458039e-08 -3.799691e-06 -1.542611e-05 3.763332e-05 -3.760481e-05 -1.504192e-05 - 7729.400000 -2.249136e-05 -1.834341e-06 -7.432461e-08 -3.800301e-06 -1.087131e-05 2.901642e-05 -4.151561e-05 -2.260013e-05 - 7729.600000 -2.245991e-05 -1.834951e-06 -7.422811e-08 -3.799338e-06 5.760953e-06 1.516369e-05 -3.360001e-05 -2.362811e-05 - 7729.800000 -2.245191e-05 -1.838691e-06 -7.437209e-08 -3.799837e-06 -3.199518e-07 2.017689e-05 -3.993102e-05 -1.611945e-05 - 7730.000000 -2.242580e-05 -1.844793e-06 -7.460835e-08 -3.800023e-06 -3.522390e-06 2.216884e-05 -5.285490e-05 -2.506310e-05 - 7730.200000 -2.241314e-05 -1.854345e-06 -7.483914e-08 -3.799540e-06 -6.797978e-06 2.581552e-05 -5.203320e-05 -1.927148e-05 - 7730.400000 -2.242516e-05 -1.866676e-06 -7.536307e-08 -3.799896e-06 -6.490780e-06 3.394727e-05 -5.528831e-05 -1.780550e-05 - 7730.600000 -2.242561e-05 -1.881230e-06 -7.586940e-08 -3.799838e-06 -4.929452e-06 3.354475e-05 -5.559209e-05 -2.488479e-05 - 7730.800000 -2.241735e-05 -1.896471e-06 -7.647911e-08 -3.799803e-06 -4.843701e-06 2.779323e-05 -5.445470e-05 -2.494888e-05 - 7731.000000 -2.242643e-05 -1.912903e-06 -7.706913e-08 -3.799727e-06 -8.373102e-06 1.577825e-05 -6.301890e-05 -2.766086e-05 - 7731.200000 -2.241843e-05 -1.930167e-06 -7.766229e-08 -3.799790e-06 -8.911664e-06 1.385485e-05 -5.746522e-05 -2.131884e-05 - 7731.400000 -2.244381e-05 -1.949743e-06 -7.846965e-08 -3.799544e-06 -1.174643e-06 8.124086e-06 -6.495034e-05 -1.713832e-05 - 7731.600000 -2.243939e-05 -1.967332e-06 -7.896759e-08 -3.800100e-06 -5.438766e-06 7.136964e-06 -5.535106e-05 -7.515994e-06 - 7731.800000 -2.243554e-05 -1.986130e-06 -7.956020e-08 -3.799741e-06 -7.670501e-06 4.124609e-06 -5.225128e-05 -1.571105e-05 - 7732.000000 -2.244177e-05 -2.003454e-06 -8.007475e-08 -3.799760e-06 -4.451508e-06 -3.820916e-07 -6.389826e-05 -2.095742e-05 - 7732.200000 -2.246250e-05 -2.021665e-06 -8.045234e-08 -3.799536e-06 -1.210075e-06 9.807694e-06 -6.662969e-05 -1.586180e-05 - 7732.400000 -2.250024e-05 -2.039502e-06 -8.097275e-08 -3.799571e-06 -6.688799e-06 1.394375e-05 -4.909329e-05 -6.528399e-06 - 7732.600000 -2.251055e-05 -2.055358e-06 -8.137259e-08 -3.799733e-06 -1.131681e-05 7.785746e-06 -4.627889e-05 -1.100879e-05 - 7732.800000 -2.252848e-05 -2.071343e-06 -8.165791e-08 -3.799251e-06 -8.766215e-06 1.681059e-05 -5.917642e-05 -7.700615e-07 - 7733.000000 -2.255583e-05 -2.086482e-06 -8.201350e-08 -3.799675e-06 -8.175776e-06 1.667821e-05 -6.642972e-05 -6.319660e-06 - 7733.200000 -2.258177e-05 -2.100847e-06 -8.225807e-08 -3.799501e-06 -6.187861e-06 1.813522e-05 -6.123201e-05 -2.236988e-05 - 7733.400000 -2.260317e-05 -2.114961e-06 -8.249388e-08 -3.799336e-06 -2.553003e-06 1.815635e-05 -5.721836e-05 -1.589880e-05 - 7733.600000 -2.262926e-05 -2.125802e-06 -8.260446e-08 -3.799420e-06 1.759924e-06 1.042107e-05 -4.908057e-05 1.042595e-05 - 7733.800000 -2.265345e-05 -2.136551e-06 -8.273359e-08 -3.799498e-06 -3.610500e-07 1.467535e-05 -4.896965e-05 -2.677978e-06 - 7734.000000 -2.265613e-05 -2.144695e-06 -8.282510e-08 -3.799484e-06 -5.646233e-07 2.070766e-05 -4.770975e-05 -1.374027e-05 - 7734.200000 -2.266079e-05 -2.152347e-06 -8.286892e-08 -3.799193e-06 1.887204e-06 1.910353e-05 -4.113515e-05 -1.317941e-05 - 7734.400000 -2.267942e-05 -2.159274e-06 -8.304147e-08 -3.799876e-06 -5.043172e-06 2.224207e-05 -4.361514e-05 -1.014702e-05 - 7734.600000 -2.267665e-05 -2.161449e-06 -8.307583e-08 -3.799444e-06 -4.661152e-06 2.678407e-05 -3.217163e-05 -1.723606e-05 - 7734.800000 -2.267849e-05 -2.165859e-06 -8.325236e-08 -3.799330e-06 -4.493822e-06 3.227269e-05 -3.079117e-05 -1.462824e-05 - 7735.000000 -2.267226e-05 -2.165644e-06 -8.319786e-08 -3.799593e-06 -3.161339e-06 3.318788e-05 -2.457630e-05 -9.106090e-06 - 7735.200000 -2.261171e-05 -2.166972e-06 -8.343866e-08 -3.799344e-06 -1.058252e-05 2.853735e-05 -2.130882e-05 -1.443129e-05 - 7735.400000 -2.265780e-05 -2.168795e-06 -8.352541e-08 -3.799879e-06 -8.819449e-06 2.942648e-05 -3.033401e-05 -1.077163e-05 - 7735.600000 -2.267808e-05 -2.169109e-06 -8.370935e-08 -3.799154e-06 -1.976739e-05 2.915447e-05 -2.901177e-05 -1.230287e-05 - 7735.800000 -2.268079e-05 -2.171872e-06 -8.411217e-08 -3.799799e-06 -2.039765e-05 2.991414e-05 -2.703034e-05 -1.623587e-05 - 7736.000000 -2.262810e-05 -2.169549e-06 -8.432723e-08 -3.799242e-06 -1.861006e-05 1.953021e-05 -2.353319e-05 -1.161365e-05 - 7736.200000 -2.263471e-05 -2.170012e-06 -8.456407e-08 -3.799654e-06 -1.151731e-05 9.970356e-06 -2.147807e-05 -6.025432e-06 - 7736.400000 -2.264156e-05 -2.168788e-06 -8.479409e-08 -3.799365e-06 -6.999851e-06 6.659118e-06 -1.528050e-05 -7.078687e-06 - 7736.600000 -2.261538e-05 -2.167730e-06 -8.510257e-08 -3.799611e-06 -1.151005e-05 9.233853e-06 -1.372205e-05 -6.080412e-06 - 7736.800000 -2.259638e-05 -2.167644e-06 -8.557698e-08 -3.799517e-06 -1.281895e-05 1.554847e-05 -1.424621e-05 -3.191734e-06 - 7737.000000 -2.249674e-05 -2.164859e-06 -8.582480e-08 -3.799189e-06 -1.235922e-05 1.929810e-05 -4.823610e-06 -6.007431e-06 - 7737.200000 -2.245566e-05 -2.164107e-06 -8.618408e-08 -3.799792e-06 -1.385553e-05 2.434403e-05 -5.837600e-06 -1.151818e-05 - 7737.400000 -2.251044e-05 -2.163819e-06 -8.658212e-08 -3.799272e-06 -1.619805e-05 3.466876e-05 -1.426678e-05 -1.874458e-05 - 7737.600000 -2.255663e-05 -2.168245e-06 -8.706077e-08 -3.799529e-06 -1.859145e-05 2.554198e-05 2.571473e-06 -5.498173e-06 - 7737.800000 -2.259002e-05 -2.171841e-06 -8.751150e-08 -3.799493e-06 -1.943610e-05 2.125379e-05 -2.468309e-06 -4.374638e-06 - 7738.000000 -2.259295e-05 -2.176529e-06 -8.805964e-08 -3.799454e-06 -1.353441e-05 1.523818e-05 -4.479051e-06 -7.761027e-06 - 7738.200000 -2.265945e-05 -2.179879e-06 -8.848343e-08 -3.799761e-06 -8.652555e-06 1.692067e-05 1.096478e-06 -7.602866e-06 - 7738.400000 -2.261414e-05 -2.179508e-06 -8.892466e-08 -3.799260e-06 3.241548e-06 1.942207e-05 -6.970494e-06 2.505913e-06 - 7738.600000 -2.267155e-05 -2.187511e-06 -8.942380e-08 -3.799840e-06 2.582691e-08 1.792850e-05 -1.648256e-05 -1.826831e-06 - 7738.800000 -2.269180e-05 -2.188953e-06 -8.988204e-08 -3.799348e-06 -3.565164e-06 1.765524e-05 -1.255366e-05 -6.939493e-06 - 7739.000000 -2.270772e-05 -2.194505e-06 -9.037626e-08 -3.799479e-06 -6.027667e-06 2.620974e-05 -1.622676e-05 -6.654579e-06 - 7739.227860 -2.270554e-05 -2.199605e-06 -9.075564e-08 -3.799687e-06 -1.113074e-05 2.010592e-05 -1.312597e-05 -7.121368e-06 - 7739.483581 -2.268007e-05 -2.201649e-06 -9.114160e-08 -3.799313e-06 -1.263263e-05 2.248902e-05 -5.867321e-06 -1.120377e-05 - 7739.767162 -2.267591e-05 -2.207518e-06 -9.170671e-08 -3.799635e-06 -1.290888e-05 2.482997e-05 -1.177702e-05 -1.477426e-05 - 7740.078604 -2.266886e-05 -2.212564e-06 -9.229809e-08 -3.799626e-06 -6.032608e-06 3.064874e-05 -2.620444e-05 -1.336459e-05 - 7740.417905 -2.265711e-05 -2.215909e-06 -9.272594e-08 -3.799554e-06 -4.312672e-06 3.430095e-05 -3.018503e-05 -1.719556e-05 - 7740.785067 -2.258784e-05 -2.217337e-06 -9.314842e-08 -3.799582e-06 -4.739340e-06 3.523586e-05 -2.599020e-05 -1.693346e-05 - 7741.180090 -2.253931e-05 -2.217450e-06 -9.348640e-08 -3.799562e-06 4.594768e-06 3.533492e-05 -2.794301e-05 -1.650624e-05 - 7741.602973 -2.258387e-05 -2.218268e-06 -9.387446e-08 -3.799601e-06 5.319386e-06 3.774558e-05 -2.324577e-05 -1.993622e-05 - 7742.053716 -2.262465e-05 -2.216510e-06 -9.409929e-08 -3.799556e-06 3.837106e-07 2.505289e-05 -1.974099e-05 -1.674858e-05 - 7742.532319 -2.272466e-05 -2.214019e-06 -9.426011e-08 -3.799542e-06 -8.038113e-06 2.346833e-05 -2.383228e-05 -1.679654e-05 - 7743.038783 -2.271454e-05 -2.205505e-06 -9.420620e-08 -3.799524e-06 -3.088660e-06 2.537937e-05 -2.194084e-05 -1.589958e-05 - 7743.573107 -2.259121e-05 -2.193735e-06 -9.401836e-08 -3.799569e-06 4.368080e-06 2.364702e-05 -2.167801e-05 -1.983063e-05 - 7744.135292 -2.258945e-05 -2.189373e-06 -9.413422e-08 -3.799554e-06 -1.819163e-06 2.650347e-05 -1.842847e-05 -1.271772e-05 - 7744.725337 -2.264279e-05 -2.186209e-06 -9.433647e-08 -3.799550e-06 -1.010416e-05 2.375103e-05 -1.684876e-05 -1.450599e-05 - 7745.343242 -2.270741e-05 -2.188864e-06 -9.479129e-08 -3.799558e-06 -9.822636e-06 2.490686e-05 -2.122419e-05 -1.883370e-05 - 7745.989008 -2.273763e-05 -2.194763e-06 -9.525856e-08 -3.799531e-06 -9.703685e-06 4.183358e-05 -1.918039e-05 -1.760343e-05 - 7746.662634 -2.270133e-05 -2.203321e-06 -9.569817e-08 -3.799536e-06 -5.250226e-06 3.734481e-05 -9.420403e-06 -9.433236e-06 - 7747.364120 -2.265908e-05 -2.216238e-06 -9.607651e-08 -3.799561e-06 -4.574938e-06 3.360555e-05 7.885391e-07 8.553278e-07 - 7748.093467 -2.246076e-05 -2.224257e-06 -9.586488e-08 -3.799600e-06 -4.833593e-06 3.044216e-05 -6.988886e-06 9.543955e-07 - 7748.850674 -2.241046e-05 -2.238266e-06 -9.569684e-08 -3.799654e-06 1.983910e-07 3.121482e-05 -1.272173e-05 3.996144e-07 - 7749.635741 -2.259805e-05 -2.266167e-06 -9.588900e-08 -3.799580e-06 1.108216e-05 4.094544e-05 -1.814019e-05 -3.079003e-06 - 7750.448669 -2.277338e-05 -2.292227e-06 -9.562500e-08 -3.799626e-06 1.082689e-05 4.125762e-05 -1.375963e-05 -3.076652e-06 - 7751.289457 -2.280291e-05 -2.314165e-06 -9.493542e-08 -3.799648e-06 3.506427e-06 3.124436e-05 -5.738472e-06 5.405820e-07 - 7752.158106 -2.280577e-05 -2.335584e-06 -9.398225e-08 -3.799677e-06 9.678026e-06 2.673118e-05 -9.974830e-06 -1.147707e-05 - 7753.054614 -2.281285e-05 -2.356118e-06 -9.289724e-08 -3.799680e-06 6.002437e-06 2.346196e-05 -9.295994e-06 -1.156571e-05 - 7753.978983 -2.280325e-05 -2.374174e-06 -9.160666e-08 -3.799697e-06 8.286776e-07 3.272490e-05 3.383730e-06 -3.112428e-06 - 7754.931213 -2.274428e-05 -2.389073e-06 -9.019601e-08 -3.799714e-06 -2.706409e-06 3.323692e-05 -6.530360e-06 -3.475243e-06 - 7755.911303 -2.267864e-05 -2.399799e-06 -8.887688e-08 -3.799706e-06 1.090007e-06 2.363562e-05 -1.528973e-06 -1.678685e-06 - 7756.919253 -2.270985e-05 -2.409310e-06 -8.774559e-08 -3.799719e-06 8.459315e-07 1.604165e-05 -1.289732e-05 -1.258617e-05 - 7757.955064 -2.273926e-05 -2.416334e-06 -8.700329e-08 -3.799764e-06 8.204001e-06 1.887875e-05 -7.015890e-06 -1.241696e-05 - 7759.018734 -2.278230e-05 -2.418512e-06 -8.676190e-08 -3.799767e-06 3.151240e-06 2.472424e-05 -1.599806e-05 -1.194110e-05 - 7760.110266 -2.279887e-05 -2.415839e-06 -8.680329e-08 -3.799750e-06 -7.826499e-06 3.139362e-05 -2.716616e-05 -1.026543e-05 - 7761.232723 -2.282249e-05 -2.415605e-06 -8.741328e-08 -3.799737e-06 3.440380e-06 3.266843e-05 -2.894242e-05 -1.169866e-05 - 7762.367373 -2.281474e-05 -2.415923e-06 -8.857790e-08 -3.799754e-06 1.673778e-06 3.249575e-05 -1.911758e-05 -1.383627e-05 - 7763.514214 -2.278836e-05 -2.417504e-06 -9.036443e-08 -3.799768e-06 -2.159854e-06 2.691669e-05 -2.362489e-05 -1.991214e-05 - 7764.673248 -2.258503e-05 -2.399670e-06 -9.193331e-08 -3.799736e-06 2.411171e-06 2.144441e-05 -2.015412e-05 -1.965602e-05 - 7765.844473 -2.213979e-05 -2.358558e-06 -9.277067e-08 -3.799792e-06 9.758726e-06 2.190508e-05 -1.500720e-05 -8.392279e-06 - 7767.027890 -2.255132e-05 -2.399797e-06 -9.723211e-08 -3.799753e-06 1.599060e-05 2.838962e-05 -1.715622e-05 -3.764248e-06 - 7768.223499 -2.287486e-05 -2.436310e-06 -1.017028e-07 -3.799772e-06 1.511480e-05 2.851943e-05 -1.749340e-05 -4.337874e-06 - 7769.431300 -2.286147e-05 -2.432514e-06 -1.043837e-07 -3.799730e-06 2.637008e-06 1.454317e-05 -1.199940e-05 -1.587776e-05 - 7770.651293 -2.288102e-05 -2.423363e-06 -1.063864e-07 -3.799714e-06 -5.382350e-07 1.248320e-05 -1.332282e-05 -1.285840e-05 - 7771.883478 -2.290719e-05 -2.413104e-06 -1.077430e-07 -3.799727e-06 -1.204713e-06 1.480326e-05 -8.742631e-06 -5.550975e-06 - 7773.127855 -2.294385e-05 -2.401966e-06 -1.083566e-07 -3.799667e-06 3.170516e-06 2.181602e-05 -8.198828e-06 -3.222713e-06 - 7774.384423 -2.295055e-05 -2.390651e-06 -1.085794e-07 -3.799676e-06 1.262344e-05 2.166108e-05 -1.466293e-05 -3.675326e-07 - 7775.653184 -2.294907e-05 -2.382190e-06 -1.086522e-07 -3.799650e-06 4.615633e-07 2.606715e-05 -2.020247e-05 -1.324165e-06 - 7776.934136 -2.296119e-05 -2.374698e-06 -1.087687e-07 -3.799623e-06 -6.932929e-06 3.583105e-05 -1.205250e-05 -3.037616e-06 - 7778.227280 -2.296890e-05 -2.362677e-06 -1.087127e-07 -3.799666e-06 -7.479481e-06 4.791175e-05 -1.107177e-05 4.696905e-06 - 7779.532617 -2.296275e-05 -2.347211e-06 -1.084585e-07 -3.799626e-06 -8.515928e-06 4.323147e-05 -1.361780e-05 -5.858496e-06 - 7780.850145 -2.297369e-05 -2.333666e-06 -1.078687e-07 -3.799591e-06 -6.815529e-06 3.585806e-05 -2.492976e-05 -4.812203e-06 - 7782.179865 -2.297437e-05 -2.323199e-06 -1.070233e-07 -3.799631e-06 -7.791534e-06 2.867923e-05 -1.913276e-05 -4.533727e-07 - 7783.521777 -2.300159e-05 -2.317179e-06 -1.062687e-07 -3.799604e-06 -3.286117e-06 3.501927e-05 -1.416775e-05 -3.168512e-07 - 7784.875881 -2.300707e-05 -2.317221e-06 -1.054474e-07 -3.799622e-06 -3.535004e-08 3.658032e-05 -3.715165e-06 3.234419e-07 - 7786.242177 -2.300324e-05 -2.322686e-06 -1.048338e-07 -3.799591e-06 -3.913613e-06 2.679035e-05 -1.399624e-05 -1.373771e-06 - 7787.620664 -2.300698e-05 -2.331929e-06 -1.042412e-07 -3.799621e-06 -7.984784e-06 3.754929e-05 -2.375099e-05 8.366224e-06 - 7789.011344 -2.302613e-05 -2.340378e-06 -1.032551e-07 -3.799629e-06 -1.269149e-05 4.807426e-05 -1.673678e-05 1.141219e-05 - 7790.414215 -2.302961e-05 -2.348322e-06 -1.021713e-07 -3.799579e-06 -1.271707e-05 4.744712e-05 -1.164235e-05 1.545123e-05 - 7791.829279 -2.303980e-05 -2.357118e-06 -1.012521e-07 -3.799661e-06 -7.598482e-06 5.450209e-05 -8.462404e-06 1.536744e-05 - 7793.256534 -2.304910e-05 -2.367976e-06 -1.007593e-07 -3.799615e-06 -6.229389e-06 4.365977e-05 -4.576832e-06 1.014816e-05 - 7794.695981 -2.305274e-05 -2.377483e-06 -1.004030e-07 -3.799621e-06 -1.627318e-05 3.663606e-05 -6.886082e-06 1.061309e-06 - 7796.147620 -2.304068e-05 -2.387060e-06 -9.991785e-08 -3.799677e-06 -1.672835e-05 4.022535e-05 -7.116389e-06 -7.373314e-07 - 7797.611452 -2.303248e-05 -2.396574e-06 -9.900635e-08 -3.799626e-06 -6.753743e-06 5.151171e-05 -8.762360e-06 5.387916e-06 - 7799.087475 -2.304739e-05 -2.407018e-06 -9.766426e-08 -3.799667e-06 -6.405211e-06 4.225902e-05 -1.108414e-05 1.845855e-06 - 7800.575689 -2.305218e-05 -2.416569e-06 -9.607415e-08 -3.799658e-06 -1.621519e-05 2.409632e-05 -1.128794e-05 2.597703e-06 - 7802.076096 -2.301314e-05 -2.426657e-06 -9.417370e-08 -3.799637e-06 -1.962353e-05 1.718349e-05 -1.034610e-05 -7.326866e-06 - 7803.588695 -2.291477e-05 -2.435351e-06 -9.223439e-08 -3.799666e-06 -2.391047e-05 1.835587e-05 -1.388979e-05 -2.999615e-06 - 7805.113485 -2.289200e-05 -2.442813e-06 -9.052874e-08 -3.799683e-06 -1.316946e-05 2.988227e-05 -1.301872e-05 -2.946622e-06 - 7806.650468 -2.301860e-05 -2.457197e-06 -8.967809e-08 -3.799654e-06 -1.708001e-05 2.417025e-05 -1.793769e-05 -4.992655e-06 - 7808.199642 -2.308845e-05 -2.467082e-06 -8.939277e-08 -3.799678e-06 -1.144009e-05 2.623917e-05 -1.437577e-05 -2.760766e-06 - 7809.761009 -2.315185e-05 -2.474392e-06 -9.000257e-08 -3.799653e-06 -1.045823e-05 2.549441e-05 -2.620740e-05 3.104357e-07 - 7811.334567 -2.316129e-05 -2.477672e-06 -9.116539e-08 -3.799679e-06 -1.650393e-05 2.616788e-05 -9.326053e-06 7.181813e-06 - 7812.920317 -2.316106e-05 -2.481643e-06 -9.290661e-08 -3.799627e-06 -5.717704e-06 2.963840e-05 -1.393425e-06 1.215116e-05 - 7814.518259 -2.316995e-05 -2.487506e-06 -9.486179e-08 -3.799638e-06 -5.366761e-06 2.605810e-05 -7.738396e-06 1.009740e-05 - 7816.128393 -2.321063e-05 -2.494524e-06 -9.709235e-08 -3.799726e-06 -8.671537e-06 2.683447e-05 -5.581605e-06 9.816679e-06 - 7817.750719 -2.322178e-05 -2.503582e-06 -9.962984e-08 -3.799608e-06 -5.719549e-06 2.773393e-05 3.379063e-06 3.495172e-06 - 7819.385237 -2.323809e-05 -2.510549e-06 -1.023909e-07 -3.799681e-06 -8.964619e-06 2.274499e-05 4.120099e-06 -4.526208e-06 - 7821.031946 -2.323590e-05 -2.517915e-06 -1.052583e-07 -3.799693e-06 -5.079817e-06 2.788467e-05 3.495331e-10 -1.162611e-05 - 7822.690848 -2.324423e-05 -2.524202e-06 -1.081856e-07 -3.799633e-06 2.460688e-06 3.413334e-05 -4.649896e-06 -2.645628e-06 - 7824.361942 -2.323985e-05 -2.530965e-06 -1.109973e-07 -3.799639e-06 4.837059e-06 3.758652e-05 5.108475e-07 -3.009477e-07 - 7826.045227 -2.320981e-05 -2.537114e-06 -1.138330e-07 -3.799710e-06 3.703934e-06 4.442185e-05 3.946699e-07 -3.977178e-06 - 7827.740704 -2.318525e-05 -2.543312e-06 -1.167567e-07 -3.799678e-06 3.388703e-06 4.077388e-05 -1.620475e-06 -1.049169e-05 - 7829.448374 -2.317397e-05 -2.549545e-06 -1.194617e-07 -3.799702e-06 -1.574869e-06 3.735899e-05 -1.423459e-05 -8.771911e-06 - 7831.168235 -2.316323e-05 -2.555823e-06 -1.218068e-07 -3.799681e-06 1.091598e-06 3.717706e-05 -1.750539e-05 9.411969e-07 - 7832.900288 -2.319269e-05 -2.562884e-06 -1.236554e-07 -3.799678e-06 -3.210264e-06 3.422838e-05 -2.333595e-05 -2.098488e-06 - 7834.644533 -2.318397e-05 -2.566086e-06 -1.245740e-07 -3.799675e-06 2.183737e-06 3.117577e-05 -1.490542e-05 7.744396e-06 - 7836.400970 -2.315509e-05 -2.566278e-06 -1.246490e-07 -3.799677e-06 8.359186e-06 3.591979e-05 -1.523429e-05 3.409699e-06 - 7838.169598 -2.314791e-05 -2.562308e-06 -1.237450e-07 -3.799696e-06 1.028000e-05 3.662804e-05 -3.994139e-05 -1.022275e-05 - 7839.950419 -2.322189e-05 -2.570357e-06 -1.232787e-07 -3.799675e-06 1.022566e-06 3.438636e-05 -2.936548e-05 -7.936503e-06 - 7841.743432 -2.331471e-05 -2.584798e-06 -1.231626e-07 -3.799665e-06 -2.760915e-07 2.818774e-05 -3.344833e-05 -1.355157e-05 - 7843.548636 -2.334681e-05 -2.596316e-06 -1.231768e-07 -3.799720e-06 -4.104427e-06 3.617188e-05 -3.135078e-05 -1.014066e-05 - 7845.366032 -2.334841e-05 -2.607879e-06 -1.233477e-07 -3.799670e-06 -4.801395e-06 3.961263e-05 -2.614188e-05 -5.305218e-06 - 7847.195621 -2.328410e-05 -2.612585e-06 -1.230902e-07 -3.799694e-06 -4.928146e-06 4.234539e-05 -2.509445e-05 -6.237089e-07 - 7849.037401 -2.320992e-05 -2.619466e-06 -1.229953e-07 -3.799710e-06 -2.405606e-06 4.769853e-05 -2.155554e-05 7.777604e-07 - 7850.891373 -2.332887e-05 -2.645074e-06 -1.236367e-07 -3.799701e-06 -4.286445e-06 4.635103e-05 -1.532335e-05 -9.083647e-06 - 7852.757537 -2.329953e-05 -2.652815e-06 -1.234045e-07 -3.799668e-06 -8.554493e-07 4.626451e-05 -9.156116e-06 1.782232e-06 - 7854.635893 -2.337266e-05 -2.664940e-06 -1.232716e-07 -3.799725e-06 -7.190747e-06 4.302680e-05 -2.292342e-05 5.948214e-06 - 7856.526441 -2.339106e-05 -2.668948e-06 -1.224348e-07 -3.799679e-06 -5.716400e-06 3.769190e-05 -2.030913e-05 2.242888e-06 - 7858.429181 -2.337528e-05 -2.668991e-06 -1.208231e-07 -3.799658e-06 -7.965627e-06 3.833681e-05 -2.090134e-05 -2.995423e-06 - 7860.344112 -2.337661e-05 -2.667456e-06 -1.186776e-07 -3.799710e-06 -4.711000e-06 4.115179e-05 -2.197502e-05 -1.937327e-06 - 7862.271236 -2.337035e-05 -2.664517e-06 -1.161608e-07 -3.799675e-06 -2.734724e-06 4.956562e-05 -3.909624e-05 -1.603623e-05 - 7864.210552 -2.331977e-05 -2.660990e-06 -1.135768e-07 -3.799679e-06 -6.570550e-06 4.105309e-05 -3.039733e-05 -8.156775e-06 - 7866.162059 -2.328434e-05 -2.657532e-06 -1.107867e-07 -3.799752e-06 -1.100717e-05 3.644982e-05 -2.904215e-05 8.499521e-07 - 7868.125758 -2.334388e-05 -2.658498e-06 -1.084056e-07 -3.799663e-06 2.736421e-06 3.726106e-05 -3.346918e-05 -4.028586e-06 - 7870.101649 -2.335081e-05 -2.661471e-06 -1.061934e-07 -3.799745e-06 9.316774e-06 3.213645e-05 -3.588552e-05 -1.147522e-05 - 7872.089733 -2.334983e-05 -2.665455e-06 -1.045427e-07 -3.799747e-06 9.655748e-07 3.046081e-05 -3.683119e-05 -3.794528e-06 - 7874.090008 -2.328632e-05 -2.667492e-06 -1.035197e-07 -3.799747e-06 -1.699262e-06 2.795383e-05 -4.009137e-05 3.658118e-06 - 7876.102475 -2.334747e-05 -2.674536e-06 -1.031029e-07 -3.799737e-06 3.388228e-06 3.104880e-05 -3.107145e-05 2.254052e-06 - 7878.127133 -2.348503e-05 -2.684147e-06 -1.036247e-07 -3.799792e-06 3.536543e-06 2.932179e-05 -1.251699e-05 -1.203625e-05 - 7880.163984 -2.355767e-05 -2.691089e-06 -1.052078e-07 -3.799820e-06 3.899394e-06 3.818418e-05 -2.012261e-05 -1.155000e-05 - 7882.213027 -2.358523e-05 -2.696430e-06 -1.075228e-07 -3.799765e-06 -1.173246e-06 4.035218e-05 -1.116907e-05 -1.198955e-05 - 7884.274261 -2.356750e-05 -2.698832e-06 -1.105505e-07 -3.799803e-06 -1.937121e-06 3.759868e-05 5.803796e-06 3.447763e-06 - 7886.347688 -2.357388e-05 -2.701890e-06 -1.142921e-07 -3.799820e-06 6.774484e-06 3.942170e-05 1.059068e-05 -2.499465e-06 - 7888.433306 -2.358909e-05 -2.706182e-06 -1.187801e-07 -3.799846e-06 1.107603e-05 3.659234e-05 1.406686e-05 -6.413333e-06 - 7890.531117 -2.359650e-05 -2.711917e-06 -1.238890e-07 -3.799860e-06 5.448548e-06 3.612919e-05 -9.069219e-07 -7.672186e-06 - 7892.641119 -2.356692e-05 -2.717980e-06 -1.291541e-07 -3.799846e-06 1.594299e-06 3.766331e-05 -2.340484e-06 -1.349818e-05 - 7894.763313 -2.357339e-05 -2.726274e-06 -1.342499e-07 -3.799876e-06 3.010169e-06 4.226271e-05 1.110491e-05 -7.676047e-06 - 7896.897699 -2.362475e-05 -2.737886e-06 -1.387277e-07 -3.799861e-06 1.970480e-06 4.664338e-05 1.526003e-05 -3.960688e-06 - 7899.044277 -2.362625e-05 -2.746877e-06 -1.417175e-07 -3.799881e-06 8.991043e-06 4.233734e-05 -1.214699e-05 -5.675701e-06 - 7901.203047 -2.359197e-05 -2.757105e-06 -1.431465e-07 -3.799817e-06 1.610210e-05 4.138047e-05 -1.986142e-05 -3.522255e-06 - 7903.374008 -2.361715e-05 -2.772300e-06 -1.432115e-07 -3.799861e-06 1.240080e-05 5.040887e-05 -1.366268e-05 -2.023494e-06 - 7905.557162 -2.364737e-05 -2.788436e-06 -1.422820e-07 -3.799799e-06 6.092716e-06 4.675191e-05 -1.804594e-05 -8.103947e-06 - 7907.752508 -2.365390e-05 -2.805773e-06 -1.410229e-07 -3.799794e-06 1.542163e-06 3.700606e-05 -2.932048e-05 -1.204157e-05 - 7909.960045 -2.362067e-05 -2.821696e-06 -1.397242e-07 -3.799759e-06 -1.151859e-06 3.130464e-05 -2.443692e-05 -3.847801e-06 - 7912.179775 -2.364004e-05 -2.839617e-06 -1.387730e-07 -3.799782e-06 -1.234463e-06 2.484951e-05 9.629372e-07 -5.039215e-06 - 7914.411696 -2.366762e-05 -2.855975e-06 -1.381916e-07 -3.799778e-06 1.439328e-05 2.370130e-05 7.421269e-06 -9.699394e-06 - 7916.655809 -2.358703e-05 -2.861917e-06 -1.374779e-07 -3.799759e-06 1.124215e-05 2.291056e-05 6.667731e-06 2.899687e-06 - 7918.912114 -2.360643e-05 -2.869302e-06 -1.374143e-07 -3.799748e-06 6.928485e-06 2.454086e-05 7.142794e-06 3.967332e-08 - 7921.180611 -2.365783e-05 -2.882034e-06 -1.380198e-07 -3.799724e-06 5.466587e-06 2.470526e-05 1.102458e-05 9.012267e-07 - 7923.461300 -2.372304e-05 -2.894295e-06 -1.388047e-07 -3.799779e-06 -4.214641e-06 2.325418e-05 -4.186142e-07 -8.721866e-07 - 7925.754181 -2.373452e-05 -2.900518e-06 -1.392555e-07 -3.799879e-06 -3.225779e-06 1.817946e-05 -1.691471e-06 -2.795269e-06 - 7928.059254 -2.379164e-05 -2.907187e-06 -1.399902e-07 -3.799787e-06 1.970362e-06 1.650534e-05 8.419282e-06 4.330247e-06 - 7930.376518 -2.383748e-05 -2.913721e-06 -1.406694e-07 -3.799778e-06 6.188001e-06 1.808331e-05 1.930823e-05 1.687734e-06 - 7932.705975 -2.388118e-05 -2.919813e-06 -1.413020e-07 -3.799891e-06 3.685190e-06 2.677486e-05 1.892113e-05 5.414042e-06 - 7935.047623 -2.388506e-05 -2.925860e-06 -1.419169e-07 -3.799883e-06 1.148511e-05 1.848736e-05 1.369273e-05 4.967423e-06 - 7937.401464 -2.386002e-05 -2.930566e-06 -1.422044e-07 -3.799863e-06 5.540588e-06 2.298195e-05 1.922900e-05 5.351409e-06 - 7939.767496 -2.383674e-05 -2.933604e-06 -1.423447e-07 -3.799855e-06 4.573803e-06 2.196053e-05 2.336259e-05 2.403976e-06 - 7942.145720 -2.370328e-05 -2.921539e-06 -1.410666e-07 -3.799853e-06 7.265450e-06 2.737620e-05 1.784880e-05 1.093579e-05 - 7944.536136 -2.391156e-05 -2.954302e-06 -1.411951e-07 -3.799871e-06 2.545376e-06 3.532160e-05 1.408137e-05 1.327825e-05 - 7946.938744 -2.391588e-05 -2.960373e-06 -1.397307e-07 -3.799942e-06 1.346981e-05 2.256064e-05 5.088987e-06 6.209249e-06 - 7949.353544 -2.392960e-05 -2.966759e-06 -1.382204e-07 -3.799894e-06 2.849875e-06 2.681074e-05 3.629605e-07 3.629791e-06 - 7951.780536 -2.389865e-05 -2.972107e-06 -1.367845e-07 -3.799931e-06 -1.526344e-06 2.888316e-05 8.960288e-06 1.495739e-05 - 7954.219720 -2.383825e-05 -2.974296e-06 -1.355527e-07 -3.799886e-06 -5.777629e-06 3.905751e-05 1.529843e-05 1.575310e-05 - 7956.671096 -2.377440e-05 -2.974806e-06 -1.346902e-07 -3.799894e-06 2.741976e-06 4.060829e-05 1.702942e-05 1.213301e-05 - 7959.134663 -2.366166e-05 -2.975813e-06 -1.343467e-07 -3.799910e-06 -2.433988e-07 3.942388e-05 2.062029e-05 1.972434e-05 - 7961.610423 -2.368907e-05 -2.983650e-06 -1.351232e-07 -3.799915e-06 -5.424186e-06 3.838108e-05 2.744552e-05 1.472195e-05 - 7964.098374 -2.376360e-05 -2.991588e-06 -1.369715e-07 -3.799938e-06 -1.241070e-05 3.952245e-05 2.146236e-05 1.081707e-05 - 7966.598517 -2.387291e-05 -3.000276e-06 -1.396644e-07 -3.799952e-06 -1.398293e-05 4.412564e-05 1.851303e-05 1.015475e-05 - 7969.110852 -2.394703e-05 -3.011719e-06 -1.428831e-07 -3.799993e-06 -1.248497e-05 4.704448e-05 1.497639e-05 1.854366e-05 - 7971.635380 -2.397267e-05 -3.027413e-06 -1.467802e-07 -3.799957e-06 -9.343555e-06 3.806505e-05 8.606606e-06 5.118201e-06 - 7974.172099 -2.397035e-05 -3.032434e-06 -1.501863e-07 -3.799998e-06 -6.139452e-06 3.346870e-05 1.079765e-05 1.214445e-05 - 7976.721009 -2.392018e-05 -3.037865e-06 -1.530456e-07 -3.799964e-06 -8.659366e-06 3.166898e-05 7.929510e-06 1.451373e-05 - 7979.282112 -2.395863e-05 -3.051562e-06 -1.557628e-07 -3.799975e-06 -4.347507e-06 3.099513e-05 -5.878529e-07 5.667753e-06 - 7981.855407 -2.403021e-05 -3.069938e-06 -1.581544e-07 -3.799966e-06 -8.836779e-07 3.409899e-05 5.004664e-06 8.481478e-06 - 7984.440894 -2.409086e-05 -3.090315e-06 -1.602815e-07 -3.799996e-06 -1.178065e-05 2.839052e-05 3.982237e-06 1.431538e-05 - 7987.038572 -2.408427e-05 -3.103196e-06 -1.619872e-07 -3.800009e-06 -1.453030e-05 3.259876e-05 5.673687e-06 1.110818e-05 - 7989.648443 -2.406302e-05 -3.115870e-06 -1.636430e-07 -3.799963e-06 -4.606895e-06 4.457470e-05 1.699880e-05 1.417061e-05 - 7992.270505 -2.405463e-05 -3.125931e-06 -1.653751e-07 -3.799997e-06 -7.930133e-06 4.434447e-05 1.370410e-05 8.003599e-06 - 7994.904759 -2.408874e-05 -3.137881e-06 -1.670335e-07 -3.799985e-06 -1.742993e-05 3.847149e-05 1.855051e-06 1.642329e-06 - 7997.551205 -2.408997e-05 -3.145932e-06 -1.683874e-07 -3.800005e-06 -6.324357e-06 3.700865e-05 1.603620e-05 2.947728e-06 - 8000.209844 -2.412647e-05 -3.156288e-06 -1.694846e-07 -3.799985e-06 -3.959326e-07 3.971908e-05 1.748037e-05 7.151327e-07 - 8002.880674 -2.416955e-05 -3.165333e-06 -1.700394e-07 -3.800003e-06 -7.406630e-07 3.908518e-05 1.227081e-05 1.984313e-06 - 8005.563696 -2.419749e-05 -3.173810e-06 -1.698830e-07 -3.800010e-06 -1.944664e-06 4.718313e-05 7.438235e-06 -1.504716e-06 - 8008.258909 -2.418034e-05 -3.182953e-06 -1.696391e-07 -3.800010e-06 -8.561254e-06 4.480983e-05 2.690002e-06 -5.098384e-06 - 8010.966315 -2.418583e-05 -3.189432e-06 -1.692252e-07 -3.799982e-06 -1.069401e-05 3.369388e-05 3.615878e-06 6.862729e-06 - 8013.685913 -2.421459e-05 -3.198889e-06 -1.691027e-07 -3.800007e-06 -6.128420e-06 3.263328e-05 7.062826e-06 1.037004e-05 - 8016.417702 -2.422487e-05 -3.209650e-06 -1.689131e-07 -3.799987e-06 -6.507097e-06 2.419356e-05 1.166988e-06 9.621389e-06 - 8019.161684 -2.421530e-05 -3.219896e-06 -1.689029e-07 -3.800021e-06 -6.379546e-06 3.030382e-05 5.000506e-06 5.815285e-06 - 8021.917857 -2.419487e-05 -3.228726e-06 -1.690002e-07 -3.800025e-06 -7.738056e-06 2.436822e-05 2.606552e-05 4.110898e-06 - 8024.686222 -2.421982e-05 -3.237283e-06 -1.692370e-07 -3.800029e-06 -6.339366e-06 1.177159e-05 1.291712e-05 -5.422340e-06 - 8027.466780 -2.426233e-05 -3.248063e-06 -1.696694e-07 -3.800049e-06 -7.684851e-06 1.000510e-05 1.469468e-05 -5.236620e-06 - 8030.259529 -2.430162e-05 -3.256787e-06 -1.699298e-07 -3.800060e-06 -1.174802e-05 1.813973e-05 1.222212e-05 6.265250e-06 - 8033.064470 -2.429920e-05 -3.265406e-06 -1.699970e-07 -3.800042e-06 -8.976222e-06 1.660735e-05 5.739827e-07 2.954550e-06 - 8035.881602 -2.425027e-05 -3.272547e-06 -1.698145e-07 -3.800064e-06 -1.454654e-05 2.572949e-05 6.598142e-07 -8.335281e-07 - 8038.710927 -2.421455e-05 -3.273761e-06 -1.692843e-07 -3.800052e-06 -1.147480e-05 2.517637e-05 -5.836864e-06 -9.824032e-07 - 8041.552444 -2.414024e-05 -3.268497e-06 -1.687941e-07 -3.800045e-06 -7.887719e-06 1.745976e-05 -4.860494e-06 -3.769743e-06 - 8044.406153 -2.432399e-05 -3.305554e-06 -1.705180e-07 -3.800060e-06 -1.187511e-05 2.506084e-05 -1.536172e-05 -1.177138e-05 - 8047.272053 -2.432213e-05 -3.318201e-06 -1.713391e-07 -3.800043e-06 -1.685098e-05 2.441645e-05 -1.941468e-05 -1.140118e-06 - 8050.150146 -2.438388e-05 -3.334576e-06 -1.725653e-07 -3.800054e-06 -1.661229e-05 1.498834e-05 -1.314534e-05 1.380771e-06 - 8053.040430 -2.440112e-05 -3.350567e-06 -1.741526e-07 -3.800078e-06 -1.196980e-05 1.362918e-05 -4.960349e-06 2.577450e-06 - 8055.942906 -2.441306e-05 -3.364552e-06 -1.760616e-07 -3.800039e-06 -1.468579e-05 1.627869e-05 -4.222075e-06 -5.016318e-06 - 8058.857574 -2.441936e-05 -3.378251e-06 -1.782212e-07 -3.800084e-06 -5.884625e-06 3.105735e-05 -6.133785e-06 -3.394709e-06 - 8061.784435 -2.445636e-05 -3.392221e-06 -1.806905e-07 -3.800036e-06 -1.975154e-06 2.983800e-05 -3.366251e-07 -2.030013e-06 - 8064.723487 -2.444179e-05 -3.399830e-06 -1.827776e-07 -3.800086e-06 -2.642904e-06 1.310131e-05 3.521344e-06 5.676232e-06 - 8067.674730 -2.410168e-05 -3.361775e-06 -1.823110e-07 -3.800059e-06 -3.734177e-06 1.087513e-05 1.184331e-05 7.432608e-06 - 8070.638166 -2.443464e-05 -3.420139e-06 -1.866323e-07 -3.800054e-06 -1.199914e-05 6.883718e-06 -5.472147e-07 6.511766e-06 - 8073.613794 -2.449375e-05 -3.441750e-06 -1.886778e-07 -3.800086e-06 -7.657769e-06 9.370490e-06 -5.541755e-06 6.993052e-06 - 8076.601614 -2.448230e-05 -3.451135e-06 -1.897972e-07 -3.800089e-06 -1.215319e-05 1.249948e-05 2.583288e-06 3.045524e-06 - 8079.601625 -2.453504e-05 -3.464872e-06 -1.914185e-07 -3.800096e-06 -1.246539e-05 1.740093e-05 9.500522e-08 2.795154e-06 - 8082.613829 -2.455288e-05 -3.475149e-06 -1.930563e-07 -3.800103e-06 -1.045965e-05 1.846371e-05 -9.776406e-07 -1.155231e-06 - 8085.638224 -2.429776e-05 -3.449884e-06 -1.930736e-07 -3.800062e-06 -2.893602e-06 2.022276e-05 -7.997686e-06 -6.848795e-06 - 8088.674811 -2.442293e-05 -3.478491e-06 -1.960579e-07 -3.800082e-06 -3.733982e-06 1.760293e-05 -1.000551e-05 -7.011696e-06 - 8091.723590 -2.460332e-05 -3.516918e-06 -1.995682e-07 -3.800102e-06 -1.662109e-06 2.454465e-05 -1.383308e-05 -1.306097e-05 - 8094.784561 -2.458742e-05 -3.527799e-06 -2.011222e-07 -3.800051e-06 3.508049e-06 2.447964e-05 -7.833990e-06 -9.746449e-06 - 8097.857724 -2.462099e-05 -3.538035e-06 -2.025228e-07 -3.800101e-06 -5.953347e-08 2.076876e-05 -2.227689e-05 -6.262084e-06 - 8100.943079 -2.464125e-05 -3.548603e-06 -2.038275e-07 -3.800108e-06 1.031297e-05 3.196728e-05 -2.779242e-05 5.973683e-06 - 8104.040626 -2.465799e-05 -3.561486e-06 -2.049304e-07 -3.800101e-06 1.871550e-05 2.965118e-05 -2.869178e-05 1.633285e-05 - 8107.150365 -2.466965e-05 -3.572659e-06 -2.059102e-07 -3.800083e-06 1.397372e-05 2.710785e-05 -2.227450e-05 1.108913e-05 - 8110.272295 -2.470180e-05 -3.584004e-06 -2.068902e-07 -3.800131e-06 1.431025e-05 1.065383e-05 -2.017294e-05 1.766905e-05 - 8113.406418 -2.471627e-05 -3.592236e-06 -2.075751e-07 -3.800099e-06 1.855922e-05 6.909297e-06 -3.176475e-05 3.900774e-06 - 8116.552732 -2.471084e-05 -3.598215e-06 -2.078986e-07 -3.800111e-06 1.626542e-05 9.817965e-06 -3.090964e-05 1.060206e-05 - 8119.711239 -2.469643e-05 -3.605825e-06 -2.081766e-07 -3.800119e-06 8.553063e-06 1.251663e-05 -3.908969e-05 1.106472e-05 - 8122.881937 -2.470794e-05 -3.613639e-06 -2.082556e-07 -3.800121e-06 5.119835e-06 1.125579e-05 -4.049426e-05 8.902541e-06 - 8126.064827 -2.469693e-05 -3.620105e-06 -2.082633e-07 -3.800103e-06 2.291114e-06 1.694085e-05 -3.001240e-05 1.709952e-05 - 8129.259909 -2.468971e-05 -3.628601e-06 -2.084740e-07 -3.800103e-06 1.006962e-05 1.577437e-05 -2.144948e-05 1.209404e-05 - 8132.467183 -2.469578e-05 -3.639088e-06 -2.090084e-07 -3.800125e-06 1.084980e-05 9.606660e-06 -2.805557e-05 1.569968e-05 - 8135.686649 -2.467868e-05 -3.647217e-06 -2.094116e-07 -3.800100e-06 8.079334e-06 1.437073e-05 -2.131472e-05 2.191245e-05 - 8138.918307 -2.462196e-05 -3.651569e-06 -2.097236e-07 -3.800112e-06 8.045101e-07 1.495583e-05 -2.037947e-05 2.260459e-05 - 8142.162157 -2.448299e-05 -3.644210e-06 -2.094964e-07 -3.800112e-06 4.725766e-06 1.616094e-05 -1.931361e-05 2.389908e-05 - 8145.418198 -2.400647e-05 -3.580217e-06 -2.058925e-07 -3.800081e-06 1.576074e-05 1.074437e-05 -1.397298e-05 2.541879e-05 - 8148.686432 -2.344930e-05 -3.518628e-06 -2.025004e-07 -3.800113e-06 3.880885e-07 2.533429e-05 -2.034930e-05 2.155981e-05 - 8151.966857 -2.363545e-05 -3.573397e-06 -2.060492e-07 -3.800080e-06 -4.247687e-07 2.386921e-05 -2.949225e-05 2.712022e-05 - 8155.259474 -2.382649e-05 -3.613554e-06 -2.089952e-07 -3.800128e-06 6.519749e-06 1.409633e-05 -3.814666e-05 2.022732e-05 - 8158.564284 -2.399293e-05 -3.630922e-06 -2.108883e-07 -3.800088e-06 -4.398178e-06 1.386136e-05 -3.527858e-05 2.200908e-05 - 8161.881285 -2.458899e-05 -3.722073e-06 -2.172982e-07 -3.800136e-06 -1.265816e-05 2.006750e-05 -3.375962e-05 1.584481e-05 - 8165.210478 -2.509573e-05 -3.826711e-06 -2.246923e-07 -3.800118e-06 -1.024610e-05 2.474977e-05 -3.352402e-05 9.017293e-06 - 8168.551863 -2.508376e-05 -3.841721e-06 -2.268280e-07 -3.800124e-06 -9.659342e-07 2.454461e-05 -3.531596e-05 7.237892e-06 - 8171.905440 -2.504610e-05 -3.849406e-06 -2.284534e-07 -3.800127e-06 4.683181e-06 3.353536e-05 -2.934392e-05 6.861138e-06 - 8175.271209 -2.505269e-05 -3.861457e-06 -2.301493e-07 -3.800097e-06 -2.109147e-06 4.058198e-05 -2.936362e-05 1.007061e-05 - 8178.649169 -2.504140e-05 -3.873663e-06 -2.316596e-07 -3.800122e-06 8.416486e-06 2.748484e-05 -3.108925e-05 1.374512e-05 - 8182.039322 -2.506529e-05 -3.887787e-06 -2.331175e-07 -3.800162e-06 2.109211e-05 3.303929e-05 -1.452598e-05 1.813006e-05 - 8185.441666 -2.506757e-05 -3.899236e-06 -2.343413e-07 -3.800104e-06 2.377932e-05 3.762616e-05 -1.918981e-05 1.811930e-05 - 8188.856203 -2.512057e-05 -3.915202e-06 -2.359965e-07 -3.800154e-06 2.139666e-05 3.379179e-05 -7.445620e-06 7.429961e-06 - 8192.282931 -2.514603e-05 -3.929952e-06 -2.376455e-07 -3.800115e-06 1.497016e-05 2.786595e-05 -8.747647e-06 1.042350e-05 - 8195.721851 -2.514085e-05 -3.943750e-06 -2.393582e-07 -3.800131e-06 1.077907e-05 2.729214e-05 4.664870e-07 3.796727e-05 - 8199.172964 -2.506324e-05 -3.951983e-06 -2.408019e-07 -3.800131e-06 2.041575e-05 3.470934e-05 -1.056152e-05 3.351546e-05 - 8202.636268 -2.495227e-05 -3.955984e-06 -2.421738e-07 -3.800124e-06 1.671353e-05 3.110790e-05 -1.616742e-05 3.255940e-05 - 8206.111764 -2.493454e-05 -3.970257e-06 -2.440941e-07 -3.800162e-06 1.676857e-05 3.526253e-05 -1.999754e-05 3.547659e-05 - 8209.599451 -2.503720e-05 -3.992073e-06 -2.464704e-07 -3.800123e-06 1.448914e-05 3.765674e-05 -2.302577e-05 3.516720e-05 - 8213.099331 -2.507218e-05 -4.005390e-06 -2.482545e-07 -3.800149e-06 2.282577e-05 3.366794e-05 -5.679442e-06 3.807366e-05 - 8216.611403 -2.513013e-05 -4.020774e-06 -2.502852e-07 -3.800140e-06 1.259440e-05 2.913697e-05 -1.232782e-05 4.028573e-05 - 8220.135666 -2.518960e-05 -4.038984e-06 -2.524144e-07 -3.800148e-06 5.277626e-06 2.855460e-05 -2.669434e-05 3.415805e-05 - 8223.672122 -2.518955e-05 -4.049769e-06 -2.540936e-07 -3.800157e-06 1.516108e-05 2.215492e-05 -2.255967e-06 3.941375e-05 - 8227.220769 -2.523327e-05 -4.065523e-06 -2.559668e-07 -3.800141e-06 1.315625e-05 1.922266e-05 -1.400350e-05 3.298293e-05 - 8230.781609 -2.516512e-05 -4.074579e-06 -2.571944e-07 -3.800147e-06 1.974831e-05 1.234166e-05 -2.155970e-05 1.370840e-05 - 8234.354640 -2.517067e-05 -4.089521e-06 -2.586608e-07 -3.800138e-06 1.590796e-05 2.046313e-05 -2.327179e-05 1.016349e-05 - 8237.939863 -2.522777e-05 -4.108484e-06 -2.602924e-07 -3.800141e-06 1.170524e-05 3.186489e-05 -2.862230e-05 3.518804e-06 - 8241.537278 -2.523587e-05 -4.123036e-06 -2.614789e-07 -3.800152e-06 8.791932e-06 3.847981e-05 -2.916011e-05 4.225516e-06 - 8245.146885 -2.524693e-05 -4.139672e-06 -2.627651e-07 -3.800151e-06 8.660531e-06 3.670808e-05 -2.993171e-05 1.200896e-05 - 8248.768684 -2.529537e-05 -4.158533e-06 -2.640692e-07 -3.800178e-06 7.756672e-06 3.339569e-05 -3.367480e-05 4.285119e-06 - 8252.402675 -2.534782e-05 -4.178729e-06 -2.652473e-07 -3.800148e-06 1.456383e-05 1.954893e-05 -3.817571e-05 7.927817e-06 - 8256.048857 -2.532222e-05 -4.190767e-06 -2.659779e-07 -3.800160e-06 1.424423e-05 1.914704e-05 -2.825058e-05 9.200977e-06 - 8259.707232 -2.531088e-05 -4.203822e-06 -2.667335e-07 -3.800152e-06 1.715606e-05 1.433972e-05 -3.188055e-05 1.065293e-05 - 8263.377799 -2.534621e-05 -4.222665e-06 -2.680337e-07 -3.800175e-06 1.639429e-05 9.455035e-06 -3.142508e-05 -3.249328e-06 - 8267.060557 -2.536778e-05 -4.238462e-06 -2.693955e-07 -3.800161e-06 2.339522e-05 1.025002e-05 -3.437276e-05 3.741418e-06 - 8270.755507 -2.541495e-05 -4.256473e-06 -2.711672e-07 -3.800155e-06 2.437704e-05 1.385951e-05 -2.190857e-05 1.563046e-05 - 8274.462650 -2.541846e-05 -4.269772e-06 -2.729616e-07 -3.800149e-06 2.773509e-05 1.447973e-05 -9.526487e-06 1.693640e-05 - 8278.181984 -2.539019e-05 -4.281665e-06 -2.746064e-07 -3.800171e-06 2.138045e-05 1.374058e-05 -2.001842e-05 8.174760e-07 - 8281.913510 -2.534130e-05 -4.284808e-06 -2.759896e-07 -3.800168e-06 2.484671e-05 1.845627e-05 -2.554187e-05 -3.568230e-08 - 8285.657228 -2.541582e-05 -4.309065e-06 -2.786689e-07 -3.800170e-06 2.649492e-05 1.440112e-05 -3.165267e-05 -2.370843e-07 - 8289.413138 -2.543329e-05 -4.325595e-06 -2.808617e-07 -3.800173e-06 2.714054e-05 1.317225e-05 -2.677380e-05 1.366232e-06 - 8293.181239 -2.545043e-05 -4.339248e-06 -2.827662e-07 -3.800173e-06 2.530573e-05 1.293106e-05 -1.663936e-05 1.617872e-06 - 8296.961533 -2.545115e-05 -4.351818e-06 -2.848242e-07 -3.800171e-06 2.956132e-05 8.968685e-06 -1.561686e-05 -5.217070e-06 - 8300.754019 -2.546854e-05 -4.367212e-06 -2.870057e-07 -3.800190e-06 2.116141e-05 8.237803e-06 -2.296491e-05 -8.888183e-06 - 8304.558696 -2.548031e-05 -4.378607e-06 -2.887628e-07 -3.800165e-06 1.575804e-05 4.533594e-06 -2.007717e-05 -8.593347e-06 - 8308.375565 -2.548333e-05 -4.391096e-06 -2.905862e-07 -3.800205e-06 1.195308e-05 8.020053e-06 -1.743280e-05 -3.690643e-06 - 8312.204627 -2.544410e-05 -4.398402e-06 -2.918598e-07 -3.800177e-06 1.633592e-05 9.434773e-06 -1.176120e-05 -1.696818e-06 - 8316.045880 -2.544363e-05 -4.406676e-06 -2.932635e-07 -3.800225e-06 2.240878e-05 1.572819e-05 -5.051798e-06 -2.034873e-06 - 8319.899325 -2.544596e-05 -4.408889e-06 -2.943197e-07 -3.800207e-06 1.807765e-05 2.640994e-05 4.567569e-06 7.207763e-06 - 8323.764962 -2.545717e-05 -4.409754e-06 -2.952639e-07 -3.800190e-06 2.087169e-05 3.335972e-05 -8.519838e-06 1.567482e-05 - 8327.642791 -2.538087e-05 -4.390774e-06 -2.949682e-07 -3.800233e-06 1.885609e-05 2.428053e-05 -7.618278e-06 9.465545e-06 - 8331.532812 -2.540590e-05 -4.313938e-06 -2.906725e-07 -3.800230e-06 1.613422e-05 2.209498e-05 -1.656794e-05 1.217183e-06 - 8335.435025 -2.539381e-05 -4.151799e-06 -2.805158e-07 -3.800245e-06 3.084591e-05 2.138091e-05 -2.385439e-05 -1.110786e-06 - 8339.349429 -2.518577e-05 -3.718446e-06 -2.515414e-07 -3.800222e-06 2.982284e-05 1.697564e-05 -1.438831e-05 -5.973856e-06 - 8343.276026 -2.424206e-05 -2.332729e-06 -1.562607e-07 -3.800238e-06 2.812450e-05 1.376854e-05 -4.321941e-06 -1.077239e-05 - 8347.214814 -2.256144e-05 -1.280967e-06 -8.367719e-08 -3.800255e-06 1.852510e-05 2.058916e-05 6.187291e-06 -7.634803e-06 - 8351.165795 -2.195535e-05 -7.567945e-07 -4.765286e-08 -3.800264e-06 1.544994e-05 2.066025e-05 5.668485e-06 -1.317499e-05 - 8355.128967 -2.260409e-05 -8.293060e-07 -5.265317e-08 -3.800230e-06 1.156838e-05 2.111724e-05 -4.639485e-06 -1.030677e-05 - 8359.104331 -2.305210e-05 -1.074730e-06 -6.984191e-08 -3.800265e-06 1.206843e-05 1.874695e-05 -1.213416e-05 3.328652e-06 - 8363.091888 -2.316118e-05 -1.210397e-06 -7.950087e-08 -3.800248e-06 7.943723e-06 1.365740e-05 -7.635561e-06 7.344941e-06 - 8367.091636 -2.338258e-05 -1.188046e-06 -7.817312e-08 -3.800237e-06 9.952734e-06 1.709748e-05 -5.675143e-06 1.375387e-06 - 8371.103575 -2.361759e-05 -1.210870e-06 -7.987421e-08 -3.800261e-06 7.102001e-06 1.761560e-05 -6.452328e-06 -3.345973e-06 - 8375.127707 -2.372567e-05 -1.323332e-06 -8.790172e-08 -3.800239e-06 6.590794e-07 2.277344e-05 -1.697211e-05 -1.242763e-05 - 8379.164031 -2.363275e-05 -1.390608e-06 -9.286218e-08 -3.800260e-06 9.445241e-06 3.533515e-05 -1.315759e-05 -6.774352e-07 - 8383.212547 -2.340488e-05 -1.343049e-06 -8.973879e-08 -3.800273e-06 -2.337528e-06 4.575058e-05 -1.517701e-05 5.327365e-06 - 8387.273254 -2.322481e-05 -1.287335e-06 -8.593100e-08 -3.800267e-06 3.546303e-07 3.812066e-05 -2.103413e-05 1.313524e-05 - 8391.346154 -2.314829e-05 -1.254831e-06 -8.374092e-08 -3.800273e-06 -2.600580e-08 3.374847e-05 -2.235657e-05 8.811645e-06 - 8395.431245 -2.313525e-05 -1.191084e-06 -7.942922e-08 -3.800277e-06 1.605023e-06 3.915535e-05 -1.129730e-05 5.644578e-06 - 8399.528529 -2.312498e-05 -1.122348e-06 -7.474456e-08 -3.800276e-06 2.666703e-06 3.866339e-05 -3.674452e-06 3.692480e-06 - 8403.638004 -2.319523e-05 -1.067565e-06 -7.093829e-08 -3.800278e-06 1.424349e-05 2.648231e-05 -7.989667e-06 -2.446155e-06 - 8407.759671 -2.325391e-05 -1.056176e-06 -7.033559e-08 -3.800283e-06 6.889940e-06 2.716916e-05 -7.512915e-06 2.733544e-06 - 8411.893530 -2.333486e-05 -1.096387e-06 -7.337942e-08 -3.800272e-06 4.811573e-06 3.799381e-05 -5.247768e-06 4.569931e-06 - 8416.039581 -2.336360e-05 -1.149240e-06 -7.730299e-08 -3.800305e-06 1.730613e-06 4.080562e-05 -3.380774e-06 1.615985e-06 - 8420.197824 -2.340105e-05 -1.195470e-06 -8.088107e-08 -3.800274e-06 -3.434154e-06 3.625931e-05 -3.615779e-06 -7.082230e-06 - 8424.368258 -2.347293e-05 -1.233478e-06 -8.381091e-08 -3.800280e-06 -3.024693e-06 3.179081e-05 -6.762892e-06 1.618092e-06 - 8428.550885 -2.355139e-05 -1.264243e-06 -8.629035e-08 -3.800281e-06 -3.718382e-06 2.215888e-05 -8.781072e-06 1.290630e-06 - 8432.745704 -2.352814e-05 -1.273359e-06 -8.724441e-08 -3.800273e-06 -7.310949e-07 2.988564e-05 -1.525242e-05 3.079345e-06 - 8436.952714 -2.346342e-05 -1.264692e-06 -8.694571e-08 -3.800293e-06 -6.273940e-06 1.907108e-05 -1.875905e-05 7.598084e-07 - 8441.171916 -2.349805e-05 -1.260853e-06 -8.683806e-08 -3.800304e-06 -2.537459e-06 1.381479e-05 -2.527911e-05 6.032541e-06 - 8445.403311 -2.341521e-05 -1.253352e-06 -8.656256e-08 -3.800296e-06 -5.507418e-06 2.997941e-05 -2.716527e-05 1.772160e-05 - 8449.646897 -2.343064e-05 -1.247924e-06 -8.644504e-08 -3.800306e-06 4.254824e-06 3.898554e-05 -2.088353e-05 1.632030e-05 - 8453.902675 -2.356818e-05 -1.244450e-06 -8.646052e-08 -3.800297e-06 8.824732e-06 3.225173e-05 -1.549171e-05 1.310655e-05 - 8458.170645 -2.357940e-05 -1.248834e-06 -8.698699e-08 -3.800291e-06 6.217025e-06 2.897453e-05 -1.165753e-05 1.301945e-05 - 8462.450807 -2.358825e-05 -1.254382e-06 -8.760701e-08 -3.800314e-06 -2.125075e-06 4.330802e-05 -1.978257e-05 1.380881e-05 - 8466.743161 -2.358767e-05 -1.271734e-06 -8.923767e-08 -3.800308e-06 4.065688e-06 3.936380e-05 -2.774693e-05 1.362424e-05 - 8471.047707 -2.357719e-05 -1.303911e-06 -9.188870e-08 -3.800295e-06 8.069483e-06 2.986271e-05 -2.449043e-05 1.086402e-05 - 8475.364444 -2.355562e-05 -1.327845e-06 -9.400019e-08 -3.800299e-06 1.951145e-05 3.925621e-05 -2.162705e-05 1.283698e-05 - 8479.693374 -2.355374e-05 -1.321796e-06 -9.372969e-08 -3.800306e-06 1.431728e-05 3.840410e-05 -7.137264e-06 1.371081e-05 - 8484.034495 -2.353316e-05 -1.293092e-06 -9.190722e-08 -3.800310e-06 1.820032e-05 4.026442e-05 -1.205649e-05 1.121289e-05 - 8488.387809 -2.345353e-05 -1.266658e-06 -9.018429e-08 -3.800324e-06 9.780316e-06 4.078572e-05 -1.208362e-05 1.389027e-05 - 8492.753314 -2.353197e-05 -1.262083e-06 -9.003611e-08 -3.800331e-06 1.045515e-05 3.349658e-05 -1.068863e-05 7.891132e-06 - 8497.131011 -2.366370e-05 -1.270553e-06 -9.091217e-08 -3.800322e-06 1.357269e-05 3.382130e-05 -9.097456e-06 8.669872e-06 - 8501.520900 -2.368613e-05 -1.281004e-06 -9.191475e-08 -3.800332e-06 5.933464e-06 3.220995e-05 -1.764106e-05 6.619405e-06 - 8505.922981 -2.368548e-05 -1.284820e-06 -9.252378e-08 -3.800331e-06 3.186251e-06 2.629509e-05 -2.146421e-05 1.004077e-05 - 8510.337254 -2.367962e-05 -1.287065e-06 -9.290424e-08 -3.800344e-06 7.332424e-06 2.294172e-05 -2.282800e-05 1.452748e-05 - 8514.763719 -2.372282e-05 -1.289164e-06 -9.326239e-08 -3.800347e-06 4.723865e-06 1.226132e-05 -3.131564e-05 1.604984e-05 - 8519.202376 -2.375994e-05 -1.298513e-06 -9.413358e-08 -3.800363e-06 -2.398738e-06 1.506539e-05 -4.043975e-05 1.053836e-05 - 8523.653224 -2.375529e-05 -1.318632e-06 -9.588647e-08 -3.800362e-06 -2.734074e-06 1.853528e-05 -3.935757e-05 7.636882e-06 - 8528.116265 -2.376974e-05 -1.346472e-06 -9.819817e-08 -3.800355e-06 -2.258024e-07 2.294711e-05 -3.467208e-05 1.159871e-05 - 8532.591497 -2.378683e-05 -1.381977e-06 -1.012856e-07 -3.800366e-06 -3.277977e-06 2.917600e-05 -3.283241e-05 1.938181e-05 - 8537.078922 -2.375379e-05 -1.412208e-06 -1.039472e-07 -3.800370e-06 -2.687688e-06 2.583323e-05 -2.985052e-05 2.360769e-05 - 8541.578538 -2.371448e-05 -1.426290e-06 -1.052776e-07 -3.800372e-06 3.663011e-06 1.989158e-05 -2.883854e-05 1.725225e-05 - 8546.090346 -2.376301e-05 -1.420327e-06 -1.051296e-07 -3.800367e-06 6.451112e-06 1.152195e-05 -1.156233e-05 1.969987e-05 - 8550.614346 -2.380125e-05 -1.404800e-06 -1.041682e-07 -3.800369e-06 9.226425e-06 1.318814e-05 -7.806807e-06 1.727427e-05 - 8555.150538 -2.378382e-05 -1.390676e-06 -1.032796e-07 -3.800394e-06 9.480245e-06 1.990120e-05 -3.232316e-06 2.472929e-05 - 8559.698922 -2.371862e-05 -1.389348e-06 -1.034558e-07 -3.800412e-06 6.924491e-06 2.947707e-05 -4.718451e-06 2.447739e-05 - 8564.259498 -2.356062e-05 -1.384125e-06 -1.033166e-07 -3.800403e-06 -5.416831e-06 2.230619e-05 -8.294533e-06 2.788429e-05 - 8568.832266 -2.311119e-05 -1.361735e-06 -1.019593e-07 -3.800404e-06 -9.082416e-06 2.641757e-05 -1.342729e-05 1.628205e-05 - 8573.417226 -2.304023e-05 -1.355895e-06 -1.017799e-07 -3.800416e-06 -5.364812e-07 3.974325e-05 -2.203317e-05 9.366760e-06 - 8578.014377 -2.356259e-05 -1.384426e-06 -1.041942e-07 -3.800425e-06 1.518976e-06 3.728962e-05 -2.302850e-05 1.208822e-05 - 8582.623721 -2.372686e-05 -1.409779e-06 -1.063538e-07 -3.800434e-06 4.757716e-06 3.272623e-05 -1.908510e-05 8.135847e-06 - 8587.245256 -2.369171e-05 -1.416541e-06 -1.072545e-07 -3.800439e-06 3.472117e-06 2.888201e-05 -2.410600e-05 9.446906e-06 - 8591.878983 -2.377006e-05 -1.424182e-06 -1.081094e-07 -3.800432e-06 1.439619e-08 2.678079e-05 -5.321658e-05 1.279601e-05 - 8596.524902 -2.384173e-05 -1.441907e-06 -1.099036e-07 -3.800451e-06 6.134962e-07 2.934614e-05 -4.365160e-05 1.374475e-05 - 8601.183013 -2.381184e-05 -1.460089e-06 -1.116421e-07 -3.800468e-06 5.907167e-07 2.460463e-05 -3.999481e-05 3.896751e-06 - 8605.853316 -2.387212e-05 -1.472230e-06 -1.129753e-07 -3.800495e-06 -4.112933e-06 1.359224e-05 -3.040375e-05 5.390279e-06 - 8610.535811 -2.372795e-05 -1.487688e-06 -1.145589e-07 -3.800496e-06 -5.481574e-06 1.079003e-05 -3.103904e-05 5.327584e-06 - 8615.230498 -2.362974e-05 -1.492747e-06 -1.152859e-07 -3.800493e-06 -1.921773e-06 1.222062e-05 -3.259523e-05 6.236991e-07 - 8619.937377 -2.255050e-05 -1.425952e-06 -1.104984e-07 -3.800499e-06 -4.763040e-06 2.233163e-05 -4.600711e-05 -7.965795e-07 - 8624.656448 -2.339332e-05 -1.493837e-06 -1.160847e-07 -3.800509e-06 -1.061314e-05 2.610877e-05 -3.588540e-05 1.050887e-06 - 8629.387710 -2.378623e-05 -1.524030e-06 -1.187785e-07 -3.800524e-06 -1.250312e-05 1.829147e-05 -3.845104e-05 5.515020e-06 - 8634.131165 -2.400373e-05 -1.517656e-06 -1.185749e-07 -3.800550e-06 -2.207360e-06 1.545341e-05 -3.931814e-05 7.629492e-06 - 8638.886811 -2.392866e-05 -1.516120e-06 -1.188383e-07 -3.800565e-06 -3.631791e-06 2.006418e-05 -3.704247e-05 8.401156e-06 - 8643.654649 -2.378313e-05 -1.512877e-06 -1.189006e-07 -3.800592e-06 3.847863e-06 2.692916e-05 -4.636807e-05 1.360425e-05 - 8648.434679 -2.399890e-05 -1.527863e-06 -1.203920e-07 -3.800616e-06 7.058003e-06 2.348780e-05 -5.271332e-05 1.822639e-05 - 8653.226901 -2.406668e-05 -1.525018e-06 -1.204857e-07 -3.800628e-06 1.406634e-06 1.678378e-05 -5.223029e-05 1.839359e-05 - 8658.031315 -2.408241e-05 -1.524010e-06 -1.206932e-07 -3.800655e-06 -1.072838e-06 1.956919e-05 -4.018893e-05 2.073984e-05 - 8662.847921 -2.400693e-05 -1.524351e-06 -1.210131e-07 -3.800683e-06 -1.035756e-06 2.710134e-05 -4.013660e-05 2.392635e-05 - 8667.676719 -2.360881e-05 -1.509547e-06 -1.202205e-07 -3.800720e-06 -3.349253e-06 3.077500e-05 -3.801776e-05 2.094168e-05 - 8672.517709 -2.347269e-05 -1.536227e-06 -1.227751e-07 -3.800766e-06 9.849122e-07 2.756762e-05 -3.374481e-05 1.525987e-05 - 8677.370891 -2.370113e-05 -1.555581e-06 -1.246680e-07 -3.800825e-06 6.438811e-07 2.200709e-05 -4.088859e-05 1.027840e-05 - 8682.236264 -2.401729e-05 -1.590404e-06 -1.278504e-07 -3.800878e-06 3.384974e-06 1.871906e-05 -3.497825e-05 1.167193e-05 - 8687.113830 -2.326658e-05 -1.551315e-06 -1.250454e-07 -3.683442e-06 1.384162e-05 1.308347e-05 -3.465716e-05 1.834546e-06 diff --git a/aimmdb/_tests/test_aimm.py b/aimmdb/_tests/test_aimm.py deleted file mode 100644 index 1620c41..0000000 --- a/aimmdb/_tests/test_aimm.py +++ /dev/null @@ -1,146 +0,0 @@ -import copy - -import numpy as np -import pandas as pd -from tiled.client import from_tree -from tiled.queries import Key -from tiled.validation_registration import ValidationRegistry - -import aimmdb -from aimmdb.adapters.aimm import AIMMCatalog -from aimmdb.validation import validate_xas_transmission - -from .utils import fail_with_status_code - - -def get_client(tmpdir, dataset_to_specs=None, validation_registry=None): - dataset_to_specs = dataset_to_specs or {} - validation_registry = validation_registry or ValidationRegistry() - - data_directory = tmpdir / "data" - data_directory.mkdir() - - tree = AIMMCatalog.from_mongomock( - data_directory, - dataset_to_specs=dataset_to_specs, - ) - - api_key = "secret" - c = from_tree( - tree, - api_key=api_key, - authentication={"single_user_api_key": api_key}, - validation_registry=validation_registry, - ) - - return c - - -def test_basic(tmpdir): - c = get_client(tmpdir) - assert type(c) == aimmdb.client.AIMMCatalog - - -def test_write_array(tmpdir): - c = get_client(tmpdir) - - x = np.random.rand(100, 100) - metadata = {"foo": "bar"} - - # can't write without specifying dataset - with fail_with_status_code(400): - result = c["uid"].write_array(x, metadata=metadata) - - metadata.update(dataset="sandbox1", myid=1) - c["uid"].write_array(x, metadata=metadata) - - results = c["uid"].search(Key("myid") == 1) - result = results.values().first() - result_array = result.read() - - np.testing.assert_equal(result_array, x) - for k, v in metadata.items(): - assert result.metadata[k] == v - - -def test_write_dataframe(tmpdir): - c = get_client(tmpdir) - - df = pd.DataFrame({"a": np.random.rand(100), "b": np.random.rand(100)}) - metadata = {"foo": "bar"} - - # can't write without specifying dataset - with fail_with_status_code(400): - result = c["uid"].write_dataframe(df, metadata=metadata) - - metadata.update(dataset="sandbox1", myid=1) - c["uid"].write_dataframe(df, metadata=metadata) - - results = c["uid"].search(Key("myid") == 1) - result = results.values().first() - result_df = result.read() - - pd.testing.assert_frame_equal(result_df, df) - - for k, v in metadata.items(): - assert result.metadata[k] == v - - -def test_validation(tmpdir): - validation_registry = ValidationRegistry() - validation_registry.register("XAS_trans", validate_xas_transmission) - dataset_to_specs = {"xas": ["XAS_trans"]} - - c = get_client( - tmpdir, - dataset_to_specs=dataset_to_specs, - validation_registry=validation_registry, - ) - - metadata = { - "dataset": "xas", - "element": {"symbol": "Au", "edge": "K"}, - "facility": {"name": "ALS"}, - "beamline": {"name": "foo"}, - "myid": 1, - } - df = pd.DataFrame( - { - "energy": np.random.rand(100), - "i0": np.random.rand(100), - "itrans": np.random.rand(100), - } - ) - - c["uid"].write_dataframe(df, metadata=metadata, specs=["XAS_trans"]) - - results = c["uid"].search(Key("myid") == 1) - result = results.values().first() - result_df = result.read() - - pd.testing.assert_frame_equal(result_df, df) - - for k, v in metadata.items(): - assert result.metadata[k] == v - - # fail with wrong spec - with fail_with_status_code(400): - c["uid"].write_dataframe(df, metadata=metadata, specs=["FOO"]) - - # fail without complete metadata - metadata_incomplete = copy.deepcopy(metadata) - metadata_incomplete.pop("element") - with fail_with_status_code(400): - c["uid"].write_dataframe(df, metadata=metadata_incomplete, specs=["XAS_trans"]) - - # fail with missing columns - df_missing_columns = pd.DataFrame( - { - "energy": np.random.rand(100), - "i0": np.random.rand(100), - } - ) - with fail_with_status_code(400): - c["uid"].write_dataframe( - df_missing_columns, metadata=metadata, specs=["XAS_trans"] - ) diff --git a/aimmdb/_tests/test_eli.py b/aimmdb/_tests/test_eli.py deleted file mode 100644 index 8ac0325..0000000 --- a/aimmdb/_tests/test_eli.py +++ /dev/null @@ -1,41 +0,0 @@ -from aimmdb.ingest.eli import ingest, read_metadata_and_header -from pathlib import Path -import numpy as np -import pandas as pd - - -def test_read_md_and_header(): - test_path = Path("aimmdb/_tests/eli_test_file.dat") - md, hdr = read_metadata_and_header(test_path) - assert set(map(type, md.values())) == {str} # assert all md values are of type str - assert hdr.split() == [ - "energy", - "i0", - "it", - "ir", - "iff", - "aux1", - "aux2", - "aux3", - "aux4", - ] - - -def test_ingest(): - test_path = Path("aimmdb/_tests/eli_test_file.dat") - data = ingest(test_path, return_uid=True) - test_channels = ["transmission", "fluorescence", "reference"] - mu_channels = ["mu_trans", "mu_fluor", "mu_ref"] - for channel_data, tst_ch, mu_ch in zip(data, test_channels, mu_channels): - uid = channel_data["uid"] - assert uid == "d66dda13-d69c-4ca6-8fb7-76290ad71073" - md = channel_data["metadata"] - channel = md["channel"] - assert channel == tst_ch - df = channel_data["data"] - with open(test_path) as test_file: - data_lines = [ - line for line in test_file.readlines() if not line.startswith("#") - ] - assert df.shape[0] == len(data_lines) - assert mu_ch in list(df.columns) diff --git a/aimmdb/_tests/test_queries.py b/aimmdb/_tests/test_queries.py deleted file mode 100644 index 6e70e0d..0000000 --- a/aimmdb/_tests/test_queries.py +++ /dev/null @@ -1,176 +0,0 @@ -import string - -import numpy -import pandas -import pytest -from tiled.client import from_tree -from tiled.client.array import ArrayClient -from tiled.client.dataframe import DataFrameClient -from tiled.queries import Contains, In, Key, NotIn, Specs, StructureFamily - -from aimmdb.adapters.aimm import AIMMCatalog - - -def write_data(client): - # sandbox_0 - for letter, number in zip(list(string.ascii_lowercase), range(26)): - client["uid"].write_array( - number * numpy.ones(10), - metadata={"dataset": "sandbox_0", "letter": letter, "number": number}, - ) - - # sandbox_1 - client["uid"].write_array( - numpy.random.rand(100), - metadata={ - "dataset": "sandbox_1", - "letters": list(string.ascii_lowercase), - "name": "does_contain_z", - }, - ) - - client["uid"].write_array( - numpy.random.rand(100), - metadata={ - "dataset": "sandbox_1", - "letters": list(string.ascii_lowercase)[:-1], - "name": "does_not_contain_z", - }, - ) - - # sandbox_2 - client["uid"].write_array( - numpy.random.rand(100), metadata={"dataset": "sandbox_2", "name": "array"} - ) - client["uid"].write_dataframe( - pandas.DataFrame({"a": numpy.random.rand(100), "b": numpy.random.rand(100)}), - metadata={"dataset": "sandbox_2", "name": "dataframe"}, - ) - - # sandbox_3 - client["uid"].write_array( - numpy.random.rand(100), - metadata={"dataset": "sandbox_3", "name": "no_specs"}, - specs=[], - ) - client["uid"].write_array( - numpy.random.rand(100), - metadata={"dataset": "sandbox_3", "name": "specs_foo_bar"}, - specs=["foo", "bar"], - ) - client["uid"].write_array( - numpy.random.rand(100), - metadata={"dataset": "sandbox_3", "name": "specs_foo_bar_baz"}, - specs=["foo", "bar", "baz"], - ) - - return client - - -api_key = "secret" - - -@pytest.fixture(scope="session") -def tree(tmp_path_factory): - data_directory = tmp_path_factory.mktemp("data") - t = AIMMCatalog.from_mongomock(data_directory) - - c = from_tree( - t, - api_key=api_key, - authentication={"single_user_api_key": api_key}, - ) - - write_data(c) - - return t - - -@pytest.fixture -def client(tree): - return from_tree( - tree, - api_key=api_key, - authentication={"single_user_api_key": api_key}, - ) - - -def test_eq(client): - c = client["dataset"]["sandbox_0"]["uid"] - - for letter in list(string.ascii_lowercase): - results = c.search(Key("letter") == letter) - assert len(results) == 1 - result = results.values().first() - assert result.metadata["letter"] == letter - - -def test_noteq(client): - c = client["dataset"]["sandbox_0"]["uid"] - - for letter in list(string.ascii_lowercase): - results = c.search(Key("letter") != letter) - for v in results.values(): - assert v.metadata["letter"] != letter - - -def test_comparison(client): - c = client["dataset"]["sandbox_0"]["uid"] - - results = c.search(Key("number") >= 12) - for v in results.values(): - assert v.metadata["number"] >= 12 - - -def test_in(client): - c = client["dataset"]["sandbox_0"]["uid"] - results = c.search(In("letter", ["a", "k", "z"])) - for v in results.values(): - assert v.metadata["letter"] in ["a", "k", "z"] - - -def test_notin(client): - c = client["dataset"]["sandbox_0"]["uid"] - results = c.search(NotIn("letter", ["a", "k", "z"])) - for v in results.values(): - assert v.metadata["letter"] not in ["a", "k", "z"] - - -def test_contains(client): - c = client["dataset"]["sandbox_1"]["uid"] - - results = c.search(Contains("letters", "z")) - - assert len(results) == 1 - assert results.values().first().metadata["name"] == "does_contain_z" - - -def test_structure_family(client): - c = client["dataset"]["sandbox_2"]["uid"] - - results = c.search(StructureFamily("dataframe")) - assert len(results) > 0 - for v in results.values(): - assert isinstance(v, DataFrameClient) - - results = c.search(StructureFamily("array")) - assert len(results) > 0 - for v in results.values(): - assert isinstance(v, ArrayClient) - - -def test_specs(client): - c = client["dataset"]["sandbox_3"]["uid"] - - results = c.search(Specs(include=["foo", "bar"])) - assert len(results) > 0 - for v in results.values(): - assert "foo" in v.specs - assert "bar" in v.specs - - results = c.search(Specs(include=["foo", "bar"], exclude=["baz"])) - assert len(results) > 0 - for v in results.values(): - assert "foo" in v.specs - assert "bar" in v.specs - assert "baz" not in v.specs diff --git a/aimmdb/_tests/utils.py b/aimmdb/_tests/utils.py deleted file mode 100644 index 88b6f8d..0000000 --- a/aimmdb/_tests/utils.py +++ /dev/null @@ -1,11 +0,0 @@ -import contextlib - -import pytest -from tiled.client.utils import ClientError - - -@contextlib.contextmanager -def fail_with_status_code(status_code): - with pytest.raises(ClientError) as info: - yield - assert info.value.response.status_code == status_code diff --git a/aimmdb/access.py b/aimmdb/access.py index ca47fc8..12ba2e7 100644 --- a/aimmdb/access.py +++ b/aimmdb/access.py @@ -2,9 +2,9 @@ from fastapi import HTTPException from tiled.adapters.mapping import MapAdapter +from tiled.queries import In from tiled.utils import SpecialUsers -from aimmdb.queries import In READ = object() # sentinel WRITE = object() # sentinel @@ -25,7 +25,8 @@ def require_write_permission(method): def inner(self, *args, **kwargs): if WRITE not in self.permissions: raise HTTPException( - status_code=403, detail="principal does not have write permission" + status_code=403, + detail="principal does not have write permission", ) else: return method(self, *args, **kwargs) @@ -93,7 +94,9 @@ def __init__(self, access_lists, *, provider): self.provider = provider # FIXME how to handle a normal user with the admin role? - self.access_lists[SpecialUsers.admin] = defaultdict(lambda: {READ, WRITE}) + self.access_lists[SpecialUsers.admin] = defaultdict( + lambda: {READ, WRITE} + ) for principal_id, value in access_lists.items(): if principal_id == "public": @@ -145,5 +148,7 @@ def filter_results(self, tree, principal): # should be able to exclude datasets return tree.new_variation(principal=principal) else: - datasets = [k for k, v in principal_access_list.items() if READ in v] + datasets = [ + k for k, v in principal_access_list.items() if READ in v + ] return tree.search(In("dataset", datasets)) diff --git a/aimmdb/adapters/__init__.py b/aimmdb/adapters/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/aimmdb/adapters/aimm.py b/aimmdb/adapters/aimm.py deleted file mode 100644 index 7530aa5..0000000 --- a/aimmdb/adapters/aimm.py +++ /dev/null @@ -1,494 +0,0 @@ -import collections.abc -import copy -import os -from datetime import datetime -from pathlib import Path -from typing import Dict - -import pydantic -import pymongo -from fastapi import HTTPException -from tiled.iterviews import ItemsView, KeysView, ValuesView -from tiled.query_registration import QueryTranslationRegistry -from tiled.structures.core import StructureFamily -from tiled.utils import APACHE_ARROW_FILE_MIME_TYPE, UNCHANGED - -import aimmdb.queries -import aimmdb.uid -from aimmdb.access import READ, WRITE -from aimmdb.adapters.array import WritingArrayAdapter -from aimmdb.adapters.dataframe import WritingDataFrameAdapter -from aimmdb.queries import OperationEnum, parse_path, register_queries_helper -from aimmdb.schemas import GenericDocument - -_mime_structure_association = { - StructureFamily.array: "application/x-hdf5", - StructureFamily.dataframe: APACHE_ARROW_FILE_MIME_TYPE, -} - -key_to_query = { - "uid": "uid", - "element": "metadata.element.symbol", - "edge": "metadata.element.edge", - "dataset": "metadata.dataset", - "sample": "metadata.sample_id", -} - -Document = GenericDocument[Dict] - - -class AIMMCatalog(collections.abc.Mapping): - structure_family = "node" - specs = ["AIMMCatalog"] - - query_registry = QueryTranslationRegistry() - register_query = query_registry.register - register_query_lazy = query_registry.register_lazy - - from aimmdb.server.router import router - from aimmdb.server.router_tiled import router as router_tiled - - include_routers = [router, router_tiled] - - def __init__( - self, - *, - metadata_db, - data_directory, - queries=None, - sorting=None, - metadata=None, - principal=None, - access_policy=None, - path=None, - dataset_to_specs=None, - ): - - # FIXME try to do less everytime we construct a new object - - self.data_directory = Path(data_directory).resolve() - if not self.data_directory.exists(): - raise ValueError(f"Directory {self.data_directory} does not exist.") - if not self.data_directory.is_dir(): - raise ValueError( - f"The given directory path {self.data_directory} is not a directory." - ) - if not os.access(self.data_directory, os.W_OK): - raise ValueError(f"Directory {self.directory} is not writeable.") - - self.metadata_db = metadata_db - self.metadata_collection = metadata_db.get_collection("metadata") - self.sample_collection = metadata_db.get_collection("samples") - - self.queries = queries or [] - self.metadata = copy.deepcopy(metadata) or {} - self.principal = principal - self.access_policy = access_policy - - if sorting is None: - # _ is a special sentinal meaning 'the given order' - sorting = {"_": 1} - else: - sorting = {x[0]: x[1] for x in sorting} - - self._sorting = sorting - - self.path = list(path or []) - self.op = parse_path(self.path, key_to_query) - self.metadata["_tiled"] = {"op": self.op.dict()} - - # inject sample metadata if we have selected on sample - self.metadata["_tiled"].pop("sample", None) - sample_query = key_to_query["sample"] - if sample_query in self.op.select: - sample_id = self.op.select[sample_query] - sample = self.sample_collection.find_one({"uid": sample_id}, {"_id": False}) - if sample is not None: - self.metadata["_tiled"]["sample"] = sample - - self.dataset_to_specs = dataset_to_specs or {} - - super().__init__() - - @property - def sorting(self): - return [(k, v) for k, v in self._sorting.items()] - - @classmethod - def from_uri( - cls, - uri, - data_directory, - *, - metadata=None, - access_policy=None, - dataset_to_specs=None, - ): - if not pymongo.uri_parser.parse_uri(uri)["database"]: - raise ValueError( - f"Invalid URI: {uri!r} " f"Did you forget to include a database?" - ) - metadata_db = pymongo.MongoClient(uri).get_database() - - return cls( - metadata_db=metadata_db, - data_directory=data_directory, - metadata=metadata, - access_policy=access_policy, - dataset_to_specs=dataset_to_specs, - ) - - @classmethod - def from_mongomock( - cls, - data_directory, - *, - metadata=None, - access_policy=None, - dataset_to_specs=None, - ): - import mongomock - - mongo_client = mongomock.MongoClient() - metadata_db = mongo_client["test"] - - return cls( - metadata_db=metadata_db, - data_directory=data_directory, - metadata=metadata, - access_policy=access_policy, - dataset_to_specs=dataset_to_specs, - ) - - def permissions(self, dataset): - """ - Return the permissions of the current principal - """ - # FIXME in more sophisticated cases permissions may DEPEND on metadata - # For example only being able to write to a particular dataset - if self.access_policy is not None: - permissions = self.access_policy.permissions(self.principal, dataset) - else: - # no access_policy => anyone can read/write - permissions = {READ, WRITE} - - return permissions - - def authenticated_as(self, principal): - if self.principal is not None and self.principal != principal: - raise RuntimeError(f"Already authenticated as {self.principal}") - - if self.access_policy is not None: - tree = self.access_policy.filter_results(self, principal) - else: - tree = self.new_variation(principal=principal) - return tree - - def new_variation( - self, - metadata=UNCHANGED, - queries=UNCHANGED, - sorting=UNCHANGED, - principal=UNCHANGED, - path=UNCHANGED, - **kwargs, - ): - if metadata is UNCHANGED: - metadata = self.metadata - if queries is UNCHANGED: - queries = self.queries - if sorting is UNCHANGED: - sorting = self.sorting - if principal is UNCHANGED: - principal = self.principal - if path is UNCHANGED: - path = self.path - return type(self)( - metadata_db=self.metadata_db, - data_directory=self.data_directory, - metadata=metadata, - queries=queries, - sorting=sorting, - access_policy=self.access_policy, - principal=principal, - path=path, - dataset_to_specs=self.dataset_to_specs, - **kwargs, - ) - - def search(self, query): - """ - Return a AIMMCatalog with a subset of the mapping. - """ - return self.query_registry(query, self) - - def get_distinct(self, metadata, structure_families, specs, counts): - data = {} - - select = {"$match": self._build_mongo_query(self.op.select)} - - if counts: - project = {"$project": {"_id": 0, "value": "$_id", "count": "$count"}} - else: - project = {"$project": {"_id": 0, "value": "$_id"}} - - if metadata: - data["metadata"] = {} - - for metadata_key in metadata: - group = { - "$group": {"_id": f"$metadata.{metadata_key}", "count": {"$sum": 1}} - } - data["metadata"][f"{metadata_key}"] = list( - self.metadata_collection.aggregate([select, group, project]) - ) - - if structure_families: - group = {"$group": {"_id": "$structure_family", "count": {"$sum": 1}}} - data["structure_families"] = list( - self.metadata_collection.aggregate([select, group, project]) - ) - - if specs: - group = {"$group": {"_id": "$specs", "count": {"$sum": 1}}} - data["specs"] = list( - self.metadata_collection.aggregate([select, group, project]) - ) - - return data - - def sort(self, sorting): - return self.new_variation(sorting=sorting) - - def post_sample(self, sample): - # FIXME this is a bit adhoc (samples is not a 'real' dataset) - dataset = "samples" - permissions = self.permissions(dataset) - if WRITE not in permissions: - raise HTTPException( - status_code=403, - detail=f"principal does not have write permissions to dataset {dataset}", - ) - - sample.uid = aimmdb.uid.uid() - result = self.sample_collection.insert_one(sample.dict()) - assert result.acknowledged - return sample.uid - - def delete_sample(self, uid): - # FIXME this is a bit adhoc (samples is not a 'real' dataset) - dataset = "samples" - permissions = self.permissions(dataset) - if WRITE not in permissions: - raise HTTPException( - status_code=403, - detail=f"principal does not have write permissions to dataset {dataset}", - ) - - # FIXME should we also delete measurements which refer to this sample? - result = self.sample_collection.delete_one({"uid": uid}) - assert result.deleted_count == 1 - - def post_metadata(self, metadata, structure_family, structure, specs): - - # TODO reconsider how this should work - if self.path != ["uid"]: - raise HTTPException( - status_code=400, detail="AIMMCatalog only allows posting data to /uid" - ) - - # NOTE this is enforced outside of pydantic - # FIXME should there be a native tiled mechanism to perform default validation regardless of spec? - dataset = metadata.get("dataset") - if dataset is None: - raise HTTPException( - status_code=400, - detail="AIMMCatalog requires that metadata contain a dataset key", - ) - - permissions = self.permissions(dataset) - if WRITE not in permissions: - raise HTTPException( - status_code=403, - detail=f"principal does not have write permissions to dataset {dataset}", - ) - - key = aimmdb.uid.uid() - - try: - validated_document = Document( - uid=key, - structure_family=structure_family, - structure=structure, - metadata=metadata, - specs=specs, - mimetype=_mime_structure_association[structure_family], - last_modified=datetime.utcnow(), - ) - except pydantic.ValidationError as err: - raise HTTPException(status_code=400, detail=f"{err}") - - # at this point according to the server the metadata matches the stated specs and the user has permissions to write - # now check if we will accept these specs into the specified dataset - allowed_specs = self.dataset_to_specs.get(dataset, None) - - # FIXME think more about how to handle multiple specs - # if this dataset has a set of allowed specs then specs must be a non-empty subset - if allowed_specs is not None: - if not specs or not set(specs).issubset(allowed_specs): - raise HTTPException( - status_code=400, - detail=f"specs ({specs}) are not a non-empty subset of allowed specs ({allowed_specs}) for dataset {dataset}", - ) - - sample_id = validated_document.metadata.get("sample_id", None) - - doc_dict = validated_document.dict() - - if sample_id is not None: - sample = self.sample_collection.find_one({"uid": sample_id}, {"_id": False}) - if sample is None: - raise HTTPException( - status_code=400, detail=f"sample_id {sample_id} not found" - ) - else: - if "sample" in doc_dict["metadata"]: - doc_dict["metadata"]["sample"].update(sample) - else: - doc_dict["metadata"]["sample"] = sample - - self.metadata_collection.insert_one(doc_dict) - return key - - def _build_node_from_doc(self, doc): - doc = Document.parse_obj(doc) - dataset = doc.metadata["dataset"] - - permissions = self.permissions(dataset) - - if doc.structure_family == StructureFamily.array: - return WritingArrayAdapter( - self.metadata_collection, - self.data_directory, - doc, - permissions, - ) - elif doc.structure_family == StructureFamily.dataframe: - return WritingDataFrameAdapter( - self.metadata_collection, - self.data_directory, - doc, - permissions, - ) - else: - raise ValueError("Unsupported Structure Family value in the databse") - - def _build_mongo_query(self, *queries): - combined = self.queries + list(queries) - if combined: - return {"$and": combined} - else: - return {} - - def __getitem__(self, key): - path = self.path + [key] - op = parse_path(path, key_to_query) - - # if new path is a lookup, do it now - if op.op_enum == OperationEnum.lookup: - query = self._build_mongo_query(op.select) - docs = list(self.metadata_collection.find(query)) - - if len(docs) == 0: - raise KeyError(f"{key} not found") - - if len(docs) > 1: - raise KeyError(f"{key} matched multipled records") - - doc = docs[0] - - return self._build_node_from_doc(doc) - - else: - return self.new_variation(path=path) - - def __len__(self): - if self.op.op_enum == OperationEnum.keys: - return len(self.op.keys) - elif self.op.op_enum == OperationEnum.distinct: - query = self._build_mongo_query(self.op.select) - # NOTE _id is guarenteed unique - if self.op.distinct == "uid": - return self.metadata_collection.count_documents(query) - else: - # FIXME wasteful to do the full self.op just to get the length - return len( - self.metadata_collection.find(query).distinct(self.op.distinct) - ) - elif self.op.op_enum == OperationEnum.lookup: - raise RuntimeError("unreachable") - else: - raise RuntimeError("unreachable") - - def _keys_slice(self, start, stop, direction): - assert direction == 1, "direction=-1 should be handled by the client" - skip = start or 0 - if stop is not None: - limit = stop - skip - else: - limit = None - - order = self._sorting["_"] - - if self.op.op_enum == OperationEnum.keys: - keys = list(self.op.keys) if order == 1 else list(reversed(self.op.keys)) - yield from keys[skip : skip + limit] - elif self.op.op_enum == OperationEnum.distinct: - query = self._build_mongo_query(self.op.select) - sorting = [ - ("last_modified", order) - ] # natural given order is by last_modified - - # NOTE uid is guarenteed unique - if self.op.distinct == "uid": - for doc in ( - self.metadata_collection.find(query, {"uid": 1}) - .sort(sorting) - .skip(skip) - .limit(limit) - ): - yield doc["uid"] - else: - # FIXME wasteful to recompute this here (compute on construction?) - distinct = self.metadata_collection.find(query).distinct( - self.op.distinct - ) - if order == -1: - distinct = list(reversed(distinct)) - for v in distinct[skip : skip + limit]: - if v is not None: # FIXME how should we filter None - yield v - elif self.op.op_enum == OperationEnum.lookup: - raise RuntimeError("unreachable") - else: - raise RuntimeError("unreachable") - - def _items_slice(self, start, stop, direction): - for k in self._keys_slice(start, stop, direction): - # FIXME note this is wasteful because it requires a second db lookup to get the value - yield (k, self[k]) - - def __iter__(self): - yield from self.keys() - - def keys(self): - return KeysView(lambda: len(self), self._keys_slice) - - def values(self): - return ValuesView(lambda: len(self), self._items_slice) - - def items(self): - return ItemsView(lambda: len(self), self._items_slice) - - -register_queries_helper(AIMMCatalog) diff --git a/aimmdb/adapters/array.py b/aimmdb/adapters/array.py deleted file mode 100644 index 087dd2b..0000000 --- a/aimmdb/adapters/array.py +++ /dev/null @@ -1,105 +0,0 @@ -import os -from datetime import datetime -from sys import platform - -import dask -import h5py -import numpy as np -from tiled.adapters.array import ArrayAdapter -from tiled.server.pydantic_array import ArrayStructure - -from aimmdb.access import require_write_permission - - -def array_raise_if_inactive(method): - def inner(self, *args, **kwargs): - if self.array_adapter is None: - raise ValueError("Not active") - else: - return method(self, *args, **kwargs) - - return inner - - -class WritingArrayAdapter: - structure_family = "array" - - def __init__(self, metadata_collection, directory, doc, permissions=None): - self.metadata_collection = metadata_collection - self.directory = directory - self.doc = doc - self.array_adapter = None - self.permissions = list(permissions or []) - - if self.doc.data_url is not None: - path = self.doc.data_url.path - if platform == "win32" and path[0] == "/": - path = path[1:] - - file = h5py.File(path) - dataset = file["data"] - self.array_adapter = ArrayAdapter(dask.array.from_array(dataset)) - - # elif self.doc.data_blob is not None: - # self.array_adapter = ArrayAdapter(dask.array.from_array(self.doc.data_blob)) - - @property - def specs(self): - return self.doc.specs - - @property - def structure(self): - return ArrayStructure.from_json(self.doc.structure) - - @property - def metadata(self): - out = self.doc.metadata - _tiled = {"uid": self.doc.uid} - out["_tiled"] = _tiled - return out - - @array_raise_if_inactive - def read(self, *args, **kwargs): - return self.array_adapter.read(*args, **kwargs) - - @array_raise_if_inactive - def read_block(self, *args, **kwargs): - return self.array_adapter.read_block(*args, **kwargs) - - def microstructure(self): - return self.array_adapter.microstructure() - - def macrostructure(self): - return self.array_adapter.macrostructure() - - @require_write_permission - def put_data(self, body): - # Organize files into subdirectories with the first two - # charcters of the uid to avoid one giant directory. - path = self.directory / self.doc.uid[:2] / f"{self.doc.uid}.hdf5" - path.parent.mkdir(parents=True, exist_ok=True) - array = np.frombuffer( - body, dtype=self.doc.structure.micro.to_numpy_dtype() - ).reshape(self.doc.structure.macro.shape) - with h5py.File(path, "w") as file: - file.create_dataset("data", data=array) - - result = self.metadata_collection.update_one( - {"uid": self.doc.uid}, - { - "$set": { - "data_url": f"file://localhost/{str(path).replace(os.sep, '/')}", - "last_modified": datetime.utcnow(), - } - }, - ) - - assert result.matched_count == 1 - assert result.modified_count == 1 - - @require_write_permission - def delete(self): - path = self.directory / self.doc.uid[:2] / f"{self.doc.uid}.hdf5" - os.remove(path) - result = self.metadata_collection.delete_one({"uid": self.doc.uid}) - assert result.deleted_count == 1 diff --git a/aimmdb/adapters/dataframe.py b/aimmdb/adapters/dataframe.py deleted file mode 100644 index 70f3bca..0000000 --- a/aimmdb/adapters/dataframe.py +++ /dev/null @@ -1,102 +0,0 @@ -import os -from datetime import datetime -from sys import platform - -import pandas as pd -from tiled.adapters.dataframe import DataFrameAdapter -from tiled.serialization.dataframe import deserialize_arrow -from tiled.structures.dataframe import DataFrameStructure - -from aimmdb.access import require_write_permission - - -def dataframe_raise_if_inactive(method): - def inner(self, *args, **kwargs): - if self.dataframe_adapter is None: - raise ValueError("Not active") - else: - return method(self, *args, **kwargs) - - return inner - - -# FIXME write specs -class WritingDataFrameAdapter: - structure_family = "dataframe" - - def __init__(self, metadata_collection, directory, doc, permissions=None): - self.metadata_collection = metadata_collection - self.directory = directory - self.doc = doc - self.dataframe_adapter = None - self.permissions = list(permissions or []) - - if self.doc.data_url is not None: - path = self.doc.data_url.path - if platform == "win32" and path[0] == "/": - path = path[1:] - - self.dataframe_adapter = DataFrameAdapter.from_pandas( - pd.read_parquet(path), npartitions=1 - ) - - @property - def specs(self): - return self.doc.specs - - @property - def structure(self): - return DataFrameStructure.from_json(self.doc.structure) - - @property - def metadata(self): - out = self.doc.metadata - _tiled = {"uid": self.doc.uid} - out["_tiled"] = _tiled - return out - - @dataframe_raise_if_inactive - def read(self, *args, **kwargs): - return self.dataframe_adapter.read(*args, **kwargs) - - @dataframe_raise_if_inactive - def read_partition(self, *args, **kwargs): - return self.dataframe_adapter.read_partition(*args, **kwargs) - - def microstructure(self): - return self.dataframe_adapter.microstructure() - - def macrostructure(self): - return self.dataframe_adapter.macrostructure() - - @require_write_permission - def put_data(self, body): - - # Organize files into subdirectories with the first two - # charcters of the uid to avoid one giant directory. - path = self.directory / self.doc.uid[:2] / self.doc.uid - path.parent.mkdir(parents=True, exist_ok=True) - - dataframe = deserialize_arrow(body) - - dataframe.to_parquet(path) - result = self.metadata_collection.update_one( - {"uid": self.doc.uid}, - { - "$set": { - "data_url": f"file://localhost/{str(path).replace(os.sep, '/')}", - "last_modified": datetime.utcnow(), - } - }, - ) - - assert result.matched_count == 1 - assert result.modified_count == 1 - - @require_write_permission - def delete(self): - path = self.directory / self.doc.uid[:2] / self.doc.uid - # FIXME handle case where file does not exist - os.remove(path) - result = self.metadata_collection.delete_one({"uid": self.doc.uid}) - assert result.deleted_count == 1 diff --git a/aimmdb/adapters/xas.py b/aimmdb/adapters/xas.py deleted file mode 100644 index 74adb39..0000000 --- a/aimmdb/adapters/xas.py +++ /dev/null @@ -1,6 +0,0 @@ -from tiled.adapters.dataframe import DataFrameAdapter - - -# dataframe adapter representing XAS data -class XASAdapter(DataFrameAdapter): - specs = ["XAS"] diff --git a/aimmdb/client.py b/aimmdb/client.py index 0a78dcf..c9032bf 100644 --- a/aimmdb/client.py +++ b/aimmdb/client.py @@ -83,7 +83,9 @@ def _keys_slice(self, start, stop, direction): and op_dict["distinct"] == "metadata.sample_id" ): for k, v in super()._items_slice(start, stop, direction): - yield SampleKey(uid=k, name=v.metadata["_tiled"]["sample"]["name"]) + yield SampleKey( + uid=k, name=v.metadata["_tiled"]["sample"]["name"] + ) elif op_dict["op_enum"] == "distinct" and op_dict["distinct"] == "uid": for k, v in super()._items_slice(start, stop, direction): if isinstance(v, XASClient): @@ -99,7 +101,12 @@ def _items_slice(self, start, stop, direction): and op_dict["distinct"] == "metadata.sample_id" ): for k, v in super()._items_slice(start, stop, direction): - yield (SampleKey(uid=k, name=v.metadata["_tiled"]["sample"]["name"]), v) + yield ( + SampleKey( + uid=k, name=v.metadata["_tiled"]["sample"]["name"] + ), + v, + ) elif op_dict["op_enum"] == "distinct" and op_dict["distinct"] == "uid": for k, v in super()._items_slice(start, stop, direction): if isinstance(v, XASClient): diff --git a/aimmdb/graphql.py b/aimmdb/graphql.py deleted file mode 100644 index cf21515..0000000 --- a/aimmdb/graphql.py +++ /dev/null @@ -1,68 +0,0 @@ -from typing import Any, Optional - -import strawberry -from fastapi import Depends, Security -from strawberry.fastapi import GraphQLRouter -from strawberry.permission import BasePermission -from strawberry.tools import create_type -from strawberry.types import Info -from tiled.server.authentication import get_current_principal -from tiled.server.dependencies import get_root_tree - - -async def get_context( - principal=Security(get_current_principal, scopes=["read:metadata"]), - root_tree=Depends(get_root_tree), -): - return {"principal": principal, "root_tree": root_tree} - - -class WritePermission(BasePermission): - message = "User does not have write permission" - - async def has_permission(self, source: Any, info: Info, **kwargs) -> bool: - try: - principal = info.context["principal"] - root = info.context["root_tree"] - return root.access_policy.has_write_permission(principal) - except Exception as e: - print(f"Error while checking WritePermission: {e}") - return False - - -class ReadPermission(BasePermission): - message = "User does not have read permission" - - async def has_permission(self, source: Any, info: Info, **kwargs) -> bool: - try: - principal = info.context["principal"] - root = info.context["root_tree"] - return root.access_policy.has_read_permission(principal) - except Exception as e: - print(f"Error while checking ReadPermission: {e}") - return False - - -@strawberry.field(permission_classes=[ReadPermission]) -def hello(info: Info) -> str: - principal = info.context["principal"] - return f"Hello {principal}" - - -@strawberry.mutation(permission_classes=[WritePermission]) -def record_message(message: str, info: Info) -> Optional[str]: - root = info.context["root_tree"] - db = root.db - try: - result = db.messages.insert_one({"message": message}) - return str(result.inserted_id) - except RuntimeError as e: - print(e) - return None - - -GQLQuery = create_type("Query", [hello]) -GQLMutation = create_type("Mutation", [record_message]) - -GQLSchema = strawberry.Schema(query=GQLQuery, mutation=GQLMutation) -GQLRouter = GraphQLRouter(GQLSchema, context_getter=get_context, graphiql=False) diff --git a/aimmdb/ingest/README.rst b/aimmdb/ingest/README.rst deleted file mode 100644 index 8fcfbed..0000000 --- a/aimmdb/ingest/README.rst +++ /dev/null @@ -1,48 +0,0 @@ - -Ingestion steps for NSLS-II Inner Shell Spectroscopy (ISS) beamline -================================== - -This ingestion pipeline reads ``.dat`` files. These files contain commented lines (denoted by #) aka metadata, and columnated data beneath the metadata. The pipeline is tested on some example data found at ``aimmdb/_tests/eli_test_file.dat``. - - -* For all comment lines, if they contain a colon, remove starting hash and split at colon to create key-value pairs -* The only comment line without colon should be the header for columnated data -* Place key-value pairs in temporary metadata dictionary, ``temp_md`` -* Columnated data should contain energy, i0, it, ir, iff, and aux channels -* Use data in .dat file to calculate ``mu_trans``, ``mu_fluor``, and ``mu_ref`` (see equations below) -* Split the data into three entries for AIMMDB - * One entry for each mu channel (transmission, fluorescence, reference) - * Each entry contains DataFrame with two columns (energy, mu), plus metadata dictionary equivalent to ``temp_md`` with key added for the channel - * Optionally include uid as third element in each entry - -``mu`` transmission -------------------- - -We store a dataframe with column ``mu_trans`` which is calculated via - -.. code:: - - mu_trans = -log(I_trans / I_0) - -This is the intensity of the transmission signal, where :math:`I_0` is the background intensity. - -``mu`` fluorescence -------------------- - -We store a dataframe with column called ``mu_fluor`` which is calculated via - -.. code:: - - mu_fluor = I_fluor / I_0 - -This is the intensity of the fluorescence signal. Note there is no logarithmic scaling like above. - -``mu`` fluorescence -------------------- - -We store a dataframe with column called ``mu_ref`` which is calculated via - -.. code:: - - mu_ref = -log(I_ref / I_0) - diff --git a/aimmdb/ingest/__init__.py b/aimmdb/ingest/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/aimmdb/ingest/eli.py b/aimmdb/ingest/eli.py deleted file mode 100644 index 7c03dac..0000000 --- a/aimmdb/ingest/eli.py +++ /dev/null @@ -1,104 +0,0 @@ -import numpy as np -import pandas as pd -from pathlib import Path - - -def read_metadata_and_header(path): - """Read through commented lines of dat file to get metadata and DataFrame header - - Parameters - ---------- - path: str, or path object - path to .dat file from ISS beamline - - Returns - ------- - tuple[dict[str, str], str] - First element is dictionary of metadata. - Second element is header as single string, with column names separated by whitespace. - """ - metadata: dict - header: str - with open(path, "r") as dat_file: - lines = dat_file.readlines() - # remove starting hash and whitespace - comment_lines = [line[2:] for line in lines if line.startswith("#")] - - metadata = { - # split line at colon for key-value pairs and strip whitespace from values - line.split(":", maxsplit=1)[0]: line.split(":", maxsplit=1)[1].strip() - for line in comment_lines - if ":" in line - } - - # only comment line without colon should be header - header = [line for line in comment_lines if ":" not in line][0] - - return metadata, header - - -def ingest(path, return_uid=False): - """Prepare scan data from Eli (ISS beamline) for entry into AIMMDB - - Data is stored in .dat file which contains commented lines (denoted by #) with metadata, - and columnated data below the metadata. - Data columns should correspond to energy, i0, it, ir, iff, and aux channels. - DataFrame for aimmdb contains only energy and absorption coefficient (mu). - There are several ways to calculate mu based on the mode of the measurement: - - mu_trans = -ln(it/i0) - - mu_fluor = iff/i0 - - mu_ref = -ln(ir/i0) - - These are each calculated and three database entries are created. Each entry contains a DataFrame with energy and mu - as columns, as well as a metadata dictionary containing the commented metadata from the file plus an additional key - indicating the measurement channel (trans, fluor, or ref). - - Parameters - ---------- - path: str, or path object - path to .dat file from ISS beamline - - Returns - ------- - tuple({'data': DataFrame, 'metadata': dict}, {'data': DataFrame, 'metadata': dict}, {'data': DataFrame, 'metadata': dict}) - Database entries corresponding to the transmission, fluorescence, and reference channels. - - Other Parameters - ---------------- - return_uid: bool - Optional keyword to return uid as third element in each entry. - The uid should be present in the metadata, but it is an especially important - piece of information that may be useful to store separately. - """ - temp_md, hdr = read_metadata_and_header(path) - - temp_data = pd.read_csv(path, delim_whitespace=True, comment="#", names=hdr.split()) - temp_data["mu_trans"] = -np.log(temp_data["it"] / temp_data["i0"]) - temp_data["mu_fluor"] = temp_data["iff"] / temp_data["i0"] - temp_data["mu_ref"] = -np.log(temp_data["ir"] / temp_data["i0"]) - - df_trans = temp_data[["energy", "mu_trans"]] - temp_md["channel"] = "transmission" - md_trans = temp_md.copy() - - df_fluor = temp_data[["energy", "mu_fluor"]] - temp_md["channel"] = "fluorescence" - md_fluor = temp_md.copy() - - df_ref = temp_data[["energy", "mu_ref"]] - temp_md["channel"] = "reference" - md_ref = temp_md.copy() - - if return_uid: - uid = temp_md["Scan.uid"] - return ( - dict(data=df_trans, metadata=md_trans, uid=uid), - dict(data=df_fluor, metadata=md_fluor, uid=uid), - dict(data=df_ref, metadata=md_ref, uid=uid), - ) - else: - return ( - dict(data=df_trans, metadata=md_trans), - dict(data=df_fluor, metadata=md_fluor), - dict(data=df_ref, metadata=md_ref), - ) diff --git a/aimmdb/postprocessing/__init__.py b/aimmdb/postprocessing/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/aimmdb/postprocessing/operations.py b/aimmdb/postprocessing/operations.py deleted file mode 100644 index 2ab5852..0000000 --- a/aimmdb/postprocessing/operations.py +++ /dev/null @@ -1,639 +0,0 @@ -"""Module for housing post-processing operations.""" - -from abc import ABC, abstractmethod -from datetime import datetime - -from monty.json import MSONable -import numpy as np -import pandas as pd -from scipy.interpolate import InterpolatedUnivariateSpline -from sklearn.linear_model import LinearRegression -from tiled.client.dataframe import DataFrameClient -from larch import Group as xafsgroup -from larch.xafs import pre_edge - -from aimmdb.postprocessing import utils -from aimmdb.uid import uid - - -class Operator(MSONable, ABC): - """Base operator class. Tracks everything required through a combination - of the MSONable base class and by using an additional datetime key to track - when the operator was logged into the metadata of a new node. - - .. important:: - - The __call__ method must be derived for every operator. In particular, - this operator should take as arguments at least one data point (node). - """ - - @abstractmethod - def _process_data(self): - ... - - @abstractmethod - def _process_metadata(self): - ... - - @abstractmethod - def __call__(self, inp): - ... - - -class UnaryOperator(Operator): - """Specialized operator class which takes only a single input. This input - must be of instance :class:`DataFrameClient`. - - Particularly, the operator object's ``__call__`` method can be executed on - either a :class:`DataFrameClient` or :class:`Node` object. If run on the - :class:`DataFrameClient`, the operator call will return a single dictionary - with the keys "data" and "metadata", as one would expect. If the input is - of type :class:`Node`, then an attempt is made to iterate through all - children of that node, executing the operator on each instance - individually. A list of dictionaries is then returned. - """ - - def _process_metadata(self, metadata): - """Processing of the metadata dictionary object. Takes the - :class:`dict` object as input and returns a modified - dictionary with the following changes: - - 1. metadata["_tiled"]["uid"] is replaced with a new uuid string. - 2. metadata["post_processing"] is created with keys that indicate - the current state of the class, the parent ids - - Parameters - ---------- - metadata : dict - The metadata dictionary accessed via ``df_client.metadata``. - - Returns - ------- - dict - The new metadata object for the post-processed child. - """ - - dt = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") - return { - "_post_processing": { - "parents": [metadata["_tiled"]["uid"]], - "operator": self.as_dict(), - "kwargs": self.__dict__, - "datetime": f"{dt} UTC", - }, - } - - def __call__(self, inp): - if isinstance(inp, DataFrameClient): - return { - "data": self._process_data(inp.read()), - "metadata": self._process_metadata(inp.metadata), - } - elif isinstance(inp, dict): - return { - "data": self._process_data(inp["data"]), - "metadata": self._process_metadata(inp["metadata"]), - } - else: - raise ValueError( - f"Input type {type(inp)} must be either DataFrameClient or " - "dict" - ) - - -class MisoOperator(Operator): - """ - Multiple input single output (MISO) operator class. - Specialized operator class which takes an arbitrary number of inputs - and returns a single output. - All inputs must be of instance :class:`DataFrameClient` or `dict`. - - Particularly, the operator object's ``__call__`` method can be executed on - an arbitrary number of :class:`DataFrameClient` or `dict` objects. The operator will - return a single dictionary with keys "data" and "metadata". - """ - - def _process_metadata(self, *metadata): - """Processing of the metadata dictionary objects. Takes arbitrary number - of :class:`dict` objects as input and returns a new dictionary as output - with the following: - - 1. metadata["_tiled"]["uid"] is replaced with a new uuid string. - 2. metadata["post_processing"] is created with keys that indicate - the current state of the class, the parent ids - - Parameters - ---------- - metadata : dict - The metadata dictionaries accessed via ``df_client.metadata``. - - Returns - ------- - dict - The new metadata object for the post-processed child. - """ - - dt = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") - return { - "_post_processing": { - "parents": [md["_tiled"]["uid"] for md in metadata], - "operator": self.as_dict(), - "kwargs": self.__dict__, - "datetime": f"{dt} UTC", - }, - } - - def __call__(self, *inps): - if all(isinstance(inp, (DataFrameClient, dict)) for inp in inps): - inp_data = [ - inp.read() if isinstance(inp, DataFrameClient) else inp["data"] - for inp in inps - ] - inp_metadata = [ - inp.metadata - if isinstance(inp, DataFrameClient) - else inp["metadata"] - for inp in inps - ] - return { - "data": self._process_data(*inp_data), - "metadata": self._process_metadata(*inp_metadata), - } - - else: - raise ValueError( - f"All inputs must be of type DataFrameClient or dict" - ) - - -class MimoOperator(Operator): - """ - Multiple input multiple output (MIMO) operator class. - Specialized operator class which takes an arbitrary number of inputs - and returns a list with an equal number of outputs. - All inputs must be of instance :class:`DataFrameClient` or `dict`. - - Particularly, the operator object's ``__call__`` method can be executed on - an arbitrary number of :class:`DataFrameClient` or `dict` objects. For each - object passed some operation will be performed and the result will be returned - as a `dict` with keys "data" and "metatdata". - """ - - def _process_metadata(self, *metadata): - """Processing of the metadata dictionary objects. Takes arbitrary number - of :class:`dict` objects as input and returns a new dictionary for each input - with the following: - - 1. metadata["_tiled"]["uid"] is replaced with a new uid string. - 2. metadata["post_processing"] is created with keys that indicate - the current state of the class. This includes a "parent" key - with the uid of the specific object that was operated on, and - a "relatives" key with the uids of all operator inputs. - - Parameters - ---------- - metadata : dict - The metadata dictionaries accessed via ``df_client.metadata``. - - Returns - ------- - list of dict - List of new metadata object for each post-processed child. - """ - - dt = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") - input_uids = [md["_tiled"]["uid"] for md in metadata] - return [ - { - "_post_processing": { - "parent": md["_tiled"]["uid"], - "relatives": input_uids, - "operator": self.as_dict(), - "kwargs": self.__dict__, - "datetime": f"{dt} UTC", - }, - } - for md in metadata - ] # return dict for each entry - - def __call__(self, *inps): - if all(isinstance(inp, (DataFrameClient, dict)) for inp in inps): - inp_data = [ - inp.read() if isinstance(inp, DataFrameClient) else inp["data"] - for inp in inps - ] - inp_metadata = [ - inp.metadata - if isinstance(inp, DataFrameClient) - else inp["metadata"] - for inp in inps - ] - out_data = self._process_data(*inp_data) - out_metadata = self._process_metadata(*inp_metadata) - return [ - { - "data": d, - "metadata": md, - } - for d, md in zip(out_data, out_metadata) - ] - - else: - raise ValueError( - f"All inputs must be of type DataFrameClient or dict" - ) - - -class GroupIdentity(MimoOperator): - """Modified identity operation to work with MimoOperator baseclass. - Does nothing. Primarily used for testing.""" - - def __init__(self): - super().__init__() - - def _process_data(self, *dfs): - """ - Parameters - ---------- - dfs : tuple of pandas.DataFrame - The dataframe objects to process. - - Returns - ------- - list of pandas.DataFrame - """ - - return [df for df in dfs] - - -class AverageData(MisoOperator): - """Average data (mu) from multiple XAS spectra. - Also calculates standard deviation at each energy point. - - Parameters - ---------- - x_columns : str, optional - References a single column in the DataFrames (the "x-axis"). - This should be the same for all DataFrames. Default is "energy". - y_column : str, optional - References a single column in the DataFrames (the "y-axis"). - This is the data that will be averaged from each DataFrame. - Default is "mu". - """ - - def __init__(self, x_column="energy", y_column="mu"): - self.x_column = x_column - self.y_column = y_column - - def _process_data(self, *dfs): - """ - Takes in an arbitrary number of :class:`pd.DataFrame` objects. - The "y_column" is taken from each DataFrame and averaged. - - Returns: - -------- - pd.DataFrame - Averaged data in new DataFrame. - Standard deviation is added to new "stddev" column. - """ - x_values = dfs[0][self.x_column] - assert all( - (df[self.x_column] == x_values).all() for df in dfs - ), "all data should have the same x-values before averaging" - all_data = np.array([df[self.y_column] for df in dfs]) - averaged_data = np.mean(all_data, axis=0) - std_dev = np.std(all_data, axis=0) - new_data = { - self.x_column: x_values, - self.y_column: averaged_data, - "stddev": std_dev, - } - - return pd.DataFrame(new_data) - - -class Identity(UnaryOperator): - """The identity operation. Does nothing. Primarily used for testing - purposes.""" - - def __init__(self): - super().__init__() - - def _process_data(self, df): - """ - Parameters - ---------- - df : pandas.DataFrame - The dataframe object to process. - - Returns - ------- - pandas.DataFrame - """ - - return df - - -class StandardizeGrid(UnaryOperator): - """Interpolates specified columns onto a common grid. - - Parameters - ---------- - x0 : float - The lower bound of the grid to interpolate onto. - xf : float - The upper bound of the grid to interpolate onto. - nx : int - The number of interpolation points. - interpolated_univariate_spline_kwargs : dict, optional - Keyword arguments to be passed to the - :class:`InterpolatedUnivariateSpline`. See - [here](https://docs.scipy.org/doc/scipy/reference/generated/ - scipy.interpolate.InterpolatedUnivariateSpline.html) for the - documentation on this class. - x_column : str, optional - References a single column in the DataFrameClient (this is the - "x-axis"). - y_columns : list, optional - References a list of columns in the DataFrameClient (these are the - "y-axes"). - """ - - def __init__( - self, - *, - x0, - xf, - nx, - interpolated_univariate_spline_kwargs=dict(), - x_column="energy", - y_columns=["mu"], - ): - self.x0 = x0 - self.xf = xf - self.nx = nx - self.interpolated_univariate_spline_kwargs = ( - interpolated_univariate_spline_kwargs - ) - self.x_column = x_column - self.y_columns = y_columns - - def _process_data(self, df): - """Takes in a dictionary of the data amd metadata. The data is a - :class:`pd.DataFrame`, and the metadata is itself a dictionary. - Returns the same dictionary with processed data and metadata. - """ - - new_grid = np.linspace(self.x0, self.xf, self.nx) - new_data = {self.x_column: new_grid} - for column in self.y_columns: - ius = InterpolatedUnivariateSpline( - df[self.x_column], - df[column], - **self.interpolated_univariate_spline_kwargs, - ) - new_data[column] = ius(new_grid) - - return pd.DataFrame(new_data) - - -class RemoveBackground(UnaryOperator): - """Fit the pre-edge region to a Victoreen function and subtract it from the - spectrum. - - Parameters - ---------- - x0 : float - The lower bound of energy range on which the background is fitted. - xf : float - The upper bound of energy range on which the background is fitted. - x_column : str, optional - References a single column in the DataFrameClient (this is the - "x-axis"). - y_columns : list, optional - References a list of columns in the DataFrameClient (these are the - "y-axes"). - victoreen_order : int - The order of Victoreen function. The selected data is fitted to - Victoreen pre-edge function (in which one fits a line to - :math:`E^n \\mu(E)` for some value of :math:`n`. - """ - - def __init__( - self, *, x0, xf, x_column="energy", y_columns=["mu"], victoreen_order=0 - ): - self.x0 = x0 - self.xf = xf - self.victoreen_order = victoreen_order - self.x_column = x_column - self.y_columns = y_columns - - def _process_data(self, df): - """ - Notes - ----- - ``LinearRegression().fit()`` takes 2-D arrays as input. This can be - explored for batch processing of multiple spectra - """ - - assert self.x0 < self.xf, "Invalid range, make sure x0 < xf" - - bg_data = df.loc[ - (df[self.x_column] >= self.x0) * (df[self.x_column] < self.xf) - ] - - new_data = {self.x_column: df[self.x_column]} - for column in self.y_columns: - y = bg_data[column] * bg_data[self.x_column] ** self.victoreen_order - reg = LinearRegression().fit( - bg_data[self.x_column].to_numpy().reshape(-1, 1), - y.to_numpy().reshape(-1, 1), - ) - background = reg.predict( - df[self.x_column].to_numpy().reshape(-1, 1) - ) - new_data[column] = ( - df.loc[:, column].to_numpy() - background.flatten() - ) - - return pd.DataFrame(new_data) - - -class StandardizeIntensity(UnaryOperator): - """Scale the intensity so they vary in similar range. Does this by taking - a specific range of the specrum and dividing out a quadratic fit to that - region. - - Parameters - ---------- - x0 : float - The lower bound of energy range for which the mean is calculated. If - None, the first. - point in the energy grid is used. Default is None. - yf : float - The upper bound of energy range for which the mean is calculated. If - None, the last. - point in the energy grid is used. Default is None. - x_column : str, optional - References a single column in the DataFrameClient (this is the - "x-axis"). Default is "energy". - y_columns : list, optional - References a list of columns in the DataFrameClient (these are the - "y-axes"). Default is ["mu"]. - """ - - def __init__(self, *, x0, xf, x_column="energy", y_columns=["mu"], deg=2): - self.x0 = x0 - self.xf = xf - self.x_column = x_column - self.y_columns = y_columns - self.deg = deg - - def _process_data(self, df): - """ - Takes in a dictionary of the data amd metadata. The data is a - :class:`pd.DataFrame`, and the metadata is itself a dictionary. - Returns the same dictionary with processed data and metadata. - - """ - - grid = np.array(df.loc[:, self.x_column]) - if self.x0 is None: - self.x0 = grid[0] - if self.xf is None: - self.xf = grid[-1] - assert self.x0 < self.xf, "Invalid range, make sure x0 < xf" - select_mean_range = (grid > self.x0) & (grid < self.xf) - - new_data = {self.x_column: df[self.x_column]} - for column in self.y_columns: - y = df.loc[:, column] - y = y[select_mean_range] - x = grid[select_mean_range] - try: - p0 = np.polyfit(x, y, deg=self.deg) - except TypeError: - return None # Range failure - new_data.update({column: df.loc[:, column] / np.polyval(p0, grid)}) - - return pd.DataFrame(new_data) - - -class Smooth(UnaryOperator): - """Return the simple moving average of spectra with a rolling window. - - Parameters - ---------- - window : float, in eV. - The rolling window in eV over which the average intensity is taken. - x_column : str, optional - References a single column in the DataFrameClient (this is the - "x-axis"). - y_columns : list, optional - References a list of columns in the DataFrameClient (these are the - "y-axes"). - """ - - def __init__(self, *, window=10.0, x_column="energy", y_columns=["mu"]): - self.window = window - self.x_column = x_column - self.y_columns = y_columns - - def _process_data(self, df): - """ - Takes in a dictionary of the data amd metadata. The data is a - :class:`pd.DataFrame`, and the metadata is itself a dictionary. - Returns the same dictionary with processed data and metadata. - - Returns: - -------- - dict - A dictionary of the data and metadata. The data is a :class:`pd.DataFrame`, - and the metadata is itself a dictionary. - """ - - grid = df.loc[:, self.x_column] - new_data = {self.x_column: df[self.x_column]} - for column in self.y_columns: - y = df.loc[:, column] - y_smooth = utils.simple_moving_average(grid, y, window=self.window) - new_data.update({column: y_smooth}) - - return pd.DataFrame(new_data) - - -class NormalizeLarch(UnaryOperator): - """Return XAS spectrum normalized using larch. - Post-edge is normalized such that spectral features oscillate around 1. - - Calls larch `pre_edge` function on data to perfrom normalization. - This function performs several steps: - 1. determine E0 (if not supplied) from max of deriv(mu) - 2. fit a line to the region below the edge - 3. fit a quadratic curve to the region above the edge - 4. extrapolate the two curves to E0 and take their difference - to determine the edge jump - - Normalized spectrum (`norm_mu`) is calculated via the following: - `norm_mu = (mu - pre_edge_line) / edge_jump` - - To flatten the spectrum the fitted post-edge quadratic curve is subtracted - from the post-edge. - - - Parameters - ---------- - x_column : str, optional - References a single column in the DataFrameClient (this is the - "x-axis"). Default is "energy". - y_columns : list, optional - References a list of columns in the DataFrameClient (these are the - "y-axes"). Default is ["mu"]. - larch_pre_edge_kwargs : dict, optional - Dictionary of keyword arguments to be passed into larch pre_edge function. - Can be used to specify normalization parameters that are otherwise - calculated in larch (e.g., e0, edge jump size, pre-edge range, etc.). - See https://xraypy.github.io/xraylarch/xafs_preedge.html for pre_edge - documentation. - - """ - - def __init__( - self, - *, - x_column="energy", - y_columns=["mu"], - larch_pre_edge_kwargs=dict(), - ): - self.x_column = x_column - self.y_columns = y_columns - self.larch_pre_edge_kwargs = larch_pre_edge_kwargs - - def _process_data(self, df): - new_data = {self.x_column: df[self.x_column]} - for column in self.y_columns: - larch_group = xafsgroup() - larch_group.energy = np.array(df[self.x_column]) - larch_group.mu = np.array(df[column]) - pre_edge( - larch_group, - group=larch_group, - **self.larch_pre_edge_kwargs, - ) - norm_mu = larch_group.flat - new_data.update({column: norm_mu}) - - return pd.DataFrame(new_data) - - -# TODO -class Classify(UnaryOperator): - """Label the spectrum as "good", "noisy" or "discard" based on the quality - of the spectrum.""" - - ... - - -# TODO -class PreNormalize(UnaryOperator): - ... diff --git a/aimmdb/postprocessing/pipeline.py b/aimmdb/postprocessing/pipeline.py deleted file mode 100644 index 74b2fb1..0000000 --- a/aimmdb/postprocessing/pipeline.py +++ /dev/null @@ -1,57 +0,0 @@ -from monty.json import MSONable -import tiled -from aimm_post_processing import operations as op - - - -class Pipeline(MSONable): - """The data pipeline that contains a chain of operations - """ - def __init__(self, operation_list): - self.pull_first = False # whether has Pull as the first operation - if isinstance(operation_list[0], op.Pull): - self.pull_first = True - self.init_operation = operation_list.pop(0) - else: - self.init_operation = op.Identity() - self.operation_list = operation_list - - def run(self, data): - if self.pull_first: - assert isinstance(data, tiled.client.dataframe.DataFrameClient), \ - """The first operation of your pipeline is Pull, which only takes - "tiled.client.dataframe.DataFrameClient" as input. - """ - else: - assert isinstance(data, dict), \ - """No Pull operation found, only python dictionary is accepted. - """ - data = self.init_operation(data) - pp_history = {0: data["metadata"]["post_processing"]} - for i, operation in enumerate(self.operation_list): - data = operation(data) - pp_history[i+1] = data["metadata"]["post_processing"] - data["metadata"]["post_processing"] = pp_history - return data - - @property - def info(self): - if self.pull_first: - print(self.init_operation) - for operation in self.operation_list: - print(operation) - - def __add__(self, ob): - assert isinstance(ob, self.__class__) - assert not ob.pull_first, \ - "Only first pipeline can have Pull operation" - if self.pull_first: - first_operation = [self.init_operation] - else: - first_operation = [] - new_operation_list = first_operation \ - + self.operation_list \ - + ob.operation_list - - return Pipeline(new_operation_list) - \ No newline at end of file diff --git a/aimmdb/postprocessing/utils.py b/aimmdb/postprocessing/utils.py deleted file mode 100644 index 652c616..0000000 --- a/aimmdb/postprocessing/utils.py +++ /dev/null @@ -1,19 +0,0 @@ -# import general data science modules -import numpy as np - - -def simple_moving_average(x, y, window): - """Reutrn the simple moving average of a data sequence `y` over a rolling window defined on `x`. - Note that the amount of grid points in an interval always exceeds the amount of spacings of - that interval by one. The `window` refers to spacings instead of grid points. - """ - # amount of grid points that accounts for the window in eV (approximately) - half_window = round(window / 2 / (x[1] - x[0])) - - smoothed = [] - for i in range(len(x)): - if i <= half_window: # deal with left bound - smoothed.append(y[: i + half_window + 1].mean()) - else: # python handles right bound automatically - smoothed.append(y[i - half_window : i + half_window + 1].mean()) - return np.array(smoothed) diff --git a/aimmdb/queries.py b/aimmdb/queries.py deleted file mode 100644 index 6a118e0..0000000 --- a/aimmdb/queries.py +++ /dev/null @@ -1,165 +0,0 @@ -from enum import Enum -from typing import Any, Dict, List - -import pydantic -from tiled.queries import (Comparison, Contains, Eq, In, NotEq, NotIn, Specs, - StructureFamily) - -JSONSerializable = Any # Feel free to refine this. - - -def make_mongo_query_in(query, prefix=None): - assert isinstance(query, In) - mongo_key = ".".join([prefix, query.key]) if prefix else query.key - mongo_query = {mongo_key: {"$in": query.value}} - return mongo_query - - -def make_mongo_query_notin(query, prefix=None): - assert isinstance(query, NotIn) - mongo_key = ".".join([prefix, query.key]) if prefix else query.key - mongo_query = {mongo_key: {"$nin": query.value}} - return mongo_query - - -def make_mongo_query_eq(query, prefix=None): - assert isinstance(query, Eq) - mongo_key = ".".join([prefix, query.key]) if prefix else query.key - mongo_query = {mongo_key: {"$eq": query.value}} - return mongo_query - - -def make_mongo_query_neq(query, prefix=None): - assert isinstance(query, NotEq) - mongo_key = ".".join([prefix, query.key]) if prefix else query.key - mongo_query = {mongo_key: {"$ne": query.value}} - return mongo_query - - -def make_mongo_query_comparison(query, prefix=None): - assert isinstance(query, Comparison) - op = query.operator - if op not in {"le", "lt", "ge", "gt"}: - raise ValueError(f"Unexpected operator {query.operator}.") - mongo_op = {"lt": "$lt", "le": "$lte", "gt": "$gt", "ge": "$gte"}[op] - mongo_key = ".".join([prefix, query.key]) if prefix else query.key - mongo_query = {mongo_key: {mongo_op: query.value}} - return mongo_query - - -def make_mongo_query_contains(query, prefix=None): - assert isinstance(query, Contains) - mongo_key = ".".join([prefix, query.key]) if prefix else query.key - mongo_query = {mongo_key: query.value} - return mongo_query - - -def run_eq(query, tree): - mongo_query = make_mongo_query_eq(query, prefix="metadata") - return tree.new_variation(queries=tree.queries + [mongo_query]) - - -def run_neq(query, tree): - mongo_query = make_mongo_query_neq(query, prefix="metadata") - return tree.new_variation(queries=tree.queries + [mongo_query]) - - -def run_comparison(query, tree): - mongo_query = make_mongo_query_comparison(query, prefix="metadata") - return tree.new_variation(queries=tree.queries + [mongo_query]) - - -def run_contains(query, tree): - mongo_query = make_mongo_query_contains(query, prefix="metadata") - return tree.new_variation(queries=tree.queries + [mongo_query]) - - -def run_in(query, tree): - mongo_query = make_mongo_query_in(query, prefix="metadata") - return tree.new_variation(queries=tree.queries + [mongo_query]) - - -def run_notin(query, tree): - mongo_query = make_mongo_query_notin(query, prefix="metadata") - return tree.new_variation(queries=tree.queries + [mongo_query]) - - -def run_structure_family(query, tree): - mongo_query = {"structure_family": query.value.value} - return tree.new_variation(queries=tree.queries + [mongo_query]) - - -def run_specs(query, tree): - mongo_queries = [] - - if query.include: - mongo_queries.append({"specs": {"$all": query.include}}) - - if query.exclude: - mongo_queries.append({"specs": {"$nin": query.exclude}}) - return tree.new_variation(queries=tree.queries + mongo_queries) - - -def register_queries_helper(cls): - cls.register_query(Eq, run_eq) - cls.register_query(NotEq, run_neq) - cls.register_query(Comparison, run_comparison) - cls.register_query(Contains, run_contains) - cls.register_query(In, run_in) - cls.register_query(NotIn, run_notin) - cls.register_query(StructureFamily, run_structure_family) - cls.register_query(Specs, run_specs) - - -class OperationEnum(str, Enum): - distinct = "distinct" - lookup = "lookup" - keys = "keys" - - -class Distinct(pydantic.BaseModel): - op_enum: OperationEnum = "distinct" - select: Dict - distinct: str - - -class Keys(pydantic.BaseModel): - op_enum: OperationEnum = "keys" - select: Dict - keys: List[str] - - -class Lookup(pydantic.BaseModel): - op_enum: OperationEnum = "lookup" - select: Dict - - @pydantic.validator("select") - def check_select(cls, select): - if "uid" not in select: - raise ValueError("Lookup operation must have uid specified") - return select - - -def parse_path(path, key_to_query): - valid_keys = set(key_to_query.keys()) - keys = path[0::2] - values = path[1::2] - - if not set(keys).issubset(valid_keys): - invalid_keys = set(keys) - valid_keys - raise KeyError(f"keys {invalid_keys} not in {valid_keys}") - - select = {key_to_query[k]: v for k, v in zip(keys, values)} - leftover_keys = valid_keys - set(keys) - # if we have more keys then values then get distinct values for the last key - if len(keys) == len(values) + 1: - return Distinct(select=select, distinct=key_to_query[keys[-1]]) - - # if keys and values are matched then perform a lookup if uid was provided otherwise get remaining keys - elif len(keys) == len(values): - if "uid" in keys: - return Lookup(select=select) - else: - return Keys(select=select, keys=leftover_keys) - - raise KeyError(f"{len(keys)=}, {len(values)=}") diff --git a/aimmdb/schemas.py b/aimmdb/schemas.py index 0471325..4dcce2e 100644 --- a/aimmdb/schemas.py +++ b/aimmdb/schemas.py @@ -34,7 +34,9 @@ def validate_structure_matches_structure_family(cls, values): # actual_structure_type = cls.__annotations__["structure"] # this is what was filled in for StructureT actual_structure = values.get("structure") # Given the structure_family, we know what the structure type should be. - expected_structure_type = structure_association[values.get("structure_family")] + expected_structure_type = structure_association[ + values.get("structure_family") + ] if values.get("expected_structure_type") == StructureFamily.node: raise Exception( f"{expected_structure_type} is not currently supported as a writable structure" @@ -51,7 +53,10 @@ def check_data_source(cls, values): # with the current data types without getting any conflicts # if values.get('data_blob') is None and values.get('data_url') is None: # raise ValueError("Not Valid: data_blob and data_url are both None. Use one of them") - if values.get("data_blob") is not None and values.get("data_url") is not None: + if ( + values.get("data_blob") is not None + and values.get("data_url") is not None + ): raise ValueError( "Not Valid: data_blob and data_url contain values. Use just one" ) diff --git a/aimmdb/serialization.py b/aimmdb/serialization.py deleted file mode 100644 index f7fa88c..0000000 --- a/aimmdb/serialization.py +++ /dev/null @@ -1,26 +0,0 @@ -import io - -import numpy as np -import pyarrow as pa -import pyarrow.parquet as pq - - -def serialize_npy(x): - with io.BytesIO() as f: - np.save(f, x) - buf = f.getvalue() - return memoryview(buf) - - -def serialize_parquet(df): - table = pa.Table.from_pandas(df) - sink = pa.BufferOutputStream() - pq.write_table(table, sink) - buf = sink.getvalue() - return memoryview(buf) - - -def deserialize_parquet(data): - reader = pa.BufferReader(data) - table = pq.read_table(reader) - return table.to_pandas() diff --git a/aimmdb/server/__init__.py b/aimmdb/server/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/aimmdb/server/pydantic_dataframe.py b/aimmdb/server/pydantic_dataframe.py deleted file mode 100644 index b72f524..0000000 --- a/aimmdb/server/pydantic_dataframe.py +++ /dev/null @@ -1,19 +0,0 @@ -from typing import List, Tuple, Union - -import pydantic - - -class DataFrameMicroStructure(pydantic.BaseModel): - meta: bytes # Arrow-encoded DataFrame - divisions: bytes # Arrow-encoded DataFrame - - -class DataFrameMacroStructure(pydantic.BaseModel): - npartitions: int - columns: List[str] - resizable: Union[bool, Tuple[bool, ...]] = False - - -class DataFrameStructure(pydantic.BaseModel): - micro: DataFrameMicroStructure - macro: DataFrameMacroStructure diff --git a/aimmdb/server/router.py b/aimmdb/server/router.py deleted file mode 100644 index 7b989c9..0000000 --- a/aimmdb/server/router.py +++ /dev/null @@ -1,54 +0,0 @@ -import pydantic -from fastapi import APIRouter, Depends, HTTPException, Request, Security -from tiled.server.core import json_or_msgpack -from tiled.server.dependencies import get_current_principal, get_root_tree - -from aimmdb.schemas import SampleData - - -class PostSampleResponse(pydantic.BaseModel): - uid: str - - -router = APIRouter() - - -@router.post("/sample", response_model=PostSampleResponse) -def post_sample( - request: Request, - sample: SampleData, - root=Security(get_root_tree, scopes=["write:data", "write:metadata"]), - principal: str = Depends(get_current_principal), -): - entry = root.authenticated_as(principal) - try: - uid = entry.post_sample(sample) - except AttributeError: - raise HTTPException( - status_code=404, detail="tree does not support posting sample metadata" - ) - - return json_or_msgpack(request, {"uid": uid}) - - -@router.delete("/sample/{uid}") -def delete_sample( - request: Request, - uid: str, - root=Security(get_root_tree, scopes=["write:data", "write:metadata"]), - principal: str = Depends(get_current_principal), -): - entry = root.authenticated_as(principal) - try: - entry.delete_sample(uid) - except AttributeError: - raise HTTPException( - status_code=404, detail="tree does not support deleting sample metadata" - ) - - return json_or_msgpack(request, None) - - -@router.get("/sample") -def get_sample(): - pass diff --git a/aimmdb/server/router_tiled.py b/aimmdb/server/router_tiled.py deleted file mode 100644 index 7903e0c..0000000 --- a/aimmdb/server/router_tiled.py +++ /dev/null @@ -1,4 +0,0 @@ -# place for routes to be upstreamed into tiled -from fastapi import APIRouter - -router = APIRouter() diff --git a/aimmdb/utils.py b/aimmdb/utils.py index 6da7eab..eb7da3e 100644 --- a/aimmdb/utils.py +++ b/aimmdb/utils.py @@ -11,7 +11,9 @@ def make_dict(x): if isinstance(x, pydantic.BaseModel): return {k: make_dict(v) for k, v in x} elif dataclasses.is_dataclass(x): - return {f.name: make_dict(getattr(x, f.name)) for f in dataclasses.fields(x)} + return { + f.name: make_dict(getattr(x, f.name)) for f in dataclasses.fields(x) + } else: return x @@ -68,7 +70,10 @@ def get_share_aimmdb_path(): while path != "/": share_tiled = join(path, "share", "aimmdb") if exists( - join(share_tiled, ".identifying_file_5fde776bf5ee64081be861ce6f02490b") + join( + share_tiled, + ".identifying_file_5fde776bf5ee64081be861ce6f02490b", + ) ): # We have the found the right directory, # or one that is trying very hard to pretend to be! diff --git a/aimmdb/validation.py b/aimmdb/validation.py index ae07c45..9a05643 100644 --- a/aimmdb/validation.py +++ b/aimmdb/validation.py @@ -6,7 +6,9 @@ def validate_xas_metadata(metadata, structure_family, structure, spec): if structure_family != "dataframe": - raise ValidationError(f"structure_family {structure_family} != dataframe") + raise ValidationError( + f"structure_family {structure_family} != dataframe" + ) try: metadata = ExperimentalXASMetadata.parse_obj(metadata) except pydantic.ValidationError as e: diff --git a/deploy/local/config.yml b/deploy/local/config.yml index ef58025..fb292ec 100644 --- a/deploy/local/config.yml +++ b/deploy/local/config.yml @@ -1,15 +1,14 @@ trees: - path: / - tree: aimmdb.adapters.aimm:AIMMCatalog.from_uri - # tree: aimmdb.adapters.mongo:MongoAdapter.from_uri + tree: catalog args: - uri: mongodb://root:${MONGO_PASSWORD}@localhost:27018/aimm?authSource=admin - data_directory: ./data - dataset_to_specs: - nmc: - - XAS_TFY - - XAS_TEY - - XAS_trans + uri: ./catalog.db + writable_storage: /data/aimm/data + # dataset_to_specs: + # ncm: + # - XAS_TFY + # - XAS_TEY + # - XAS_trans access_control: access_policy: aimmdb.access:DatasetAccessPolicy args: @@ -31,7 +30,12 @@ authentication: tiled_admins: - provider: toy id: joe -validation: - XAS_TFY: aimmdb.validation:validate_xas_tfy - XAS_TEY: aimmdb.validation:validate_xas_tey - XAS_trans: aimmdb.validation:validate_xas_transmission +# specs: +# - spec: XAS_TFY +# validator: aimmdb.validation:validate_xas_tfy +# - spec: XAS_TEY +# validator: aimmdb.validation:validate_xas_tey +# - spec: XAS_trans +# validator: aimmdb.validation:validate_xas_transmission +# - spec: HasBatteryChargeData +# validator: aimmdb.validation:validate_battery_charge_data diff --git a/deploy/spin/config/config.yml b/deploy/spin/config/config.yml index c84c174..6b0501a 100644 --- a/deploy/spin/config/config.yml +++ b/deploy/spin/config/config.yml @@ -1,82 +1,51 @@ trees: - path: / - tree: aimmdb.adapters.aimm:AIMMCatalog.from_uri + tree: catalog args: - uri: mongodb://root:${MONGO_PASSWORD}@mongodb:27017/aimm?authSource=admin - data_directory: /data - dataset_to_specs: - ncm: - - XAS_TFY - - XAS_TEY - - XAS_trans - newville: - - XAS + uri: postgresql+asyncpg://tiled:${TILED_DATABASE_PASSWORD}@postgres/tiled + writable_storage: /data/aimm/data + # dataset_to_specs: + # ncm: + # - XAS_TFY + # - XAS_TEY + # - XAS_trans access_control: - access_policy: aimmdb.access:DatasetAccessPolicy + access_policy: tiled.access_policies:SimpleAccessPolicy args: provider: orcid access_lists: - 0000-0003-3670-0431: # Joe - default: rw - 0000-0002-5947-6017: # Dan - default: r - sandbox: rw - samples: rw - 0000-0002-1539-0297: # Dylan - default: r - sandbox: rw - samples: rw - 0000-0002-3337-2930: # Eli - default: r - sandbox: rw - samples: rw - 0000-0002-5269-0125: # Alex - default: r - sandbox: rw - samples: rw - 0000-0003-4351-6085: # Deyu - default: r - sandbox: rw - samples: rw - 0000-0003-0666-8063: # Wanli - default: r - sandbox: rw - samples: rw - 0000-0001-5266-5408: # Zhu - default: r - sandbox: rw - samples: rw - 0000-0002-2473-0193: # Juan - default: rw - sandbox: rw - samples: rw - 0000-0003-0922-1363: # Maria - default: r - sandbox: rw - samples: rw - 0000-0002-5181-9513: # Matt - default: r - sandbox: rw - samples: rw - 0000-0001-5651-8405: # Xiaohui - default: r - sandbox: rw - samples: rw - 0000-0001-9869-9005: # Fanchen - default: r - sandbox: rw - samples: rw - public: - newville: r + 0000-0002-5947-6017: tiled.access_policies:ALL_ACCESS # Dan + 0000-0002-1539-0297: tiled.access_policies:ALL_ACCESS # Dylan + 0000-0002-3337-2930: tiled.access_policies:ALL_ACCESS # Eli + 0000-0002-5269-0125: tiled.access_policies:ALL_ACCESS # Alex + 0000-0003-4351-6085: tiled.access_policies:ALL_ACCESS # Deyu + 0000-0003-0666-8063: tiled.access_policies:ALL_ACCESS # Wanli + 0000-0001-5266-5408: tiled.access_policies:ALL_ACCESS # Zhu + 0000-0002-2473-0193: tiled.access_policies:ALL_ACCESS # Juan + 0000-0003-0922-1363: tiled.access_policies:ALL_ACCESS # Maria + 0000-0002-5181-9513: tiled.access_policies:ALL_ACCESS # Matt + 0000-0001-5651-8405: tiled.access_policies:ALL_ACCESS # Xiaohui + 0000-0001-9869-9005: tiled.access_policies:ALL_ACCESS # Fanchen + 0000-0003-1779-8007: tiled.access_policies:ALL_ACCESS # Mikhail + 0000-0001-8885-1552: tiled.access_policies:ALL_ACCESS # Inhui + 0000-0003-2516-2586: tiled.access_policies:ALL_ACCESS # Gihyeok + admins: + - 0000-0002-5947-6017 # Dan + - 0000-0002-1539-0297 # Dylan + - 0000-0002-2473-0193 # Juan + public: + - newville + - nmc_sim + - nmc_sim_structure authentication: allow_anonymous_access: true providers: - provider: orcid - authenticator: aimmdb.authentication:AIMMAuthenticator + authenticator: tiled.authenticators:OIDCAuthenticator args: client_id: ${ORCID_CLIENT_ID} client_secret: ${ORCID_CLIENT_SECRET} - redirect_uri: https://aimm.lbl.gov/api/auth/provider/orcid/login + # redirect_uri: https://aimm.lbl.gov/api/auth/provider/orcid/login public_keys: - kty: "RSA" e: "AQAB" @@ -90,15 +59,15 @@ authentication: tiled_admins: - provider: orcid id: 0000-0003-3670-0431 -database: - uri: "postgresql://tiled:${TILED_DATABASE_PASSWORD}@postgres/tiled" - pool_size: 5 uvicorn: host: 0.0.0.0 port: 8000 -validation: - XAS: aimmdb.validation:validate_xas_metadata - XAS_TFY: aimmdb.validation:validate_xas_tfy - XAS_TEY: aimmdb.validation:validate_xas_tey - XAS_trans: aimmdb.validation:validate_xas_transmission - HasBatteryChargeData: aimmdb.validation:validate_battery_charge_data +# specs: +# - spec: XAS_TFY +# validator: aimmdb.validation:validate_xas_tfy +# - spec: XAS_TEY +# validator: aimmdb.validation:validate_xas_tey +# - spec: XAS_trans +# validator: aimmdb.validation:validate_xas_transmission +# - spec: HasBatteryChargeData +# validator: aimmdb.validation:validate_battery_charge_data diff --git a/deploy/spin/docker/tiled/Dockerfile b/deploy/spin/docker/tiled/Dockerfile deleted file mode 100644 index 880548e..0000000 --- a/deploy/spin/docker/tiled/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM ghcr.io/bluesky/tiled:v0.1.0a74 as base - -FROM base as builder - -WORKDIR /build -COPY . . -RUN pip install . - -FROM base as app -COPY --from=builder $VIRTUAL_ENV $VIRTUAL_ENV -COPY deploy/spin/docker/tiled/gunicorn_config.py . -ENV GUNICORN_CONF="/deploy/gunicorn_config.py" diff --git a/deploy/spin/docker/tiled/gunicorn_config.py b/deploy/spin/docker/tiled/gunicorn_config.py deleted file mode 100644 index ef407c7..0000000 --- a/deploy/spin/docker/tiled/gunicorn_config.py +++ /dev/null @@ -1,11 +0,0 @@ -bind = "0.0.0.0:8000" -workers = 4 -worker_class = "uvicorn.workers.UvicornWorker" -worker_connections = 1000 -timeout = 60 -keepalive = 2 -wsgi_app = "tiled.server.app:app_factory()" -worker_tmp_dir = "/dev/shm" -errorlog = "-" -accesslog = "-" -loglevel = "warning" diff --git a/deploy/spin/k8s/backup-db.sh b/deploy/spin/k8s/backup-db.sh new file mode 100755 index 0000000..e7a6153 --- /dev/null +++ b/deploy/spin/k8s/backup-db.sh @@ -0,0 +1,3 @@ +# This doesn't work yet, but it's a start...the pod name is the name of deployment, not the actual pod + +rancher kubectl exec postgres-backup -n aimm -- bash -c "pg_dump postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres/tiled > /backup/database.sql" \ No newline at end of file diff --git a/deploy/spin/k8s/ingress.yaml b/deploy/spin/k8s/ingress.yaml new file mode 100644 index 0000000..b9826cb --- /dev/null +++ b/deploy/spin/k8s/ingress.yaml @@ -0,0 +1,31 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: tiled + namespace: aimm +spec: + rules: + - host: tiled-ingress.aimm.production.svc.spin.nersc.org + http: + paths: + - backend: + service: + name: tiled + port: + number: 8000 + path: / + pathType: ImplementationSpecific + - host: aimm.lbl.gov + http: + paths: + - backend: + service: + name: tiled + port: + number: 8000 + path: / + pathType: ImplementationSpecific + tls: + - hosts: + - aimm.lbl.gov + secretName: aimm diff --git a/deploy/spin/k8s/postgres-backup.yaml b/deploy/spin/k8s/postgres-backup.yaml new file mode 100644 index 0000000..1346b29 --- /dev/null +++ b/deploy/spin/k8s/postgres-backup.yaml @@ -0,0 +1,75 @@ +## Evantualy this will be a chron job to backup regularly. However, this +## is not super necessary given how few updates the aimmdb will likely receive + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres-backup + namespace: aimm +spec: + selector: + matchLabels: + workload.user.cattle.io/workloadselector: deployment-aimm-postgres-backup + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + type: RollingUpdate + template: + metadata: + labels: + workload.user.cattle.io/workloadselector: deployment-aimm-postgres-backup + spec: + containers: + - env: + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + - name: POSTGRES_USER + value: postgres + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: postgrespass + optional: false + command: + - "sleep" + - "999999" + image: postgres:14 + imagePullPolicy: Always + name: postgres + resources: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + privileged: false + readOnlyRootFilesystem: false + runAsNonRoot: true + runAsUser: 79966 + stdin: true + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + tty: true + volumeMounts: + - mountPath: /var/lib/postgresql/data + name: postgres-data-pv + - mountPath: /backup + name: db-backup + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: + fsGroup: 94721 + terminationGracePeriodSeconds: 30 + volumes: + - name: postgres-data-pv + persistentVolumeClaim: + claimName: postrgres-pvc + - hostPath: + path: /global/cfs/projectdirs/m3792/aimm/backup + type: Directory + name: db-backup diff --git a/deploy/spin/k8s/postgres.yaml b/deploy/spin/k8s/postgres.yaml new file mode 100644 index 0000000..02dd87b --- /dev/null +++ b/deploy/spin/k8s/postgres.yaml @@ -0,0 +1,95 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres + namespace: aimm +spec: + selector: + matchLabels: + workload.user.cattle.io/workloadselector: deployment-aimm-postgres + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 0 + type: RollingUpdate + template: + metadata: + labels: + workload.user.cattle.io/workloadselector: deployment-aimm-postgres + spec: + containers: + - env: + - name: PGDATA + value: /var/lib/postgresql/data/pgdata + - name: POSTGRES_USER + value: postgres + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: postgrespass + optional: false + # command: + # - "sleep" + # - "999999" + image: postgres:14 + imagePullPolicy: Always + name: postgres + resources: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + privileged: false + readOnlyRootFilesystem: false + runAsNonRoot: true + runAsUser: 79966 + stdin: true + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + tty: true + volumeMounts: + - mountPath: /var/lib/postgresql/data + name: postgres-data-pv + # - mountPath: /backup + # name: db-backup + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: + fsGroup: 94721 + terminationGracePeriodSeconds: 30 + volumes: + - name: postgres-data-pv + persistentVolumeClaim: + claimName: postrgres-pvc + # - hostPath: + # path: /global/cfs/projectdirs/m3792/aimm/backup + # type: Directory + # name: db-backup +--- +apiVersion: v1 +kind: Service +metadata: + name: postgres + namespace: aimm +spec: + clusterIP: None + clusterIPs: + - None + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: default + port: 42 + protocol: TCP + targetPort: 42 + selector: + workload.user.cattle.io/workloadselector: deployment-aimm-postgres + sessionAffinity: None + type: ClusterIP diff --git a/deploy/spin/k8s/tiled.yaml b/deploy/spin/k8s/tiled.yaml new file mode 100644 index 0000000..686766a --- /dev/null +++ b/deploy/spin/k8s/tiled.yaml @@ -0,0 +1,147 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tiled + namespace: aimm +spec: + selector: + matchLabels: + workload.user.cattle.io/workloadselector: deployment-aimm-tiled + template: + metadata: + labels: + workload.user.cattle.io/workloadselector: deployment-aimm-tiled + spec: + affinity: {} + containers: + - command: + - sleep + - "999999" + # - command: + # - tiled + # - serve + # - config + env: + - name: ORCID_CLIENT_ID + value: APP-0ROS9DU5F717F7XN + - name: TILED_CONFIG + value: /config/main + - name: TILED_INTERNAL_CACHE_LOG_LEVEL + value: INFO + - name: ORCID_CLIENT_SECRET + valueFrom: + secretKeyRef: + key: ORCID_CLIENT_SECRET + name: tiled + optional: false + - name: TILED_SERVER_SECRET_KEYS + valueFrom: + secretKeyRef: + key: TILED_SERVER_SECRET_KEYS + name: tiled + optional: false + - name: TILED_DATABASE_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: postgres-tiled-pass + optional: false + image: ghcr.io/bluesky/tiled:v0.1.0a111 + imagePullPolicy: Always + name: tiled + resources: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + privileged: false + readOnlyRootFilesystem: false + runAsNonRoot: true + runAsUser: 79966 + stdin: true + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + tty: true + volumeMounts: + - mountPath: /deploy/config # mount config from the git-sync container + name: aimmdb-github + subPath: main/deploy/spin/config + readOnly: true + - mountPath: /data + name: tiled-data + # - mountPath: /opt/venv/share/tiled/templates/index.html CANNOT DO THIS UNTIL WE MERGE aimmdb PR + # name: aimmdb-github + # subPath: main/deploy/spin/web-frontend/templates/index.html + # readOnly: true + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: + fsGroup: 94721 + terminationGracePeriodSeconds: 30 + + + initContainers: + # A sidecar container that downloads current main from setttings github repo + # and places it into an emptydir volume. This gets picked up by tiled backend + # which mountains files + - name: git-sync + image: k8s.gcr.io/git-sync:v3.1.6 + env: + - name: GIT_SYNC_REPO + value: "https://github.com/AI-multimodal/aimmdb.git" + - name: GIT_SYNC_BRANCH + value: "main" + - name: GIT_SYNC_ROOT + value: "/aimmdb-github" + - name: GIT_SYNC_DEST + value: "main" + - name: GIT_SYNC_ONE_TIME + value: "true" + volumeMounts: + - name: aimmdb-github + readOnly: false + mountPath: /aimmdb-github + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_BIND_SERVICE + drop: + - ALL + privileged: false + readOnlyRootFilesystem: false + runAsNonRoot: true + runAsUser: 79966 + volumes: + - name: tiled-data + persistentVolumeClaim: + claimName: tiled-pvc + - name: aimmdb-github + emptyDir: +--- +apiVersion: v1 +kind: Service +metadata: + name: tiled + namespace: aimm +spec: + clusterIP: None + clusterIPs: + - None + internalTrafficPolicy: Cluster + ipFamilies: + - IPv4 + ipFamilyPolicy: SingleStack + ports: + - name: default + port: 8000 + protocol: TCP + targetPort: 8000 + selector: + workload.user.cattle.io/workloadselector: deployment-aimm-tiled + sessionAffinity: None + type: ClusterIP \ No newline at end of file diff --git a/deploy/spin/web-frontend/templates/index.html b/deploy/spin/web-frontend/templates/index.html new file mode 100644 index 0000000..1f0a3be --- /dev/null +++ b/deploy/spin/web-frontend/templates/index.html @@ -0,0 +1,67 @@ +{% extends "page.html" %} +{% block stylesheet %} +{{ super() }} + +{% endblock %} +{% block main %} +
$ pip install "tiled[client]"
+$ python
+>>> from tiled.client import from_uri
+>>> client = from_uri("{{ root_url }}")
+ {% if binder_link %}
+ Alternatively, try it in the cloud on Binder.
+ {% endif %}
+
+ The Tiled API can be accessed from any Internet-connected software,
+ including graphical programs that accept URLs and commandline
+ utilities like wget
and curl
.
+
+ For tutorials, guides, and more details, see Tiled's project documentation. +
+ ++ Like Jupyter Notebook, Tiled is something you can easily run yourself, on your laptop. + Tiled can also scale up for large multi-user deployment, like JupyterHub. +
+ + + +