{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\"SWAN\"\n", "\"EP-SFT\"\n", "

\n", "

Integration of SWAN with Spark clusters

\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The current setup allows to execute PySpark operations on CERN Hadoop and Spark clusters. \n", "\n", "This notebook illustrates the use of __Spark in SWAN to access CERN Accelerator logging service data__." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Connect to the cluster (NXCals)\n", "In the SWAN configuration menu:\n", "- Choose the NXCals project software stack\n", "- Choose the NXCals Hadoop cluster" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To connect to a cluster, click on the star button on the top and follow the instructions\n", "* The star button only appears if you have selected a SPARK cluster in the configuration\n", "* The star button is active after the notebook kernel is ready\n", "* SELECT NXCALS configuration bundle\n", "* Access to the cluster and NXCALS data is controlled by acc-logging-team, please contact acc-logging-team@cern.ch\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# NXCals DataExtraction API - Examples\n", "See NXCals API documentation at: http://nxcals-docs.web.cern.ch/current/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1) Extract data using device/property pairs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Inspect data" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "23/03/12 21:18:01 WARN URLConfigurationSource: No URLs will be polled as dynamic configuration sources.\n" ] } ], "source": [ "# source the nxcals query builders\n", "from nxcals.api.extraction.data.builders import *\n", "\n", "# define the extraction Spark DataFrame using the NXCALS API\n", "# see also \n", "df1 = ( DevicePropertyDataQuery.builder(spark)\n", " .system('CMW')\n", " .startTime('2022-11-01 00:00:00.000')\n", " .endTime('2022-11-02 00:00:00.000')\n", " .entity()\n", " .device('RADMON.PS-10')\n", " .property('ExpertMonitoringAcquisition')\n", " .build()\n", " )" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "root\n", " |-- PinDiodeVoltageOutOfRange: boolean (nullable = true)\n", " |-- Radfet1VoltageOutOfRange: boolean (nullable = true)\n", " |-- Radfet2VoltageOutOfRange: boolean (nullable = true)\n", " |-- __record_timestamp__: long (nullable = true)\n", " |-- __record_version__: long (nullable = true)\n", " |-- acqStamp: long (nullable = true)\n", " |-- class: string (nullable = true)\n", " |-- current_18V: double (nullable = true)\n", " |-- current_8V5: double (nullable = true)\n", " |-- current_memBanks: double (nullable = true)\n", " |-- current_radfet: double (nullable = true)\n", " |-- cyclestamp: long (nullable = true)\n", " |-- device: string (nullable = true)\n", " |-- property: string (nullable = true)\n", " |-- pt100Value: double (nullable = true)\n", " |-- selector: string (nullable = true)\n", " |-- temperatureDeported: double (nullable = true)\n", " |-- temperatureSensorBoard: double (nullable = true)\n", " |-- voltage_18V: double (nullable = true)\n", " |-- voltage_3V3: double (nullable = true)\n", " |-- voltage_3VNeg: double (nullable = true)\n", " |-- voltage_5V: double (nullable = true)\n", " |-- voltage_memoryBank2: double (nullable = true)\n", " |-- voltage_sensorAdcRef: double (nullable = true)\n", " |-- warningBits: integer (nullable = true)\n", " |-- nxcals_entity_id: long (nullable = true)\n", "\n" ] } ], "source": [ "df1.printSchema()" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+-------------------+------------------+------------------+------------+------------------+\n", "| acqStamp| voltage_18V| current_18V| device| pt100Value|\n", "+-------------------+------------------+------------------+------------+------------------+\n", "|1667260801078283000| null| null|RADMON.PS-10| 109.4169887|\n", "|1667260802078290000| null| 44.00730505585671|RADMON.PS-10|109.29791806000001|\n", "|1667260803078315000| 20.02644650638104|44.098701328039176|RADMON.PS-10|109.08954444000001|\n", "|1667260805078360000| 20.02644650638104| 44.1291667521|RADMON.PS-10|108.70256486000001|\n", "|1667260807078387000|20.024923235177997|44.464286416769035|RADMON.PS-10| 109.49140785|\n", "|1667260808078408000| null| 44.02253776788712|RADMON.PS-10| 108.77698401|\n", "|1667260809078413000| null| 44.40335556864739|RADMON.PS-10| 108.76210018|\n", "|1667260811078467000|20.024923235177997| 44.38812285661698|RADMON.PS-10| null|\n", "|1667260812078480000| null|44.053003191947944|RADMON.PS-10| null|\n", "|1667260813078499000| null| null|RADMON.PS-10| 109.05977678|\n", "|1667260814078513000| 20.02796977758408| 44.00730505585671|RADMON.PS-10|108.68768103000001|\n", "|1667260815078547000|20.024923235177997| 44.38812285661698|RADMON.PS-10| 109.22349891|\n", "|1667260816078531000| null| 44.00730505585671|RADMON.PS-10| 108.95558997|\n", "|1667260817078565000| null| 44.40335556864739|RADMON.PS-10|109.53605934000001|\n", "|1667260820078616000| null| 44.11393404006959|RADMON.PS-10|108.97047380000001|\n", "|1667260821078618000| 20.02644650638104| null|RADMON.PS-10|108.73233252000001|\n", "|1667260822078631000| null| 43.97683963179589|RADMON.PS-10|109.53605934000001|\n", "|1667260823078639000| null|44.053003191947944|RADMON.PS-10|109.46164019000001|\n", "|1667260824078638000| null| 44.31195929646493|RADMON.PS-10| null|\n", "|1667260829078727000| 20.02644650638104| null|RADMON.PS-10|108.92582231000002|\n", "+-------------------+------------------+------------------+------------+------------------+\n", "only showing top 20 rows\n", "\n" ] } ], "source": [ "df1.select('acqStamp','voltage_18V','current_18V','device','pt100Value').show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Register the dataFrame as temporary table (myData) to write direct SQL queries." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "23/03/12 21:18:14 WARN package: Truncated the string representation of a plan since it was too large. This behavior can be adjusted by setting 'spark.sql.debug.maxToStringFields'.\n" ] } ], "source": [ "df1.createOrReplaceTempView(\"myData\")" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+-------------------+-------------------+\n", "| min(acqStamp)| max(acqStamp)|\n", "+-------------------+-------------------+\n", "|1667260800078284000|1667347199568841000|\n", "+-------------------+-------------------+\n", "\n" ] } ], "source": [ "# a simple select with min / max\n", "spark.sql(\"select min(acqStamp), max(acqStamp) from myData\").show()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+------------+--------+\n", "| device|count(1)|\n", "+------------+--------+\n", "|RADMON.PS-10| 86399|\n", "+------------+--------+\n", "\n" ] } ], "source": [ "# perform some aggregations\n", "spark.sql(\"select device, count(*) from myData group by device\").show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Draw a plot using matplotlib" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "23/03/12 21:18:29 WARN CheckAllocator: More than one DefaultAllocationManager on classpath. Choosing first found\n" ] } ], "source": [ "# Select the data columns of interest\n", "# fetch data into a Pandas dataframe for visualization\n", "import pandas as pd\n", "\n", "p_df = df1.select('acqStamp','current_18V').filter(\"current_18V is not null\").toPandas()\n" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA5MAAAF3CAYAAAA4pR80AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAB7OUlEQVR4nO3ddZwbdf7H8dd3re4GpbI1WtrSltKWGlKgAsWdQw445A44HG45rNgPPdzl6OF2QA8WrWE1WupG3d112+1+f39Msptsko1sZiP7fj4efTSZTGa++8lkMp/5mrHWIiIiIiIiIhKNjEQXQERERERERFKPkkkRERERERGJmpJJERERERERiZqSSREREREREYmakkkRERERERGJmpJJERERERERiVpWogsQTw0bNrS5ubmJLoaIiIiIiEhCTJkyZaO1tlFF7Cutksnc3FwmT56c6GKIiIiIiIgkhDFmWUXtS81cRUREREREJGpKJkVERERERCRqSiZFREREREQkamnVZzKY/fv3s3LlSvbu3ZvoolQ6VatWpVmzZmRnZye6KCIiIiIiEmdpn0yuXLmSWrVqkZubizEm0cWpNKy1bNq0iZUrV9KqVatEF0dEREREROIs7Zu57t27lwYNGiiRrGDGGBo0aKAaYRERERGRNJX2ySSgRDJBFHcRERERkfRVKZJJERERERERiS8lk2numWeeYffu3WWuc9ddd9G8eXNq1qzpt3z58uUMGDCAI444gi5duvD1118D0KpVK+bPn++37k033cTjjz8e38KLiIiIiEjSUjKZpA4cOFDm80hFkkyeeuqpTJo0KWD5Qw89xHnnncfUqVP58MMPufbaawG44IIL+PDDD4vXKyoq4tNPP+X888+PqYwiIiIikp52FRTyz89nsrOgMNFFERek/Wiuvu7/cjZzVm+P6zY7Nq3Nfad2KnOdt99+myeffBJjDF26dCEzM5NTTjmFc845B4CaNWuyc+dOxo4dy/3338/BBx/MtGnTeOmll/yez5w5k7y8PMaOHUtBQQHXXXcd11xzDWPHjmXYsGE0bNiQWbNmceSRR/Luu+/y/PPPs3r1agYMGEDDhg0ZM2ZM0PL17t076HJjDNu3O/Hatm0bTZs2BeDCCy/k/PPP57777gPgp59+Ijc3l5YtW8YUQxERERFJT//+ZQnvT1xOo5pVuHngoYkujsRZpUomE2H27Nk8/PDD/PrrrzRs2JDNmzdzyy23hFx/0qRJzJo1i1atWjF27Fi/56+99hp16tTht99+o6CggH79+jFo0CAApk6dyuzZs2natCn9+vXj119/5YYbbuCpp55izJgxNGzYMOqyDxs2jEGDBvH888+za9cuRo4cCUCXLl3IyMhg+vTpdO3alQ8//JALL7wwtgCJiIiISNoqss7/1trEFkRcUamSyXA1iG4YPXo055xzTnEyV79+/TLX79Wrl9+8jL7Pv//+e2bMmMGnn34KOLWFCxYsICcnh169etGsWTMAunXrxtKlS+nfv3+5yv7BBx9w2WWXceuttzJ+/HguueQSZs2aRUZGBhdeeCEffvghnTp1YsSIETzwwAPl2peIiIiIiKQW9Zl0mbU2YIqMrKwsioqKil/ft29f8Ws1atTwW9f3ubWW559/nmnTpjFt2jSWLFlSXDNZpUqV4vUyMzMpLCx/u/Q333yT8847D4A+ffqwd+9eNm7cCDhNXT/++GNGjhxJly5daNy4cbn3JyIiIpXTjr37ueTNiRQeKEp0USRKSzbuYuWWssfnkPSlZNJlJ5xwAh9//DGbNm0CYPPmzeTm5jJlyhQARowYwf79+yPa1uDBg3n55ZeL1//jjz/YtWtXme+pVasWO3bsiKnsLVq0YNSoUQDMnTuXvXv30qhRIwDatGlDgwYNyMvLUxNXERERKZfDh33Pzws20u+x0YkuikRpwJNj6f9Y8HE5JP0pmXRZp06duOuuuzj22GPp2rUrt9xyC1dddRU//vgjvXr1YuLEiQG1kaFceeWVdOzYke7du9O5c2euueaasDWQV199NSeddBIDBgwIuc4dd9xBs2bN2L17N82aNWPYsGEA/Otf/+L111+na9euXHjhhQwfPtyvlvXCCy9k3rx5nHnmmRGVX0RERKQs67YXJLoIIhIFk06dYXv06GEnT57st2zu3LkcdthhCSqRKP4iIiISTm5efvHjpY8OTWBJJFrezy7U5/bsyAU8PfIPbji+LbcMal+RRau0jDFTrLU9KmJfqpkUERERERGRqCmZrESOOuoounXr5vdv5syZiS6WiIiIpKHte/eTm5fPexOXlbne5l37ynxd3DV79TZy8/KZsmyz3/LTX/iF458cG7D+x7+tIDcvn627Az+3z6euJDcvn007S5or79l/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xfx9+dao3zNzVXTzWkJJv+7tewvJ+8zp/60zmoiIJAv9JiXRPJPGmKbGmK8TXY50U6QukyIShPpTi4iIlJOySXdHc/Wy1o4FxgZZnuvzeDVwcqTvFRERERERkcRJmppJERERERGRlKFOkxVTMymJM37xpkQXQUQqmRkrt5Gblx/1+/70+kSa1K4CwMotewJez83Lp1GtKuUun4iISFyomatqJt0Ubg5IERHxt257QaKLICIiIhFSMikiIiIiIiJRUzIpIiIiIiISJat2rkomRUQkdewLM7euiIiIVBwlkyIikjK27dmf6CKIiIiIh5JJERERERERiZqSSREREREREYmakkkRERERERGJmpJJERERERGRKFkN5qpkUkRERERERKKnZFJERERERESipmRSREREREREoqZkUkREREREJErGJLoEiadkUkRERERERKKmZFJERERERCRKGs1VyaSIiIiIiIjEQMmkiIiIiIiIRE3JpIiIiIiIiERNyaSIiIiIiEiU1GVSyaSIiIiIiEjUrEbgiSyZNMb0i2SZiIiIiIiIVA6R1kw+H+EyERERERERqQSyynrRGNMH6As0Msbc4vNSbSDTzYKJiIiIiIgkK2NMoouQcGUmk0AOUNOzXi2f5duBc9wqlIiIiIiIiCS3MpNJa+2PwI/GmOHW2mUVVCYRERERERFJcuFqJr2qGGNeA3J932OtPd6NQomIiIiIiCQzNXKNPJn8BHgFeAM44F5x0ouaUYuIiIiISLqKNJkstNa+7GpJREREREREUoRmmYx8apAvjTHXGmMONsbU9/5ztWQiIiIiIiKStCKtmfyz5//bfZZZoHV8iyMiIiIiIpL8rFXdZETJpLW2ldsFSUc6vkREREREJF1F1MzVGFPdGHO3Z0RXjDHtjDGnuFs0ERERERERSVaR9pl8C9gH9PU8Xwk85EqJREREREREJOlFmky2sdY+DuwHsNbuQVOriIiIiIhIJaUebZEnk/uMMdXwxMwY0wYocK1UIiIiIiIiktQiHc31PuBboLkx5j2gH3CZW4VKF0Z1tyIiIiIikqbCJpPGmAygHnAW0BuneeuN1tqNLpdNREREREREklTYZNJaW2SMud5a+zGQXwFlEhERERERSWqaBjDyPpM/GGNuM8Y0N8bU9/5ztWQiIiIiIiKStCLtM3mF5//rfJZZoHV8iyMiIiIiIiKpINI+k3nW2o8qoDwiIiIiIiJJT4NtRtDM1VpbhH+NpIiIiIiIiFRy6jMpIiIiIiIiUVOfSREREREREYlaRMmktbaV2wVJR0YNqUVERERE0pKmBokwmTTGXBpsubX27QjemwlMBlZZa0/xWX4b8ATQyFq7sdR7mgNvAwcBRcBr1tpnIymriIiIiIiIuC/SZq49fR5XBU4AfsdJ+MK5EZgL1PYu8CSLA4HlId5TCNxqrf3dGFMLmGKM+cFaOyfC8oqIiIiIiIiLIm3m+nff58aYOsA74d5njGkGDAUeBm7xeelp4A5gRIj9rQHWeB7vMMbMBQ4BlEyKiIiIiIgkgUhHcy1tN9AugvWewUkai7wLjDGn4TR5nR7JjowxucARwMSoSykiIiIiIiKuiLTP5Jc4o7eCk4B2BD4O855TgPXW2inGmOM8y6oDdwGDItxvTeC/wE3W2u0h1rkauBqgRYsWkWxWREREREREyqnMZNIY0xZoAjzps7gQyARWhdl2P+A0Y8zJOP0sa+M0jW0FTPeMdNoM+N0Y08tau7bUvrNxEsn3rLWfhdqJtfY14DWAHj16JNWYSlZDPImIiIiISJoK18z1GWCHtfZHn3+/4jRzfaasN1pr77TWNrPW5gIXAKOttWdbaxtba3M9y1cC3YMkkgZ4E5hrrX0qlj9MRERERERE3BMumcy11s4ovdBaOxnIjWdBjDFNjTFfe572Ay4BjjfGTPP8Ozme+6sImmdSRERERETSVbg+k1XLeK1apDux1o4FxgZZnuvzeDVwsufxL4AyMRERERERkSQVrmbyN2PMVaUXGmP+Akxxp0giIiIiIiKS7MLVTN4EfG6MuYiS5LEHkAOc6WK5REREREREJImVmUxaa9cBfY0xA4DOnsX51trRrpdMREREREREklZE80xaa8cAY1wui4iIiIiIiKSIcH0mRURERERERAIomRQREREREZGoKZkUERERERGRqCmZdJEmyhQRERERkXSlZFJERERERESipmRSREREREREoqZkUkRERERERKKmZFJERERERESipmRSREREREREoqZkUkRERERERKKmZFJERERERESipmRSREREREQidnq3pokugiQJJZMiIiIiklBLHx2a6CJIFM49snmiiyBJQsmki2yiCyAiIiIiIuISJZMiIiIiIhIxqyoT8VAyKSIi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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import matplotlib\n", "from matplotlib.ticker import FuncFormatter, MaxNLocator\n", "%matplotlib inline\n", "\n", "data = p_df.sort_values(by='acqStamp')\n", "\n", "def format_fn(tick_val, tick_pos):\n", " return pd.to_datetime(tick_val,unit='ns')\n", "\n", "myplot=data.plot(x='acqStamp',y='current_18V', figsize=(15,5))\n", "myplot.set_xlabel('Time')\n", "myplot.set_ylabel('Current')\n", "\n", "myplot.xaxis.set_major_formatter(FuncFormatter(format_fn))\n", "myplot.xaxis.set_major_locator(MaxNLocator(integer=True))\n", "myplot.tick_params(axis='x', which='major', labelsize='small', labelcolor='r', rotation=45)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2) Read TGM data" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "# Map data extraction to a Spark DataFrame using the NXCALS API\n", "tgmData = ( DevicePropertyDataQuery.builder(spark)\n", " .system('CMW')\n", " .startTime('2022-11-01 00:00:00.000')\n", " .endTime('2022-11-02 00:00:00.000')\n", " .entity()\n", " .device(\"CPS.TGM\")\n", " .property(\"FULL-TELEGRAM.STRC\")\n", " .build()\n", " )" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
BATCHBEAMIDBPNMCOMLNCYCLECYTAGDESTDEST2DURNFREE14...USER__record_timestamp____record_version__acqStampclasscyclestampdevicepropertyselectornxcals_entity_id
005709064None48NaNPS_DUMPNONE1NaN...ZERO166726081390000000001667260813850000000CPS.TGM1667260813900000000CPS.TGMFULL-TELEGRAM.STRCCPS.USER.ALL46955
101655525None22NaNNTOFNONE1NaN...TOF166726084870000000001667260848650000000CPS.TGM1667260848700000000CPS.TGMFULL-TELEGRAM.STRCCPS.USER.ALL46955
\n", "

2 rows × 34 columns

\n", "
" ], "text/plain": [ " BATCH BEAMID BPNM COMLN CYCLE CYTAG DEST DEST2 DURN FREE14 ... \\\n", "0 0 57090 64 None 48 NaN PS_DUMP NONE 1 NaN ... \n", "1 0 16555 25 None 22 NaN NTOF NONE 1 NaN ... \n", "\n", " USER __record_timestamp__ __record_version__ acqStamp class \\\n", "0 ZERO 1667260813900000000 0 1667260813850000000 CPS.TGM \n", "1 TOF 1667260848700000000 0 1667260848650000000 CPS.TGM \n", "\n", " cyclestamp device property selector \\\n", "0 1667260813900000000 CPS.TGM FULL-TELEGRAM.STRC CPS.USER.ALL \n", "1 1667260848700000000 CPS.TGM FULL-TELEGRAM.STRC CPS.USER.ALL \n", "\n", " nxcals_entity_id \n", "0 46955 \n", "1 46955 \n", "\n", "[2 rows x 34 columns]" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "tgmData.toPandas()[:2]" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+--------+-----+\n", "| USER|count|\n", "+--------+-----+\n", "| MD4| 263|\n", "| LHCIND2| 212|\n", "| EAST1| 4205|\n", "| AD| 746|\n", "| LHC5| 70|\n", "| MD6| 276|\n", "|LHCPILOT| 64|\n", "| ION3| 1095|\n", "| ZERO|15940|\n", "| SFTPRO3| 3473|\n", "| ION1| 2168|\n", "| EAST3| 6691|\n", "| MD2| 297|\n", "| LHC3| 1205|\n", "| MD10| 93|\n", "| SFTPRO1| 1364|\n", "| TOF|13072|\n", "| MD5| 117|\n", "| SFTPRO2| 1921|\n", "+--------+-----+\n", "\n" ] } ], "source": [ "# Aggregate and count per user\n", "tgmData.groupBy(\"USER\").count().show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## DataQuery example" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# Map the data into a dataframe, extract using DataQuery in the NXCALS api\n", "df = ( DataQuery.builder(spark).entities()\n", " .system(\"CMW\")\n", " .keyValuesEq({\"device\": \"LHC_STATS\", \"property\": \"Calculations\"})\n", " .timeWindow(\"2022-10-10 00:00:00.0\", \"2022-11-10 00:00:00.0\")\n", " .build()\n", " )" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "root\n", " |-- ALICE_BKGD1: double (nullable = true)\n", " |-- ALICE_BKGD2: double (nullable = true)\n", " |-- ALICE_BKGD3: double (nullable = true)\n", " |-- ALICE_BPTX_DELTA_T: double (nullable = true)\n", " |-- ALICE_HALF_CROSSING_ANGLE: double (nullable = true)\n", " |-- ALICE_LUMI_REGION_CENTROID_X: double (nullable = true)\n", " |-- ALICE_LUMI_REGION_CENTROID_Y: double (nullable = true)\n", " |-- ALICE_LUMI_REGION_CENTROID_Z: double (nullable = true)\n", " |-- ALICE_LUMI_REGION_SIZE_X: double (nullable = true)\n", " |-- ALICE_LUMI_REGION_SIZE_Y: double (nullable = true)\n", " |-- ALICE_LUMI_REGION_SIZE_Z: double (nullable = true)\n", " |-- ALICE_SPECTROMETER: double (nullable = true)\n", " |-- ALICE_TILT_H: double (nullable = true)\n", " |-- ALICE_TILT_V: double (nullable = true)\n", " |-- ATLAS_BKGD1: double (nullable = true)\n", " |-- ATLAS_BKGD2: double (nullable = true)\n", " |-- ATLAS_BKGD3: double (nullable = true)\n", " |-- ATLAS_BPTX_DELTA_T: double (nullable = true)\n", " |-- ATLAS_HALF_CROSSING_ANGLE: double (nullable = true)\n", " |-- ATLAS_LUMI_REGION_SIZE_X: double (nullable = true)\n", " |-- ATLAS_LUMI_REGION_SIZE_Y: double (nullable = true)\n", " |-- ATLAS_LUMI_REGION_SIZE_Z: double (nullable = true)\n", " |-- ATLAS_TILT_H: double (nullable = true)\n", " |-- ATLAS_TILT_V: double (nullable = true)\n", " |-- B1_AVG_BUNCH_INTENSITY: double (nullable = true)\n", " |-- B1_BUNCH_LENGTH_MEAN_EOF: double (nullable = true)\n", " |-- B1_BUNCH_LENGTH_MEAN_SSB: double (nullable = true)\n", " |-- B1_INTENSITY_ATLAS_CMS_SSB: double (nullable = true)\n", " |-- B1_INTENSITY_DCBCT_SSB: double (nullable = true)\n", " |-- B1_INTENSITY_SSB: double (nullable = true)\n", " |-- B1_NUMBER_BUNCHES: integer (nullable = true)\n", " |-- B1_PARTICLE_TYPE: string (nullable = true)\n", " |-- B2_AVG_BUNCH_INTENSITY: double (nullable = true)\n", " |-- B2_BUNCH_LENGTH_MEAN_EOF: double (nullable = true)\n", " |-- B2_BUNCH_LENGTH_MEAN_SSB: double (nullable = true)\n", " |-- B2_INTENSITY_ATLAS_CMS_SSB: double (nullable = true)\n", " |-- B2_INTENSITY_DCBCT_SSB: double (nullable = true)\n", " |-- B2_INTENSITY_SSB: double (nullable = true)\n", " |-- B2_NUMBER_BUNCHES: integer (nullable = true)\n", " |-- B2_PARTICLE_TYPE: string (nullable = true)\n", " |-- BETA_STAR_ALICE: double (nullable = true)\n", " |-- BETA_STAR_ATLAS: double (nullable = true)\n", " |-- BETA_STAR_CMS: double (nullable = true)\n", " |-- BETA_STAR_LHCB: double (nullable = true)\n", " |-- BR1_H_ROT_EMITTANCE_AVG: double (nullable = true)\n", " |-- BR1_H_ROT_INTENSITY_AVG: double (nullable = true)\n", " |-- BR1_H_ROT_TAIL_AVG: double (nullable = true)\n", " |-- BR1_V_ROT_EMITTANCE_AVG: double (nullable = true)\n", " |-- BR1_V_ROT_INTENSITY_AVG: double (nullable = true)\n", " |-- BR1_V_ROT_TAIL_AVG: double (nullable = true)\n", " |-- BR2_H_ROT_EMITTANCE_AVG: double (nullable = true)\n", " |-- BR2_H_ROT_INTENSITY_AVG: double (nullable = true)\n", " |-- BR2_H_ROT_TAIL_AVG: double (nullable = true)\n", " |-- BR2_V_ROT_EMITTANCE_AVG: double (nullable = true)\n", " |-- BR2_V_ROT_INTENSITY_AVG: double (nullable = true)\n", " |-- BR2_V_ROT_TAIL_AVG: double (nullable = true)\n", " |-- BR3_H_ROT_EMITTANCE_AVG: double (nullable = true)\n", " |-- BR3_H_ROT_INTENSITY_AVG: double (nullable = true)\n", " |-- BR3_H_ROT_TAIL_AVG: double (nullable = true)\n", " |-- BR3_V_ROT_EMITTANCE_AVG: double (nullable = true)\n", " |-- BR3_V_ROT_INTENSITY_AVG: double (nullable = true)\n", " |-- BR3_V_ROT_TAIL_AVG: double (nullable = true)\n", " |-- BR4_H_ROT_EMITTANCE_AVG: double (nullable = true)\n", " |-- BR4_H_ROT_INTENSITY_AVG: double (nullable = true)\n", " |-- BR4_H_ROT_TAIL_AVG: double (nullable = true)\n", " |-- BR4_V_ROT_EMITTANCE_AVG: double (nullable = true)\n", " |-- BR4_V_ROT_INTENSITY_AVG: double (nullable = true)\n", " |-- BR4_V_ROT_TAIL_AVG: double (nullable = true)\n", " |-- BUNCH_SPACING_B1: integer (nullable = true)\n", " |-- CMS_BKGD1: double (nullable = true)\n", " |-- CMS_BKGD2: double (nullable = true)\n", " |-- CMS_BKGD3: double (nullable = true)\n", " |-- CMS_BPTX_DELTA_T: double (nullable = true)\n", " |-- CMS_HALF_CROSSING_ANGLE: double (nullable = true)\n", " |-- CMS_LUMI_REGION_SIZE_X: double (nullable = true)\n", " |-- CMS_LUMI_REGION_SIZE_Y: double (nullable = true)\n", " |-- CMS_LUMI_REGION_SIZE_Z: double (nullable = true)\n", " |-- CMS_TILT_H: double (nullable = true)\n", " |-- CMS_TILT_V: double (nullable = true)\n", " |-- CPS:BRIGHTNESS_AVG_FT: double (nullable = true)\n", " |-- CPS:BRIGHTNESS_AVG_INJ: double (nullable = true)\n", " |-- EMITTANCE_BSRT_B1_H_EOF: double (nullable = true)\n", " |-- EMITTANCE_BSRT_B1_H_SSB: double (nullable = true)\n", " |-- EMITTANCE_BSRT_B1_V_EOF: double (nullable = true)\n", " |-- EMITTANCE_BSRT_B1_V_SSB: double (nullable = true)\n", " |-- EMITTANCE_BSRT_B2_H_EOF: double (nullable = true)\n", " |-- EMITTANCE_BSRT_B2_H_SSB: double (nullable = true)\n", " |-- EMITTANCE_BSRT_B2_V_EOF: double (nullable = true)\n", " |-- EMITTANCE_BSRT_B2_V_SSB: double (nullable = true)\n", " |-- EMITTANCE_FROM_LUMI_SSB: double (nullable = true)\n", " |-- ENERGY: double (nullable = true)\n", " |-- FILL_NUMBER: integer (nullable = true)\n", " |-- HEATLOAD_SSB_ARC12: double (nullable = true)\n", " |-- HEATLOAD_SSB_ARC23: double (nullable = true)\n", " |-- HEATLOAD_SSB_ARC34: double (nullable = true)\n", " |-- HEATLOAD_SSB_ARC45: double (nullable = true)\n", " |-- HEATLOAD_SSB_ARC56: double (nullable = true)\n", " |-- HEATLOAD_SSB_ARC67: double (nullable = true)\n", " |-- HEATLOAD_SSB_ARC78: double (nullable = true)\n", " |-- HEATLOAD_SSB_ARC81: double (nullable = true)\n", " |-- IS_HB: boolean (nullable = true)\n", " |-- IS_IONS: boolean (nullable = true)\n", " |-- IS_MD: boolean (nullable = true)\n", " |-- IS_PROTONS: boolean (nullable = true)\n", " |-- IS_PROTON_ION: boolean (nullable = true)\n", " |-- IS_STABLE_BEAMS: boolean (nullable = true)\n", " |-- IS_TS: boolean (nullable = true)\n", " |-- LHC:INJECTION_SCHEME: string (nullable = true)\n", " |-- LHCB_BKGD1: double (nullable = true)\n", " |-- LHCB_BKGD2: double (nullable = true)\n", " |-- LHCB_BKGD3: double (nullable = true)\n", " |-- LHCB_BPTX_DELTA_T: double (nullable = true)\n", " |-- LHCB_HALF_CROSSING_ANGLE: double (nullable = true)\n", " |-- LHCB_LUMI_REGION_SIZE_X: double (nullable = true)\n", " |-- LHCB_LUMI_REGION_SIZE_Y: double (nullable = true)\n", " |-- LHCB_LUMI_REGION_SIZE_Z: double (nullable = true)\n", " |-- LHCB_POLARITY: double (nullable = true)\n", " |-- LHCB_SPECTROMETER: double (nullable = true)\n", " |-- LHCB_TILT_H: double (nullable = true)\n", " |-- LHCB_TILT_V: double (nullable = true)\n", " |-- LHC_BEAM_TYPE: string (nullable = true)\n", " |-- LUMI_ALICE_DELIVERED: double (nullable = true)\n", " |-- LUMI_ALICE_PEAK: double (nullable = true)\n", " |-- LUMI_ATLAS_DELIVERED: double (nullable = true)\n", " |-- LUMI_ATLAS_PEAK: double (nullable = true)\n", " |-- LUMI_CMS_DELIVERED: double (nullable = true)\n", " |-- LUMI_CMS_PEAK: double (nullable = true)\n", " |-- LUMI_LHCB_DELIVERED: double (nullable = true)\n", " |-- LUMI_LHCB_PEAK: double (nullable = true)\n", " |-- LUMI_LIFETIME_ATLAS_EOF: double (nullable = true)\n", " |-- LUMI_LIFETIME_ATLAS_REL_ERROR_EOF: double (nullable = true)\n", " |-- LUMI_LIFETIME_ATLAS_REL_ERROR_SSB: double (nullable = true)\n", " |-- LUMI_LIFETIME_ATLAS_SSB: double (nullable = true)\n", " |-- LUMI_LIFETIME_CMS_EOF: double (nullable = true)\n", " |-- LUMI_LIFETIME_CMS_REL_ERROR_EOF: double (nullable = true)\n", " |-- LUMI_LIFETIME_CMS_REL_ERROR_SSB: double (nullable = true)\n", " |-- LUMI_LIFETIME_CMS_SSB: double (nullable = true)\n", " |-- LUMI_LIFETIME_EOF: double (nullable = true)\n", " |-- LUMI_LIFETIME_REL_ERROR_EOF: double (nullable = true)\n", " |-- LUMI_LIFETIME_REL_ERROR_SSB: double (nullable = true)\n", " |-- LUMI_LIFETIME_SSB: double (nullable = true)\n", " |-- NUMBER_COLLISIONS_IP1_5: integer (nullable = true)\n", " |-- NUMBER_COLLISIONS_IP2: integer (nullable = true)\n", " |-- NUMBER_COLLISIONS_IP8: integer (nullable = true)\n", " |-- PR_H_ROT_EMITTANCE_AVG_FT: double (nullable = true)\n", " |-- PR_H_ROT_EMITTANCE_AVG_INJ: double (nullable = true)\n", " |-- PR_H_ROT_INTENSITY_AVG: double (nullable = true)\n", " |-- PR_H_ROT_INTENSITY_AVG_FT: double (nullable = true)\n", " |-- PR_H_ROT_TAIL_AVG_FT: double (nullable = true)\n", " |-- PR_H_ROT_TAIL_AVG_INJ: double (nullable = true)\n", " |-- PR_V_ROT_EMITTANCE_AVG_FT: double (nullable = true)\n", " |-- PR_V_ROT_EMITTANCE_AVG_INJ: double (nullable = true)\n", " |-- PR_V_ROT_INTENSITY_AVG: double (nullable = true)\n", " |-- PR_V_ROT_INTENSITY_AVG_FT: double (nullable = true)\n", " |-- PR_V_ROT_TAIL_AVG_FT: double (nullable = true)\n", " |-- PR_V_ROT_TAIL_AVG_INJ: double (nullable = true)\n", " |-- PSB:BRIGHTNESS_AVG_R1: double (nullable = true)\n", " |-- PSB:BRIGHTNESS_AVG_R2: double (nullable = true)\n", " |-- PSB:BRIGHTNESS_AVG_R3: double (nullable = true)\n", " |-- PSB:BRIGHTNESS_AVG_R4: double (nullable = true)\n", " |-- SPS:BUNCH_BRIGHTNESS_AVG_IN: double (nullable = true)\n", " |-- SPS_H_ROT:EMITTANCE_AVG_FT: double (nullable = true)\n", " |-- SPS_H_ROT:EMITTANCE_AVG_INJ: double (nullable = true)\n", " |-- SPS_H_ROT_IN:BUNCH_INT: double (nullable = true)\n", " |-- SPS_H_ROT_IN:EMITTANCE: double (nullable = true)\n", " |-- SPS_H_ROT_IN:ENERGY: double (nullable = true)\n", " |-- SPS_H_ROT_IN:TAIL_POP: double (nullable = true)\n", " |-- SPS_V_ROT:EMITTANCE_AVG_FT: double (nullable = true)\n", " |-- SPS_V_ROT:EMITTANCE_AVG_INJ: double (nullable = true)\n", " |-- SPS_V_ROT_IN:BUNCH_INT: double (nullable = true)\n", " |-- SPS_V_ROT_IN:EMITTANCE: double (nullable = true)\n", " |-- SPS_V_ROT_IN:ENERGY: double (nullable = true)\n", " |-- SPS_V_ROT_IN:TAIL_POP: double (nullable = true)\n", " |-- TIME_DURATION_BM_ACCESS_NO_BEAM: long (nullable = true)\n", " |-- TIME_DURATION_BM_BEAM_IN: long (nullable = true)\n", " |-- TIME_DURATION_BM_MACHINE_SETUP: long (nullable = true)\n", " |-- TIME_DURATION_BM_RAMP_SQUEEZE: long (nullable = true)\n", " |-- TIME_DURATION_BM_STABLE: long (nullable = true)\n", " |-- TIME_DURATION_FILL: long (nullable = true)\n", " |-- TIME_DURATION_FTSQAD: long (nullable = true)\n", " |-- TIME_DURATION_INJECTION: long (nullable = true)\n", " |-- TIME_DURATION_RAMP: long (nullable = true)\n", " |-- TIME_DURATION_SETUP: long (nullable = true)\n", " |-- TIME_DURATION_STABLEBEAMS: long (nullable = true)\n", " |-- TIME_DURATION_TURNAROUND: long (nullable = true)\n", " |-- TIME_END_FILL: long (nullable = true)\n", " |-- TIME_END_STABLEBEAM: long (nullable = true)\n", " |-- TIME_START_FILL: long (nullable = true)\n", " |-- TIME_START_FLATTOP: long (nullable = true)\n", " |-- TIME_START_INJECTION: long (nullable = true)\n", " |-- TIME_START_STABLEBEAMS: long (nullable = true)\n", " |-- YEAR: long (nullable = true)\n", " |-- __record_timestamp__: long (nullable = true)\n", " |-- __record_version__: long (nullable = true)\n", " |-- acqStamp: long (nullable = true)\n", " |-- class: string (nullable = true)\n", " |-- cyclestamp: long (nullable = true)\n", " |-- device: string (nullable = true)\n", " |-- property: string (nullable = true)\n", " |-- selector: string (nullable = true)\n", " |-- nxcals_entity_id: long (nullable = true)\n", "\n" ] } ], "source": [ "df.printSchema()" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+-------------------+---------+--------------------+\n", "| acqStamp| device| LUMI_ATLAS_PEAK|\n", "+-------------------+---------+--------------------+\n", "|1667905679423738525|LHC_STATS| null|\n", "|1667864783774363525|LHC_STATS| 3.5779993534088135|\n", "|1667822484470738525|LHC_STATS| null|\n", "|1667774087439988525|LHC_STATS| null|\n", "|1667703231948988525|LHC_STATS|0.002851842204108...|\n", "|1667629713050363525|LHC_STATS| 19311.009765625|\n", "|1667490492435738525|LHC_STATS| null|\n", "|1667321660221238525|LHC_STATS| 19136.162109375|\n", "|1667218881892238525|LHC_STATS| null|\n", "|1667152839888738525|LHC_STATS| null|\n", "|1667010181393738525|LHC_STATS| 19072.6171875|\n", "|1666650939478488525|LHC_STATS| 19087.2265625|\n", "|1666353810345738525|LHC_STATS| null|\n", "|1666340687922238525|LHC_STATS| 2665.25634765625|\n", "|1666339796457488525|LHC_STATS| null|\n", "|1666268334454488525|LHC_STATS| 18732.56640625|\n", "|1666263572235863525|LHC_STATS| null|\n", "|1666185949344738525|LHC_STATS| 2549.858154296875|\n", "|1666049957622238525|LHC_STATS| null|\n", "|1666016050093613525|LHC_STATS| null|\n", "+-------------------+---------+--------------------+\n", "only showing top 20 rows\n", "\n" ] } ], "source": [ "df.select(\"acqStamp\", \"device\", \"LUMI_ATLAS_PEAK\").show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### BPT downsampling" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "from cern.nxcals.pyquery.builders import *\n", "from pyspark.sql.functions import *\n", "\n", "sdf = DataQuery(spark).byVariables() \\\n", " .system('CMW') \\\n", " .startTime('2022-01-01 00:00:00.00') \\\n", " .endTime('2022-12-31 00:00:00.00') \\\n", " .variables(['LHC.BCTFR.A6R4.B1:BEAM_INTENSITY', 'LHC.BCTFR.A6R4.B2:BEAM_INTENSITY']) \\\n", " .buildDataset()\n" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "# extract with downsampling\n", "# average data on bins of 1h\n", "\n", "sdf_ds = ( sdf.withColumn('time_bin', floor(col('nxcals_timestamp') / 3600e9)*3600)\n", " .groupby(['nxcals_variable_name', 'time_bin']).mean('nxcals_value') \n", " .withColumnRenamed('avg(nxcals_value)', 'nxcals_value') \\\n", " .orderBy('time_bin')\n", " )" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "16869" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sdf_ds.count()" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+--------------------------------+----------+------------+\n", "|nxcals_variable_name |time_bin |nxcals_value|\n", "+--------------------------------+----------+------------+\n", "|LHC.BCTFR.A6R4.B2:BEAM_INTENSITY|1640995200|0.0 |\n", "|LHC.BCTFR.A6R4.B1:BEAM_INTENSITY|1640995200|0.0 |\n", "|LHC.BCTFR.A6R4.B2:BEAM_INTENSITY|1640998800|0.0 |\n", "+--------------------------------+----------+------------+\n", "only showing top 3 rows\n", "\n" ] } ], "source": [ "sdf_ds.show(3, False)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+--------------------+----------------+-------------------+--------------------+--------------------+\n", "| nxcals_value|nxcals_entity_id| nxcals_timestamp|nxcals_variable_name| time_bin|\n", "+--------------------+----------------+-------------------+--------------------+--------------------+\n", "|3.363701276527677...| 46424|1666656000010076000|LHC.BCTFR.A6R4.B2...|{2022-10-25 02:00...|\n", "|3.362054560455108E14| 46420|1666656001010080000|LHC.BCTFR.A6R4.B1...|{2022-10-25 02:00...|\n", "|3.363426610018308E14| 46424|1666656001010080000|LHC.BCTFR.A6R4.B2...|{2022-10-25 02:00...|\n", "+--------------------+----------------+-------------------+--------------------+--------------------+\n", "only showing top 3 rows\n", "\n" ] } ], "source": [ "# Show another method for creating time bins\n", "\n", "sdf.withColumn('time_bin', window(timestamp_seconds(col('nxcals_timestamp')/1e9), '10 minutes')).show(3)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "# spark.stop()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "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.9.12" }, "sparkconnect": { "bundled_options": [ "NXCALS_NEW", "NXCALS" ], "list_of_options": [] } }, "nbformat": 4, "nbformat_minor": 2 }