Update moisture_rnn.py
[notebooks.git] / fmda / read_and_clean_tutorial.ipynb
blob169a7b02dd0ed698620c247c3371d6f50a5dc4c1
2  "cells": [
3   {
4    "cell_type": "code",
5    "execution_count": null,
6    "id": "9ddd1d89-abdb-4627-a0ca-23db006b62f4",
7    "metadata": {},
8    "outputs": [],
9    "source": [
10     "import yaml\n",
11     "import pickle\n",
12     "import os.path as osp\n",
13     "import subprocess\n",
14     "from urllib.parse import urlparse\n",
15     "import numpy as np\n",
16     "import matplotlib.pyplot as plt\n",
17     "from utils import time_intp, str2time, filter_nan_values, read_pkl, read_yml"
18    ]
19   },
20   {
21    "cell_type": "code",
22    "execution_count": null,
23    "id": "3c141ad1-b997-485f-a4a7-d0c1ee79eb09",
24    "metadata": {},
25    "outputs": [],
26    "source": []
27   },
28   {
29    "cell_type": "markdown",
30    "id": "609ea544-ed92-40a6-892b-1943e9f6f620",
31    "metadata": {},
32    "source": [
33     "## Setup"
34    ]
35   },
36   {
37    "cell_type": "code",
38    "execution_count": null,
39    "id": "41b0d403-7d6b-44f4-963f-8dc492ae0126",
40    "metadata": {},
41    "outputs": [],
42    "source": [
43     "retrieve_url(\"https://demo.openwfm.org/web/data/fmda/dicts/fmda_nw_202401-05_f05.pkl\", \"data/fmda_nw_202401-05_f05.pkl\")"
44    ]
45   },
46   {
47    "cell_type": "code",
48    "execution_count": null,
49    "id": "5a2972e2-e360-43b8-9706-01aee586096c",
50    "metadata": {},
51    "outputs": [],
52    "source": []
53   },
54   {
55    "cell_type": "code",
56    "execution_count": null,
57    "id": "e69e37b9-73ef-45a1-9738-844f26dc3323",
58    "metadata": {},
59    "outputs": [],
60    "source": [
61     "data_params = read_yml(\"params_data.yaml\")\n",
62     "data_params"
63    ]
64   },
65   {
66    "cell_type": "code",
67    "execution_count": null,
68    "id": "6b5c3c82-84ba-426c-b8d9-f540b5026158",
69    "metadata": {},
70    "outputs": [],
71    "source": [
72     "dat = read_pkl(\"data/test_CA_202401.pkl\")"
73    ]
74   },
75   {
76    "cell_type": "code",
77    "execution_count": null,
78    "id": "5b2aeecb-89e6-41d0-af88-59a07b929edc",
79    "metadata": {},
80    "outputs": [],
81    "source": [
82     "dat['NV040_202401']['RAWS']['fm']"
83    ]
84   },
85   {
86    "cell_type": "markdown",
87    "id": "dae0e47b-02eb-4759-9b95-3cc1b281d41e",
88    "metadata": {},
89    "source": [
90     "## Filters"
91    ]
92   },
93   {
94    "cell_type": "code",
95    "execution_count": null,
96    "id": "8d6fbd18-adad-4370-add7-164275fc010d",
97    "metadata": {},
98    "outputs": [],
99    "source": [
100     "def filter_fmc(x, data_params=data_params):\n",
101     "    # Vector to track which values of input x are set to na\n",
102     "    na_vec = np.zeros_like(x)\n",
103     "    \n",
104     "    # Filter extreme lows\n",
105     "    condition = x<= data_params['min_fm']\n",
106     "    x[condition] = np.nan\n",
107     "    na_vec[np.where(condition)] = 1\n",
108     "    \n",
109     "    # Filter extreme highs\n",
110     "    condition = x>= data_params['max_fm']\n",
111     "    x[condition] = np.nan\n",
112     "    na_vec[condition] = 1\n",
113     "    \n",
114     "    return x, na_vec"
115    ]
116   },
117   {
118    "cell_type": "code",
119    "execution_count": null,
120    "id": "e49e7951-228c-44ee-ae54-d941e9a350f2",
121    "metadata": {},
122    "outputs": [],
123    "source": [
124     "def filter_rain(r, data_params=data_params):\n",
125     "    # Vector to track which values of input x are set to na\n",
126     "    na_vec = np.zeros_like(r)\n",
127     "    \n",
128     "    # Filter extreme lows\n",
129     "    condition = r< data_params['min_rain']\n",
130     "    r[condition] = np.nan\n",
131     "    na_vec[np.where(condition)] = 1\n",
132     "    \n",
133     "    # Filter extreme highs\n",
134     "    condition = r>= data_params['max_rain']\n",
135     "    r[condition] = np.nan\n",
136     "    na_vec[condition] = 1    \n",
137     "\n",
138     "    return r, na_vec"
139    ]
140   },
141   {
142    "cell_type": "code",
143    "execution_count": null,
144    "id": "957c0a4f-874c-4cf7-ad73-45053c2fdecc",
145    "metadata": {},
146    "outputs": [],
147    "source": [
148     "def filter_wind(w, data_params=data_params):\n",
149     "    # Vector to track which values of input x are set to na\n",
150     "    na_vec = np.zeros_like(w)\n",
151     "    \n",
152     "    # Filter extreme lows\n",
153     "    condition = w< data_params['min_wind']\n",
154     "    w[condition] = np.nan\n",
155     "    na_vec[np.where(condition)] = 1\n",
156     "    \n",
157     "    # Filter extreme highs\n",
158     "    condition = w>= data_params['max_wind']\n",
159     "    w[condition] = np.nan\n",
160     "    na_vec[condition] = 1    \n",
161     "\n",
162     "    return w, na_vec"
163    ]
164   },
165   {
166    "cell_type": "code",
167    "execution_count": null,
168    "id": "7b6b4347-6abe-4c21-8318-06a766d67d21",
169    "metadata": {},
170    "outputs": [],
171    "source": [
172     "# Useful Cases:\n",
173     "    # NV040_202401: more raws observations than HRRR, interp should shorten\n",
174     "    # NV026_202401: raws 10min obs, interp should shorten\n",
175     "    # CGVC1_202401: missing only a few observations, interp should lengthen\n",
176     "    # YNWC1_202401: only 2 observations, should be filtered entirely"
177    ]
178   },
179   {
180    "cell_type": "code",
181    "execution_count": null,
182    "id": "74d3b25a-6803-41c5-855b-92ed980d3fcb",
183    "metadata": {},
184    "outputs": [],
185    "source": [
186     "def time_intp(t1, v1, t2):\n",
187     "    # Check if t1 v1 t2 are 1D arrays\n",
188     "    if t1.ndim != 1:\n",
189     "        logging.error(\"Error: t1 is not a 1D array. Dimension: %s\", t1.ndim)\n",
190     "        return None\n",
191     "    if v1.ndim != 1:\n",
192     "        logging.error(\"Error: v1 is not a 1D array. Dimension %s:\", v1.ndim)\n",
193     "        return None\n",
194     "    if t2.ndim != 1:\n",
195     "        logging.errorr(\"Error: t2 is not a 1D array. Dimension: %s\", t2.ndim)\n",
196     "        return None\n",
197     "    # Check if t1 and v1 have the same length\n",
198     "    if len(t1) != len(v1):\n",
199     "        logging.error(\"Error: t1 and v1 have different lengths: %s %s\",len(t1),len(v1))\n",
200     "        return None\n",
201     "    t1_no_nan, v1_no_nan = filter_nan_values(t1, v1)\n",
202     "    # print('t1_no_nan.dtype=',t1_no_nan.dtype)\n",
203     "    # Convert datetime objects to timestamps\n",
204     "    t1_stamps = np.array([t.timestamp() for t in t1_no_nan])\n",
205     "    t2_stamps = np.array([t.timestamp() for t in t2])\n",
206     "    "
207    ]
208   },
209   {
210    "cell_type": "code",
211    "execution_count": null,
212    "id": "2e1a9438-3bfa-4c6d-8f4e-2888409ecb75",
213    "metadata": {},
214    "outputs": [],
215    "source": [
216     "len(dat.keys())"
217    ]
218   },
219   {
220    "cell_type": "code",
221    "execution_count": null,
222    "id": "f7e77394-dea3-4b24-82ed-6ce3c7dab21e",
223    "metadata": {},
224    "outputs": [],
225    "source": [
226     "def filter_nan_cases(d, data_params=data_params):\n",
227     "    # Remove cases with too many NAN relative to interp target. Use to avoid over-interpolating\n",
228     "    ks = [] # accumulate keys to remove\n",
229     "    for k in dat:\n",
230     "        n_fm = dat[k]['RAWS']['fm'].shape[0]\n",
231     "        n_obs = dat[k]['HRRR']['time'].shape[0]\n",
232     "        pct_na = (1 - n_fm / n_obs)\n",
233     "        if pct_na > data_params['max_pct_na']:\n",
234     "            print(f\"Removing key {k} due to extensive missing data. Percent NA relative to HRRR: {np.round(pct_na, 3)}\")\n",
235     "            ks.append(k)\n",
236     "    for k in ks: d.pop(k, None)"
237    ]
238   },
239   {
240    "cell_type": "code",
241    "execution_count": null,
242    "id": "faffc4ea-1b96-4ab4-af44-e2555eba39e1",
243    "metadata": {},
244    "outputs": [],
245    "source": [
246     "filter_nan_cases(dat)"
247    ]
248   },
249   {
250    "cell_type": "code",
251    "execution_count": null,
252    "id": "ac4c695e-bcc6-4e53-b934-f3837dac70ca",
253    "metadata": {},
254    "outputs": [],
255    "source": [
256     "len(dat.keys())"
257    ]
258   },
259   {
260    "cell_type": "code",
261    "execution_count": null,
262    "id": "c3fb7817-82b4-49ee-8c62-ef7308648c02",
263    "metadata": {},
264    "outputs": [],
265    "source": []
266   },
267   {
268    "cell_type": "code",
269    "execution_count": null,
270    "id": "a9f0b53b-b291-4592-ab0a-d05a6d2f770c",
271    "metadata": {},
272    "outputs": [],
273    "source": []
274   },
275   {
276    "cell_type": "code",
277    "execution_count": null,
278    "id": "9b7af652-5836-480f-861c-09bacaf035ea",
279    "metadata": {},
280    "outputs": [],
281    "source": [
282     "d = dat['NV026_202401']"
283    ]
284   },
285   {
286    "cell_type": "code",
287    "execution_count": null,
288    "id": "c5d7d2d6-cbae-402c-8585-a48ceba8f431",
289    "metadata": {},
290    "outputs": [],
291    "source": [
292     "d['RAWS']['fm'].shape"
293    ]
294   },
295   {
296    "cell_type": "code",
297    "execution_count": null,
298    "id": "ceb44038-b166-4827-a9ab-f62f51971c39",
299    "metadata": {},
300    "outputs": [],
301    "source": [
302     "d['RAWS']['time_raws'].shape"
303    ]
304   },
305   {
306    "cell_type": "code",
307    "execution_count": null,
308    "id": "481bb0b6-b5de-4244-89bc-24b6073e5cd4",
309    "metadata": {},
310    "outputs": [],
311    "source": [
312     "d['HRRR']['f01']['Ed'].shape"
313    ]
314   },
315   {
316    "cell_type": "code",
317    "execution_count": null,
318    "id": "88d3d4b6-c482-4158-ae13-daf729c2a496",
319    "metadata": {},
320    "outputs": [],
321    "source": [
322     "d['HRRR']['time'].shape"
323    ]
324   },
325   {
326    "cell_type": "code",
327    "execution_count": null,
328    "id": "d834581e-eb4a-494f-894a-5c81ff92bf85",
329    "metadata": {},
330    "outputs": [],
331    "source": [
332     "from utils import str2time\n",
333     "d = dat['NV040_202401']\n",
334     "time_raws=str2time(d['RAWS']['time_raws']) \n",
335     "time_hrrr=str2time(d['HRRR']['time'])\n",
336     "\n",
337     "t1 = np.array([t.timestamp() for t in time_raws])\n",
338     "t2 = np.array([t.timestamp() for t in time_hrrr])"
339    ]
340   },
341   {
342    "cell_type": "code",
343    "execution_count": null,
344    "id": "266ac8f6-119b-4424-b162-9077ab76b8e4",
345    "metadata": {},
346    "outputs": [],
347    "source": [
348     "tnew = np.interp(t2, t1, t1)"
349    ]
350   },
351   {
352    "cell_type": "code",
353    "execution_count": null,
354    "id": "1950759a-a332-4054-aee1-b086fbf4c39c",
355    "metadata": {},
356    "outputs": [],
357    "source": [
358     "np.isin(tnew, t1).mean()"
359    ]
360   },
361   {
362    "cell_type": "code",
363    "execution_count": null,
364    "id": "8b93c8ae-cfbb-4344-beda-5d3f60ed8ed9",
365    "metadata": {},
366    "outputs": [],
367    "source": []
368   },
369   {
370    "cell_type": "code",
371    "execution_count": null,
372    "id": "1c9a2263-9ec2-4c7e-9c79-90f8209a4c87",
373    "metadata": {},
374    "outputs": [],
375    "source": []
376   },
377   {
378    "cell_type": "code",
379    "execution_count": null,
380    "id": "9e2a78e5-330a-49ce-9dc9-babcb580d0d4",
381    "metadata": {},
382    "outputs": [],
383    "source": [
384     "d = dat['LIB03_202401']"
385    ]
386   },
387   {
388    "cell_type": "code",
389    "execution_count": null,
390    "id": "08b4c474-4332-4b45-9110-d8a21432cdf9",
391    "metadata": {},
392    "outputs": [],
393    "source": [
394     "d['RAWS']['fm'].shape"
395    ]
396   },
397   {
398    "cell_type": "code",
399    "execution_count": null,
400    "id": "1c12c514-37db-4b13-a35d-bd28651c00b4",
401    "metadata": {},
402    "outputs": [],
403    "source": [
404     "d['RAWS']['time_raws'].shape"
405    ]
406   },
407   {
408    "cell_type": "code",
409    "execution_count": null,
410    "id": "9846b2ae-38a8-4f0b-96a6-1c21d0ecb616",
411    "metadata": {},
412    "outputs": [],
413    "source": [
414     "d['HRRR']['f01']['Ed'].shape"
415    ]
416   },
417   {
418    "cell_type": "code",
419    "execution_count": null,
420    "id": "614fe317-8233-4dbf-97c8-c2d8d8923fea",
421    "metadata": {},
422    "outputs": [],
423    "source": [
424     "d['HRRR']['time'].shape"
425    ]
426   },
427   {
428    "cell_type": "code",
429    "execution_count": null,
430    "id": "40be5a62-06ec-4623-9684-bf186c3bcd1d",
431    "metadata": {},
432    "outputs": [],
433    "source": []
434   },
435   {
436    "cell_type": "code",
437    "execution_count": null,
438    "id": "081e0202-2bc0-4bd8-b4ab-f5eec289b70c",
439    "metadata": {},
440    "outputs": [],
441    "source": []
442   },
443   {
444    "cell_type": "code",
445    "execution_count": null,
446    "id": "31a1d814-9028-4213-ad9d-fabf1e35b554",
447    "metadata": {},
448    "outputs": [],
449    "source": []
450   },
451   {
452    "cell_type": "code",
453    "execution_count": null,
454    "id": "42de9659-3725-4f92-b17c-455126e89c47",
455    "metadata": {},
456    "outputs": [],
457    "source": []
458   },
459   {
460    "cell_type": "code",
461    "execution_count": null,
462    "id": "37cb45e7-b46b-429b-a9be-6c3a35677a28",
463    "metadata": {},
464    "outputs": [],
465    "source": []
466   },
467   {
468    "cell_type": "code",
469    "execution_count": null,
470    "id": "3f007941-6682-4022-9b78-48c214152635",
471    "metadata": {},
472    "outputs": [],
473    "source": []
474   },
475   {
476    "cell_type": "code",
477    "execution_count": null,
478    "id": "20687996-8267-4e93-9e24-b9515259e256",
479    "metadata": {},
480    "outputs": [],
481    "source": []
482   },
483   {
484    "cell_type": "code",
485    "execution_count": null,
486    "id": "55ce3b0e-7135-43ff-86ab-379c50b349db",
487    "metadata": {},
488    "outputs": [],
489    "source": [
490     "time_raws = str2time(dat['NV040_202401']['RAWS']['time_raws'])\n",
491     "time_hrrr = str2time(dat['NV040_202401']['HRRR']['time'])\n",
492     "fm = dat['NV040_202401']['RAWS']['fm']\n",
493     "rain = dat['NV040_202401']['HRRR']['f01']['rain']"
494    ]
495   },
496   {
497    "cell_type": "code",
498    "execution_count": null,
499    "id": "cc4fd0b0-286b-4cd9-88c4-59e996348235",
500    "metadata": {},
501    "outputs": [],
502    "source": [
503     "len(time_raws) == len(fm)"
504    ]
505   },
506   {
507    "cell_type": "code",
508    "execution_count": null,
509    "id": "1680ed39-a021-4631-a764-40f354cf6a09",
510    "metadata": {},
511    "outputs": [],
512    "source": [
513     "filter_fmc(fm)"
514    ]
515   },
516   {
517    "cell_type": "code",
518    "execution_count": null,
519    "id": "8a3c405a-f976-4756-aaec-63998d58203d",
520    "metadata": {},
521    "outputs": [],
522    "source": [
523     "filter_rain(rain)"
524    ]
525   },
526   {
527    "cell_type": "code",
528    "execution_count": null,
529    "id": "5f49d9d4-2edf-434e-8812-c8c6ef3fbb2f",
530    "metadata": {},
531    "outputs": [],
532    "source": [
533     "filter_wind(dat['NV040_202401']['HRRR']['f01']['wind'])"
534    ]
535   },
536   {
537    "cell_type": "code",
538    "execution_count": null,
539    "id": "3d6a8fe7-1864-475a-a4f3-0fe04806ad50",
540    "metadata": {},
541    "outputs": [],
542    "source": [
543     "dat['NV040_202401']['RAWS']['wind']"
544    ]
545   },
546   {
547    "cell_type": "code",
548    "execution_count": null,
549    "id": "25ad1ce4-2060-4ece-932a-396813e56dc6",
550    "metadata": {},
551    "outputs": [],
552    "source": [
553     "dat['CNFC1_202401']['RAWS'].keys()"
554    ]
555   },
556   {
557    "cell_type": "code",
558    "execution_count": null,
559    "id": "a58ca663-074d-4eb4-a644-c9e05a415e65",
560    "metadata": {},
561    "outputs": [],
562    "source": [
563     "dat['CNFC1_202401']['RAWS']['solar']"
564    ]
565   },
566   {
567    "cell_type": "code",
568    "execution_count": null,
569    "id": "c2f27bfb-73fc-4bc6-9abc-ac1f5ab46acd",
570    "metadata": {},
571    "outputs": [],
572    "source": [
573     "dat['CNFC1_202401']['HRRR']['f01']['wind']"
574    ]
575   },
576   {
577    "cell_type": "code",
578    "execution_count": null,
579    "id": "74b98be4-55b1-4db2-81de-5f650aa00bb2",
580    "metadata": {},
581    "outputs": [],
582    "source": [
583     "dat['CNFC1_202401']['HRRR']['f01']['soilm']"
584    ]
585   },
586   {
587    "cell_type": "code",
588    "execution_count": null,
589    "id": "915f9534-ff84-4844-bde4-dce567d222c5",
590    "metadata": {},
591    "outputs": [],
592    "source": []
593   },
594   {
595    "cell_type": "code",
596    "execution_count": null,
597    "id": "cd2f357d-c813-4aa0-b3f7-cdc72f1f660c",
598    "metadata": {},
599    "outputs": [],
600    "source": [
601     "for k in dat:\n",
602     "    print(\"~\"*50)\n",
603     "    print(k)\n",
604     "    print(f\"HRRR Shape: {dat[k]['HRRR']['f01']['Ew'].shape}\")\n",
605     "    print(f\"RAWS Shape: {dat[k]['RAWS']['fm'].shape}\")"
606    ]
607   },
608   {
609    "cell_type": "code",
610    "execution_count": null,
611    "id": "1ab4cb8b-1aa8-4541-a5cc-041c493d8894",
612    "metadata": {},
613    "outputs": [],
614    "source": [
615     "dat['LIB03_202401']['RAWS']['soil_moisture']"
616    ]
617   },
618   {
619    "cell_type": "code",
620    "execution_count": null,
621    "id": "f62a897e-eeb8-4951-b64f-8b6ee11bc92a",
622    "metadata": {},
623    "outputs": [],
624    "source": [
625     "dat['LIB03_202401']['HRRR']['f01']['soilm']"
626    ]
627   },
628   {
629    "cell_type": "code",
630    "execution_count": null,
631    "id": "5037b7f3-a749-4b27-9e4c-f6c8d4fb8b6d",
632    "metadata": {},
633    "outputs": [],
634    "source": [
635     "for k in dat:\n",
636     "    print(\"~\"*50)\n",
637     "    print(k)\n",
638     "    # Filter RAWS\n",
639     "    fm, filter_vec = filter_fmc(dat[k][\"RAWS\"]['fm'])\n",
640     "    print(f\"Percent FMC Observations Filtered: {np.mean(filter_vec)}\")\n",
641     "    if 'rain' in dat[k][\"RAWS\"].keys():\n",
642     "        rain, filter_vec = filter_rain(dat[k][\"RAWS\"]['rain'])\n",
643     "        print(f\"Percent Rain Observations Filtered: {np.mean(filter_vec)}\")\n",
644     "    if 'wind' in dat[k][\"RAWS\"].keys():\n",
645     "        wind, filter_vec = filter_rain(dat[k][\"RAWS\"]['wind'])\n",
646     "        print(f\"Percent Wind Observations Filtered: {np.mean(filter_vec)}\")\n",
647     "    # Filter HRRR unncessesary? "
648    ]
649   },
650   {
651    "cell_type": "code",
652    "execution_count": null,
653    "id": "abd5985c-c727-44fb-a1d6-b212dc24d3ac",
654    "metadata": {},
655    "outputs": [],
656    "source": []
657   },
658   {
659    "cell_type": "code",
660    "execution_count": null,
661    "id": "3e6849f7-e983-446e-9d1b-26a1b4c693fd",
662    "metadata": {},
663    "outputs": [],
664    "source": []
665   },
666   {
667    "cell_type": "code",
668    "execution_count": null,
669    "id": "3b307ae1-980d-487a-aad4-f2fc0a87cbcf",
670    "metadata": {},
671    "outputs": [],
672    "source": []
673   },
674   {
675    "cell_type": "code",
676    "execution_count": null,
677    "id": "6d7b7335-589e-49bd-88bd-20b7b2a40611",
678    "metadata": {},
679    "outputs": [],
680    "source": []
681   },
682   {
683    "cell_type": "code",
684    "execution_count": null,
685    "id": "982de3ce-e883-4eab-88dd-41295da16e7f",
686    "metadata": {},
687    "outputs": [],
688    "source": []
689   },
690   {
691    "cell_type": "code",
692    "execution_count": null,
693    "id": "940e36a7-1597-4bac-8a82-3ecb602e124c",
694    "metadata": {},
695    "outputs": [],
696    "source": []
697   },
698   {
699    "cell_type": "code",
700    "execution_count": null,
701    "id": "b34546f9-5c28-4c29-9148-0473fa9e00c1",
702    "metadata": {},
703    "outputs": [],
704    "source": []
705   },
706   {
707    "cell_type": "code",
708    "execution_count": null,
709    "id": "81a421c8-ed47-40f2-83c2-d258bce764f4",
710    "metadata": {},
711    "outputs": [],
712    "source": []
713   },
714   {
715    "cell_type": "code",
716    "execution_count": null,
717    "id": "897f84d1-4ac8-478a-82f1-ed59052b0199",
718    "metadata": {},
719    "outputs": [],
720    "source": [
721     "def foo():\n",
722     "    d = read_pkl()\n",
723     "    dat = format_fmda_data()\n",
724     "    dat = filter_data(dat)\n",
725     "    return dat"
726    ]
727   },
728   {
729    "cell_type": "code",
730    "execution_count": null,
731    "id": "ed4112af-2b76-4b57-8d2e-1e5e0cba3b42",
732    "metadata": {},
733    "outputs": [],
734    "source": [
735     "def format_fmda_data(d):\n",
736     "    # Inputs:\n",
737     "    #    d: (dict) fmda dictionary, output of process in wrfxpy\n",
738     "\n",
739     "    return d"
740    ]
741   },
742   {
743    "cell_type": "code",
744    "execution_count": null,
745    "id": "b0ebb758-d1ec-477f-b6af-207dbe2a01d1",
746    "metadata": {},
747    "outputs": [],
748    "source": []
749   },
750   {
751    "cell_type": "code",
752    "execution_count": null,
753    "id": "e4d704f9-cb10-4b3a-a65d-cf1a26ddb9d4",
754    "metadata": {},
755    "outputs": [],
756    "source": []
757   },
758   {
759    "cell_type": "code",
760    "execution_count": null,
761    "id": "c5972b2b-eab2-4705-8401-6aa746203ac1",
762    "metadata": {},
763    "outputs": [],
764    "source": []
765   },
766   {
767    "cell_type": "code",
768    "execution_count": null,
769    "id": "0818c399-be45-4520-9b9e-d847a73ea1bf",
770    "metadata": {},
771    "outputs": [],
772    "source": []
773   },
774   {
775    "cell_type": "code",
776    "execution_count": null,
777    "id": "94ad78d5-47a0-4c9e-abe8-9f3cfc67208f",
778    "metadata": {},
779    "outputs": [],
780    "source": []
781   }
782  ],
783  "metadata": {
784   "kernelspec": {
785    "display_name": "Python 3 (ipykernel)",
786    "language": "python",
787    "name": "python3"
788   },
789   "language_info": {
790    "codemirror_mode": {
791     "name": "ipython",
792     "version": 3
793    },
794    "file_extension": ".py",
795    "mimetype": "text/x-python",
796    "name": "python",
797    "nbconvert_exporter": "python",
798    "pygments_lexer": "ipython3",
799    "version": "3.12.5"
800   }
801  },
802  "nbformat": 4,
803  "nbformat_minor": 5