earth 0.11.10 → 0.11.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. data/Gemfile +4 -0
  2. data/Guardfile +35 -0
  3. data/README.markdown +94 -20
  4. data/Rakefile +4 -0
  5. data/earth.gemspec +14 -12
  6. data/lib/earth/air/aircraft.rb +2 -2
  7. data/lib/earth/air/aircraft_instance.rb +2 -2
  8. data/lib/earth/air/aircraft_instance_seat_class.rb +2 -2
  9. data/lib/earth/air/airline.rb +2 -2
  10. data/lib/earth/air/airport.rb +2 -2
  11. data/lib/earth/air/bts_aircraft.rb +2 -2
  12. data/lib/earth/air/flight_distance_class.rb +1 -1
  13. data/lib/earth/air/flight_distance_class_seat_class.rb +1 -1
  14. data/lib/earth/air/flight_seat_class.rb +1 -1
  15. data/lib/earth/air/flight_segment.rb +1 -1
  16. data/lib/earth/automobile/automobile_fuel.rb +1 -1
  17. data/lib/earth/automobile/automobile_make.rb +1 -1
  18. data/lib/earth/automobile/automobile_make_model.rb +1 -1
  19. data/lib/earth/automobile/automobile_make_model_year.rb +1 -1
  20. data/lib/earth/automobile/automobile_make_model_year_variant.rb +1 -1
  21. data/lib/earth/automobile/automobile_make_year.rb +1 -1
  22. data/lib/earth/automobile/automobile_make_year_fleet.rb +1 -1
  23. data/lib/earth/automobile/automobile_model.rb +1 -1
  24. data/lib/earth/automobile/automobile_size_class.rb +1 -1
  25. data/lib/earth/automobile/automobile_size_class_year.rb +1 -1
  26. data/lib/earth/automobile/automobile_type_fuel_control.rb +1 -1
  27. data/lib/earth/automobile/automobile_type_fuel_year.rb +1 -1
  28. data/lib/earth/automobile/automobile_type_fuel_year_age.rb +1 -1
  29. data/lib/earth/automobile/automobile_type_fuel_year_control.rb +1 -1
  30. data/lib/earth/automobile/automobile_type_year.rb +2 -2
  31. data/lib/earth/automobile/automobile_year.rb +1 -1
  32. data/lib/earth/bus/bus_class.rb +1 -1
  33. data/lib/earth/bus/bus_fuel.rb +2 -2
  34. data/lib/earth/bus/bus_fuel_control.rb +2 -2
  35. data/lib/earth/bus/bus_fuel_year_control.rb +2 -2
  36. data/lib/earth/computation/computation_carrier.rb +2 -2
  37. data/lib/earth/computation/computation_carrier_instance_class.rb +2 -2
  38. data/lib/earth/computation/computation_carrier_region.rb +2 -2
  39. data/lib/earth/conversions_ext.rb +26 -7
  40. data/lib/earth/diet/diet_class.rb +2 -2
  41. data/lib/earth/diet/food_group.rb +2 -2
  42. data/lib/earth/eia.rb +13 -13
  43. data/lib/earth/fuel/fuel.rb +22 -13
  44. data/lib/earth/fuel/fuel/data_miner.rb +36 -44
  45. data/lib/earth/fuel/fuel_price.rb +1 -1
  46. data/lib/earth/fuel/fuel_type.rb +2 -2
  47. data/lib/earth/fuel/fuel_year.rb +4 -2
  48. data/lib/earth/fuel/greenhouse_gas.rb +2 -2
  49. data/lib/earth/hospitality/commercial_building_energy_consumption_survey_response.rb +14 -5
  50. data/lib/earth/hospitality/commercial_building_energy_consumption_survey_response/data_miner.rb +22 -1
  51. data/lib/earth/hospitality/country_lodging_class.rb +3 -3
  52. data/lib/earth/hospitality/country_lodging_class/data_miner.rb +7 -5
  53. data/lib/earth/hospitality/lodging_class.rb +1 -1
  54. data/lib/earth/hospitality/lodging_property.rb +8 -8
  55. data/lib/earth/industry/cbecs_energy_intensity.rb +59 -6
  56. data/lib/earth/industry/cbecs_energy_intensity/data_miner.rb +266 -69
  57. data/lib/earth/industry/industry.rb +1 -1
  58. data/lib/earth/industry/industry_product.rb +2 -2
  59. data/lib/earth/industry/industry_product_line.rb +2 -2
  60. data/lib/earth/industry/industry_sector.rb +2 -2
  61. data/lib/earth/industry/mecs_energy.rb +26 -15
  62. data/lib/earth/industry/mecs_energy/data_miner.rb +39 -23
  63. data/lib/earth/industry/mecs_ratio.rb +13 -10
  64. data/lib/earth/industry/mecs_ratio/data_miner.rb +14 -14
  65. data/lib/earth/industry/merchant.rb +2 -2
  66. data/lib/earth/industry/merchant_category.rb +2 -2
  67. data/lib/earth/industry/merchant_category_industry.rb +2 -2
  68. data/lib/earth/industry/product_line.rb +2 -2
  69. data/lib/earth/industry/product_line_industry_product.rb +2 -2
  70. data/lib/earth/industry/sector.rb +2 -2
  71. data/lib/earth/locality/census_division.rb +2 -2
  72. data/lib/earth/locality/census_division/data_miner.rb +4 -14
  73. data/lib/earth/locality/census_region.rb +2 -2
  74. data/lib/earth/locality/climate_division.rb +1 -17
  75. data/lib/earth/locality/country.rb +14 -28
  76. data/lib/earth/locality/country/data_miner.rb +8 -2
  77. data/lib/earth/locality/egrid_country.rb +1 -1
  78. data/lib/earth/locality/egrid_region.rb +4 -1
  79. data/lib/earth/locality/egrid_region/data_miner.rb +4 -1
  80. data/lib/earth/locality/egrid_subregion.rb +1 -1
  81. data/lib/earth/locality/egrid_subregion/data_miner.rb +1 -0
  82. data/lib/earth/locality/petroleum_administration_for_defense_district.rb +3 -3
  83. data/lib/earth/locality/state.rb +2 -7
  84. data/lib/earth/locality/zip_code.rb +1 -1
  85. data/lib/earth/pet/breed.rb +2 -2
  86. data/lib/earth/pet/breed_gender.rb +2 -2
  87. data/lib/earth/pet/gender.rb +2 -2
  88. data/lib/earth/pet/species.rb +2 -2
  89. data/lib/earth/pet/species/data_miner.rb +0 -9
  90. data/lib/earth/rail/country_rail_class.rb +1 -1
  91. data/lib/earth/rail/country_rail_traction.rb +1 -1
  92. data/lib/earth/rail/country_rail_traction_class.rb +1 -1
  93. data/lib/earth/rail/national_transit_database_company.rb +2 -2
  94. data/lib/earth/rail/national_transit_database_mode.rb +2 -2
  95. data/lib/earth/rail/national_transit_database_record.rb +2 -2
  96. data/lib/earth/rail/national_transit_database_record/data_miner.rb +12 -33
  97. data/lib/earth/rail/rail_class.rb +1 -1
  98. data/lib/earth/rail/rail_company.rb +1 -1
  99. data/lib/earth/rail/rail_company_traction.rb +1 -1
  100. data/lib/earth/rail/rail_company_traction_class.rb +1 -1
  101. data/lib/earth/rail/rail_fuel.rb +1 -1
  102. data/lib/earth/rail/rail_traction.rb +1 -1
  103. data/lib/earth/residence/air_conditioner_use.rb +2 -2
  104. data/lib/earth/residence/clothes_machine_use.rb +2 -2
  105. data/lib/earth/residence/dishwasher_use.rb +2 -2
  106. data/lib/earth/residence/residence_appliance.rb +2 -2
  107. data/lib/earth/residence/residence_class.rb +2 -2
  108. data/lib/earth/residence/residence_fuel_price.rb +2 -2
  109. data/lib/earth/residence/residence_fuel_price/data_miner.rb +0 -5
  110. data/lib/earth/residence/residence_fuel_type.rb +2 -2
  111. data/lib/earth/residence/residential_energy_consumption_survey_response.rb +3 -3
  112. data/lib/earth/residence/residential_energy_consumption_survey_response/data_miner.rb +0 -5
  113. data/lib/earth/residence/urbanity.rb +2 -2
  114. data/lib/earth/shipping/carrier.rb +3 -2
  115. data/lib/earth/shipping/carrier/data_miner.rb +1 -0
  116. data/lib/earth/shipping/carrier_mode.rb +2 -2
  117. data/lib/earth/shipping/shipment_mode.rb +2 -2
  118. data/lib/earth/version.rb +1 -1
  119. data/spec/earth/air/aircraft_spec.rb +421 -0
  120. data/spec/earth/fuel/fuel_spec.rb +35 -0
  121. data/spec/earth/hospitality/lodging_fuel_use_equation_spec.rb +96 -0
  122. data/spec/earth/industry/cbecs_energy_intensity_spec.rb +102 -0
  123. data/spec/earth/industry/mecs_energy_spec.rb +36 -44
  124. data/spec/earth/industry/mecs_ratio_spec.rb +24 -17
  125. data/spec/earth/locality/country_spec.rb +0 -9
  126. data/spec/spec_helper.rb +8 -3
  127. data/spec/support/integration.rb +17 -0
  128. data/vendor/geokit-rails/init.rb +2 -1
  129. data/vendor/geokit-rails/lib/geokit-rails.rb +1 -0
  130. metadata +63 -36
  131. data/lib/earth/hospitality/lodging_fuel_use_equation.rb +0 -26
  132. data/lib/earth/hospitality/lodging_fuel_use_equation/data_miner.rb +0 -20
  133. data/test/test_aircraft_match.rb +0 -732
@@ -1,5 +1,5 @@
1
1
  class FuelPrice < ActiveRecord::Base
2
- set_primary_key :name
2
+ self.primary_key = "name"
3
3
 
4
4
  belongs_to :fuel_type, :foreign_key => 'name' # weird
5
5
 
@@ -1,6 +1,6 @@
1
1
  # DEPRECATED but FuelPurchase still uses this
2
2
  class FuelType < ActiveRecord::Base
3
- set_primary_key :name
3
+ self.primary_key = "name"
4
4
 
5
5
  has_many :prices, :class_name => 'FuelPrice', :foreign_key => 'name' # weird
6
6
 
@@ -24,4 +24,4 @@ class FuelType < ActiveRecord::Base
24
24
  # col :energy_content_units
25
25
  # col :carbon_content, :type => :float
26
26
  # col :carbon_content_units
27
- end
27
+ end
@@ -1,5 +1,7 @@
1
1
  class FuelYear < ActiveRecord::Base
2
- set_primary_key :name
2
+ self.primary_key = "name"
3
+
4
+ belongs_to :fuel, :foreign_key => 'fuel_name'
3
5
 
4
6
  col :name
5
7
  col :fuel_name
@@ -57,4 +59,4 @@ class FuelYear < ActiveRecord::Base
57
59
  # end
58
60
  #
59
61
  # FIXME TODO verify units
60
- end
62
+ end
@@ -1,5 +1,5 @@
1
1
  class GreenhouseGas < ActiveRecord::Base
2
- set_primary_key :name
2
+ self.primary_key = "name"
3
3
 
4
4
  class << self
5
5
  def [](abbreviation)
@@ -52,4 +52,4 @@ class GreenhouseGas < ActiveRecord::Base
52
52
  # end
53
53
  # end
54
54
 
55
- end
55
+ end
@@ -1,13 +1,13 @@
1
1
  require 'earth/locality'
2
2
  class CommercialBuildingEnergyConsumptionSurveyResponse < ActiveRecord::Base
3
- set_primary_key :id
4
- set_table_name :cbecs_responses
3
+ self.primary_key = "id"
4
+ self.table_name = :cbecs_responses
5
5
 
6
6
  extend CohortScope
7
7
  self.minimum_cohort_size = 8 # CBECS doesn't report averages based on fewer than 20 samples
8
8
 
9
9
  def self.lodging_records
10
- where :detailed_activity => ['Hotel', 'Motel or inn']
10
+ where(:detailed_activity => ['Hotel', 'Motel or inn'], :first_activity => nil)
11
11
  end
12
12
 
13
13
  col :id, :type => :integer
@@ -23,6 +23,7 @@ class CommercialBuildingEnergyConsumptionSurveyResponse < ActiveRecord::Base
23
23
  col :area_units
24
24
  col :floors, :type => :integer
25
25
  col :lodging_rooms, :type => :integer
26
+ col :percent_cooled, :type => :float
26
27
  col :principal_activity
27
28
  col :detailed_activity
28
29
  col :first_activity
@@ -45,9 +46,17 @@ class CommercialBuildingEnergyConsumptionSurveyResponse < ActiveRecord::Base
45
46
  col :fuel_oil_use_units
46
47
  col :fuel_oil_energy, :type => :float
47
48
  col :fuel_oil_energy_units
48
- col :steam_use, :type => :float
49
- col :steam_use_units
49
+ col :district_heat_use, :type => :float
50
+ col :district_heat_use_units
50
51
  col :stratum, :type => :integer
51
52
  col :pair, :type => :integer
52
53
  col :weighting, :type => :float
54
+ col :electricity_per_room_night, :type => :float # for lodging fuzzy weighting
55
+ col :electricity_per_room_night_units # for lodging fuzzy weighting
56
+ col :natural_gas_per_room_night, :type => :float # for lodging fuzzy weighting
57
+ col :natural_gas_per_room_night_units # for lodging fuzzy weighting
58
+ col :fuel_oil_per_room_night, :type => :float # for lodging fuzzy weighting
59
+ col :fuel_oil_per_room_night_units # for lodging fuzzy weighting
60
+ col :district_heat_per_room_night, :type => :float # for lodging fuzzy weighting
61
+ col :district_heat_per_room_night_units # for lodging fuzzy weighting
53
62
  end
@@ -35,6 +35,14 @@ CommercialBuildingEnergyConsumptionSurveyResponse.class_eval do
35
35
  store 'lodging_rooms', :field_name => 'LODGRM8'
36
36
  end
37
37
 
38
+ import 'building characteristics from the 2003 EIA Commercial Building Energy Consumption Survey',
39
+ :url => 'http://www.eia.gov/emeu/cbecs/cbecs2003/public_use_2003/data/FILE03.csv',
40
+ :skip => 1,
41
+ :headers => ["PUBID8","REGION8","CENDIV8","SQFT8","SQFTC8","YRCONC8","PBA8","ELUSED8","NGUSED8","FKUSED8","PRUSED8","STUSED8","HWUSED8","HEATP8","HTLS508","FURNAC8","BOILER8","PKGHT8","SLFCON8","HTPMPH8","STHW8","OTHTEQ8","FURNP8","BOILP8","PKGHP8","SLFCNP8","HTPHP8","STHWP8","OTHTP8","MAINHT8","PKGHPS8","SPLHPS8","RMHPS8","AIRHPT8","GRDHPT8","WTRHPT8","NWMNHT8","RDHTNF8","HWRDHT8","COOLP8","PKGCL8","RCAC8","ACWNWL8","HTPMPC8","CHWT8","CHILLR8","EVAPCL8","OTCLEQ8","PKGCP8","RCACP8","ACWNWP8","HTPCP8","CHWTP8","CHILP8","EVAPP8","OTCLP8","MAINCL8","PKGCPS8","SPLCPS8","RMCPS8","AIRCPT8","GRDCPT8","WTRCPT8","NWMNCL8","RDCLNF8","HWRDCL8","VAV8","ECN8","MAINT8","EMCS8","ADJWT8","STRATUM8","PAIR8"] do
42
+ key 'id', :field_name => 'PUBID8'
43
+ store 'percent_cooled', :synthesize => Proc.new { |row| row['COOLP8'].to_f / 100.0 }
44
+ end
45
+
38
46
  import 'electricity use from the 2003 EIA Commercial Building Energy Consumption Survey',
39
47
  :url => 'http://www.eia.gov/emeu/cbecs/cbecs2003/public_use_2003/data/FILE15.csv',
40
48
  :skip => 1,
@@ -55,7 +63,20 @@ CommercialBuildingEnergyConsumptionSurveyResponse.class_eval do
55
63
  store 'natural_gas_energy', :field_name => 'NGBTU8', :from_units => :kbtus, :to_units => :megajoules
56
64
  store 'fuel_oil_use', :field_name => 'FKCNS8', :from_units => :gallons, :to_units => :litres
57
65
  store 'fuel_oil_energy', :field_name => 'FKBTU8', :from_units => :kbtus, :to_units => :megajoules
58
- store 'steam_use', :field_name => 'DHBTU8', :from_units => :kbtus, :to_units => :megajoules
66
+ store 'district_heat_use', :field_name => 'DHBTU8', :from_units => :kbtus, :to_units => :megajoules
67
+ end
68
+
69
+ process "Derive fuel intensities per room night for lodging buildings" do
70
+ # days/year * weeks/day * years/month = weeks/month
71
+ # weeks/month * months used in a year = weeks used in a year
72
+ # weeks used in a year * hours/week = hours used in a year
73
+ # hours used in a year * days/hour = days used in a year
74
+ [:natural_gas, :fuel_oil, :electricity, :district_heat].each do |fuel|
75
+ lodging_records.update_all %{
76
+ #{fuel}_per_room_night = #{fuel}_use / (365.0 / 7.0 / 12.0 * months_used * weekly_hours / 24.0 * lodging_rooms),
77
+ #{fuel}_per_room_night_units = #{fuel}_use_units || '_per_room_night'
78
+ }
79
+ end
59
80
  end
60
81
  end
61
82
  end
@@ -1,6 +1,6 @@
1
1
  require 'earth/locality'
2
2
  class CountryLodgingClass < ActiveRecord::Base
3
- set_primary_key :name
3
+ self.primary_key = "name"
4
4
 
5
5
  col :name
6
6
  col :country_iso_3166_code
@@ -12,7 +12,7 @@ class CountryLodgingClass < ActiveRecord::Base
12
12
  col :fuel_oil_intensity_units
13
13
  col :electricity_intensity, :type => :float
14
14
  col :electricity_intensity_units
15
- col :steam_intensity, :type => :float
16
- col :steam_intensity_units
15
+ col :district_heat_intensity, :type => :float
16
+ col :district_heat_intensity_units
17
17
  col :weighting, :type => :float
18
18
  end
@@ -9,17 +9,19 @@ CountryLodgingClass.class_eval do
9
9
  store 'cbecs_detailed_activity'
10
10
  end
11
11
 
12
- process "Ensure CommercialBuildingEnergyConsumptionSurveyResponse is populated" do
12
+ process "Ensure CommercialBuildingEnergyConsumptionSurveyResponse and Country are populated" do
13
13
  CommercialBuildingEnergyConsumptionSurveyResponse.run_data_miner!
14
+ Country.run_data_miner!
14
15
  end
15
16
 
16
17
  process "Calculate US lodging class fuel intensities from CommercialBuildingEnergyConsumptionSurveyResponse" do
18
+ occupancy_rate = Country.united_states.lodging_occupancy_rate
17
19
  connection.select_values("SELECT DISTINCT cbecs_detailed_activity FROM #{CountryLodgingClass.quoted_table_name}").each do |cbecs_activity|
18
- [:natural_gas, :fuel_oil, :electricity, :steam].each do |fuel|
20
+ [:natural_gas, :fuel_oil, :electricity, :district_heat].each do |fuel|
19
21
  where(:cbecs_detailed_activity => cbecs_activity).update_all(%{
20
22
  #{fuel}_intensity = (
21
23
  SELECT SUM(
22
- weighting * #{fuel}_use / (365.0 / 7.0 / 12.0 * months_used * weekly_hours / 24.0 * lodging_rooms * 0.59)
24
+ weighting * #{fuel}_use / (365.0 / 7.0 / 12.0 * months_used * weekly_hours / 24.0 * lodging_rooms * #{occupancy_rate})
23
25
  ) / SUM(weighting)
24
26
  FROM #{CommercialBuildingEnergyConsumptionSurveyResponse.quoted_table_name}
25
27
  WHERE detailed_activity = '#{cbecs_activity}'
@@ -29,9 +31,9 @@ CountryLodgingClass.class_eval do
29
31
 
30
32
  where(:cbecs_detailed_activity => cbecs_activity).update_all(%{
31
33
  natural_gas_intensity_units = 'cubic_metres_per_room_night',
32
- fuel_oil_intensity_units = 'litrs_per_room_night',
34
+ fuel_oil_intensity_units = 'litres_per_room_night',
33
35
  electricity_intensity_units = 'kilowatt_hours_per_room_night',
34
- steam_intensity_units = 'megajoules_per_room_night',
36
+ district_heat_intensity_units = 'megajoules_per_room_night',
35
37
  weighting = (
36
38
  SELECT SUM(weighting)
37
39
  FROM #{CommercialBuildingEnergyConsumptionSurveyResponse.quoted_table_name}
@@ -1,6 +1,6 @@
1
1
  require 'earth/locality'
2
2
  class LodgingClass < ActiveRecord::Base
3
- set_primary_key :name
3
+ self.primary_key = "name"
4
4
 
5
5
  col :name
6
6
  end
@@ -1,7 +1,7 @@
1
1
  require 'earth/locality'
2
2
  # Copyright 2011 Brighter Planet, Inc.
3
3
  class LodgingProperty < ActiveRecord::Base
4
- set_primary_key :northstar_id
4
+ self.primary_key = "northstar_id"
5
5
 
6
6
  # So Lodging can look up LodgingClass from LodgingProperty
7
7
  belongs_to :lodging_class, :foreign_key => 'lodging_class_name'
@@ -18,12 +18,12 @@ class LodgingProperty < ActiveRecord::Base
18
18
  col :construction_year, :type => :integer
19
19
  col :renovation_year, :type => :integer
20
20
  col :lodging_class_name
21
- col :restaurant
22
- col :air_conditioning
23
- col :mini_bar
24
- col :refrigerator
25
- col :hot_tub
26
- col :pools_indoor, :type => :integer
27
- col :pools_outdoor, :type => :integer
21
+ col :restaurants, :type => :integer
22
+ col :ac_coverage, :type => :float
23
+ col :mini_bar_coverage, :type => :float
24
+ col :fridge_coverage, :type => :float
25
+ col :hot_tubs, :type => :float # float b/c fallback needs to be a float
26
+ col :pools_indoor, :type => :float # float b/c fallback needs to be a float
27
+ col :pools_outdoor, :type => :float # float b/c fallback needs to be a float
28
28
  col :update_date
29
29
  end
@@ -1,11 +1,64 @@
1
1
  require 'earth/locality'
2
+
2
3
  class CbecsEnergyIntensity < ActiveRecord::Base
3
- set_primary_key :name
4
+ self.primary_key = "name"
4
5
 
5
- col :name
6
- col :naics_code
7
- col :census_division_number, :type => :integer
8
- col :total_electricity_consumption, :type => :float
9
- col :total_floorspace, :type => :float
6
+ col :name, :index => true
7
+ col :principal_building_activity
8
+ col :naics_code, :index => true
9
+ col :census_region_number, :type => :integer, :index => true
10
+ col :census_division_number, :type => :integer, :index => true
11
+
12
+ col :electricity, :type => :float
13
+ col :electricity_units
14
+ col :electricity_floorspace, :type => :float
15
+ col :electricity_floorspace_units
10
16
  col :electricity_intensity, :type => :float
17
+ col :electricity_intensity_units
18
+
19
+ col :natural_gas, :type => :float
20
+ col :natural_gas_units
21
+ col :natural_gas_floorspace, :type => :float
22
+ col :natural_gas_floorspace_units
23
+ col :natural_gas_intensity, :type => :float
24
+ col :natural_gas_intensity_units
25
+
26
+ col :fuel_oil, :type => :float
27
+ col :fuel_oil_units
28
+ col :fuel_oil_floorspace, :type => :float
29
+ col :fuel_oil_floorspace_units
30
+ col :fuel_oil_intensity, :type => :float
31
+ col :fuel_oil_intensity_units
32
+
33
+ col :district_heat, :type => :float
34
+ col :district_heat_units
35
+ col :district_heat_floorspace, :type => :float
36
+ col :district_heat_floorspace_units
37
+ col :district_heat_intensity, :type => :float
38
+ col :district_heat_intensity_units
39
+
40
+ scope :divisional, where('census_region_number IS NOT NULL AND census_division_number IS NOT NULL')
41
+ scope :regional, where('census_region_number IS NOT NULL AND census_division_number IS NULL')
42
+ scope :national, where(:census_region_number => nil, :census_division_number => nil)
43
+
44
+ # Find the first record whose census_division_number matches number and whose naics_code matches code.
45
+ # If no record found chop off the last character of code and try again, and so on.
46
+ def self.find_by_naics_code_and_census_division_number(code, number)
47
+ if code.blank?
48
+ record = nil
49
+ else
50
+ record = where('census_division_number = ? AND naics_code = ?', number, code).first
51
+ record ||= find_by_naics_code_and_census_division_number(code[0..-2], number)
52
+ end
53
+ record
54
+ end
55
+
56
+ def fuel_ratios
57
+ energy = 0
58
+ FUELS.keys.each { |fuel| energy += send(fuel).to_f }
59
+ FUELS.keys.inject({}) do |ratios, fuel|
60
+ ratios[fuel] = send(fuel).to_f / energy.to_f
61
+ ratios
62
+ end
63
+ end
11
64
  end
@@ -1,109 +1,306 @@
1
1
  require 'earth/eia'
2
+ require 'earth/industry'
2
3
  require 'earth/locality/data_miner'
4
+
3
5
  CbecsEnergyIntensity.class_eval do
4
- const_set(:CENSUS_DIVISIONS, {
5
- 'New England Division' => {
6
- :column => 0,
7
- :code => 1,
8
- :table => 'c17'
9
- },
10
- 'Middle Atlantic Division' => {
11
- :column => 1,
12
- :code => 2,
13
- :table => 'c17'
14
- },
15
- 'East North Central Division' => {
16
- :column => 2,
17
- :code => 3,
18
- :table => 'c17'
6
+ const_set :FUELS, {
7
+ :electricity => {
8
+ :consumption => :billion_kilowatt_hours,
9
+ :intensity => :kilowatt_hours_per_square_foot,
10
+ :set => 10
19
11
  },
20
- 'West North Central Division' => {
21
- :column => 0,
22
- :code => 4,
23
- :table => 'c18'
12
+ :natural_gas => {
13
+ :consumption => :billion_cubic_feet_of_natural_gas,
14
+ :intensity => :cubic_feet_of_natural_gas_per_square_foot,
15
+ :set => 11
24
16
  },
25
- 'South Atlantic Division' => {
26
- :column => 1,
27
- :code => 5,
28
- :table => 'c18'
17
+ :fuel_oil => {
18
+ :consumption => :million_gallons_of_fuel_oil,
19
+ :intensity => :gallons_of_fuel_oil_per_square_foot,
20
+ :set => 12
29
21
  },
30
- 'East South Central Division' => {
31
- :column => 2,
32
- :code => 6,
33
- :table => 'c18'
34
- },
35
- 'West South Central Division' => {
36
- :column => 0,
37
- :code => 7,
38
- :table => 'c19'
39
- },
40
- 'Mountain Division' => {
41
- :column => 1,
42
- :code => 8,
43
- :table => 'c19'
22
+ :district_heat => {
23
+ :consumption => :trillion_btu,
24
+ :intensity => :trillion_btu_per_million_square_feet,
25
+ :set => 13
26
+ }
27
+ }
28
+
29
+ const_set(:CBECS, {
30
+ :region_tables => {
31
+ :electricity => 'c15',
32
+ :natural_gas => 'c25',
33
+ :fuel_oil => 'c35'
44
34
  },
45
- 'Pacific Division' => {
46
- :column => 2,
47
- :code => 9,
48
- :table => 'c19'
35
+ :regions => {
36
+ 'North-east' => {
37
+ :census_region => 1,
38
+ :column => 1,
39
+
40
+ :divisions => {
41
+ 'New England Division' => {
42
+ :column => 0,
43
+ :census_division => 1,
44
+ :table => {
45
+ :electricity => 'c17',
46
+ :natural_gas => 'c27'
47
+ }
48
+ },
49
+ 'Middle Atlantic Division' => {
50
+ :column => 1,
51
+ :census_division => 2,
52
+ :table => {
53
+ :electricity => 'c17',
54
+ :natural_gas => 'c27'
55
+ }
56
+ }
57
+ }
58
+ },
59
+ 'Mid-west' => {
60
+ :census_region => 2,
61
+ :column => 2,
62
+ :table => {
63
+ :electricity => 'c16',
64
+ :natural_gas => 'c26',
65
+ :fuel_oil => 'c36'
66
+ },
67
+
68
+ :divisions => {
69
+ 'East North Central Division' => {
70
+ :column => 2,
71
+ :census_division => 3,
72
+ :table => {
73
+ :electricity => 'c17',
74
+ :natural_gas => 'c27'
75
+ }
76
+ },
77
+ 'West North Central Division' => {
78
+ :column => 0,
79
+ :census_division => 4,
80
+ :table => {
81
+ :electricity => 'c18',
82
+ :natural_gas => 'c28'
83
+ }
84
+ }
85
+ }
86
+ },
87
+ 'South' => {
88
+ :census_region => 3,
89
+ :column => 3,
90
+ :table => {
91
+ :electricity => 'c16',
92
+ :natural_gas => 'c26',
93
+ :fuel_oil => 'c36'
94
+ },
95
+
96
+ :divisions => {
97
+ 'South Atlantic Division' => {
98
+ :column => 1,
99
+ :census_division => 5,
100
+ :table => {
101
+ :electricity => 'c18',
102
+ :natural_gas => 'c28'
103
+ }
104
+ },
105
+ 'East South Central Division' => {
106
+ :column => 2,
107
+ :census_division => 6,
108
+ :table => {
109
+ :electricity => 'c18',
110
+ :natural_gas => 'c28'
111
+ }
112
+ },
113
+ 'West South Central Division' => {
114
+ :column => 0,
115
+ :census_division => 7,
116
+ :table => {
117
+ :electricity => 'c19',
118
+ :natural_gas => 'c29'
119
+ }
120
+ }
121
+ }
122
+ },
123
+ 'West' => {
124
+ :census_region => 4,
125
+ :column => 4,
126
+ :table => {
127
+ :electricity => 'c16',
128
+ :natural_gas => 'c26',
129
+ :fuel_oil => 'c36'
130
+ },
131
+
132
+ :divisions => {
133
+ 'Mountain Division' => {
134
+ :column => 1,
135
+ :census_division => 8,
136
+ :table => {
137
+ :electricity => 'c19',
138
+ :natural_gas => 'c29'
139
+ }
140
+ },
141
+ 'Pacific Division' => {
142
+ :column => 2,
143
+ :census_division => 9,
144
+ :table => {
145
+ :electricity => 'c19',
146
+ :natural_gas => 'c29'
147
+ }
148
+ }
149
+ }
150
+ }
49
151
  }
50
152
  })
51
-
153
+
52
154
  const_set(:NAICS_CODE_SYNTHESIZER, lambda { |row|
53
155
  case row[0].to_s
54
156
  when /Education/
55
- 611110
157
+ 61
56
158
  when /Food Sales/
57
159
  445
58
160
  when /Food Service/
59
161
  722
60
162
  when /Health Care/
61
- 622110
163
+ 62 # FIXME TODO should only be 621 and 622
62
164
  when /Inpatient/
63
- 622110
165
+ 622
64
166
  when /Outpatient/
65
- 622111
167
+ 621
66
168
  when /Lodging/
67
- 721
68
- when /Retail (Other Than Mall)/
69
- 44
169
+ 721 # FIXME TODO should really be 623, 62422, 721, maybe 8131
170
+ when /Retail \(Other Than Mall\)/
171
+ 44 # FIXME TODO should really be 44 and 45 excluding 445 and 454
70
172
  when /Office/
71
- #TODO
173
+ 55 # Management of Companies and Enterprises FIXME TODO should be all NAICS codes that identify an office
72
174
  when /Public Assembly/
73
175
  #TODO
74
176
  when /Public Order and Safety/
75
- 922120
177
+ 922
76
178
  when /Religious Worship/
77
- 813110
179
+ 8131
78
180
  when /Service/
79
- #TODO
181
+ 81 # other services (except public administration) FIXME TODO exclude 8131 and include all NAICS codes that are services
80
182
  when /Warehouse and Storage/
81
- 493110
183
+ 493
82
184
  when /Other/
83
185
  #TODO
84
186
  when /Vacant/
85
187
  #TODO
86
188
  end
87
189
  })
88
-
190
+
89
191
  data_miner do
90
- CbecsEnergyIntensity::CENSUS_DIVISIONS.each do |division, data|
91
- import "2003 CBECS #{data[:table].upcase} - Electricity Consumption and Intensity - #{division}",
92
- :url => "http://www.eia.gov/emeu/cbecs/cbecs2003/detailed_tables_2003/2003set10/2003excel/#{data[:table]}.xls",
93
- :headers => false,
94
- :select => ::Proc.new { |row| CbecsEnergyIntensity::NAICS_CODE_SYNTHESIZER.call(row) },
95
- :crop => (21..37) do
96
- key :name, :synthesize => ::Proc.new { |row| "#{Industry.format_naics_code(CbecsEnergyIntensity::NAICS_CODE_SYNTHESIZER.call(row))}-#{data[:code]}" }
97
- store :naics_code, :synthesize => CbecsEnergyIntensity::NAICS_CODE_SYNTHESIZER
98
- store :census_division_number, :static => data[:code]
99
- store :total_electricity_consumption, :field_number => data[:column] + 1
100
- store :total_floorspace, :field_number => data[:column] + 4
101
- store :electricity_intensity, :field_number => data[:column] + 7
192
+ CbecsEnergyIntensity::CBECS[:regions].each do |region_name, region_data|
193
+ region_number = region_data[:census_region]
194
+
195
+ # By Census Division
196
+ #
197
+ region_data[:divisions].each do |division, division_data|
198
+ division_data[:table].each do |energy_source, table|
199
+ import "2003 CBECS #{table.upcase} - Electricity Consumption and Intensity - #{division}",
200
+ :url => "http://www.eia.gov/emeu/cbecs/cbecs2003/detailed_tables_2003/2003set#{CbecsEnergyIntensity::FUELS[energy_source][:set]}/2003excel/#{table}.xls",
201
+ :headers => false,
202
+ :select => Proc.new { |row| CbecsEnergyIntensity::NAICS_CODE_SYNTHESIZER.call(row) }, # only select rows where we can translate activity to a NAICS code
203
+ :crop => (21..37) do
204
+ key :name, :synthesize => Proc.new { |row|
205
+ "#{Industry.format_naics_code(CbecsEnergyIntensity::NAICS_CODE_SYNTHESIZER.call(row))}-#{region_number}-#{division_data[:census_division]}"
206
+ }
207
+
208
+ store :principal_building_activity, :synthesize => Proc.new { |row| row[0].gsub(/[\.\(\)]/,'').strip }
209
+ store :naics_code, :synthesize => CbecsEnergyIntensity::NAICS_CODE_SYNTHESIZER
210
+ store :census_region_number, :static => region_number
211
+ store :census_division_number, :static => division_data[:census_division]
212
+
213
+ fuel_data = CbecsEnergyIntensity::FUELS[energy_source]
214
+ store energy_source, :units => :megajoules, :synthesize => Proc.new { |row|
215
+ Earth::EIA.convert_value(row[division_data[:column] + 1], :from => fuel_data[:consumption], :to => :megajoules)
216
+ }
217
+ store "#{energy_source}_floorspace", :units => :square_metres, :synthesize => Proc.new { |row|
218
+ Earth::EIA.convert_value(row[division_data[:column] + 4], :from => :million_square_feet, :to => :square_metres)
219
+ }
220
+ store "#{energy_source}_intensity", :units => :megajoules_per_square_metre, :synthesize => Proc.new { |row|
221
+ Earth::EIA.convert_value(row[division_data[:column] + 7], :from => fuel_data[:intensity], :to => :megajoules_per_square_metre)
222
+ }
223
+ end
224
+ end
225
+ end
226
+ end
227
+
228
+ ## By Census Region
229
+ ##
230
+ CbecsEnergyIntensity::CBECS[:region_tables].each do |energy_source, table|
231
+ CbecsEnergyIntensity::CBECS[:regions].each do |region, region_data|
232
+ import "2003 CBECS #{table.upcase} - #{energy_source.to_s.titleize} Consumption and Intensity - #{region.capitalize} Region",
233
+ :url => "http://www.eia.gov/emeu/cbecs/cbecs2003/detailed_tables_2003/2003set#{CbecsEnergyIntensity::FUELS[energy_source][:set]}/2003excel/#{table}.xls",
234
+ :select => Proc.new { |row| CbecsEnergyIntensity::NAICS_CODE_SYNTHESIZER.call(row) }, # only select rows where we can translate activity to a NAICS code
235
+ :headers => false,
236
+ :crop => (energy_source == :fuel_oil ? (16..19) : (21..37)) do
237
+
238
+ key :name, :synthesize => Proc.new { |row|
239
+ "#{Industry.format_naics_code(CbecsEnergyIntensity::NAICS_CODE_SYNTHESIZER.call(row))}-#{region_data[:census_region]}"
240
+ }
241
+
242
+ store :census_region_number, :static => region_data[:census_region]
243
+ store :principal_building_activity, :synthesize => Proc.new { |row| row[0].gsub(/[\.\(\)]/,'').strip }
244
+ store :naics_code, :synthesize => CbecsEnergyIntensity::NAICS_CODE_SYNTHESIZER
245
+
246
+ store energy_source, :units => :megajoules, :synthesize => Proc.new { |row|
247
+ Earth::EIA.convert_value(row[region_data[:column]], :from => CbecsEnergyIntensity::FUELS[energy_source][:consumption],
248
+ :to => :megajoules)
249
+ }
250
+ store "#{energy_source}_floorspace", :units => :square_metres, :synthesize => Proc.new { |row|
251
+ Earth::EIA.convert_value(row[region_data[:column] + 4], :from => :million_square_feet, :to => :square_metres)
252
+ }
253
+ store "#{energy_source}_intensity", :units => :megajoules_per_square_metre, :synthesize => Proc.new { |row|
254
+ Earth::EIA.convert_value(row[region_data[:column] + 8], :from => CbecsEnergyIntensity::FUELS[energy_source][:intensity],
255
+ :to => :megajoules_per_square_metre)
256
+ }
257
+ end
102
258
  end
103
259
  end
104
260
 
105
- process :normalize_fuels do
106
- Earth::EIA.normalize(CbecsEnergyIntensity, [:total_electricity_consumption, :total_floorspace, :electricity_intensity])
261
+ # National
262
+ import "2003 CBECS C1 - District Heat Consumption and Intensity - US Total",
263
+ :url => "http://www.eia.gov/emeu/cbecs/cbecs2003/detailed_tables_2003/2003set9/2003excel/c1.xls",
264
+ :headers => false,
265
+ :select => Proc.new { |row| CbecsEnergyIntensity::NAICS_CODE_SYNTHESIZER.call(row) }, # only select rows where we can translate activity to a NAICS code
266
+ :crop => (21..37) do
267
+ key :name, :synthesize => Proc.new { |row|
268
+ Industry.format_naics_code(CbecsEnergyIntensity::NAICS_CODE_SYNTHESIZER.call(row))
269
+ }
270
+ store :principal_building_activity, :synthesize => Proc.new { |row| row[0].gsub(/[\.\(\)]/,'').strip }
271
+ store :naics_code, :synthesize => CbecsEnergyIntensity::NAICS_CODE_SYNTHESIZER
272
+
273
+ {:electricity => [4,5], :natural_gas => [6], :fuel_oil => [7], :district_heat => [8]}.each do |energy_source, columns|
274
+ store energy_source, :units => :megajoules, :synthesize => Proc.new { |row|
275
+ total_energy = nil
276
+ columns.each do |column|
277
+ value = Earth::EIA.convert_value(row[column], :from => :trillion_btus, :to => :megajoules)
278
+ if value
279
+ total_energy ||= 0
280
+ total_energy += value
281
+ end
282
+ end
283
+ total_energy
284
+ }
285
+ store "#{energy_source}_floorspace", :units => :square_metres, :synthesize => Proc.new { |row|
286
+ Earth::EIA.convert_value(row[2], :from => :million_square_feet, :to => :square_metres)
287
+ }
288
+ store "#{energy_source}_intensity", :units => :megajoules_per_square_metre, :synthesize => Proc.new { |row|
289
+ total_energy = nil
290
+ columns.each do |column|
291
+ value = Earth::EIA.convert_value(row[column])
292
+ if value
293
+ total_energy ||= 0
294
+ total_energy += value
295
+ end
296
+ end
297
+ if total_energy
298
+ intensity = total_energy / row[2].to_f
299
+ Earth::EIA.convert_value(intensity, :from => :trillion_btus_per_million_square_feet,
300
+ :to => :megajoules_per_square_metre)
301
+ end
302
+ }
303
+ end
107
304
  end
108
305
  end
109
306
  end