def dam_capacity(self): section = self.section('DamCapacity', 'BRAT Dam Capacity Results') conn = sqlite3.connect(self.database) conn.row_factory = _dict_factory curs = conn.cursor() fields = [('Existing complex size', 'Sum(mCC_EX_CT)'), ('Historic complex size', 'Sum(mCC_HPE_CT)'), ('Existing vegetation capacity', 'Sum((iGeo_len / 1000) * oVC_EX)'), ('Historic vegetation capacity', 'Sum((iGeo_len / 1000) * oVC_HPE)'), ('Existing capacity', 'Sum((iGeo_len / 1000) * oCC_EX)'), ('Historic capacity', 'Sum((iGeo_len / 1000) * oCC_HPE)')] curs.execute('SELECT {} FROM vwReaches'.format(', '.join( [field for label, field in fields]))) row = curs.fetchone() table_dict = { fields[i][0]: row[fields[i][1]] for i in range(len(fields)) } RSReport.create_table_from_dict(table_dict, section) self.dam_capacity_lengths('oCC_EX', section) self.dam_capacity_lengths('oCC_HPE', section)
def report_intro(self): # Create a section node to start adding things to. Section nodes are added to the table of contents if # they have a title. If you don't specify a el_parent argument these sections will simply be added # to the report body in the order you call them. section = self.section('ReportIntro', 'Introduction') # This project has a db so we'll need a connection conn = sqlite3.connect(self.database) conn.row_factory = _dict_factory curs = conn.cursor() row = curs.execute( 'SELECT Sum(iGeo_Len) AS TotalLength, Count(ReachID) AS TotalReaches FROM vwReaches' ).fetchone() values = { 'Number of reaches': '{0:,d}'.format(row['TotalReaches']), 'Total reach length (km)': '{0:,.0f}'.format(row['TotalLength'] / 1000), 'Total reach length (miles)': '{0:,.0f}'.format(row['TotalLength'] * 0.000621371) } row = curs.execute(''' SELECT WatershedID "Watershed ID", W.Name "Watershed Name", E.Name Ecoregion, CAST(AreaSqKm AS TEXT) "Area (Sqkm)", States FROM Watersheds W INNER JOIN Ecoregions E ON W.EcoregionID = E.EcoregionID ''').fetchone() values.update(row) curs.execute('SELECT KeyInfo, ValueInfo FROM Metadata') values.update({ row['KeyInfo'].replace('_', ' '): row['ValueInfo'] for row in curs.fetchall() }) # Here we're creating a new <div> to wrap around the table for stylign purposes table_wrapper = ET.Element('div', attrib={'class': 'tableWrapper'}) RSReport.create_table_from_dict(values, table_wrapper, attrib={'id': 'SummTable'}) RSReport.create_table_from_sql( ['Reach Type', 'Total Length (km)', '% of Total'], 'SELECT ReachType, Sum(iGeo_Len) / 1000 As Length, 100 * Sum(iGeo_Len) / TotalLength AS TotalLength ' 'FROM vwReaches INNER JOIN (SELECT Sum(iGeo_Len) AS TotalLength FROM vwReaches) GROUP BY ReachType', self.database, table_wrapper, attrib={'id': 'SummTable_sql'}) # Append my table_wrapper div (which now contains both tables above) to the section section.append(table_wrapper)
def ownership(self): section = self.section('Ownership', 'Ownership') RSReport.create_table_from_sql( [ 'Ownership Agency', 'Number of Reach Segments', 'Length (km)', '% of Total Length' ], 'SELECT IFNULL(Agency, "None"), Count(ReachID), Sum(iGeo_Len) / 1000, 100* Sum(iGeo_Len) / TotalLength FROM vwReaches' ' INNER JOIN (SELECT Sum(iGeo_Len) AS TotalLength FROM vwReaches) GROUP BY Agency', self.database, section, attrib={'class': 'fullwidth'})
def reach_attribute(self, attribute, units, parent_el): # Use a class here because it repeats section = self.section(None, attribute, parent_el, level=2) conn = sqlite3.connect(self.database) conn.row_factory = _dict_factory curs = conn.cursor() # Summary statistics (min, max etc) for the current attribute curs.execute( 'SELECT Count({0}) "Values", Max({0}) Maximum, Min({0}) Minimum, Avg({0}) Average FROM vwReaches WHERE {0} IS NOT NULL' .format(attribute)) values = curs.fetchone() reach_wrapper_inner = ET.Element( 'div', attrib={'class': 'reachAtributeInner'}) section.append(reach_wrapper_inner) # Add the number of NULL values curs.execute( 'SELECT Count({0}) "NULL Values" FROM vwReaches WHERE {0} IS NULL'. format(attribute)) values.update(curs.fetchone()) RSReport.create_table_from_dict(values, reach_wrapper_inner) # Box plot image_path = os.path.join(self.images_dir, 'attribute_{}.png'.format(attribute)) curs.execute('SELECT {0} FROM vwReaches WHERE {0} IS NOT NULL'.format( attribute)) values = [row[attribute] for row in curs.fetchall()] box_plot(values, attribute, attribute, image_path) img_wrap = ET.Element('div', attrib={'class': 'imgWrap'}) img = ET.Element('img', attrib={ 'class': 'boxplot', 'alt': 'boxplot', 'src': '{}/{}'.format(os.path.basename(self.images_dir), os.path.basename(image_path)) }) img_wrap.append(img) reach_wrapper_inner.append(img_wrap)
def dam_capacity_lengths(self, capacity_field, elParent): conn = sqlite3.connect(self.database) curs = conn.cursor() curs.execute( 'SELECT Name, MaxCapacity FROM DamCapacities ORDER BY MaxCapacity') bins = [(row[0], row[1]) for row in curs.fetchall()] curs.execute('SELECT Sum(iGeo_Len) / 1000 FROM vwReaches') total_length_km = curs.fetchone()[0] data = [] last_bin = 0 cumulative_length_km = 0 for name, max_capacity in bins: curs.execute( 'SELECT Sum(iGeo_len) / 1000 FROM vwReaches WHERE {} <= {}'. format(capacity_field, max_capacity)) rowi = curs.fetchone() if not rowi or rowi[0] is None: bin_km = 0 else: bin_km = rowi[0] - cumulative_length_km cumulative_length_km = rowi[0] data.append(('{}: {} - {}'.format(name, last_bin, max_capacity), bin_km, bin_km * 0.621371, 100 * bin_km / total_length_km)) last_bin = max_capacity data.append( ('Total', cumulative_length_km, cumulative_length_km * 0.621371, 100 * cumulative_length_km / total_length_km)) RSReport.create_table_from_tuple_list( (capacity_field, 'Stream Length (km)', 'Stream Length (mi)', 'Percent'), data, elParent)
def conservation(self): section = self.section('Conservation', 'Conservation') fields = [('Risk', 'DamRisks', 'RiskID'), ('Opportunity', 'DamOpportunities', 'OpportunityID'), ('Limitation', 'DamLimitations', 'LimitationID')] for label, table, idfield in fields: RSReport.header(3, label, section) RSReport.create_table_from_sql( [label, 'Total Length (km)', 'Reach Count', '%'], 'SELECT DR.Name, Sum(iGeo_Len) / 1000, Count(R.{1}), 100 * Sum(iGeo_Len) / TotalLength' ' FROM {0} DR LEFT JOIN vwReaches R ON DR.{1} = R.{1}' ' JOIN (SELECT Sum(iGeo_Len) AS TotalLength FROM vwReaches)' ' GROUP BY DR.{1}'.format(table, idfield), self.database, section) RSReport.header(3, 'Conflict Attributes', section) for attribute in ['iPC_Canal', 'iPC_DivPts', 'iPC_Privat']: self.reach_attribute(attribute, 'meters', section)
def vegetation(self): section = self.section('Vegetation', 'Vegetation') conn = sqlite3.connect(self.database) # conn.row_factory = _dict_factory curs = conn.cursor() for epochid, veg_type in [(2, 'Historic Vegetation'), (1, 'Existing Vegetation')]: RSReport.header(3, veg_type, section) pEl = ET.Element('p') pEl.text = 'The 30 most common {} types within the 100m reach buffer.'.format( veg_type.lower()) section.append(pEl) RSReport.create_table_from_sql([ 'Vegetation ID', 'Vegetation Type', 'Total Area (sqkm)', 'Default Suitability', 'Override Suitability', 'Effective Suitability' ], """ SELECT VegetationID, Name, (CAST(TotalArea AS REAL) / 1000000) AS TotalAreaSqKm, DefaultSuitability, OverrideSuitability, EffectiveSuitability FROM vwReachVegetationTypes WHERE (EpochID = {}) AND (Buffer = 100) ORDER BY TotalArea DESC LIMIT 30""" .format(epochid), self.database, section) try: # Calculate the area weighted suitability curs.execute(""" SELECT WeightedSum / SumTotalArea FROM (SELECT Sum(CAST(TotalArea AS REAL) * CAST(EffectiveSuitability AS REAL) / 1000000) WeightedSum FROM vwReachVegetationTypes WHERE EpochID = {0} AND Buffer = 100) JOIN (SELECT CAST(Sum(TotalArea) AS REAL) / 1000000 SumTotalArea FROM vwReachVegetationTypes WHERE EpochID = {0} AND Buffer = 100)""" .format(epochid)) area_weighted_avg_suitability = curs.fetchone()[0] RSReport.header(3, 'Suitability Breakdown', section) pEl = ET.Element('p') pEl.text = """The area weighted average {} suitability is {}. The breakdown of the percentage of the 100m buffer within each suitability class across all reaches in the watershed.""".format( veg_type.lower(), RSReport.format_value(area_weighted_avg_suitability)[0]) section.append(pEl) RSReport.create_table_from_sql( ['Suitability Class', '% with 100m Buffer'], """ SELECT EffectiveSuitability, 100.0 * SArea / SumTotalArea FROM ( SELECT CAST(Sum(TotalArea) AS REAL) / 1000000 SArea, EffectiveSuitability FROM vwReachVegetationTypes WHERE EpochID = {0} AND Buffer = 100 GROUP BY EffectiveSuitability ) JOIN ( SELECT CAST(Sum(TotalArea) AS REAL) / 1000000 SumTotalArea FROM vwReachVegetationTypes WHERE EpochID = {0} AND Buffer = 100 ) ORDER BY EffectiveSuitability """.format(epochid), self.database, section, id_cols=id_cols) except Exception as ex: self.log.warning('Error calculating vegetation report')
def hydrology_plots(self): section = self.section('HydrologyPlots', 'Hydrology') conn = sqlite3.connect(self.database) curs = conn.cursor() curs.execute('SELECT MaxDrainage, QLow, Q2 FROM Watersheds') row = curs.fetchone() RSReport.create_table_from_dict( { 'Max Draiange (sqkm)': row[0], 'Baseflow': row[1], 'Peak Flow': row[2] }, section, attrib={'class': 'fullwidth'}) RSReport.header(3, 'Hydrological Parameters', section) RSReport.create_table_from_sql( [ 'Parameter', 'Data Value', 'Data Units', 'Conversion Factor', 'Equation Value', 'Equation Units' ], 'SELECT Parameter, Value, DataUnits, Conversion, ConvertedValue, EquationUnits FROM vwHydroParams', self.database, section, attrib={'class': 'fullwidth'}) variables = [('iHyd_QLow', 'Baseflow (CFS)'), ('iHyd_Q2', 'Peak Flow (CFS)'), ('iHyd_SPLow', 'Baseflow Stream Power (Watts)'), ('iHyd_SP2', 'Peak Flow Stream Power (Watts)'), ('iGeo_Slope', 'Slope (degrees)')] plot_wrapper = ET.Element('div', attrib={'class': 'hydroPlotWrapper'}) section.append(plot_wrapper) for variable, ylabel in variables: self.log.info( 'Generating XY scatter for {} against drainage area.'.format( variable)) image_path = os.path.join( self.images_dir, 'drainage_area_{}.png'.format(variable.lower())) curs.execute('SELECT iGeo_DA, {} FROM vwReaches'.format(variable)) values = [(row[0], row[1]) for row in curs.fetchall()] xyscatter(values, 'Drainage Area (sqkm)', ylabel, variable, image_path) img_wrap = ET.Element('div', attrib={'class': 'imgWrap'}) img = ET.Element('img', attrib={ 'src': '{}/{}'.format( os.path.basename(self.images_dir), os.path.basename(image_path)), 'alt': 'boxplot' }) img_wrap.append(img) plot_wrapper.append(img_wrap)