From f50bdc62fe4555aada8dc9eb04feb91da777ca6d Mon Sep 17 00:00:00 2001 From: Victoria Orlova Date: Sun, 8 Mar 2026 22:09:57 +0300 Subject: [PATCH 1/2] Add HW2 notebook --- HW2/HW2.ipynb | 621 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 621 insertions(+) create mode 100644 HW2/HW2.ipynb diff --git a/HW2/HW2.ipynb b/HW2/HW2.ipynb new file mode 100644 index 0000000..b1d56ea --- /dev/null +++ b/HW2/HW2.ipynb @@ -0,0 +1,621 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# HW2 – Using APIs for UniProt and Ensembl\n", + "**Author:** Victoria Orlova " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "import json\n", + "import re\n", + "import pandas as pd\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "def http_function(endpoint, **kwargs):\n", + " \"\"\"\n", + " Generic HTTP GET function that returns the JSON response.\n", + " \"\"\"\n", + " headers = kwargs.get('headers', {})\n", + " kwargs['headers'] = headers\n", + " response = requests.get(endpoint, **kwargs)\n", + " return response" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def get_uniprot(accession):\n", + " \"\"\"\n", + " Retrieve protein data from UniProt REST API for a single accession.\n", + " Returns a Response object.\n", + " \"\"\"\n", + " endpoint = f\"https://rest.uniprot.org/uniprotkb/{accession}\"\n", + " return http_function(endpoint, headers={'Accept': 'application/json'})" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def uniprot_parse_response(resp):\n", + " \"\"\"\n", + " Parse UniProt JSON response (requests.Response object) and extract:\n", + " organism, geneInfo, sequenceInfo, type.\n", + " Returns a dictionary with those fields, or {'error': ...} on failure.\n", + " \"\"\"\n", + " try:\n", + " data = resp.json()\n", + " except Exception as e:\n", + " return {'error': f'Failed to parse JSON: {str(e)}'}\n", + "\n", + " try:\n", + " organism = data.get('organism', {}).get('scientificName', 'N/A')\n", + " geneInfo = data.get('genes', [])\n", + " seq = data.get('sequence', {})\n", + " sequenceInfo = {\n", + " 'value': seq.get('value', ''),\n", + " 'length': seq.get('length', 'N/A'),\n", + " 'molWeight': seq.get('molWeight', 'N/A'),\n", + " 'crc64': seq.get('crc64', 'N/A'),\n", + " 'md5': seq.get('md5', 'N/A')\n", + " }\n", + " entry_type = 'protein'\n", + " return {\n", + " 'organism': organism,\n", + " 'geneInfo': geneInfo,\n", + " 'sequenceInfo': sequenceInfo,\n", + " 'type': entry_type\n", + " }\n", + " except Exception as e:\n", + " return {'error': f'UniProt parsing failed: {str(e)}'}" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def get_ensembl(id):\n", + " \"\"\"\n", + " Retrieve gene/transcript/protein data from Ensembl REST API.\n", + " Returns a Response object.\n", + " \"\"\"\n", + " endpoint = f\"https://rest.ensembl.org/lookup/id/{id}\"\n", + " headers = {'Content-Type': 'application/json'}\n", + " return http_function(endpoint, headers=headers)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def ensembl_parse_response(resp: dict):\n", + " \"\"\"\n", + " Parse Ensembl JSON response and extract:\n", + " object_type, assembly_name, species, db_type, biotype,\n", + " display_name, id, description, canonical_transcript, source\n", + " \"\"\"\n", + " \n", + " try:\n", + " resp = resp.json()\n", + " except Exception as e:\n", + " return {'error': f'Failed to parse JSON: {str(e)}'}\n", + " \n", + " try:\n", + " if 'error' in resp:\n", + " return {'error': resp['error']}\n", + " \n", + " return {\n", + " 'object_type': resp.get('object_type', 'N/A'),\n", + " 'assembly_name': resp.get('assembly_name', 'N/A'),\n", + " 'species': resp.get('species', 'N/A'),\n", + " 'db_type': resp.get('db_type', 'N/A'),\n", + " 'biotype': resp.get('biotype', 'N/A'),\n", + " 'display_name': resp.get('display_name', 'N/A'),\n", + " 'id': resp.get('id', 'N/A'),\n", + " 'description': resp.get('description', 'N/A'),\n", + " 'canonical_transcript': resp.get('canonical_transcript', 'N/A'),\n", + " 'source': resp.get('source', 'N/A')\n", + " }\n", + " except Exception as e:\n", + " return {'error': f'Ensembl parsing failed: {str(e)}'}" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def main(ids):\n", + " \"\"\"\n", + " Accepts a list of IDs, determines their type (UniProt or Ensembl) using regex,\n", + " fetches and parses data from the appropriate API, and returns a pandas DataFrame.\n", + " If an ID is invalid or an error occurs, an error column is added.\n", + " \"\"\"\n", + " uniprot_pattern = r'^[A-Z][0-9][A-Z0-9]{3,}[0-9]$'\n", + " ensembl_pattern = r'^ENS[A-Z]*[GTEP][0-9]{11}$'\n", + "\n", + " records = []\n", + "\n", + " for raw_id in ids:\n", + " acc = raw_id.strip()\n", + " record = {'ID': acc}\n", + "\n", + " try:\n", + " if re.match(uniprot_pattern, acc):\n", + " resp = get_uniprot(acc)\n", + " info = uniprot_parse_response(resp)\n", + " if 'error' in info:\n", + " record['error'] = info['error']\n", + " else:\n", + " record.update(info)\n", + " record['geneInfo'] = json.dumps(record['geneInfo'])\n", + " record['sequenceInfo'] = json.dumps(record['sequenceInfo'])\n", + "\n", + " elif re.match(ensembl_pattern, acc):\n", + " resp = get_ensembl(acc)\n", + " info = ensembl_parse_response(resp)\n", + " if 'error' in info:\n", + " record['error'] = info['error']\n", + " else:\n", + " record.update(info)\n", + "\n", + " else:\n", + " record['error'] = 'ID format not recognized'\n", + "\n", + " except requests.exceptions.HTTPError as e:\n", + " error_msg = f'HTTP error: {e.response.status_code}'\n", + " try:\n", + " err_data = e.response.json()\n", + " if 'messages' in err_data:\n", + " error_msg += ' - ' + ', '.join(err_data['messages'])\n", + " elif 'error' in err_data:\n", + " error_msg += ' - ' + err_data['error']\n", + " except:\n", + " pass\n", + " record['error'] = error_msg\n", + " except Exception as e:\n", + " record['error'] = f'Unexpected error: {str(e)}'\n", + "\n", + " records.append(record)\n", + "\n", + " df = pd.DataFrame(records)\n", + " if 'error' in df.columns:\n", + " cols = [c for c in df.columns if c != 'error'] + ['error']\n", + " df = df[cols]\n", + " return df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Testing with the example IDs from test_data.txt" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_uniprot('P11473')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_uniprot('helloworld')" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'url': 'http://rest.uniprot.org/uniprotkb/helloworld',\n", + " 'messages': [\"The 'accession' value has invalid format. It should be a valid UniProtKB accession\"]}" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_uniprot('helloworld').json()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'organism': 'Homo sapiens',\n", + " 'geneInfo': [{'geneName': {'evidences': [{'evidenceCode': 'ECO:0000312',\n", + " 'source': 'HGNC',\n", + " 'id': 'HGNC:12679'}],\n", + " 'value': 'VDR'},\n", + " 'synonyms': [{'value': 'NR1I1'}]}],\n", + " 'sequenceInfo': {'value': 'MEAMAASTSLPDPGDFDRNVPRICGVCGDRATGFHFNAMTCEGCKGFFRRSMKRKALFTCPFNGDCRITKDNRRHCQACRLKRCVDIGMMKEFILTDEEVQRKREMILKRKEEEALKDSLRPKLSEEQQRIIAILLDAHHKTYDPTYSDFCQFRPPVRVNDGGGSHPSRPNSRHTPSFSGDSSSSCSDHCITSSDMMDSSSFSNLDLSEEDSDDPSVTLELSQLSMLPHLADLVSYSIQKVIGFAKMIPGFRDLTSEDQIVLLKSSAIEVIMLRSNESFTMDDMSWTCGNQDYKYRVSDVTKAGHSLELIEPLIKFQVGLKKLNLHEEEHVLLMAICIVSPDRPGVQDAALIEAIQDRLSNTLQTYIRCRHPPPGSHLLYAKMIQKLADLRSLNEEHSKQYRCLSFQPECSMKLTPLVLEVFGNEIS',\n", + " 'length': 427,\n", + " 'molWeight': 48289,\n", + " 'crc64': 'F95F300D042C4CB7',\n", + " 'md5': '0D963ACD4A34674368324EE026023597'},\n", + " 'type': 'protein'}" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "uniprot_parse_response(get_uniprot('P11473'))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_ensembl('ENSMUSG00000041147')" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_ensembl('helloworld')" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'error': \"ID 'helloworld' not found\"}" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_ensembl('helloworld').json()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'object_type': 'Gene',\n", + " 'assembly_name': 'GRCm39',\n", + " 'species': 'mus_musculus',\n", + " 'db_type': 'core',\n", + " 'biotype': 'protein_coding',\n", + " 'display_name': 'Brca2',\n", + " 'id': 'ENSMUSG00000041147',\n", + " 'description': 'breast cancer 2, early onset [Source:MGI Symbol;Acc:MGI:109337]',\n", + " 'canonical_transcript': 'ENSMUST00000044620.11',\n", + " 'source': 'ensembl_havana'}" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ensembl_parse_response(get_ensembl('ENSMUSG00000041147'))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "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", + " \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", + "
IDorganismgeneInfosequenceInfotypeobject_typeassembly_namespeciesdb_typebiotypedisplay_nameiddescriptioncanonical_transcriptsourceerror
0P11473Homo sapiens[{\"geneName\": {\"evidences\": [{\"evidenceCode\": ...{\"value\": \"MEAMAASTSLPDPGDFDRNVPRICGVCGDRATGFH...proteinNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
1Q91XI3Ictidomys tridecemlineatus[{\"geneName\": {\"value\": \"INS\"}}]{\"value\": \"MALWTRLLPLLALLALLGPDPAQAFVNQHLCGSHL...proteinNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
2helloNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNID format not recognized
3ENSG00000157764NaNNaNNaNNaNGeneGRCh38homo_sapienscoreprotein_codingBRAFENSG00000157764B-Raf proto-oncogene, serine/threonine kinase ...ENST00000646891.2ensembl_havanaNaN
4ENSG00000139618NaNNaNNaNNaNGeneGRCh38homo_sapienscoreprotein_codingBRCA2ENSG00000139618BRCA2 DNA repair associated [Source:HGNC Symbo...ENST00000380152.8ensembl_havanaNaN
\n", + "
" + ], + "text/plain": [ + " ID organism \\\n", + "0 P11473 Homo sapiens \n", + "1 Q91XI3 Ictidomys tridecemlineatus \n", + "2 hello NaN \n", + "3 ENSG00000157764 NaN \n", + "4 ENSG00000139618 NaN \n", + "\n", + " geneInfo \\\n", + "0 [{\"geneName\": {\"evidences\": [{\"evidenceCode\": ... \n", + "1 [{\"geneName\": {\"value\": \"INS\"}}] \n", + "2 NaN \n", + "3 NaN \n", + "4 NaN \n", + "\n", + " sequenceInfo type object_type \\\n", + "0 {\"value\": \"MEAMAASTSLPDPGDFDRNVPRICGVCGDRATGFH... protein NaN \n", + "1 {\"value\": \"MALWTRLLPLLALLALLGPDPAQAFVNQHLCGSHL... protein NaN \n", + "2 NaN NaN NaN \n", + "3 NaN NaN Gene \n", + "4 NaN NaN Gene \n", + "\n", + " assembly_name species db_type biotype display_name \\\n", + "0 NaN NaN NaN NaN NaN \n", + "1 NaN NaN NaN NaN NaN \n", + "2 NaN NaN NaN NaN NaN \n", + "3 GRCh38 homo_sapiens core protein_coding BRAF \n", + "4 GRCh38 homo_sapiens core protein_coding BRCA2 \n", + "\n", + " id description \\\n", + "0 NaN NaN \n", + "1 NaN NaN \n", + "2 NaN NaN \n", + "3 ENSG00000157764 B-Raf proto-oncogene, serine/threonine kinase ... \n", + "4 ENSG00000139618 BRCA2 DNA repair associated [Source:HGNC Symbo... \n", + "\n", + " canonical_transcript source error \n", + "0 NaN NaN NaN \n", + "1 NaN NaN NaN \n", + "2 NaN NaN ID format not recognized \n", + "3 ENST00000646891.2 ensembl_havana NaN \n", + "4 ENST00000380152.8 ensembl_havana NaN " + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "main(['P11473', 'Q91XI3', 'hello', 'ENSG00000157764', 'ENSG00000139618'])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From ed8ecb2b8b402624899335c8cd3f4358934c6cab Mon Sep 17 00:00:00 2001 From: Victoria Orlova Date: Mon, 16 Mar 2026 23:04:22 +0300 Subject: [PATCH 2/2] Add HW3 notebook --- HW3/HW3.ipynb | 460 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 460 insertions(+) create mode 100644 HW3/HW3.ipynb diff --git a/HW3/HW3.ipynb b/HW3/HW3.ipynb new file mode 100644 index 0000000..ce360be --- /dev/null +++ b/HW3/HW3.ipynb @@ -0,0 +1,460 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# HW3 " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install openmeteo_requests" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import openmeteo_requests\n", + "from datetime import datetime" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Iterator classes" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "class IncreaseSpeed:\n", + " \"\"\"\n", + " Iterator for increasing speed step by step.\n", + " \"\"\"\n", + " def __init__(self, current_speed: int, max_speed: int, step: int = 10):\n", + " self.current = current_speed\n", + " self.max_speed = max_speed\n", + " self.step = step\n", + "\n", + " def __iter__(self):\n", + " return self\n", + "\n", + " def __next__(self):\n", + " if self.current + self.step > self.max_speed:\n", + " raise StopIteration\n", + " self.current += self.step\n", + " return self.current" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "class DecreaseSpeed:\n", + " \"\"\"\n", + " Iterator for decreasing speed step by step.\n", + " \"\"\"\n", + " def __init__(self, current_speed: int, min_speed: int = 0, step: int = 10):\n", + " self.current = current_speed\n", + " self.min_speed = min_speed\n", + " self.step = step\n", + "\n", + " def __iter__(self):\n", + " return self\n", + "\n", + " def __next__(self):\n", + " if self.current - self.step < self.min_speed:\n", + " raise StopIteration\n", + " self.current -= self.step\n", + " return self.current" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Car class" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "class Car:\n", + " _total_cars_on_road = 0\n", + "\n", + " def __init__(self, max_speed: int, current_speed: int = 0):\n", + " self.max_speed = max_speed\n", + " self.current_speed = current_speed\n", + " # Car is considered on the road if its speed > 0\n", + " self.state = current_speed > 0\n", + " if self.state:\n", + " Car._total_cars_on_road += 1\n", + "\n", + " # --- regular methods ---\n", + " def accelerate(self, upper_border=None, step=10):\n", + " \"\"\"Increase speed, optionally to a given border.\"\"\"\n", + " old_speed = self.current_speed\n", + "\n", + " if not self.state: # car is parked\n", + " self.state = True\n", + " Car._total_cars_on_road += 1\n", + " target = upper_border if upper_border is not None else step\n", + " if target > self.max_speed:\n", + " target = self.max_speed\n", + " self.current_speed = target\n", + " print(f\"INFO: The speed of this car has been increased from {old_speed} to {self.current_speed}\")\n", + " return\n", + " \n", + " inc = IncreaseSpeed(self.current_speed, self.max_speed, step) # Car on road\n", + " if upper_border is not None:\n", + " # gradually increase up to upper_border\n", + " for new_speed in inc:\n", + " if new_speed > upper_border:\n", + " break\n", + " self.current_speed = new_speed\n", + " print(f\"INFO: Speed increases by {step}\")\n", + " if self.current_speed < upper_border: # ensure final speed == upper_border\n", + " self.current_speed = upper_border\n", + " else:\n", + " try: # increase by one step\n", + " self.current_speed = next(inc)\n", + " print(f\"INFO: Speed increases by {step}\")\n", + " except StopIteration:\n", + " pass\n", + " print(f\"INFO: The speed of this car has been increased from {old_speed} to {self.current_speed}\")\n", + "\n", + " def brake(self, lower_border=None, step=10):\n", + " \"\"\"Decrease speed, optionally to a given border.\"\"\"\n", + " if not self.state:\n", + " print(\"INFO: Car is already parked.\")\n", + " return\n", + "\n", + " old_speed = self.current_speed\n", + " dec = DecreaseSpeed(self.current_speed, min_speed=0, step=step)\n", + " if lower_border is not None:\n", + " for new_speed in dec:\n", + " if new_speed < lower_border:\n", + " break\n", + " self.current_speed = new_speed\n", + " print(f\"INFO: Speed decreases by {step}\")\n", + " if self.current_speed > lower_border:\n", + " self.current_speed = max(lower_border, 0)\n", + " else:\n", + " try:\n", + " self.current_speed = next(dec)\n", + " print(f\"INFO: Speed decreases by {step}\")\n", + " except StopIteration:\n", + " pass\n", + " print(f\"INFO: The speed of this car has been decreased from {old_speed} to {self.current_speed}\")\n", + "\n", + "\n", + " def parking(self):\n", + " \"\"\"Take the car off the road (speed must be 0).\"\"\"\n", + " if not self.state:\n", + " print(\"INFO: Car is already parked.\")\n", + " return\n", + " # bring speed to 0 if needed\n", + " if self.current_speed > 0:\n", + " self.brake(lower_border=0)\n", + " else:\n", + " print(f\"INFO: The speed of this car has been decreased from {self.current_speed} to {self.current_speed}\")\n", + " self.state = False\n", + " Car._total_cars_on_road -= 1\n", + " print(\"Parking the car...\")\n", + "\n", + " @classmethod\n", + " def total_cars(cls):\n", + " \"\"\"Return the total number of cars currently on the road.\"\"\"\n", + " return cls._total_cars_on_road\n", + "\n", + " @staticmethod\n", + " def show_weather():\n", + " \"\"\"Fetch and display current weather in St. Petersburg.\"\"\"\n", + " openmeteo = openmeteo_requests.Client()\n", + " url = \"https://api.open-meteo.com/v1/forecast\"\n", + " params = {\n", + " \"latitude\": 59.9386,\n", + " \"longitude\": 30.3141,\n", + " \"current\": [\"temperature_2m\", \"apparent_temperature\", \"rain\", \"wind_speed_10m\"],\n", + " \"wind_speed_unit\": \"ms\",\n", + " \"timezone\": \"Europe/Moscow\"\n", + " }\n", + " try:\n", + " response = openmeteo.weather_api(url, params=params)[0]\n", + " current = response.Current()\n", + " temp = current.Variables(0).Value()\n", + " apparent_temp = current.Variables(1).Value()\n", + " rain = current.Variables(2).Value()\n", + " wind = current.Variables(3).Value()\n", + "\n", + " print(f\"Current temperature: {round(temp, 0)} C\")\n", + " print(f\"Current apparent_temperature: {round(apparent_temp, 0)} C\")\n", + " print(f\"Current rain: {rain} mm\")\n", + " print(f\"Current wind_speed: {round(wind, 1)} m/s\")\n", + " except Exception as e:\n", + " print(f\"Weather service error: {e}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Testing with the provided example" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total cars on road: 2\n" + ] + } + ], + "source": [ + "car1 = Car(100, 20) # max_speed = 100, initial speed = 5\n", + "car2 = Car(60, 30) # max_speed = 60, initial speed = 30\n", + "car3 = Car(100, 0) # a car that is off road upon creation\n", + "print(f\"Total cars on road: {Car.total_cars()}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: Speed increases by 10\n", + "INFO: Speed increases by 10\n", + "INFO: Speed increases by 10\n", + "INFO: Speed increases by 10\n", + "INFO: Speed increases by 10\n", + "INFO: Speed increases by 10\n", + "INFO: Speed increases by 10\n", + "INFO: Speed increases by 10\n", + "INFO: The speed of this car has been increased from 20 to 100\n" + ] + } + ], + "source": [ + "car1.accelerate(100)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: Speed increases by 10\n", + "INFO: Speed increases by 10\n", + "INFO: The speed of this car has been increased from 30 to 50\n" + ] + } + ], + "source": [ + "car2.accelerate(50)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Speed of car 1: 100\n" + ] + } + ], + "source": [ + "print(\"Speed of car 1:\", car1.current_speed)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Speed of car 2: 50\n" + ] + } + ], + "source": [ + "print(\"Speed of car 2:\", car2.current_speed)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: Speed decreases by 10\n", + "INFO: Speed decreases by 10\n", + "INFO: Speed decreases by 10\n", + "INFO: Speed decreases by 10\n", + "INFO: Speed decreases by 10\n", + "INFO: Speed decreases by 10\n", + "INFO: Speed decreases by 10\n", + "INFO: Speed decreases by 10\n", + "INFO: Speed decreases by 10\n", + "INFO: The speed of this car has been decreased from 100 to 10\n" + ] + } + ], + "source": [ + "car1.brake(10)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: Speed decreases by 10\n", + "INFO: Speed decreases by 10\n", + "INFO: Speed decreases by 10\n", + "INFO: Speed decreases by 10\n", + "INFO: Speed decreases by 10\n", + "INFO: The speed of this car has been decreased from 50 to 0\n", + "Total cars on road: 2\n", + "INFO: The speed of this car has been decreased from 0 to 0\n", + "Parking the car...\n", + "Total cars on road: 1\n" + ] + } + ], + "source": [ + "car2.brake(0)\n", + "print(\"Total cars on road:\", Car.total_cars())\n", + "car2.parking()\n", + "print(\"Total cars on road:\", Car.total_cars())" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: The speed of this car has been increased from 0 to 80\n", + "Current temperature: 6.0 C\n", + "Current apparent_temperature: 1.0 C\n", + "Current rain: 0.0 mm\n", + "Current wind_speed: 5.9 m/s\n", + "Total cars on road: 2\n" + ] + } + ], + "source": [ + "car3.accelerate(80)# car3 is now on the road\n", + "car3.show_weather()\n", + "print(\"Total cars on road:\", Car.total_cars())" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO: The speed of this car has been increased from 0 to 10\n", + "Total cars on road: 3\n" + ] + } + ], + "source": [ + "car2.accelerate(10) # # car2 goes from parking on the road\n", + "print(\"Total cars on road:\", Car.total_cars())" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Current temperature: 6.0 C\n", + "Current apparent_temperature: 1.0 C\n", + "Current rain: 0.0 mm\n", + "Current wind_speed: 5.9 m/s\n" + ] + } + ], + "source": [ + "Car.show_weather()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}