Source code for ents.dirtviz.client

"""Client interface with dirtviz.

TODO:
- Add caching of data
"""

from datetime import datetime

import pandas as pd
import requests


[docs] class Cell: """Class representing a cell in the Dirtviz API.""" def __init__(self, data: str): """Initialize the Cell object from a cell ID. Args: data: json data from the Dirtviz API containing cell information. """ self.id = data["id"] self.name = data["name"] self.location = data["location"] self.latitude = data["latitude"] self.longitude = data["longitude"] def __repr__(self): return f"Cell(id={self.cell_id}, name={self.name})"
[docs] class BackendClient: """Client for interacting with the Dirtviz API.""" def __init__(self, base_url: str = "https://dirtviz.jlab.ucsc.edu/api/"): """Initialize the BackendClient. Sets the base URL for the API. Defaults to the Dirtviz API. """ self.base_url = base_url
[docs] def get(self, endpoint: str, params: dict | None = None) -> dict: """Get request to the API. Args: endpoint: The API endpoint to request. params: Optional parameters for the request. Returns: A dictionary containing the response data. """ url = f"{self.base_url}{endpoint}" response = requests.get(url, params=params) response.raise_for_status() return response.json()
[docs] @staticmethod def time_to_params(start: datetime, end: datetime) -> dict: """Puts start and end datetime into an API paramter dictionary Args: dt: The datetime object to format. Returns: A string representing the formatted datetime. """ timestamp_format = "%a, %d %b %Y %H:%M:%S GMT" start_str = start.strftime(timestamp_format) end_str = end.strftime(timestamp_format) params = { "startTime": start_str, "endTime": end_str, } return params
[docs] def power_data(self, cell: Cell, start: datetime, end: datetime) -> pd.DataFrame: """Gets power data for a specific cell by name. Args: cell: The Cell object for which to get power data. start: The start date of the data. end: The end date of the data. Returns: A pandas DataFrame containing the power data. """ endpoint = f"/power/{cell.id}" params = self.time_to_params(start, end) data = self.get(endpoint, params=params) data_df = pd.DataFrame(data) data_df["timestamp"] = pd.to_datetime(data_df["timestamp"]) return data_df
[docs] def teros_data(self, cell: Cell, start: datetime, end: datetime) -> pd.DataFrame: """Gets teros data for a specific cell Args: cell: The Cell object for which to get teros data. start: The start date of the data. end: The end date of the data. Returns: A pandas DataFrame containing the teros data with columns vwc_raw, vwc_adj, temp, ec. """ endpoint = f"/teros/{cell.id}" params = self.time_to_params(start, end) data = self.get(endpoint, params=params) data_df = pd.DataFrame(data) data_df["timestamp"] = pd.to_datetime(data_df["timestamp"]) return data_df
[docs] def sensor_data( self, cell: Cell, name: str, meas: str, start: datetime, end: datetime, resample: str = "none", ) -> pd.DataFrame: """Gets generic sensor data for a specific cell Args: cell: The Cell object for which to get sensor data. name: Name of the sensor (e.g., "power", "teros"). meas: The measurement type (e.g., "v", "i", "vwc", "temp", "ec"). start: The start date of the data. end: The end date of the data. Returns: A pandas DataFrame containing the sensor data. """ endpoint = "/sensor/" params = { "cellId": cell.id, "name": name, "measurement": meas, } params = params | self.time_to_params(start, end) data = self.get(endpoint, params=params) data_df = pd.DataFrame(data) data_df["timestamp"] = pd.to_datetime(data_df["timestamp"]) return data_df
[docs] def cell_from_id(self, cell_id: int) -> Cell | None: """Get a Cell object from its ID. Args: cell_id: The ID of the cell. Returns: A Cell object. None if the cell does not exist. """ cell_list = self.cells() for cell in cell_list: if cell.id == cell_id: return cell return None
[docs] def cell_from_name(self, name: str) -> Cell | None: """Get a Cell object from its name. Args: name: The name of the cell. Returns: A Cell object. None if the cell does not exist. """ cell_list = self.cells() for cell in cell_list: if cell.name == name: return cell return None
[docs] def cells(self) -> list[Cell]: """Gets a list of all cells from the API. Returns: A list of Cell objects. """ cell_list = [] endpoint = "/cell/id" cell_data_list = self.get(endpoint) for c in cell_data_list: cell = Cell(c) cell_list.append(cell) return cell_list