diff --git a/notebooks/tel_and_site/subsys_req_ver/tma/SITCOM_2062_Rubin_Thermal_Retrieval.ipynb b/notebooks/tel_and_site/subsys_req_ver/tma/SITCOM_2062_Rubin_Thermal_Retrieval.ipynb new file mode 100644 index 00000000..93517a8a --- /dev/null +++ b/notebooks/tel_and_site/subsys_req_ver/tma/SITCOM_2062_Rubin_Thermal_Retrieval.ipynb @@ -0,0 +1,719 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e1311cfc", + "metadata": {}, + "source": [ + "## SITCOM-2062: Rubin thermal data retrieval\n", + "### Karla Peña Ramírez\n", + "May 7 2025" + ] + }, + { + "cell_type": "markdown", + "id": "372c01b3", + "metadata": {}, + "source": [ + "Here you can find the proposed code for data retrieval of either ComCam or LSSTCam temperature sensor data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d4128cf", + "metadata": {}, + "outputs": [], + "source": [ + "#Setting packages\n", + "import asyncio\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import pandas as pd\n", + "import os\n", + "import sys\n", + "import time\n", + "import warnings\n", + "import seaborn as sns\n", + "import datetime as dt\n", + "from scipy import stats\n", + "from matplotlib.dates import DateFormatter\n", + "from astropy.table import Table, join\n", + "from statsmodels.tsa.seasonal import seasonal_decompose\n", + "from sklearn.ensemble import IsolationForest\n", + "from sklearn.cluster import AgglomerativeClustering\n", + "from sklearn.preprocessing import StandardScaler\n", + "from sklearn.decomposition import PCA\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.linear_model import LinearRegression\n", + "from sklearn.preprocessing import StandardScaler\n", + "from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error\n", + "from sklearn.model_selection import cross_val_score\n", + "from scipy.cluster.hierarchy import dendrogram, linkage\n", + "from lsst.utils.packages import getEnvironmentPackages\n", + "from IPython.display import Markdown, display\n", + "#%matplotlib widget\n", + "\n", + "from astropy.time import Time, TimeDelta\n", + "from lsst_efd_client.efd_helper import merge_packed_time_series\n", + "from lsst.meas.algorithms.installGaussianPsf import FwhmPerSigma\n", + "from lsst.daf.butler import Butler \n", + "#from tqdm.notebook import tqdm\n", + "\n", + "\n", + "from sklearn.pipeline import Pipeline\n", + "from sklearn.base import BaseEstimator, TransformerMixin\n", + "from sklearn.linear_model import Ridge\n", + "from sklearn.model_selection import ShuffleSplit\n", + "import warnings\n", + "\n", + "# Ignore the many warning messages from ``merge_packed_time_series``\n", + "warnings.simplefilter(action=\"ignore\", category=FutureWarning)\n", + "\n", + "#-------Clients\n", + "from lsst_efd_client import EfdClient\n", + "client = EfdClient(\"usdf_efd\")\n", + "\n", + "#from lsst.summit.utils.efdUtils import makeEfdClient\n", + "#client = makeEfdClient()\n", + "\n", + "#from lsst.summit.utils import ConsDbClient\n", + "#os.environ[\"no_proxy\"] += \",.consdb\"\n", + "#url=\"http://consdb-pq.consdb:8080/consdb\"\n", + "#consdb=ConsDbClient(url)\n", + "#-------Clients\n", + "\n", + "def print_session_info():\n", + " # Time info\n", + " print(f\"# Session Info on {time.strftime('%Y-%m-%d at %H:%M:%S %Z', time.localtime(time.time()))}\\n\")\n", + "\n", + " # Python info\n", + " print(f\"## Python Interpreter\\n\\nVersion: {sys.version} \\nExecutable: {sys.executable}\\n\")\n", + "\n", + " # LSST info\n", + " packages = getEnvironmentPackages(True)\n", + " dev_packages = {\"lsst_distrib\": packages[\"lsst_distrib\"]}\n", + " dev_packages.update({k: v.split(\"@\")[0] for k, v in packages.items() if \"LOCAL\" in v})\n", + " print(\"## Science Pipelines\\n\\n\" + \"\\n\".join(f\"{k:<20} {v}\" for k, v in dev_packages.items()))" + ] + }, + { + "cell_type": "markdown", + "id": "7356504d", + "metadata": {}, + "source": [ + "## 1. Data retrievals. \n", + "Use either ComCam or LSSTCam on-sky temperature sensor data. We are going to use the image time stamps of the acquired images as a proxy of on-sky dome aperture.\n", + "### On-sky time ranges:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fcb9a0f6-0f24-43d5-8178-244bfbcc213e", + "metadata": {}, + "outputs": [], + "source": [ + "#Identify the repo where all the data lives and the latest consolidated processing collection\n", + "#Run > butler query-collections /repo/main \"*DRP*w_2025_0*\" | grep CHAINED\n", + "######ComCam\n", + "repo = '/repo/main'\n", + "instrument = \"LSSTComCam\"\n", + "collection = 'LSSTComCam/runs/DRP/DP1/w_2025_08/DM-49029'\n", + "#####LSSTCam\n", + "repo = '/repo/embargo'\n", + "instrument = \"LSSTCam\"\n", + "collection = 'LSSTCam/raw/all','LSSTCam/runs/nightlyValidation'\n", + "\n", + "butler = Butler(repo, collections=collection)\n", + "registry = butler.registry\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d248cd4a-f11e-4aa3-a290-920fc10dfe30", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "#Query the metadata for the **`exposure`** dimension, limiting the results to this particular instrument and range of days of observation:\n", + "######ComCam\n", + "instrument = 'LSSTComCam'\n", + "day_obs_start = 20241017\n", + "day_obs_end = 20241212\n", + "#####LSSTCam\n", + "instrument = 'LSSTCam'\n", + "day_obs_start = 20250415\n", + "day_obs_end = 20250427\n", + "\n", + "query=\"instrument='%s' AND day_obs>=%d AND day_obs<=%d\" % (instrument, day_obs_start, day_obs_end)\n", + "results = registry.queryDimensionRecords('exposure', where=query)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "937f6dfa-f741-4386-b49e-2f5537d3bd0d", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "#Taken from vv-team-notebooks/reports/TargetReport.ipynb\n", + "#Stop executing if there are no results returned:\n", + "n_results = results.count()\n", + "\n", + "if n_results <= 0:\n", + " raise StopExecution\n", + "else:\n", + " print(\"\"\"There are %d results returned from querying the butler for instrument %s between dates %d and %d (inclusive).\"\"\" % \n", + " (n_results, instrument, day_obs_start, day_obs_end))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f1aa6fd2-938e-4f1c-915a-89066f44c58f", + "metadata": {}, + "outputs": [], + "source": [ + "#Taken from vv-team-notebooks/reports/TargetReport.ipynb\n", + "#Instantiate a pandas `DataFrame` with useful columns available in the `exposure` dimension:\n", + "df_exp = pd.DataFrame(columns=['id', 'obs_id','day_obs', 'seq_num',\n", + " 'time_start','time_end' ,'type', 'reason', \n", + " 'target','filter','zenith_angle',\n", + " 'expos','ra','dec','skyangle',\n", + " 'azimuth','zenith','science_program',\n", + " 'jd','mjd'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7408f140-a0c0-4dee-9ece-84b50ccc2e86", + "metadata": {}, + "outputs": [], + "source": [ + "#Taken from vv-team-notebooks/reports/TargetReport.ipynb\n", + "#Read the query results into the new pandas `DataFrame`:\n", + "for count, info in enumerate(results):\n", + " \n", + " try:\n", + "\n", + " df_exp.loc[count] = [info.id, info.obs_id, info.day_obs, info.seq_num, \n", + " info.timespan.begin.utc.iso,\n", + " info.timespan.end.utc.iso, \n", + " info.observation_type, info.observation_reason, info.target_name, \n", + " info.physical_filter, info.zenith_angle, \n", + " info.exposure_time,info.tracking_ra, info.tracking_dec, \n", + " info.sky_angle,info.azimuth ,info.zenith_angle, \n", + " info.science_program, info.timespan.begin.jd, info.timespan.begin.mjd]\n", + "\n", + " except:\n", + " \n", + " print(\">>> Unexpected error:\", sys.exc_info()[0])\n", + " info_timespan_begin_to_string = \"2021-01-01 00:00:00.00\"\n", + " info_timespan_end_to_string = \"2051-01-01 00:00:00.00\"\n", + " info_timespan_begin_jd = 0\n", + " info_timespan_begin_mjd = 0\n", + " df_exp.loc[count] = [info.id, info.obs_id, info.day_obs, info.seq_num, \n", + " pd.to_datetime(info_timespan_begin_to_string),\n", + " pd.to_datetime(info_timespan_end_to_string), \n", + " info.observation_type, info.observation_reason, info.target_name, \n", + " info.physical_filter, info.zenith_angle, \n", + " info.exposure_time,info.tracking_ra, info.tracking_dec, \n", + " info.sky_angle,info.azimuth ,info.zenith_angle, \n", + " info.science_program, info_timespan_begin_jd, info_timespan_begin_mjd ] " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a994dc4-d683-40ca-95c7-8fcae371fcbe", + "metadata": {}, + "outputs": [], + "source": [ + "#Taken from vv-team-notebooks/reports/TargetReport.ipynb\n", + "#Clean-up the dataframe\n", + "#Re-cast the `id`, `day_obs`, and `seq_num` rows as `int`'s:\n", + "df_exp = df_exp.astype({\"id\": int,'day_obs': int,'seq_num':int})\n", + "# Replace `NaN`'s in the `ra` and `dec` columns with zero. \n", + "df_exp['ra'] = df_exp['ra'].fillna(0)\n", + "df_exp['dec'] = df_exp['dec'].fillna(0)\n", + "#Select only on-sky data\n", + "df_exp.type.unique()\n", + "df_open = df_exp[(df_exp.type == 'science') | (df_exp.type == 'cwfs') | (df_exp.type == 'focus') | (df_exp.type == 'acq')| (df_exp.type == 'flat')]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f357627b-a347-45db-951d-c6058aaec694", + "metadata": {}, + "outputs": [], + "source": [ + "#Group data by dayobs identifying the extremme dates for the exposures.\n", + "result_on_sky = df_open.groupby('day_obs').agg({\n", + " 'time_start': 'min',\n", + " 'time_end': 'max'\n", + "}).reset_index()" + ] + }, + { + "cell_type": "markdown", + "id": "eb4ae5cc-ff2f-4382-b0da-d99e2305865e", + "metadata": { + "execution": { + "iopub.execute_input": "2025-04-06T17:21:16.581011Z", + "iopub.status.busy": "2025-04-06T17:21:16.580657Z", + "iopub.status.idle": "2025-04-06T17:21:16.583441Z", + "shell.execute_reply": "2025-04-06T17:21:16.583064Z", + "shell.execute_reply.started": "2025-04-06T17:21:16.580993Z" + } + }, + "source": [ + "### Telemetry retrieval:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dce96726-b6ab-4ba5-9aed-4d598b825028", + "metadata": {}, + "outputs": [], + "source": [ + "def read_time_data():\n", + " df = result_on_sky\n", + " df['time_start'] = pd.to_datetime(df['time_start'])\n", + " df['time_end'] = pd.to_datetime(df['time_end'])\n", + " return df\n", + " \n", + "def get_time_range(df, day_obs):\n", + " day_data = df[df['day_obs'] == day_obs].iloc[0]\n", + " return day_data['time_start'], day_data['time_end']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b157e616-07f3-40f8-b58e-a396ebb50d19", + "metadata": {}, + "outputs": [], + "source": [ + "async def get_dynalene_data(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get dynalene data for a specific day_obs.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " \n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(dynTMAsupTS01) AS TMA_Supply_Dynalene, \n", + " mean(dynTMAretTS02) AS TMA_Return_Dynalene, \n", + " mean(dynCH01supTS05) AS TMA_Chiller_1\n", + " FROM \"lsst.sal.HVAC.dynaleneP05\" \n", + " WHERE time > '{start_time.isoformat()}Z' \n", + " AND time < '{end_time.isoformat()}Z' \n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results)\n", + "\n", + "\n", + "async def get_dynalene_mtmount(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get MTMount dynalene data for a specific day_obs.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " \n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(dynaleneTemperatureAzimuth0001) AS TMA_Azimuth_1,\n", + " mean(dynaleneTemperatureAzimuth0002) AS TMA_Azimuth_2,\n", + " mean(dynaleneTemperaturePier0102) AS TMA_Pier_2\n", + " FROM \"lsst.sal.MTMount.dynaleneCooling\"\n", + " WHERE time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results)\n", + "\n", + "\n", + "async def get_ess_1(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get ESS temperature data for CamHex and CamRot.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " \n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(temperatureItem0) AS CamHex_Strut_7,\n", + " mean(temperatureItem1) AS CamHex_Strut_8,\n", + " mean(temperatureItem2) AS CamHex_Strut_9,\n", + " mean(temperatureItem3) AS CamHex_Strut_10,\n", + " mean(temperatureItem4) AS CamHex_Strut_11,\n", + " mean(temperatureItem5) AS CamHex_Strut_12,\n", + " mean(temperatureItem6) AS CamRot_Motor_1,\n", + " mean(temperatureItem7) AS CamRot_Motor_2\n", + " FROM \"lsst.sal.ESS.temperature\"\n", + " WHERE salIndex = 1\n", + " AND time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results)\n", + "\n", + "\n", + "async def get_ess_106(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get ESS temperature data for M2 Tangent Links.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " \n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(temperatureItem0) AS M2_Tangent_Link_A1,\n", + " mean(temperatureItem1) AS M2_Tangent_Link_A2,\n", + " mean(temperatureItem2) AS M2_Tangent_Link_A3,\n", + " mean(temperatureItem3) AS M2_Tangent_Link_A4,\n", + " mean(temperatureItem4) AS M2_Tangent_Link_A5,\n", + " mean(temperatureItem5) AS M2_Tangent_Link_A6\n", + " FROM \"lsst.sal.ESS.temperature\"\n", + " WHERE salIndex = 106\n", + " AND time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results)\n", + "\n", + "async def get_ess_112(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get ESS temperature data for M2.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " \n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(temperatureItem0) AS ESS_112_M2\n", + " FROM \"lsst.sal.ESS.temperature\"\n", + " WHERE salIndex = 112\n", + " AND time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results)\n", + "\n", + "\n", + "async def get_ess_111(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get ESS temperature data for Camera.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " \n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(temperatureItem0) AS ESS_111_Camera\n", + " FROM \"lsst.sal.ESS.temperature\"\n", + " WHERE salIndex = 111\n", + " AND time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results)\n", + "\n", + "\n", + "async def get_ess_113(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get ESS temperature data for Dome.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " \n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(temperatureItem0) AS ESS_113_Dome\n", + " FROM \"lsst.sal.ESS.temperature\"\n", + " WHERE salIndex = 113\n", + " AND time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results)\n", + "\n", + "\n", + "async def get_ess_301(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get ESS temperature data for Outside Dome.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " \n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(temperatureItem0) AS Outside_Dome\n", + " FROM \"lsst.sal.ESS.temperature\"\n", + " WHERE salIndex = 301\n", + " AND time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results)\n", + "\n", + "\n", + "async def get_mtmount_topend_chiller(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get MTMount TopEndChiller temperature data.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " \n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(temperatureSensor0501) AS Temperature_0501,\n", + " mean(ambientTemperatureSensor0502) AS Ambient_0502,\n", + " mean(ductTemperatureSensor0506) AS Duct_0506,\n", + " mean(ductTemperatureSensor0507) AS Duct_0507,\n", + " mean(internalTemperatureElectricalCabinet0) AS Internal_Cabinet_0,\n", + " mean(internalTemperatureElectricalCabinet1) AS Internal_Cabinet_1,\n", + " mean(externalTemperatureElectricalCabinet1) AS External_Cabinet_1,\n", + " mean(internalTemperatureElectricalCabinet3) AS Internal_Cabinet_3,\n", + " mean(externalTemperatureElectricalCabinet3) AS External_Cabinet_3\n", + " FROM \"lsst.sal.MTMount.topEndChiller\"\n", + " WHERE time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results)\n", + "\n", + "\n", + "async def get_m2_temps(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get M2 temperature data.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " \n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(intake0) as M2_Intake0,\n", + " mean(intake1) as M2_Intake1,\n", + " mean(exhaust0) as M2_Exhaust0,\n", + " mean(exhaust1) as M2_Exhaust1,\n", + " mean(ring5) as M2_ring\n", + " FROM \"lsst.sal.MTM2.temperature\"\n", + " WHERE time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results)\n", + "\n", + "\n", + "async def get_m1m3_glycol(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get M1M3 glycol temperature data.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " \n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(telescopeCoolantReturnTemperature) as TMA_Coolant_Retun,\n", + " mean(telescopeCoolantSupplyTemperature) as TMA_Coolant_Supply,\n", + " mean(mirrorCoolantSupplyTemperature) as M1M3_Coolant_Supply,\n", + " mean(mirrorCoolantReturnTemperature) as M1M3_Coolant_Return,\n", + " mean(insideCellTemperature1) as Interior_Cell_1,\n", + " mean(insideCellTemperature2) as Interior_Cell_2,\n", + " mean(insideCellTemperature3) as Interior_Cell_3\n", + " FROM \"lsst.sal.MTM1M3TS.glycolLoopTemperature\"\n", + " WHERE time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results)\n", + "\n", + "\n", + "async def get_m1m3_fcu(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get M1M3 FCU temperature data.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " \n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(\"absoluteTemperature20\") AS \"FCU20\",\n", + " mean(\"absoluteTemperature50\") AS \"FCU50\",\n", + " mean(\"absoluteTemperature80\") AS \"FCU80\"\n", + " FROM \"lsst.sal.MTM1M3TS.thermalData\"\n", + " WHERE time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results) \n", + "\n", + "\n", + "async def get_glycolMTMount(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get MTMount glycol general purpose temperature data.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(glycolTemperaturePier0001) AS General_Glycol_L6_1,\n", + " mean(glycolTemperaturePier0002) AS General_Glycol_L6_2\n", + " FROM \"lsst.sal.MTMount.generalPurposeGlycolWater\" \n", + " WHERE time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results) \n", + "\n", + "\n", + "async def get_coldglycolMTMount(client, day_obs, sampling=\"1h\"):\n", + " \"\"\"Get MTMount cold glycol temperature data.\"\"\"\n", + " df = read_time_data()\n", + " start_time, end_time = get_time_range(df, int(day_obs))\n", + " query = f\"\"\"\n", + " SELECT \n", + " mean(glycolTemperaturePier0101) AS Cold_Glycol_L6\n", + " FROM \"lsst.sal.MTMount.cooling\" \n", + " WHERE time > '{start_time.isoformat()}Z'\n", + " AND time < '{end_time.isoformat()}Z'\n", + " GROUP BY time({sampling})\n", + " \"\"\"\n", + " results = await client.influx_client.query(query)\n", + " return pd.DataFrame(results) \n" + ] + }, + { + "cell_type": "markdown", + "id": "55591f4d-3bdb-4e04-85b7-9e1af4dde5de", + "metadata": {}, + "source": [ + "### Usage:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a39dc7ab-1f54-4749-a1c1-ff5978b5c555", + "metadata": {}, + "outputs": [], + "source": [ + "#Single day data:\n", + "sampling = '1m'\n", + "day_to_check = '202nnnnn' #Example: 20250430\n", + "\n", + "#Dynalene data\n", + "dynalene = await get_dynalene_data(client, sampling = sampling, day_obs=day_to_check)\n", + "dynaleneMTMount = await get_dynalene_mtmount(client, sampling = sampling, day_obs=day_to_check)\n", + "#ESS temperature data\n", + "ESS_1 = await get_ess_1(client, sampling = sampling, day_obs=day_to_check) # CamHex and CamRot\n", + "ESS_106 = await get_ess_106(client, sampling = sampling, day_obs=day_to_check) # M2 Tangent Links\n", + "ESS_112 = await get_ess_112(client, sampling = sampling, day_obs=day_to_check) # M2\n", + "ESS_111 = await get_ess_111(client, sampling = sampling, day_obs=day_to_check) # Camera\n", + "ESS_113 = await get_ess_113(client, sampling = sampling, day_obs=day_to_check) # Dome\n", + "ESS_301 = await get_ess_301(client, sampling = sampling, day_obs=day_to_check) # Outside Dome\n", + "#MTMount TopEndChiller data\n", + "MTMountTopEndChiller = await get_mtmount_topend_chiller(client, sampling = sampling, day_obs=day_to_check)\n", + "#M2 temperature data\n", + "M2Temps = await get_m2_temps(client, sampling = sampling, day_obs=day_to_check)\n", + "#M1M3 data\n", + "M1M3_glycol = await get_m1m3_glycol(client, sampling = sampling, day_obs=day_to_check) # Glycol temperatures\n", + "M1M3_FCU = await get_m1m3_fcu(client, sampling = sampling, day_obs=day_to_check) # FCU temperatures\n", + "mask1 = M1M3_FCU['FCU20'] <= 100\n", + "mask2 = M1M3_FCU['FCU50'] <= 100\n", + "mask3 = M1M3_FCU['FCU80'] <= 100\n", + "M1M3_FCU_red1 = M1M3_FCU[mask1]\n", + "M1M3_FCU_red2 = M1M3_FCU[mask2]\n", + "M1M3_FCU_red3 = M1M3_FCU[mask3]\n", + "#Glycol\n", + "glycolMTMount = await get_glycolMTMount(client, sampling = sampling, day_obs=day_to_check)\n", + "coldglycolMTMount = await get_coldglycolMTMount(client, sampling = sampling, day_obs=day_to_check)\n", + "\n", + "#Single day\n", + "data_objects = [\n", + "M1M3_glycol['M1M3_Coolant_Return'],\n", + "M1M3_FCU_red1['FCU20'],\n", + "M1M3_FCU_red2['FCU50'],\n", + "M1M3_FCU_red3['FCU80'],\n", + "M1M3_glycol['Interior_Cell_3'],\n", + "M1M3_glycol['Interior_Cell_1'],\n", + "M1M3_glycol['Interior_Cell_2'],\n", + "ESS_301['Outside_Dome'],\n", + "ESS_106['M2_Tangent_Link_A6'],\n", + "ESS_106['M2_Tangent_Link_A2'],\n", + "ESS_106['M2_Tangent_Link_A4'],\n", + "MTMountTopEndChiller['External_Cabinet_3'],\n", + "MTMountTopEndChiller['Duct_0507'],\n", + "MTMountTopEndChiller['Ambient_0502'],\n", + "MTMountTopEndChiller['Duct_0506'],\n", + "M2Temps['M2_Exhaust0'],\n", + "M2Temps['M2_Intake1'],\n", + "M2Temps['M2_Exhaust1'],\n", + "M2Temps['M2_Intake0'],\n", + "MTMountTopEndChiller['Temperature_0501'],\n", + "ESS_113['ESS_113_Dome'],\n", + "MTMountTopEndChiller['External_Cabinet_1'],\n", + "ESS_112['ESS_112_M2'],\n", + "ESS_111['ESS_111_Camera'],\n", + "ESS_106['M2_Tangent_Link_A5'],\n", + "ESS_106['M2_Tangent_Link_A3'],\n", + "M2Temps['M2_ring'],\n", + "ESS_1['CamRot_Motor_1'], \n", + "ESS_1['CamRot_Motor_2'],\n", + "ESS_1['CamHex_Strut_11'],\n", + "ESS_1['CamHex_Strut_7'],\n", + "ESS_1['CamHex_Strut_8'],\n", + "ESS_1['CamHex_Strut_12'],\n", + "ESS_1['CamHex_Strut_9'],\n", + "ESS_1['CamHex_Strut_10'],\n", + "M1M3_glycol['TMA_Coolant_Supply'],\n", + "M1M3_glycol['TMA_Coolant_Retun'],\n", + "M1M3_glycol['M1M3_Coolant_Supply'],\n", + "MTMountTopEndChiller['Internal_Cabinet_0'],\n", + "MTMountTopEndChiller['Internal_Cabinet_1'],\n", + "MTMountTopEndChiller['Internal_Cabinet_3'],\n", + "dynaleneMTMount['TMA_Pier_2'],\n", + "dynalene['TMA_Return_Dynalene'],\n", + "dynaleneMTMount['TMA_Azimuth_2'],\n", + "dynalene['TMA_Chiller_1'],\n", + "dynaleneMTMount['TMA_Azimuth_1'],\n", + "dynalene['TMA_Supply_Dynalene'],\n", + "glycolMTMount['General_Glycol_L6_1'],\n", + "glycolMTMount['General_Glycol_L6_2'], \n", + "coldglycolMTMount['Cold_Glycol_L6']\n", + "]\n", + "\n", + "df = pd.concat(data_objects, axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a4a2e7f-bb0b-4557-a356-47e6785e308f", + "metadata": {}, + "outputs": [], + "source": [ + "#Reproducibility\n", + "print_session_info()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "LSST", + "language": "python", + "name": "lsst" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.10" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}