test_conversion.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. import climate_categories as cc
  2. import primap2 as pm2
  3. import xarray as xr
  4. from src.faostat_data_primap.helper.category_aggregation import (
  5. agg_info_fao,
  6. agg_info_ipcc2006_primap_CH4,
  7. agg_info_ipcc2006_primap_CO2,
  8. agg_info_ipcc2006_primap_N2O,
  9. )
  10. from src.faostat_data_primap.helper.paths import (
  11. downloaded_data_path,
  12. extracted_data_path,
  13. )
  14. from src.faostat_data_primap.read import read_data
  15. def test_conversion_from_FAO_to_IPCC2006_PRIMAP_output_equal():
  16. # make categorisation A from yaml
  17. categorisation_a = cc.FAO
  18. # make categorisation B from yaml
  19. categorisation_b = cc.IPCC2006_PRIMAP
  20. # category FAOSTAT not yet part of climate categories, so we need to add it manually
  21. cats = {
  22. "FAO": categorisation_a,
  23. "IPCC2006_PRIMAP": categorisation_b,
  24. }
  25. # release_name = "v2024-11-14"
  26. release_name = "v2023-12-13"
  27. # reproduce 2023 data set
  28. reproduce23 = True
  29. ds_fao = (
  30. extracted_data_path
  31. # / "v2024-11-14/FAOSTAT_Agrifood_system_emissions_v2024-11-14_raw.nc"
  32. / f"{release_name}/FAOSTAT_Agrifood_system_emissions_{release_name}_raw.nc"
  33. )
  34. ds = pm2.open_dataset(ds_fao)
  35. # drop UNFCCC data
  36. ds = ds.drop_sel(source="UNFCCC")
  37. # consistency check in original categorisation
  38. ds_checked = ds.pr.add_aggregates_coordinates(agg_info=agg_info_fao) # noqa: F841
  39. # ds_checked_if = ds_checked.pr.to_interchange_format()
  40. # We need a conversion CSV file for each entity
  41. # That's a temporary workaround until convert function can filter for data variables (entities)
  42. conv = {}
  43. gases = ["CO2", "CH4", "N2O"]
  44. if reproduce23:
  45. reproduce23_filename = "_reproduce23"
  46. else:
  47. reproduce23_filename = ""
  48. for var in gases:
  49. conv[var] = cc.Conversion.from_csv(
  50. f"../../conversion_FAO_IPPCC2006_PRIMAP_{var}{reproduce23_filename}.csv",
  51. cats=cats,
  52. )
  53. # convert for each entity
  54. da_dict = {}
  55. for var in gases:
  56. da_dict[var] = ds[var].pr.convert(
  57. dim="category (FAO)",
  58. conversion=conv[var],
  59. )
  60. result = xr.Dataset(da_dict)
  61. result.attrs = ds.attrs
  62. result.attrs["cat"] = "category (IPCC2006_PRIMAP)"
  63. # convert to interchange format and back to get rid of empty categories
  64. # TODO there may be a better way to do this
  65. result_if = result.pr.to_interchange_format()
  66. result = pm2.pm2io.from_interchange_format(result_if)
  67. # aggregation for each gas for better understanding
  68. # TODO creates some duplicate code, we can combine maybe
  69. result_proc = result.pr.add_aggregates_coordinates(
  70. agg_info=agg_info_ipcc2006_primap_N2O
  71. )
  72. result_proc = result_proc.pr.add_aggregates_coordinates(
  73. agg_info=agg_info_ipcc2006_primap_CO2
  74. )
  75. result_proc = result_proc.pr.add_aggregates_coordinates(
  76. agg_info=agg_info_ipcc2006_primap_CH4
  77. )
  78. # get processed data
  79. output_filename = f"FAOSTAT_Agrifood_system_emissions_{release_name}"
  80. output_folder = extracted_data_path / release_name
  81. filepath = output_folder / (output_filename + ".nc")
  82. ds_original = pm2.open_dataset(filepath)
  83. # result_proc_if = result_proc.pr.to_interchange_format()
  84. assert ds_original.broadcast_equals(result_proc)
  85. # result_proc_if = result_proc.pr.to_interchange_format()
  86. #
  87. #
  88. #
  89. # if not output_folder.exists() :
  90. # output_folder.mkdir()
  91. #
  92. # filepath = output_folder / (output_filename + ".csv")
  93. # print(f"Writing processed primap2 file to {filepath}")
  94. # pm2.pm2io.write_interchange_format(
  95. # filepath,
  96. # result_proc_if,
  97. # )
  98. #
  99. # compression = dict(zlib=True, complevel=9)
  100. # encoding = {var : compression for var in result_proc.data_vars}
  101. # filepath = output_folder / (output_filename + ".nc")
  102. # print(f"Writing netcdf file to {filepath}")
  103. # result_proc.pr.to_netcdf(filepath, encoding=encoding)
  104. def test_read(tmp_path):
  105. domains_and_releases_to_read = [
  106. # ("farm_gate_agriculture_energy", "2024-11-14"),
  107. # ("farm_gate_emissions_crops", "2024-11-14"),
  108. # ("farm_gate_livestock", "2024-11-14"),
  109. # ("land_use_drained_organic_soils", "2024-11-14"),
  110. ("land_use_fires", "2023-11-09"),
  111. # ("land_use_forests", "2024-11-14"),
  112. # ("pre_post_agricultural_production", "2024-11-14"),
  113. ]
  114. read_data(
  115. domains_and_releases_to_read=domains_and_releases_to_read,
  116. read_path=downloaded_data_path,
  117. save_path=tmp_path,
  118. )
  119. def test_conversion_from_FAO_to_IPCC2006_PRIMAP():
  120. # make categorisation A from yaml
  121. categorisation_a = cc.FAO
  122. # make categorisation B from yaml
  123. categorisation_b = cc.IPCC2006_PRIMAP
  124. # category FAOSTAT not yet part of climate categories, so we need to add it manually
  125. cats = {
  126. "FAO": categorisation_a,
  127. "IPCC2006_PRIMAP": categorisation_b,
  128. }
  129. # release_name = "v2024-11-14"
  130. release_name = "v2023-12-13"
  131. # reproduce 2023 data set
  132. reproduce23 = True
  133. ds_fao = (
  134. extracted_data_path
  135. # / "v2024-11-14/FAOSTAT_Agrifood_system_emissions_v2024-11-14_raw.nc"
  136. / f"{release_name}/FAOSTAT_Agrifood_system_emissions_{release_name}_raw.nc"
  137. )
  138. ds = pm2.open_dataset(ds_fao)
  139. # drop UNFCCC data
  140. ds = ds.drop_sel(source="UNFCCC")
  141. # consistency check in original categorisation
  142. ds_checked = ds.pr.add_aggregates_coordinates(agg_info=agg_info_fao) # noqa: F841
  143. # ds_checked_if = ds_checked.pr.to_interchange_format()
  144. # We need a conversion CSV file for each entity
  145. # That's a temporary workaround until convert function can filter for data variables (entities)
  146. conv = {}
  147. gases = ["CO2", "CH4", "N2O"]
  148. if reproduce23:
  149. reproduce23_filename = "_reproduce23"
  150. else:
  151. reproduce23_filename = ""
  152. for var in gases:
  153. conv[var] = cc.Conversion.from_csv(
  154. f"../../conversion_FAO_IPPCC2006_PRIMAP_{var}{reproduce23_filename}.csv",
  155. cats=cats,
  156. )
  157. # convert for each entity
  158. da_dict = {}
  159. for var in gases:
  160. da_dict[var] = ds[var].pr.convert(
  161. dim="category (FAO)",
  162. conversion=conv[var],
  163. )
  164. result = xr.Dataset(da_dict)
  165. result.attrs = ds.attrs
  166. result.attrs["cat"] = "category (IPCC2006_PRIMAP)"
  167. # convert to interchange format and back to get rid of empty categories
  168. # TODO there may be a better way to do this
  169. result_if = result.pr.to_interchange_format()
  170. result = pm2.pm2io.from_interchange_format(result_if)
  171. # aggregation for each gas for better understanding
  172. # TODO creates some duplicate code, we can combine maybe
  173. result_proc = result.pr.add_aggregates_coordinates(
  174. agg_info=agg_info_ipcc2006_primap_N2O
  175. )
  176. result_proc = result_proc.pr.add_aggregates_coordinates(
  177. agg_info=agg_info_ipcc2006_primap_CO2
  178. )
  179. result_proc = result_proc.pr.add_aggregates_coordinates(
  180. agg_info=agg_info_ipcc2006_primap_CH4
  181. )
  182. result_proc_if = result_proc.pr.to_interchange_format()
  183. # save processed data
  184. output_filename = f"FAOSTAT_Agrifood_system_emissions_{release_name}"
  185. output_folder = extracted_data_path / release_name
  186. if not output_folder.exists():
  187. output_folder.mkdir()
  188. filepath = output_folder / (output_filename + ".csv")
  189. print(f"Writing processed primap2 file to {filepath}")
  190. pm2.pm2io.write_interchange_format(
  191. filepath,
  192. result_proc_if,
  193. )
  194. compression = dict(zlib=True, complevel=9)
  195. encoding = {var: compression for var in result_proc.data_vars}
  196. filepath = output_folder / (output_filename + ".nc")
  197. print(f"Writing netcdf file to {filepath}")
  198. result_proc.pr.to_netcdf(filepath, encoding=encoding)
  199. # def test_read(tmp_path):
  200. # domains_and_releases_to_read = [
  201. # # ("farm_gate_agriculture_energy", "2024-11-14"),
  202. # # ("farm_gate_emissions_crops", "2024-11-14"),
  203. # # ("farm_gate_livestock", "2024-11-14"),
  204. # # ("land_use_drained_organic_soils", "2024-11-14"),
  205. # ("land_use_fires", "2023-11-09"),
  206. # # ("land_use_forests", "2024-11-14"),
  207. # # ("pre_post_agricultural_production", "2024-11-14"),
  208. # ]
  209. #
  210. # read_data(
  211. # domains_and_releases_to_read=domains_and_releases_to_read,
  212. # read_path=downloaded_data_path,
  213. # save_path=tmp_path,
  214. # )
  215. def test_read_2023():
  216. domains_and_releases_to_read = [
  217. ("farm_gate_agriculture_energy", "2023-12-13"),
  218. ("farm_gate_emissions_crops", "2023-11-09"),
  219. ("farm_gate_livestock", "2023-11-09"),
  220. ("land_use_drained_organic_soils", "2023-11-09"),
  221. ("land_use_fires", "2023-11-09"),
  222. ("land_use_forests", "2023-11-09"),
  223. ("pre_post_agricultural_production", "2023-11-09"),
  224. # ("farm_gate_agriculture_energy", "2024-11-14"),
  225. # ("farm_gate_emissions_crops", "2024-11-14"),
  226. # ("farm_gate_livestock", "2024-11-14"),
  227. # ("land_use_drained_organic_soils", "2024-11-14"),
  228. # ("land_use_fires", "2024-11-14"),
  229. # ("land_use_forests", "2024-11-14"),
  230. # ("pre_post_agricultural_production", "2024-11-14"),
  231. ]
  232. read_data(
  233. domains_and_releases_to_read=domains_and_releases_to_read,
  234. read_path=downloaded_data_path,
  235. save_path=extracted_data_path,
  236. )
  237. def test_yaml_to_python():
  238. cat = cc.from_yaml("FAO.yaml")
  239. cat.to_python("FAO.py")
  240. def test_python_to_yaml():
  241. from FAO import spec
  242. cat = cc.from_spec(spec)
  243. assert cat
  244. def test_fao_categorisation(): # noqa: PLR0912 PLR0915
  245. spec = {
  246. "name": "FAOSTAT",
  247. "title": (
  248. "Food and Agriculture Organization of the United Nations (FAO) "
  249. "FAOSTAT data set categorisation"
  250. ),
  251. "comment": "Needed to add FAOSTAT data to PRIMAP-hist",
  252. "references": "",
  253. "institution": "FAO",
  254. "hierarchical": True,
  255. "last_update": "2024-12-10",
  256. "version": "2024",
  257. "total_sum": True,
  258. "canonical_top_level_category": "0",
  259. }
  260. categories = {}
  261. # 0. main categories
  262. categories["0"] = {
  263. "title": "Total",
  264. "comment": "All emissions and removals",
  265. "children": [["1", "2", "3", "4", "5", "6", "7"]],
  266. }
  267. children_1 = ["1.A", "1.B"]
  268. children_2 = ["2.A", "2.B", "2.C", "2.D", "2.E"]
  269. children_3 = [f"3.{i}" for i in "ABCDEFGHIJKLMNOPQR"]
  270. main_categories = (
  271. # category code, name and comment, gases, children
  272. ("1", "Crops", ["CH4", "N2O"], children_1),
  273. (
  274. "2",
  275. "Energy use in agriculture",
  276. ["CH4", "N2O", "CO2"],
  277. children_2,
  278. ),
  279. ("3", "Livestock", ["CH4", "N2O"], children_3),
  280. # ("4", "Forest", ["CO2"], children_4),
  281. # (
  282. # "5",
  283. # "Drained organic soils",
  284. # ["N2O", "CO2"],
  285. # children_5,
  286. # ),
  287. # ("6", "Fires", ["CH4", "N2O", "CO2"], children_6),
  288. # (
  289. # "7",
  290. # "Pre and post agricultural production",
  291. # ["CH4", "N2O", "CO2"],
  292. # children_7,
  293. # ),
  294. )
  295. for code, name, gases, children in main_categories:
  296. categories[code] = {
  297. "title": name,
  298. "comment": name,
  299. # "alternative_codes": code.replace(".", ""),
  300. "children": [children],
  301. "info": {"gases": gases},
  302. }
  303. # 1. crops
  304. # all crops category
  305. code_all_crops = "1.A"
  306. codes_crops = [f"1.A.{i}" for i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]
  307. categories[code_all_crops] = {
  308. "title": "All crops",
  309. "comment": "All crops",
  310. # "alternative_codes": code_all_crops.replace(".", ""),
  311. "children": [codes_crops],
  312. "info": {"gases": ["CH4", "N2O"]},
  313. }
  314. crops = [
  315. "Wheat",
  316. "Rice",
  317. "Potatoes",
  318. "Millet",
  319. "Barley",
  320. "Maize (corn)",
  321. "Sugar cane",
  322. "Beans, dry",
  323. "Oats",
  324. "Rye",
  325. "Sorghum",
  326. "Soya beans",
  327. ]
  328. crop_burnings = [
  329. True,
  330. True,
  331. False,
  332. False,
  333. False,
  334. True,
  335. True,
  336. False,
  337. False,
  338. False,
  339. False,
  340. False,
  341. ]
  342. rice_cultivations = [
  343. False,
  344. True,
  345. False,
  346. False,
  347. False,
  348. False,
  349. False,
  350. False,
  351. False,
  352. False,
  353. False,
  354. False,
  355. ]
  356. for crop, code, crop_burning, rice_cultivation in zip(
  357. crops, codes_crops, crop_burnings, rice_cultivations
  358. ):
  359. # all crops have at least N2O emissions
  360. gases_main = "N2O"
  361. if crop_burning or rice_cultivation:
  362. gases_main = ["CH4", "N2O"]
  363. # all crops have at least crop residues as child
  364. children_main = [f"{code}.a"]
  365. if crop_burning:
  366. children_main.append(f"{code}.b")
  367. if rice_cultivation:
  368. children_main.append(f"{code}.c")
  369. categories[f"{code}"] = {
  370. "title": f"{crop}",
  371. "comment": f"{crop}",
  372. # "alternative_codes": [f"{code}".replace(".", "")],
  373. "info": {"gases": gases_main},
  374. "children": [children_main],
  375. }
  376. # crop residues (every crop has it)
  377. categories[f"{code}.a.i"] = {
  378. "title": f"{crop} crop residues direct emissions",
  379. "comment": f"{crop} crop residues direct emissions",
  380. # "alternative_codes": [f"{code}.a".replace(".", "")],
  381. "info": {"gases": ["N2O"]},
  382. }
  383. categories[f"{code}.a.ii"] = {
  384. "title": f"{crop} crop residues indirect emissions",
  385. "comment": f"{crop} crop residues indirect emissions",
  386. # "alternative_codes": [f"{code}.a.i".replace(".", "")],
  387. "info": {"gases": ["N2O"]},
  388. }
  389. categories[f"{code}.a"] = {
  390. "title": f"{crop} crop residues",
  391. "comment": f"{crop} crop residues",
  392. # "alternative_codes": [f"{code}.a".replace(".", "")],
  393. "info": {"gases": ["N2O"]},
  394. "children": [[f"{code}.a.ii", f"{code}.a.i"]],
  395. }
  396. if crop_burning:
  397. categories[f"{code}.b"] = {
  398. "title": f"{crop} burning crop residues",
  399. "comment": f"{crop} burning crop residues",
  400. # "alternative_codes": [f"{code}.b".replace(".", "")],
  401. "info": {"gases": ["CH4", "N2O"]},
  402. }
  403. if rice_cultivation:
  404. categories[f"{code}.c"] = {
  405. "title": "Rice cultivation",
  406. "comment": "Rice cultivation",
  407. # "alternative_codes": [f"{code}.c".replace(".", "")],
  408. "info": {"gases": ["CH4"]},
  409. }
  410. # synthetic fertilisers
  411. codes_synthetic_fertilisers = ["1.B", "1.B.1", "1.B.2", "1.B.2.a", "1.B.2.b"]
  412. names = [
  413. "Synthetic fertilisers",
  414. "Direct emissions",
  415. "Indirect emissions",
  416. "Indirect emissions that volatilise",
  417. "Indirect emissions that leach",
  418. ]
  419. children_cats = [["1.B.1", "1.B.2"], None, ["1.B.2.a", "1.B.2.b"], None, None]
  420. for code, name, child_cat in zip(codes_synthetic_fertilisers, names, children_cats):
  421. categories[code] = {
  422. "title": name,
  423. "comment": name,
  424. # "alternative_codes": [code.replace(".", "")],
  425. "info": {"gases": ["N2O"]},
  426. }
  427. if child_cat:
  428. categories[code]["children"] = [child_cat]
  429. # 2. energy use
  430. names = [
  431. "Natural gas",
  432. "Electricity",
  433. "Coal",
  434. "Heat",
  435. "Petroleum",
  436. ]
  437. codes = children_2
  438. for name, code in zip(names, codes):
  439. categories[code] = {
  440. "title": name,
  441. "comment": name,
  442. # "alternative_codes": code.replace(".", ""),
  443. "info": {"gases": ["CH4", "N2O", "CO2"]},
  444. }
  445. # 3 livestock
  446. animals = [
  447. "Asses",
  448. "Camels",
  449. "Cattle, dairy",
  450. "Cattle, non-dairy",
  451. "Chickens, broilers",
  452. "Chickens, layers",
  453. "Goats",
  454. "Horses",
  455. "Mules and hinnies",
  456. "Sheep",
  457. "Llamas",
  458. "Chickens",
  459. "Poultry Birds",
  460. "Buffalo",
  461. "Ducks",
  462. "Swine, breeding",
  463. "Swine, market",
  464. "Turkeys",
  465. ]
  466. codes_animals = [f"3.{i}" for i in "ABCDEFGHIJKLMNOPQR"]
  467. enteric_fermentation = [
  468. "Asses",
  469. "Camels",
  470. "Cattle, dairy",
  471. "Cattle, non-dairy",
  472. "Goats",
  473. "Horses",
  474. "Sheep",
  475. "Mules and hinnies",
  476. "Buffalo",
  477. "Swine, breeding",
  478. "Swine, market",
  479. "Llamas",
  480. ]
  481. for animal, code in zip(animals, codes_animals):
  482. if animal in enteric_fermentation:
  483. gases = ["CH4"]
  484. animal_children = [f"{code}.{i}" for i in "1234"]
  485. categories[f"{code}.4"] = {
  486. "title": f"{animal} enteric fermentation",
  487. "comment": f"{animal} enteric fermentation",
  488. # "alternative_codes" : code.replace(".", ""),
  489. "info": {"gases": gases},
  490. }
  491. else:
  492. gases = ["N2O"]
  493. animal_children = [f"{code}.{i}" for i in "123"]
  494. categories[code] = {
  495. "title": animal,
  496. "comment": animal,
  497. # "alternative_codes" : code.replace(".", ""),
  498. "info": {"gases": gases},
  499. "children": [animal_children],
  500. }
  501. # manure management branch
  502. manure_management_children = [f"{code}.1.{i}" for i in "abc"]
  503. categories[f"{code}.1"] = {
  504. "title": f"{animal} manure management",
  505. "comment": f"{animal} manure management",
  506. # "alternative_codes" : code.replace(".", ""),
  507. "info": {"gases": gases},
  508. "children": [manure_management_children],
  509. }
  510. categories[f"{code}.1.a"] = {
  511. "title": f"{animal} decomposition of organic matter",
  512. "comment": f"{animal} decomposition of organic matter",
  513. # "alternative_codes" : code.replace(".", ""),
  514. "info": {"gases": "CH4"},
  515. }
  516. categories[f"{code}.1.b"] = {
  517. "title": f"{animal} manure management (Direct emissions N2O)",
  518. "comment": f"{animal} manure management (Direct emissions N2O)",
  519. # "alternative_codes" : code.replace(".", ""),
  520. "info": {"gases": "N2O"},
  521. }
  522. categories[f"{code}.1.c"] = {
  523. "title": f"{animal} manure management (Indirect emissions N2O)",
  524. "comment": f"{animal} manure management (Indirect emissions N2O)",
  525. # "alternative_codes" : code.replace(".", ""),
  526. "info": {"gases": "N2O"},
  527. }
  528. # manure left on pasture branch
  529. manure_left_on_pasture_children = [f"{code}.2.{i}" for i in "ab"]
  530. categories[f"{code}.2"] = {
  531. "title": f"{animal} manure left on pasture",
  532. "comment": f"{animal} manure left on pasture",
  533. # "alternative_codes" : code.replace(".", ""),
  534. "info": {"gases": "N2O"},
  535. "children": [manure_left_on_pasture_children],
  536. }
  537. categories[f"{code}.2.a"] = {
  538. "title": f"{animal} manure left on pasture (direct emissions N2O)",
  539. "comment": f"{animal} manure left on pasture (direct emissions N2O)",
  540. # "alternative_codes" : code.replace(".", ""),
  541. "info": {"gases": "N2O"},
  542. }
  543. categories[f"{code}.2.b"] = {
  544. "title": f"{animal} manure left on pasture (indirect emissions N2O)",
  545. "comment": f"{animal} manure left on pasture (indirect emissions N2O)",
  546. # "alternative_codes" : code.replace(".", ""),
  547. "info": {"gases": "N2O"},
  548. "children": [[f"{code}.2.b.i", f"{code}.2.b.ii"]],
  549. }
  550. categories[f"{code}.2.b.i"] = {
  551. "title": (
  552. f"{animal} manure left on pasture "
  553. f"(indirect emissions, N2O that leaches)"
  554. ),
  555. "comment": (
  556. f"{animal} manure left on pasture (indirect "
  557. f"emissions, N2O that leaches)"
  558. ),
  559. # "alternative_codes" : code.replace(".", ""),
  560. "info": {"gases": "N2O"},
  561. }
  562. categories[f"{code}.2.b.ii"] = {
  563. "title": (
  564. f"{animal} manure left on pasture "
  565. f"(indirect emissions, N2O that volatilises)"
  566. ),
  567. "comment": (
  568. f"{animal} manure left on pasture (indirect "
  569. f"emissions, N2O that volatilises)"
  570. ),
  571. # "alternative_codes" : code.replace(".", ""),
  572. "info": {"gases": "N2O"},
  573. }
  574. # manure applied branch
  575. manure_applied_children = [f"{code}.3.{i}" for i in "ab"]
  576. categories[f"{code}.3"] = {
  577. "title": f"{animal} manure applied",
  578. "comment": f"{animal} manure applied",
  579. # "alternative_codes" : code.replace(".", ""),
  580. "info": {"gases": "N2O"},
  581. "children": [manure_applied_children],
  582. }
  583. categories[f"{code}.3.a"] = {
  584. "title": f"{animal} manure applied (direct emissions N2O)",
  585. "comment": f"{animal} manure applied (direct emissions N2O)",
  586. # "alternative_codes" : code.replace(".", ""),
  587. "info": {"gases": "N2O"},
  588. }
  589. categories[f"{code}.3.b"] = {
  590. "title": f"{animal} manure applied (indirect emissions N2O)",
  591. "comment": f"{animal} manure applied (indirect emissions N2O)",
  592. # "alternative_codes" : code.replace(".", ""),
  593. "info": {"gases": "N2O"},
  594. "children": [[f"{code}.3.b.i", f"{code}.3.b.ii"]],
  595. }
  596. categories[f"{code}.3.b.i"] = {
  597. "title": (
  598. f"{animal} manure applied " f"(indirect emissions, N2O that leaches)"
  599. ),
  600. "comment": (
  601. f"{animal} manure applied (indirect " f"emissions, N2O that leaches)"
  602. ),
  603. # "alternative_codes" : code.replace(".", ""),
  604. "info": {"gases": "N2O"},
  605. }
  606. categories[f"{code}.3.b.ii"] = {
  607. "title": (
  608. f"{animal} manure applied "
  609. f"(indirect emissions, N2O that volatilises)"
  610. ),
  611. "comment": (
  612. f"{animal} manure applied (indirect "
  613. f"emissions, N2O that volatilises)"
  614. ),
  615. # "alternative_codes" : code.replace(".", ""),
  616. "info": {"gases": "N2O"},
  617. }
  618. # forests
  619. categories["4"] = {
  620. "title": "Carbon stock change in forests",
  621. "comment": "Carbon stock change in forests",
  622. "info": {"gases": "CO2"},
  623. "children": [["4.A", "4.B"]],
  624. }
  625. categories["4.A"] = {
  626. "title": "Forest land",
  627. "comment": "Forest land",
  628. "info": {"gases": "CO2"},
  629. }
  630. categories["4.B"] = {
  631. "title": "Net Forest conversion",
  632. "comment": "Net Forest conversion",
  633. "info": {"gases": "CO2"},
  634. }
  635. # drained organic soils
  636. categories["5"] = {
  637. "title": "Drained organic soils",
  638. "comment": "Drained organic soils",
  639. "info": {"gases": "CO2"},
  640. "children": [["5.A", "5.B"]],
  641. }
  642. categories["5.A"] = {
  643. "title": "Drained grassland",
  644. "comment": "Drained grassland",
  645. "info": {"gases": ["CO2", "N2O"]},
  646. }
  647. categories["5.B"] = {
  648. "title": "Drained cropland",
  649. "comment": "Drained cropland",
  650. "info": {"gases": ["CO2", "N2O"]},
  651. }
  652. # 6 Fires
  653. # Forest fires
  654. forest_fires_children = ["Humid tropical forests", "Other forests"]
  655. forest_fires_children_codes = ["6.A.1", "6.A.2"]
  656. for cat_name, code in zip(forest_fires_children, forest_fires_children_codes):
  657. categories[code] = {
  658. "title": cat_name,
  659. "comment": cat_name,
  660. "info": {"gases": ["CO2", "N2O", "CH4"]},
  661. }
  662. categories["6.A"] = {
  663. "title": "Forest fires",
  664. "comment": "Forest fires",
  665. "info": {"gases": ["CO2", "N2O", "CH4"]},
  666. "children": [forest_fires_children_codes],
  667. }
  668. # Savanna fires
  669. savanna_fires_children = [
  670. "Closed shrubland",
  671. "Grassland",
  672. "Open shrubland",
  673. "Savanna",
  674. "Woody savanna",
  675. ]
  676. savanna_fires_children_codes = ["6.B.1", "6.B.2", "6.B.3", "6.B.4", "6.B.5"]
  677. for cat_name, code in zip(savanna_fires_children, savanna_fires_children_codes):
  678. categories[code] = {
  679. "title": cat_name,
  680. "comment": cat_name,
  681. "info": {"gases": ["CO2", "N2O", "CH4"]},
  682. }
  683. categories["6.B"] = {
  684. "title": "Savanna fires",
  685. "comment": "Savanna fires",
  686. "info": {"gases": ["CO2", "N2O", "CH4"]},
  687. "children": [savanna_fires_children_codes],
  688. }
  689. # fires in organic soils
  690. categories["6.C"] = {
  691. "title": "Fires in organic soils",
  692. "comment": "Fires in organic soils",
  693. "info": {"gases": ["CO2", "N2O", "CH4"]},
  694. }
  695. # 6 fires
  696. categories["6"] = {
  697. "title": "Fires",
  698. "comment": "Fires",
  699. "info": {"gases": ["CO2", "N2O", "CH4"]},
  700. "children": [["6.A", "6.B", "6.C"]],
  701. }
  702. # 7 pre and post production
  703. pre_post_production_categories = [
  704. "Fertilizers Manufacturing",
  705. "Food Transport",
  706. "Food Retail",
  707. "Food Household Consumption",
  708. "Solid Food Waste",
  709. "Domestic Wastewater",
  710. "Industrial Wastewater",
  711. "Incineration",
  712. "Pre- and Post- Production",
  713. "Energy Use (Pre- and Post-Production)",
  714. "Agrifood Systems Waste Disposal",
  715. "Cold Chain F-Gas",
  716. "Pesticides Manufacturing",
  717. "Food Processing",
  718. "Food Packaging",
  719. ]
  720. pre_post_production_categories_codes = ["7." + i for i in "ABCDEFGHIJKLMNO"]
  721. pre_post_production_categories_gases = [
  722. ["CO2", "N2O", "KYOTOGHG (AR5GWP100)"],
  723. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)", "FGASES (AR5GWP100)"],
  724. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)", "FGASES (AR5GWP100)"],
  725. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)", "FGASES (AR5GWP100)"],
  726. ["KYOTOGHG (AR5GWP100)", "CH4"],
  727. ["KYOTOGHG (AR5GWP100)", "CH4", "N2O"],
  728. ["KYOTOGHG (AR5GWP100)", "CH4", "N2O"],
  729. ["CO2", "KYOTOGHG (AR5GWP100)"], # incineration
  730. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)", "FGASES (AR5GWP100)"],
  731. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)"],
  732. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)"],
  733. ["FGASES (AR5GWP100)"],
  734. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)"],
  735. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)", "FGASES (AR5GWP100)"],
  736. ["CO2", "CH4", "N2O", "KYOTOGHG (AR5GWP100)"],
  737. ]
  738. for cat_name, code, gases in zip(
  739. pre_post_production_categories,
  740. pre_post_production_categories_codes,
  741. pre_post_production_categories_gases,
  742. ):
  743. categories[code] = {
  744. "title": cat_name,
  745. "comment": cat_name,
  746. "info": {"gases": gases},
  747. }
  748. categories["7"] = {
  749. "title": "Pre and post agricultural production",
  750. "comment": "Pre and post agricultural production",
  751. "info": {
  752. "gases": [
  753. "CO2",
  754. "CH4",
  755. "N2O",
  756. "KYOTOGHG (AR5GWP100)",
  757. "FGASES (AR5GWP100)",
  758. ],
  759. },
  760. "children": [pre_post_production_categories_codes],
  761. }
  762. spec["categories"] = categories
  763. fao_cats = cc.HierarchicalCategorization.from_spec(spec.copy())
  764. # run print(fao_cats.show_as_tree())
  765. fao_cats.to_python("FAO.py")
  766. fao_cats.to_yaml("FAO.yaml")