test_conversion.py 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073
  1. import climate_categories as cc
  2. import primap2 as pm2
  3. import xarray as xr
  4. from src.faostat_data_primap.helper.paths import (
  5. downloaded_data_path,
  6. extracted_data_path,
  7. )
  8. from src.faostat_data_primap.read import read_data
  9. def test_conversion_from_FAO_to_IPCC2006_PRIMAP():
  10. # make categorisation A from yaml
  11. categorisation_a = cc.from_python("FAO.py")
  12. # make categorisation B from yaml
  13. categorisation_b = cc.IPCC2006_PRIMAP
  14. # category FAOSTAT not yet part of climate categories, so we need to add it manually
  15. cats = {
  16. "FAOSTAT": categorisation_a,
  17. "IPCC2006_PRIMAP": categorisation_b,
  18. }
  19. ds_fao = (
  20. extracted_data_path
  21. / "v2024-11-14/FAOSTAT_Agrifood_system_emissions_v2024-11-14_raw.nc"
  22. )
  23. ds = pm2.open_dataset(ds_fao)
  24. # consistency check in original categorisation
  25. # drop UNFCCC data
  26. ds = ds.drop_sel(source="UNFCCC")
  27. # Checking consistency of category tree in FAO categorisation
  28. # There are discrepancies of up to 100% due to rounding errors for small values
  29. # theoretical example, 0.0001 (rounded from 0.00006) + 0.0004 (rounded from 0.00036)
  30. # = 0.00042 which is then rounded to 0.0004, while the consistency check expects 0.0005
  31. # At the moment, we are only checking categories that will later be used by primap-hist.
  32. # If we want to use other categories we should expand this consistency check.
  33. agg_info_fao = {
  34. "category (FAOSTAT)": {
  35. # 1.A.1 wheat
  36. # rounding errors
  37. "1.A.1.a": {
  38. "tolerance": 1,
  39. "sources": [
  40. "1.A.1.a.i",
  41. "1.A.1.a.ii",
  42. ],
  43. "sel": {"variable": ["N2O"]},
  44. },
  45. "1.A.1": {
  46. "tolerance": 0.01,
  47. "sources": [
  48. "1.A.1.a",
  49. "1.A.1.b",
  50. ],
  51. "sel": {"variable": ["N2O", "CH4"]},
  52. },
  53. # 1.A.2 rice
  54. # rounding errors
  55. "1.A.2.a": {
  56. "tolerance": 1,
  57. "sources": [
  58. "1.A.2.a.i",
  59. "1.A.2.a.ii",
  60. ],
  61. "sel": {"variable": ["N2O"]},
  62. },
  63. "1.A.2": {
  64. "tolerance": 0.01,
  65. "sources": [
  66. "1.A.2.a",
  67. "1.A.2.b",
  68. "1.A.2.c", # rice cultivation CH4
  69. ],
  70. "sel": {"variable": ["N2O", "CH4"]},
  71. },
  72. # potatoes
  73. "1.A.3.a": {
  74. "tolerance": 1,
  75. "sources": [
  76. "1.A.3.a.i",
  77. "1.A.3.a.ii",
  78. ],
  79. "sel": {"variable": ["N2O"]},
  80. },
  81. "1.A.3": {
  82. "tolerance": 0.01,
  83. "sources": [
  84. "1.A.3.a",
  85. ],
  86. "sel": {"variable": ["N2O"]},
  87. },
  88. # millet
  89. "1.A.4.a": {
  90. "tolerance": 1,
  91. "sources": [
  92. "1.A.4.a.i",
  93. "1.A.4.a.ii",
  94. ],
  95. "sel": {"variable": ["N2O"]},
  96. },
  97. "1.A.4": {
  98. "tolerance": 0.01,
  99. "sources": [
  100. "1.A.4.a",
  101. ],
  102. "sel": {"variable": ["N2O"]},
  103. },
  104. # barley
  105. "1.A.5.a": {
  106. "tolerance": 1,
  107. "sources": [
  108. "1.A.5.a.i",
  109. "1.A.5.a.ii",
  110. ],
  111. "sel": {"variable": ["N2O"]},
  112. },
  113. "1.A.5": {
  114. "tolerance": 0.01,
  115. "sources": [
  116. "1.A.5.a",
  117. ],
  118. "sel": {"variable": ["N2O"]},
  119. },
  120. # barley
  121. "1.A.6.a": {
  122. "tolerance": 1,
  123. "sources": [
  124. "1.A.6.a.i",
  125. "1.A.6.a.ii",
  126. ],
  127. "sel": {"variable": ["N2O"]},
  128. },
  129. "1.A.6": {
  130. "tolerance": 0.01,
  131. "sources": [
  132. "1.A.6.a",
  133. "1.A.6.b",
  134. ],
  135. "sel": {"variable": ["N2O", "CH4"]},
  136. },
  137. # sugar cane
  138. "1.A.7.a": {
  139. "tolerance": 1,
  140. "sources": [
  141. "1.A.7.a.i",
  142. "1.A.7.a.ii",
  143. ],
  144. "sel": {"variable": ["N2O"]},
  145. },
  146. "1.A.7": {
  147. "tolerance": 0.01,
  148. "sources": [
  149. "1.A.7.a",
  150. "1.A.7.b",
  151. ],
  152. "sel": {"variable": ["N2O", "CH4"]},
  153. },
  154. # dry beans
  155. "1.A.8.a": {
  156. "tolerance": 1,
  157. "sources": [
  158. "1.A.8.a.i",
  159. "1.A.8.a.ii",
  160. ],
  161. "sel": {"variable": ["N2O"]},
  162. },
  163. "1.A.8": {
  164. "tolerance": 0.01,
  165. "sources": [
  166. "1.A.8.a",
  167. ],
  168. "sel": {"variable": ["N2O"]},
  169. },
  170. # oats
  171. "1.A.9.a": {
  172. "tolerance": 1,
  173. "sources": [
  174. "1.A.9.a.i",
  175. "1.A.9.a.ii",
  176. ],
  177. "sel": {"variable": ["N2O"]},
  178. },
  179. "1.A.9": {
  180. "tolerance": 0.01,
  181. "sources": [
  182. "1.A.9.a",
  183. ],
  184. "sel": {"variable": ["N2O"]},
  185. },
  186. # rye
  187. "1.A.10.a": {
  188. "tolerance": 1,
  189. "sources": [
  190. "1.A.10.a.i",
  191. "1.A.10.a.ii",
  192. ],
  193. "sel": {"variable": ["N2O"]},
  194. },
  195. "1.A.10": {
  196. "tolerance": 0.01,
  197. "sources": [
  198. "1.A.10.a",
  199. ],
  200. "sel": {"variable": ["N2O"]},
  201. },
  202. # sorghum
  203. "1.A.11.a": {
  204. "tolerance": 1,
  205. "sources": [
  206. "1.A.11.a.i",
  207. "1.A.11.a.ii",
  208. ],
  209. "sel": {"variable": ["N2O"]},
  210. },
  211. "1.A.11": {
  212. "tolerance": 0.01,
  213. "sources": [
  214. "1.A.11.a",
  215. ],
  216. "sel": {"variable": ["N2O"]},
  217. },
  218. # soya beans
  219. "1.A.12.a": {
  220. "tolerance": 1,
  221. "sources": [
  222. "1.A.12.a.i",
  223. "1.A.12.a.ii",
  224. ],
  225. "sel": {"variable": ["N2O"]},
  226. },
  227. "1.A.12": {
  228. "tolerance": 0.01,
  229. "sources": [
  230. "1.A.12.a",
  231. ],
  232. "sel": {"variable": ["N2O"]},
  233. },
  234. "1.A": {
  235. # some rounding errors for CH4
  236. "tolerance": 1,
  237. "sources": [
  238. "1.A.1",
  239. "1.A.2",
  240. "1.A.3",
  241. "1.A.4",
  242. "1.A.5",
  243. "1.A.6",
  244. "1.A.7",
  245. "1.A.8",
  246. "1.A.9",
  247. "1.A.10",
  248. "1.A.11",
  249. "1.A.12",
  250. ],
  251. },
  252. "1.B.2": {
  253. "tolerance": 0.01,
  254. "sources": [
  255. "1.B.2.a",
  256. "1.B.2.b",
  257. ],
  258. "sel": {"variable": ["N2O"]},
  259. },
  260. "1.B": {
  261. "tolerance": 1,
  262. "sources": [
  263. "1.B.1",
  264. "1.B.2",
  265. ],
  266. "sel": {"variable": ["N2O"]},
  267. },
  268. # Category 1 is not available on FAOSTAT, so that's not a check
  269. "1": {
  270. "tolerance": 0.01,
  271. "sources": [
  272. "1.A",
  273. "1.B",
  274. ],
  275. },
  276. "3": {
  277. # mostly rounding errors, Macedonia slightly higher than 100% discrepancy
  278. # Saint Pierre and Miquelon, 1992, N20 200% error, considered negligible
  279. "tolerance": 2.01,
  280. "sources": [
  281. "3.A",
  282. "3.B",
  283. "3.C",
  284. "3.D",
  285. "3.E",
  286. "3.F",
  287. "3.G",
  288. "3.H",
  289. "3.I",
  290. "3.J",
  291. "3.K",
  292. "3.L",
  293. # "3.M", # poultry is an aggregate of other categories I forgot to remove
  294. "3.N",
  295. "3.O",
  296. "3.P",
  297. "3.Q",
  298. "3.R",
  299. ],
  300. "sel": {"variable": ["CH4", "N2O"]},
  301. },
  302. "4": {
  303. "tolerance": 0.01,
  304. "sources": [
  305. "4.A",
  306. "4.B",
  307. ],
  308. "sel": {"variable": ["CO2"]},
  309. },
  310. "6.B": {
  311. # rounding errors, NLD looks problematic but hard to tell which value is right
  312. "tolerance": 1,
  313. "sources": [
  314. "6.B.1",
  315. "6.B.2",
  316. "6.B.3",
  317. "6.B.4",
  318. "6.B.5",
  319. ],
  320. "sel": {"variable": ["CH4", "N2O", "CO2"]},
  321. },
  322. }
  323. }
  324. ds_checked = ds.pr.add_aggregates_coordinates(agg_info=agg_info_fao) # noqa: F841
  325. # ds_checked_if = ds_checked.pr.to_interchange_format()
  326. # We need a comversion CSV file for each entity
  327. # That's a temporary workaround until convert function can filter for data variables (entities)
  328. conv = {}
  329. gases = ["CO2", "CH4", "N2O"]
  330. for var in gases:
  331. conv[var] = cc.Conversion.from_csv(
  332. f"../../conversion_FAO_IPPCC2006_PRIMAP_{var}.csv", cats=cats
  333. )
  334. # convert for each entity
  335. da_dict = {}
  336. for var in gases:
  337. da_dict[var] = ds[var].pr.convert(
  338. dim="category (FAOSTAT)",
  339. conversion=conv[var],
  340. )
  341. result = xr.Dataset(da_dict)
  342. result.attrs = ds.attrs
  343. result.attrs["cat"] = "category (IPCC2006_PRIMAP)"
  344. # convert to interchange format and back to get rid of empty categories
  345. result_if = result.pr.to_interchange_format()
  346. result = pm2.pm2io.from_interchange_format(result_if)
  347. agg_info = {
  348. "category (IPCC2006_PRIMAP)": {
  349. "3.C.1": {
  350. "sources": ["3.C.1.a", "3.C.1.b", "3.C.1.c"],
  351. },
  352. "M.3.C.AG": {
  353. "sources": [
  354. "3.C.1.b", # Biomass Burning In Croplands
  355. "3.C.1.c", # Biomass Burning in Grasslands
  356. "3.C.4", # Direct N2O Emissions from Managed Soils
  357. "3.C.5", # Indirect N2O Emissions from Managed Soils
  358. "3.C.6", # Indirect N2O Emissions from Manure Management
  359. ],
  360. },
  361. "M.AG.ELV": {
  362. "sources": ["M.3.C.AG"], # "M.3.D.AG" is zero
  363. },
  364. "3.C": {
  365. "sources": [
  366. "3.C.1",
  367. "3.C.2",
  368. "3.C.3",
  369. "3.C.4",
  370. "3.C.5",
  371. "3.C.6",
  372. "3.C.7",
  373. ]
  374. },
  375. # "3.D" : {"sources" : ["3.D.1", "3.D.2"]}, # we don't have it
  376. "3.A.1.a": { # cattle (dairy) + cattle (non-dairy)
  377. "sources": [
  378. "3.A.1.a.i",
  379. "3.A.1.a.ii",
  380. ]
  381. },
  382. "3.A.1": {
  383. "sources": [
  384. "3.A.1.a",
  385. "3.A.1.b",
  386. "3.A.1.c",
  387. "3.A.1.d",
  388. "3.A.1.e",
  389. "3.A.1.f",
  390. "3.A.1.g",
  391. "3.A.1.h", # 3.A.1.i poultry left out because it is a group of categories
  392. "3.A.1.j",
  393. ]
  394. },
  395. "3.A.2.a": { # decomposition of manure cattle (dairy) + cattle (non-dairy)
  396. "sources": [
  397. "3.A.2.a.i",
  398. "3.A.2.a.ii",
  399. ]
  400. },
  401. "3.A.2": {
  402. "sources": [
  403. "3.A.2.a",
  404. "3.A.2.b",
  405. "3.A.2.c",
  406. "3.A.2.d",
  407. "3.A.2.e",
  408. "3.A.2.f",
  409. "3.A.2.g",
  410. "3.A.2.h",
  411. "3.A.2.i",
  412. "3.A.2.j",
  413. ]
  414. },
  415. "3.A": {"sources": ["3.A.1", "3.A.2"]},
  416. "M.AG": {"sources": ["3.A", "M.AG.ELV"]},
  417. # "M.3.D.LU": {"sources": ["3.D.1"]},
  418. # For LULUCF Forest Land, Cropland, Grassland, is all we have
  419. "M.LULUCF": {
  420. "sources": [
  421. "3.B.1", # Carbon stock change in forests
  422. "3.B.2", # Drained grassland
  423. "3.B.3", # Drained cropland
  424. "3.C.1.a", # Biomass Burning In Forests
  425. ]
  426. }, # forest fires
  427. "3": {"sources": ["M.AG", "M.LULUCF"]},
  428. }
  429. }
  430. result_proc = result.pr.add_aggregates_coordinates(agg_info=agg_info)
  431. result_proc_if = result_proc.pr.to_interchange_format()
  432. # save processed data
  433. release_name = "v2024-11-14"
  434. output_filename = f"FAOSTAT_Agrifood_system_emissions_{release_name}"
  435. output_folder = extracted_data_path / release_name
  436. if not output_folder.exists():
  437. output_folder.mkdir()
  438. filepath = output_folder / (output_filename + ".csv")
  439. print(f"Writing processed primap2 file to {filepath}")
  440. pm2.pm2io.write_interchange_format(
  441. filepath,
  442. result_proc_if,
  443. )
  444. compression = dict(zlib=True, complevel=9)
  445. encoding = {var: compression for var in result_proc.data_vars}
  446. filepath = output_folder / (output_filename + ".nc")
  447. print(f"Writing netcdf file to {filepath}")
  448. result_proc.pr.to_netcdf(filepath, encoding=encoding)
  449. def test_read(tmp_path):
  450. domains_and_releases_to_read = [
  451. # ("farm_gate_agriculture_energy", "2024-11-14"),
  452. # ("farm_gate_emissions_crops", "2024-11-14"),
  453. # ("farm_gate_livestock", "2024-11-14"),
  454. # ("land_use_drained_organic_soils", "2024-11-14"),
  455. ("land_use_fires", "2023-11-09"),
  456. # ("land_use_forests", "2024-11-14"),
  457. # ("pre_post_agricultural_production", "2024-11-14"),
  458. ]
  459. read_data(
  460. domains_and_releases_to_read=domains_and_releases_to_read,
  461. read_path=downloaded_data_path,
  462. save_path=tmp_path,
  463. )
  464. def test_yaml_to_python():
  465. cat = cc.from_yaml("FAO.yaml")
  466. cat.to_python("FAO.py")
  467. def test_python_to_yaml():
  468. from FAO import spec
  469. cat = cc.from_spec(spec)
  470. assert cat
  471. def test_make_dict_comprehension_for_faster_typing(): # noqa: PLR0912 PLR0915
  472. spec = {
  473. "name": "FAOSTAT",
  474. "title": (
  475. "Food and Agriculture Organization of the United Nations (FAO) "
  476. "FAOSTAT data set categorisation"
  477. ),
  478. "comment": "Needed to add FAOSTAT data to PRIMAP-hist",
  479. "references": "",
  480. "institution": "FAO",
  481. "hierarchical": True,
  482. "last_update": "2024-12-10",
  483. "version": "2024",
  484. "total_sum": True,
  485. "canonical_top_level_category": "0",
  486. }
  487. categories = {}
  488. # 0. main categories
  489. categories["0"] = {
  490. "title": "Total",
  491. "comment": "All emissions and removals",
  492. "children": [["1", "2", "3", "4", "5", "6", "7"]],
  493. }
  494. children_1 = ["1.A", "1.B"]
  495. children_2 = ["2.A", "2.B", "2.C", "2.D", "2.E"]
  496. children_3 = [f"3.{i}" for i in "ABCDEFGHIJKLMNOPQR"]
  497. # children_4 = ["4.A"]
  498. # children_5 = ["5.A", "5.B"]
  499. # children_6 = ["6.A", "6.B", "6.C"]
  500. # children_7 = [f"3.{i}" for i in "ABCDEFGHIJKLM"]
  501. main_categories = (
  502. # category code, name and comment, gases, children
  503. ("1", "Crops", ["CH4", "N2O"], children_1),
  504. (
  505. "2",
  506. "Energy use in agriculture",
  507. ["CH4", "N2O", "CO2"],
  508. children_2,
  509. ),
  510. ("3", "Livestock", ["CH4", "N2O"], children_3),
  511. # ("4", "Forest", ["CO2"], children_4),
  512. # (
  513. # "5",
  514. # "Drained organic soils",
  515. # ["N2O", "CO2"],
  516. # children_5,
  517. # ),
  518. # ("6", "Fires", ["CH4", "N2O", "CO2"], children_6),
  519. # (
  520. # "7",
  521. # "Pre and post agricultural production",
  522. # ["CH4", "N2O", "CO2"],
  523. # children_7,
  524. # ),
  525. )
  526. for code, name, gases, children in main_categories:
  527. categories[code] = {
  528. "title": name,
  529. "comment": name,
  530. # "alternative_codes": code.replace(".", ""),
  531. "children": [children],
  532. "info": {"gases": gases},
  533. }
  534. # 1. crops
  535. # all crops category
  536. code_all_crops = "1.A"
  537. codes_crops = [f"1.A.{i}" for i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]
  538. categories[code_all_crops] = {
  539. "title": "All crops",
  540. "comment": "All crops",
  541. # "alternative_codes": code_all_crops.replace(".", ""),
  542. "children": [codes_crops],
  543. "info": {"gases": ["CH4", "N2O"]},
  544. }
  545. crops = [
  546. "Wheat",
  547. "Rice",
  548. "Potatoes",
  549. "Millet",
  550. "Barley",
  551. "Maize (corn)",
  552. "Sugar cane",
  553. "Beans, dry",
  554. "Oats",
  555. "Rye",
  556. "Sorghum",
  557. "Soya beans",
  558. ]
  559. crop_burnings = [
  560. True,
  561. True,
  562. False,
  563. False,
  564. False,
  565. True,
  566. True,
  567. False,
  568. False,
  569. False,
  570. False,
  571. False,
  572. ]
  573. rice_cultivations = [
  574. False,
  575. True,
  576. False,
  577. False,
  578. False,
  579. False,
  580. False,
  581. False,
  582. False,
  583. False,
  584. False,
  585. False,
  586. ]
  587. for crop, code, crop_burning, rice_cultivation in zip(
  588. crops, codes_crops, crop_burnings, rice_cultivations
  589. ):
  590. # all crops have at least N2O emissions
  591. gases_main = "N2O"
  592. if crop_burning or rice_cultivation:
  593. gases_main = ["CH4", "N2O"]
  594. # all crops have at least crop residues as child
  595. children_main = [f"{code}.a"]
  596. if crop_burning:
  597. children_main.append(f"{code}.b")
  598. if rice_cultivation:
  599. children_main.append(f"{code}.c")
  600. categories[f"{code}"] = {
  601. "title": f"{crop}",
  602. "comment": f"{crop}",
  603. # "alternative_codes": [f"{code}".replace(".", "")],
  604. "info": {"gases": gases_main},
  605. "children": [children_main],
  606. }
  607. # crop residues (every crop has it)
  608. categories[f"{code}.a.i"] = {
  609. "title": f"{crop} crop residues direct emissions",
  610. "comment": f"{crop} crop residues direct emissions",
  611. # "alternative_codes": [f"{code}.a".replace(".", "")],
  612. "info": {"gases": ["N2O"]},
  613. }
  614. categories[f"{code}.a.ii"] = {
  615. "title": f"{crop} crop residues indirect emissions",
  616. "comment": f"{crop} crop residues indirect emissions",
  617. # "alternative_codes": [f"{code}.a.i".replace(".", "")],
  618. "info": {"gases": ["N2O"]},
  619. }
  620. categories[f"{code}.a"] = {
  621. "title": f"{crop} crop residues",
  622. "comment": f"{crop} crop residues",
  623. # "alternative_codes": [f"{code}.a".replace(".", "")],
  624. "info": {"gases": ["N2O"]},
  625. "children": [[f"{code}.a.ii", f"{code}.a.i"]],
  626. }
  627. if crop_burning:
  628. categories[f"{code}.b"] = {
  629. "title": f"{crop} burning crop residues",
  630. "comment": f"{crop} burning crop residues",
  631. # "alternative_codes": [f"{code}.b".replace(".", "")],
  632. "info": {"gases": ["CH4", "N2O"]},
  633. }
  634. if rice_cultivation:
  635. categories[f"{code}.c"] = {
  636. "title": "Rice cultivation",
  637. "comment": "Rice cultivation",
  638. # "alternative_codes": [f"{code}.c".replace(".", "")],
  639. "info": {"gases": ["CH4"]},
  640. }
  641. # synthetic fertilisers
  642. codes_synthetic_fertilisers = ["1.B", "1.B.1", "1.B.2", "1.B.2.a", "1.B.2.b"]
  643. names = [
  644. "Synthetic fertilisers",
  645. "Direct emissions",
  646. "Indirect emissions",
  647. "Indirect emissions that volatilise",
  648. "Indirect emissions that leach",
  649. ]
  650. children_cats = [["1.B.1", "1.B.2"], None, ["1.B.2.a", "1.B.2.b"], None, None]
  651. for code, name, child_cat in zip(codes_synthetic_fertilisers, names, children_cats):
  652. categories[code] = {
  653. "title": name,
  654. "comment": name,
  655. # "alternative_codes": [code.replace(".", "")],
  656. "info": {"gases": ["N2O"]},
  657. }
  658. if child_cat:
  659. categories[code]["children"] = [child_cat]
  660. # 2. energy use
  661. names = [
  662. "Natural gas",
  663. "Electricity",
  664. "Coal",
  665. "Heat",
  666. "Petroleum",
  667. ]
  668. codes = children_2
  669. for name, code in zip(names, codes):
  670. categories[code] = {
  671. "title": name,
  672. "comment": name,
  673. # "alternative_codes": code.replace(".", ""),
  674. "info": {"gases": ["CH4", "N2O", "CO2"]},
  675. }
  676. # 3 livestock
  677. animals = [
  678. "Asses",
  679. "Camels",
  680. "Cattle, dairy",
  681. "Cattle, non-dairy",
  682. "Chickens, broilers",
  683. "Chickens, layers",
  684. "Goats",
  685. "Horses",
  686. "Mules and hinnies",
  687. "Sheep",
  688. "Llamas",
  689. "Chickens",
  690. "Poultry Birds",
  691. "Buffalo",
  692. "Ducks",
  693. "Swine, breeding",
  694. "Swine, market",
  695. "Turkeys",
  696. ]
  697. codes_animals = [f"3.{i}" for i in "ABCDEFGHIJKLMNOPQR"]
  698. enteric_fermentation = [
  699. "Asses",
  700. "Camels",
  701. "Cattle, dairy",
  702. "Cattle, non-dairy",
  703. "Goats",
  704. "Horses",
  705. "Sheep",
  706. "Mules and hinnies",
  707. "Buffalo",
  708. "Swine, breeding",
  709. "Swine, market",
  710. "Llamas",
  711. ]
  712. for animal, code in zip(animals, codes_animals):
  713. if animal in enteric_fermentation:
  714. gases = ["CH4"]
  715. animal_children = [f"{code}.{i}" for i in "1234"]
  716. categories[f"{code}.4"] = {
  717. "title": f"{animal} enteric fermentation",
  718. "comment": f"{animal} enteric fermentation",
  719. # "alternative_codes" : code.replace(".", ""),
  720. "info": {"gases": gases},
  721. }
  722. else:
  723. gases = ["N2O"]
  724. animal_children = [f"{code}.{i}" for i in "123"]
  725. categories[code] = {
  726. "title": animal,
  727. "comment": animal,
  728. # "alternative_codes" : code.replace(".", ""),
  729. "info": {"gases": gases},
  730. "children": [animal_children],
  731. }
  732. # manure management branch
  733. manure_management_children = [f"{code}.1.{i}" for i in "abc"]
  734. categories[f"{code}.1"] = {
  735. "title": f"{animal} manure management",
  736. "comment": f"{animal} manure management",
  737. # "alternative_codes" : code.replace(".", ""),
  738. "info": {"gases": gases},
  739. "children": [manure_management_children],
  740. }
  741. categories[f"{code}.1.a"] = {
  742. "title": f"{animal} decomposition of organic matter",
  743. "comment": f"{animal} decomposition of organic matter",
  744. # "alternative_codes" : code.replace(".", ""),
  745. "info": {"gases": "CH4"},
  746. }
  747. categories[f"{code}.1.b"] = {
  748. "title": f"{animal} manure management (Direct emissions N2O)",
  749. "comment": f"{animal} manure management (Direct emissions N2O)",
  750. # "alternative_codes" : code.replace(".", ""),
  751. "info": {"gases": "N2O"},
  752. }
  753. categories[f"{code}.1.c"] = {
  754. "title": f"{animal} manure management (Indirect emissions N2O)",
  755. "comment": f"{animal} manure management (Indirect emissions N2O)",
  756. # "alternative_codes" : code.replace(".", ""),
  757. "info": {"gases": "N2O"},
  758. }
  759. # manure left on pasture branch
  760. manure_left_on_pasture_children = [f"{code}.2.{i}" for i in "ab"]
  761. categories[f"{code}.2"] = {
  762. "title": f"{animal} manure left on pasture",
  763. "comment": f"{animal} manure left on pasture",
  764. # "alternative_codes" : code.replace(".", ""),
  765. "info": {"gases": "N2O"},
  766. "children": [manure_left_on_pasture_children],
  767. }
  768. categories[f"{code}.2.a"] = {
  769. "title": f"{animal} manure left on pasture (direct emissions N2O)",
  770. "comment": f"{animal} manure left on pasture (direct emissions N2O)",
  771. # "alternative_codes" : code.replace(".", ""),
  772. "info": {"gases": "N2O"},
  773. }
  774. categories[f"{code}.2.b"] = {
  775. "title": f"{animal} manure left on pasture (indirect emissions N2O)",
  776. "comment": f"{animal} manure left on pasture (indirect emissions N2O)",
  777. # "alternative_codes" : code.replace(".", ""),
  778. "info": {"gases": "N2O"},
  779. "children": [[f"{code}.2.b.i", f"{code}.2.b.ii"]],
  780. }
  781. categories[f"{code}.2.b.i"] = {
  782. "title": (
  783. f"{animal} manure left on pasture "
  784. f"(indirect emissions, N2O that leaches)"
  785. ),
  786. "comment": (
  787. f"{animal} manure left on pasture (indirect "
  788. f"emissions, N2O that leaches)"
  789. ),
  790. # "alternative_codes" : code.replace(".", ""),
  791. "info": {"gases": "N2O"},
  792. }
  793. categories[f"{code}.2.b.ii"] = {
  794. "title": (
  795. f"{animal} manure left on pasture "
  796. f"(indirect emissions, N2O that volatilises)"
  797. ),
  798. "comment": (
  799. f"{animal} manure left on pasture (indirect "
  800. f"emissions, N2O that volatilises)"
  801. ),
  802. # "alternative_codes" : code.replace(".", ""),
  803. "info": {"gases": "N2O"},
  804. }
  805. # manure applied branch
  806. manure_applied_children = [f"{code}.3.{i}" for i in "ab"]
  807. categories[f"{code}.3"] = {
  808. "title": f"{animal} manure applied",
  809. "comment": f"{animal} manure applied",
  810. # "alternative_codes" : code.replace(".", ""),
  811. "info": {"gases": "N2O"},
  812. "children": [manure_applied_children],
  813. }
  814. categories[f"{code}.3.a"] = {
  815. "title": f"{animal} manure applied (direct emissions N2O)",
  816. "comment": f"{animal} manure applied (direct emissions N2O)",
  817. # "alternative_codes" : code.replace(".", ""),
  818. "info": {"gases": "N2O"},
  819. }
  820. categories[f"{code}.3.b"] = {
  821. "title": f"{animal} manure applied (indirect emissions N2O)",
  822. "comment": f"{animal} manure applied (indirect emissions N2O)",
  823. # "alternative_codes" : code.replace(".", ""),
  824. "info": {"gases": "N2O"},
  825. "children": [[f"{code}.3.b.i", f"{code}.3.b.ii"]],
  826. }
  827. categories[f"{code}.3.b.i"] = {
  828. "title": (
  829. f"{animal} manure applied " f"(indirect emissions, N2O that leaches)"
  830. ),
  831. "comment": (
  832. f"{animal} manure applied (indirect " f"emissions, N2O that leaches)"
  833. ),
  834. # "alternative_codes" : code.replace(".", ""),
  835. "info": {"gases": "N2O"},
  836. }
  837. categories[f"{code}.3.b.ii"] = {
  838. "title": (
  839. f"{animal} manure applied "
  840. f"(indirect emissions, N2O that volatilises)"
  841. ),
  842. "comment": (
  843. f"{animal} manure applied (indirect "
  844. f"emissions, N2O that volatilises)"
  845. ),
  846. # "alternative_codes" : code.replace(".", ""),
  847. "info": {"gases": "N2O"},
  848. }
  849. # forests
  850. categories["4"] = {
  851. "title": "Carbon stock change in forests",
  852. "comment": "Carbon stock change in forests",
  853. "info": {"gases": "CO2"},
  854. "children": [["4.A", "4.B"]],
  855. }
  856. categories["4.A"] = {
  857. "title": "Forest land",
  858. "comment": "Forest land",
  859. "info": {"gases": "CO2"},
  860. }
  861. categories["4.B"] = {
  862. "title": "Net Forest conversion",
  863. "comment": "Net Forest conversion",
  864. "info": {"gases": "CO2"},
  865. }
  866. # drained organic soils
  867. categories["5"] = {
  868. "title": "Drained organic soils",
  869. "comment": "Drained organic soils",
  870. "info": {"gases": "CO2"},
  871. "children": [["5.A", "5.B"]],
  872. }
  873. categories["5.A"] = {
  874. "title": "Drained grassland",
  875. "comment": "Drained grassland",
  876. "info": {"gases": ["CO2", "N2O"]},
  877. }
  878. categories["5.B"] = {
  879. "title": "Drained cropland",
  880. "comment": "Drained cropland",
  881. "info": {"gases": ["CO2", "N2O"]},
  882. }
  883. # 6 Fires
  884. # Forest fires
  885. forest_fires_children = ["Humid tropical forests", "Other forests"]
  886. forest_fires_children_codes = ["6.A.1", "6.A.2"]
  887. for cat_name, code in zip(forest_fires_children, forest_fires_children_codes):
  888. categories[code] = {
  889. "title": cat_name,
  890. "comment": cat_name,
  891. "info": {"gases": ["CO2", "N2O", "CH4"]},
  892. }
  893. categories["6.A"] = {
  894. "title": "Forest fires",
  895. "comment": "Forest fires",
  896. "info": {"gases": ["CO2", "N2O", "CH4"]},
  897. "children": [forest_fires_children_codes],
  898. }
  899. # Savanna fires
  900. savanna_fires_children = [
  901. "Closed shrubland",
  902. "Grassland",
  903. "Open shrubland",
  904. "Savanna",
  905. "Woody savanna",
  906. ]
  907. savanna_fires_children_codes = ["6.B.1", "6.B.2", "6.B.3", "6.B.4", "6.B.5"]
  908. for cat_name, code in zip(savanna_fires_children, savanna_fires_children_codes):
  909. categories[code] = {
  910. "title": cat_name,
  911. "comment": cat_name,
  912. "info": {"gases": ["CO2", "N2O", "CH4"]},
  913. }
  914. categories["6.B"] = {
  915. "title": "Savanna fires",
  916. "comment": "Savanna fires",
  917. "info": {"gases": ["CO2", "N2O", "CH4"]},
  918. "children": [savanna_fires_children_codes],
  919. }
  920. # fires in organic soils
  921. categories["6.C"] = {
  922. "title": "Fires in organic soils",
  923. "comment": "Fires in organic soils",
  924. "info": {"gases": ["CO2", "N2O", "CH4"]},
  925. }
  926. # 6 fires
  927. categories["6"] = {
  928. "title": "Fires",
  929. "comment": "Fires",
  930. "info": {"gases": ["CO2", "N2O", "CH4"]},
  931. "children": [["6.A", "6.B", "6.C"]],
  932. }
  933. # 7 pre and post production
  934. pre_post_production_categories = [
  935. "Fertilizers Manufacturing",
  936. "Food Transport",
  937. "Food Retail",
  938. "Food Household Consumption",
  939. "Solid Food Waste",
  940. "Domestic Wastewater",
  941. "Industrial Wastewater",
  942. "Incineration",
  943. "Pre- and Post- Production",
  944. "Energy Use (Pre- and Post-Production)",
  945. "Agrifood Systems Waste Disposal",
  946. "Cold Chain F-Gas",
  947. "Pesticides Manufacturing",
  948. "Food Processing",
  949. "Food Packaging",
  950. ]
  951. pre_post_production_categories_codes = ["7." + i for i in "ABCDEFGHIJKLMNO"]
  952. pre_post_production_categories_gases = [
  953. ["CO2", "N2O", "KYOTOGHG (AR5GWP100)"],
  954. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)", "FGASES (AR5GWP100)"],
  955. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)", "FGASES (AR5GWP100)"],
  956. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)", "FGASES (AR5GWP100)"],
  957. ["KYOTOGHG (AR5GWP100)", "CH4"],
  958. ["KYOTOGHG (AR5GWP100)", "CH4", "N2O"],
  959. ["KYOTOGHG (AR5GWP100)", "CH4", "N2O"],
  960. ["CO2", "KYOTOGHG (AR5GWP100)"], # incineration
  961. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)", "FGASES (AR5GWP100)"],
  962. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)"],
  963. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)"],
  964. ["FGASES (AR5GWP100)"],
  965. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)"],
  966. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)", "FGASES (AR5GWP100)"],
  967. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)"],
  968. ]
  969. for cat_name, code, gases in zip(
  970. pre_post_production_categories,
  971. pre_post_production_categories_codes,
  972. pre_post_production_categories_gases,
  973. ):
  974. categories[code] = {
  975. "title": cat_name,
  976. "comment": cat_name,
  977. "info": {"gases": gases},
  978. }
  979. categories["7"] = {
  980. "title": "Pre and post agricultural production",
  981. "comment": "Pre and post agricultural production",
  982. "info": {
  983. "gases": [
  984. "CO2",
  985. "CH4",
  986. "N2O",
  987. "KYOTOGHG (AR5GWP100)",
  988. "FGASES (AR5GWP100)",
  989. ],
  990. },
  991. "children": [pre_post_production_categories_codes],
  992. }
  993. spec["categories"] = categories
  994. fao_cats = cc.HierarchicalCategorization.from_spec(spec.copy())
  995. # run print(fao_cats.show_as_tree())
  996. fao_cats.to_python("FAO.py")
  997. fao_cats.to_yaml("FAO.yaml")
  998. pass