Skip to content

Commit b4a998f

Browse files
Merge pull request #9 from scope3data/split-adtech-keys
move ad tech keys out of compute defaults
2 parents 64c4b75 + d05ce01 commit b4a998f

3 files changed

Lines changed: 137 additions & 142 deletions

File tree

poetry.lock

Lines changed: 30 additions & 42 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scope3_methodology/adtech_model.py

Lines changed: 105 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -41,43 +41,24 @@ def __init__(
4141
self.bid_request_distribution_rate = bid_request_distribution_rate
4242

4343

44-
# Parse command line to get company file
45-
parser = argparse.ArgumentParser(description="Compute emissions for an ad tech company")
46-
parser.add_argument(
47-
"-d",
48-
"--defaultsFile",
49-
default="defaults.yaml",
50-
help="Set the defaults file to use (overrides defaults.yaml)",
51-
)
52-
parser.add_argument("-v", "--verbose", action="store_true", help="Show derivation of output")
53-
parser.add_argument(
54-
"-p",
55-
"--partners",
56-
const=1,
57-
default=0,
58-
type=int,
59-
nargs="?",
60-
help="Simulate distribution partners",
61-
)
62-
parser.add_argument("companyFile", nargs=1, help="The company file to parse in YAML format")
63-
args = parser.parse_args()
64-
if args.verbose:
65-
logging.basicConfig(level=logging.INFO)
66-
67-
# Load defaults
68-
defaultsStream = open(args.defaultsFile, "r")
69-
defaultsDocument = yaml.load(defaultsStream, Loader=SafeLoader)
70-
71-
# Load facts about the company
72-
stream = open(args.companyFile[0], "r")
73-
document = yaml.load(stream, Loader=SafeLoader)
74-
if "company" not in document:
75-
raise Exception("No 'company' field found in company file")
76-
if "products" not in document["company"]:
77-
raise Exception("No 'products' field found in company file")
78-
if "sources" not in document["company"]:
79-
raise Exception("No 'sources' field found in company file")
80-
facts = get_facts_from_sources(document["company"]["sources"])
44+
def get_ad_tech_model_keys() -> set[str]:
45+
return {
46+
"bid requests processed billion per month",
47+
"cookie syncs processed billion per month",
48+
"cookie syncs processed per bid request",
49+
"cookie sync distribution ratio",
50+
"creative serving processed billion per month",
51+
"pct of bid requests processed from ad tech platforms",
52+
"bid request size in bytes",
53+
"bid request rejection pct",
54+
"server to server emissions g per gb",
55+
"server emissions mt per month",
56+
"server emissions g per kwh",
57+
"servers processing bid requests pct",
58+
"servers processing cookie syncs pct",
59+
"servers processing creative serving pct",
60+
"datacenter water intensity h2o m^3 per mwh",
61+
}
8162

8263

8364
def getProductInfo(key: str, default: float | None, product: dict[str, float], depth: int):
@@ -228,8 +209,7 @@ def getPrimaryEmissionsPerBidRequest(
228209

229210

230211
def getSecondaryEmissionsPerBidRequest(
231-
model: AdTechPlatform,
232-
distributionPartners: list[DistributionPartner],
212+
model: AdTechPlatform, distributionPartners: list[DistributionPartner], depth: int
233213
) -> float:
234214
secondaryEmissionsPerBidRequest = 0.0
235215
for edge in distributionPartners:
@@ -298,7 +278,7 @@ def getPrimaryEmissionsPerCookieSync(
298278

299279

300280
def getSecondaryEmissionsPerCookieSync(
301-
model: AdTechPlatform, distributionPartners: list[DistributionPartner]
281+
model: AdTechPlatform, distributionPartners: list[DistributionPartner], depth: int
302282
) -> float:
303283
secondary_emissions_per_cookie_sync = 0.0
304284
for edge in distributionPartners:
@@ -312,49 +292,93 @@ def getSecondaryEmissionsPerCookieSync(
312292
return secondary_emissions_per_cookie_sync
313293

314294

315-
depth = 4 if args.verbose else 0
316-
productModels = []
317-
for product in document["company"]["products"]:
318-
if "name" not in product:
319-
raise Exception("No 'name' field found in a product")
320-
321-
logging.info(f"#### {product['name']}")
322-
template = getProductInfo("template", None, product, 0)
323-
identifier = getProductInfo("identifier", None, product, 0)
324-
serverAllocation = getProductInfo("server allocation pct", 100, product, 0) / 100
325-
corporateAllocation = getProductInfo("corporate allocation pct", 100, product, 0) / 100
326-
if template not in defaultsDocument["defaults"]:
327-
raise Exception(f"Template {template} not found in defaults")
328-
defaults = defaultsDocument["defaults"][template]
329-
primaryEmissionsPerBidRequest = getPrimaryEmissionsPerBidRequest(
330-
serverAllocation, corporateAllocation, facts, defaults, depth
331-
)
332-
primaryEmissionsPerCookieSync = getPrimaryEmissionsPerCookieSync(
333-
serverAllocation, facts, defaults, depth
334-
)
335-
cookieSyncDistributionRatio = get_fact_or_default(
336-
"cookie sync distribution ratio", facts, defaults, depth - 1
337-
)
338-
bidRequestRejectionRate = (
339-
get_fact_or_default("bid request rejection pct", facts, defaults, depth - 1) / 100.0
295+
def main():
296+
297+
# Parse command line to get company file
298+
parser = argparse.ArgumentParser(description="Compute emissions for an ad tech company")
299+
parser.add_argument(
300+
"-d",
301+
"--defaultsFile",
302+
default="defaults.yaml",
303+
help="Set the defaults file to use (overrides defaults.yaml)",
340304
)
341-
model = AdTechPlatform(
342-
product["name"],
343-
identifier,
344-
primaryEmissionsPerBidRequest,
345-
primaryEmissionsPerCookieSync,
346-
cookieSyncDistributionRatio,
347-
bidRequestRejectionRate,
305+
parser.add_argument("-v", "--verbose", action="store_true", help="Show derivation of output")
306+
parser.add_argument(
307+
"-p",
308+
"--partners",
309+
const=1,
310+
default=0,
311+
type=int,
312+
nargs="?",
313+
help="Simulate distribution partners",
348314
)
349-
productModels.append(model)
315+
parser.add_argument("companyFile", nargs=1, help="The company file to parse in YAML format")
316+
args = parser.parse_args()
317+
if args.verbose:
318+
logging.basicConfig(level=logging.INFO)
319+
320+
# Load defaults
321+
defaultsStream = open(args.defaultsFile, "r")
322+
defaultsDocument = yaml.load(defaultsStream, Loader=SafeLoader)
323+
324+
# Load facts about the company
325+
stream = open(args.companyFile[0], "r")
326+
document = yaml.load(stream, Loader=SafeLoader)
327+
if "company" not in document:
328+
raise Exception("No 'company' field found in company file")
329+
if "products" not in document["company"]:
330+
raise Exception("No 'products' field found in company file")
331+
if "sources" not in document["company"]:
332+
raise Exception("No 'sources' field found in company file")
333+
facts = get_facts_from_sources(document["company"]["sources"])
334+
335+
depth = 4 if args.verbose else 0
336+
productModels = []
337+
for product in document["company"]["products"]:
338+
if "name" not in product:
339+
raise Exception("No 'name' field found in a product")
340+
341+
logging.info(f"#### {product['name']}")
342+
template = getProductInfo("template", None, product, 0)
343+
identifier = getProductInfo("identifier", None, product, 0)
344+
serverAllocation = getProductInfo("server allocation pct", 100, product, 0) / 100
345+
corporateAllocation = getProductInfo("corporate allocation pct", 100, product, 0) / 100
346+
if template not in defaultsDocument["defaults"]:
347+
raise Exception(f"Template {template} not found in defaults")
348+
defaults = defaultsDocument["defaults"][template]
349+
primaryEmissionsPerBidRequest = getPrimaryEmissionsPerBidRequest(
350+
serverAllocation, corporateAllocation, facts, defaults, depth
351+
)
352+
primaryEmissionsPerCookieSync = getPrimaryEmissionsPerCookieSync(
353+
serverAllocation, facts, defaults, depth
354+
)
355+
cookieSyncDistributionRatio = get_fact_or_default(
356+
"cookie sync distribution ratio", facts, defaults, depth - 1
357+
)
358+
bidRequestRejectionRate = (
359+
get_fact_or_default("bid request rejection pct", facts, defaults, depth - 1) / 100.0
360+
)
361+
model = AdTechPlatform(
362+
product["name"],
363+
identifier,
364+
primaryEmissionsPerBidRequest,
365+
primaryEmissionsPerCookieSync,
366+
cookieSyncDistributionRatio,
367+
bidRequestRejectionRate,
368+
)
369+
productModels.append(model)
370+
371+
print(yaml.dump({"products": productModels}, Dumper=yaml.Dumper))
372+
373+
if args.partners and args.verbose:
374+
distributionPartners: list[DistributionPartner] = []
375+
for i in range(args.partners):
376+
partner = AdTechPlatform(f"dummy {i}", f"dummy{i}.com", 0.001, 0.0001, 1.0, 0.3)
377+
distributionPartners.append(DistributionPartner(partner, 1.0))
350378

351-
print(yaml.dump({"products": productModels}, Dumper=yaml.Dumper))
379+
getSecondaryEmissionsPerBidRequest(productModels[0], distributionPartners, depth - 1)
380+
getSecondaryEmissionsPerCookieSync(productModels[0], distributionPartners, depth - 1)
352381

353-
if args.partners and args.verbose:
354-
distributionPartners: list[DistributionPartner] = []
355-
for i in range(args.partners):
356-
partner = AdTechPlatform(f"dummy {i}", f"dummy{i}.com", 0.001, 0.0001, 1.0, 0.3)
357-
distributionPartners.append(DistributionPartner(partner, 1.0))
358382

359-
getSecondaryEmissionsPerBidRequest(productModels[0], distributionPartners)
360-
getSecondaryEmissionsPerCookieSync(productModels[0], distributionPartners)
383+
if __name__ == "__main__":
384+
main()

0 commit comments

Comments
 (0)