def test_addDataRow(self): """Test adding a new row to 'main' data.""" # Create a factory and load the river unit ifactory = FmpUnitFactory() i, river = ifactory.createUnitFromFile(self.input_contents, 0, 'RIVER', 1, 1) # Add with required only args args = {rdt.CHAINAGE: 6.0, rdt.ELEVATION: 37.2} river.addRow(args, index=1) row = river.row_data['main'].rowAsList(1) testrow = [6.0, 37.2, 0.039, False, 1.0, '', 0.0, 0.0, '', '~'] self.assertListEqual(testrow, row) # Add with all args args = {rdt.CHAINAGE: 6.1, rdt.ELEVATION: 37.4, rdt.ROUGHNESS: 0.06, rdt.PANEL_MARKER: True, rdt.RPL: 1.1, rdt.BANKMARKER: 'BED', rdt.EASTING: 22.5, rdt.NORTHING: 32.5, rdt.DEACTIVATION: 'RIGHT', rdt.SPECIAL: '16'} river.addRow(args, index=2) row = river.row_data['main'].rowAsList(2) testrow = [6.1, 37.4, 0.06, True, 1.1, 'BED', 22.5, 32.5, 'RIGHT', '16'] self.assertListEqual(testrow, row) # Check it fails without required args args = {rdt.CHAINAGE: 6.2} with self.assertRaises(AttributeError): river.addRow(args, index=3) args = {rdt.ELEVATION: 36.2} with self.assertRaises(AttributeError): river.addRow(args, index=3) # Check we catch non increasing chainage args = {rdt.CHAINAGE: 5.0, rdt.ELEVATION: 37.2} with self.assertRaises(ValueError): river.addRow(args, index=3)
def test_addDataRow(self): """Test adding a new row to 'main' data.""" # Create a factory and load the river unit ifactory = FmpUnitFactory() i, spill = ifactory.createUnitFromFile(self.spill_unitdata, 0, 'SPILL', 1, 1) # Add with required only args args = {rdt.CHAINAGE: 6.0, rdt.ELEVATION: 37.2} spill.addRow(args, index=1) row = spill.row_data['main'].rowAsList(1) testrow = [6.0, 37.2, 0.00, 0.00] self.assertListEqual(testrow, row) # Add with all args args = {rdt.CHAINAGE: 8.0, rdt.ELEVATION: 39.4, rdt.EASTING: 12.0, rdt.NORTHING: 40.0} spill.addRow(args) row = spill.row_data['main'].rowAsList(4) testrow = [8.0, 39.4, 12.0, 40.0] self.assertListEqual(testrow, row) # Check it fails without required args args = {rdt.CHAINAGE: 56.2} with self.assertRaises(AttributeError): spill.addRow(args) args = {rdt.ELEVATION: 36.2} with self.assertRaises(AttributeError): spill.addRow(args) # Check we catch non increasing chainage args = {rdt.CHAINAGE: 5.1, rdt.ELEVATION: 37.2} with self.assertRaises(ValueError): spill.addRow(args, index=1)
def test_getData(self): out_data = \ ['JUNCTION Some comment stuff', 'OPEN', 'WOOD1530WDXXWOOD1530SUXXWOOD1530BU WOOD1530CU '] # Create a factory and load the river unit ifactory = FmpUnitFactory() i, junction = ifactory.createUnitFromFile(self.input_contents, 0, 'JUNCTION', 1, 1) # Get the data and check it against our template data = junction.getData() self.assertEquals(out_data, data, 'getData() formatting failed')
def test_getData(self): '''Test to check the suitability of the getData() method. ''' # Create a factory and load the river unit ifactory = FmpUnitFactory() i, river = ifactory.createUnitFromFile(self.input_contents, 0, 'RIVER', 1, 1) # Setup the list that we expect to be returned from the getData() method out_data = \ ['RIVER (Culvert Exit) CH:7932 - Trimmed to BT', 'SECTION', '1.069', ' 15.078 1.1111 1000', ' 18', ' 5.996 37.560 0.080 1.000LEFT 291391.67 86582.61LEFT 16 ', ' 6.936 37.197 0.035* 1.000 291391.43 86581.70 ', ' 7.446 36.726 0.035 1.000 291391.30 86581.21 ', ' 7.635 35.235 0.035 1.000 291391.25 86581.03 ', ' 8.561 35.196 0.035 1.000 291391.01 86580.13 ', ' 9.551 35.190 0.035 1.000BED 291390.75 86579.18 ', ' 10.323 35.229 0.035 1.000 291390.55 86578.43 ', ' 10.904 35.319 0.035 1.000 291390.40 86577.87 ', ' 12.542 35.637 0.035 1.000 291389.98 86576.29 ', ' 13.740 35.593 0.035 1.000 291389.67 86575.13 ', ' 13.788 35.592 0.035 1.000 291389.66 86575.09 ', ' 13.944 36.148 0.035 1.000 291389.62 86574.93 ', ' 15.008 36.559 0.080* 1.000 291389.34 86573.91 ', ' 16.355 37.542 0.080 1.000 291389.00 86572.60 ', ' 17.424 38.518 0.080 1.000 291388.72 86571.57 ', ' 18.449 39.037 0.080 1.000 291388.46 86570.58 ', ' 19.416 39.146 0.080 1.000 291388.21 86569.65 ', ' 19.420 39.133 0.080 1.000RIGHT 291388.21 86569.65RIGHT 4095 '] # Get the data and check it against our template data = river.getData() self.assertEquals(out_data, data, 'getData() formatting failed')
def buildDat(self, contents, arg_dict={}): """ """ self.contents = contents # Counter for the number of rows that have been read from the # file contents list. i = 0 # Get an instance of the unit factory with the number of nodes in the file. unit_factory = FmpUnitFactory() # Dictionary containing the keys to identify units in the dat file unit_vars = unit_factory.getUnitIdentifiers() # Create a unit from the header data in the first few lines of the dat file. if not self.is_ied: i, self.temp_unit = unit_factory.createUnitFromFile(self.contents, 0, 'HEADER', 0) in_unknown_section = False # Now we can update the HeaderUnit subContents self.updateSubContents() in_unknown_section = False while i < len(self.contents): # Get the line and then split it to retrieve the first word. # Check this word against the # unit_type keys we set above to see line = self.contents[i] temp_line = line.strip() if temp_line: first_word = line.split()[0].strip() else: first_word = 'Nothing' if first_word in unit_vars: # If building an UnknownUnit then create and reset if(in_unknown_section == True): self.createUnknownSection() self.updateSubContents() # Reset the reach for the UnknownUnit unit_factory.same_reach = False '''Call the unit creator function and get back the unit and the updated contents list index. Most of these variables are self explanatory, but unit_vars[first_word] is the key for the unit type to make. ''' # i, self.temp_unit = unit_factory.createUnit(self.contents, i, # unit_vars[first_word], self.cur_no_of_units) i, self.temp_unit = unit_factory.createUnitFromFile(self.contents, i, first_word, self.cur_no_of_units) '''In case we got in but found something wasn't supported. it's i-1 because we can't return onto the same line that was read or it will loop forever, so store it here and move on ''' if self.temp_unit == False: self.unknown_data.append(self.contents[i].rstrip('\n')) i += 1 self.unknown_data.append(self.contents[i].rstrip('\n')) in_unknown_section = True else: self.updateSubContents() in_unknown_section = False else: in_unknown_section = True self.unknown_data.append(self.contents[i].rstrip('\n')) i += 1 line = None del self.unknown_data return self.units
def createModelExample(): """Create a new FMP model and add a couple of river units to it. Generates a new DatCollection and adds some units with data to it. Note that the 'initialisedDat()' method that's used is a classmethod of DatCollection. It will automatically create the AUnit types that are required by Flood Modeller. These include: - HeaderUnit: the data at the top of the file. - InitialConditionsUnit: the data at/near the bottom of the file that stores all of the initial conditions for nodes. It also adds a CommentUnit as the first unit. """ # Create some data to prepopulate our RiverUnit's with. You can do it this # way (as one big dict) riv1_data = { 'name': 'riv1', 'head_data': { 'distance': 10.5 }, 'row_data': { 'main': [ { rdt.CHAINAGE: 0.0, rdt.ELEVATION: 10.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 2.0, rdt.ELEVATION: 7.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 4.0, rdt.ELEVATION: 4.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 6.0, rdt.ELEVATION: 4.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 8.0, rdt.ELEVATION: 7.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 10.0, rdt.ELEVATION: 10.0, rdt.ROUGHNESS: 0.035 }, ], } } river1 = factory.createUnit('river', **riv1_data) # Or this way (separate variables) head_data = {'distance': 12.0} row_data = { 'main': [ { rdt.CHAINAGE: 0.0, rdt.ELEVATION: 9.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 2.0, rdt.ELEVATION: 6.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 4.0, rdt.ELEVATION: 3.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 6.0, rdt.ELEVATION: 3.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 8.0, rdt.ELEVATION: 6.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 10.0, rdt.ELEVATION: 9.0, rdt.ROUGHNESS: 0.035 }, ], } river2 = factory.createUnit('river', name='riv2', head_data=head_data, row_data=row_data) # The path we'll save our new model to. new_path = "C:/path/to/fmp/model.dat" ''' Then create a new DatCollection and give it units river1 and river2. Note that you can provide kwargs to be used when adding the units under the keyword 'unit_kwargs'. An example is given with the unit_kw setup below. When this is supplied you must provide either some kwargs, or an empty dict as a placeholder for each entry in units. The kwargs at unit_kwargs index i will be used for the unit at units index i. ''' unit_kw = [{}, { 'ics': { rdt.FLOW: 3.0, rdt.STAGE: 5.0, rdt.ELEVATION: 4.5 } }] dat = DatCollection.initialisedDat(new_path, units=[river1, river2], unit_kwargs=unit_kw) ''' A different approach. You can also creat a unit with it's constructor and populate the rows after if you prefer. It's then added to the DatCollection ''' # You'll need to import the unit specific module from ship.fmp.datunits import riverunit as riv # Instantiate the unit (if name is not given it will get a default) river3 = riv.RiverUnit(name='riv3') # Set some head_data river3.head_data['distance'].value = 15.0 # Create some row_data and add it to the unit rows = [ { rdt.CHAINAGE: 0.0, rdt.ELEVATION: 8.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 2.0, rdt.ELEVATION: 5.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 4.0, rdt.ELEVATION: 2.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 6.0, rdt.ELEVATION: 2.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 8.0, rdt.ELEVATION: 5.0, rdt.ROUGHNESS: 0.035 }, { rdt.CHAINAGE: 10.0, rdt.ELEVATION: 8.0, rdt.ROUGHNESS: 0.035 }, ] for r in rows: river3.addRow(r) ''' If you call addUnit without an index it will be appended to the end of the units. Here we find the index of river2 and put river3 there. This will push river2 back up by one (i.e. order is now river1, river3, river2). Note that we can hand initial conditions in as a kwarg here like before. ''' riv2_index = dat.index(river2) dat.addUnit(river3, index=riv2_index, ics={ rdt.FLOW: 3.0, rdt.STAGE: 5.0, rdt.ELEVATION: 4.5 }) # Write the new fmp .dat file to disk dat.write() ''' It's worth noting that if you're not worried about populating the units with data from the outset it can be a very simple operation. ''' # Just get a blank DatCollection with no units (except header and ics) new_path2 = "C:/path/to/fmp/model2.dat" dat2 = DatCollection.initialisedDat(new_path2) dat2.write() ''' Final go. Create a new DatCollection but add a few empty units to it The units below will be added to the DatCollection in the order of the list. ''' units = [ factory.createUnit('refh', name='riv1'), factory.createUnit('river', name='riv2'), factory.createUnit('river', name='riv3'), factory.createUnit('arch', name='brg1'), factory.createUnit('river', name='riv4'), factory.createUnit('river', name='riv5'), factory.createUnit('htbdy', name='htbdy'), ] new_path3 = "C:/path/to/fmp/model3.dat" dat3 = DatCollection.initialisedDat(new_path3, units=units) dat3.write()
def createModelExample(): """Create a new FMP model and add a couple of river units to it. Generates a new DatCollection and adds some units with data to it. Note that the 'initialisedDat()' method that's used is a classmethod of DatCollection. It will automatically create the AUnit types that are required by Flood Modeller. These include: - HeaderUnit: the data at the top of the file. - InitialConditionsUnit: the data at/near the bottom of the file that stores all of the initial conditions for nodes. It also adds a CommentUnit as the first unit. """ # Create some data to prepopulate our RiverUnit's with. You can do it this # way (as one big dict) riv1_data = { 'name': 'riv1', 'head_data': {'distance': 10.5}, 'row_data': { 'main': [ {rdt.CHAINAGE: 0.0, rdt.ELEVATION: 10.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 2.0, rdt.ELEVATION: 7.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 4.0, rdt.ELEVATION: 4.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 6.0, rdt.ELEVATION: 4.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 8.0, rdt.ELEVATION: 7.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 10.0, rdt.ELEVATION: 10.0, rdt.ROUGHNESS: 0.035}, ], } } river1 = factory.createUnit('river', **riv1_data) # Or this way (separate variables) head_data = {'distance': 12.0} row_data = { 'main': [ {rdt.CHAINAGE: 0.0, rdt.ELEVATION: 9.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 2.0, rdt.ELEVATION: 6.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 4.0, rdt.ELEVATION: 3.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 6.0, rdt.ELEVATION: 3.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 8.0, rdt.ELEVATION: 6.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 10.0, rdt.ELEVATION: 9.0, rdt.ROUGHNESS: 0.035}, ], } river2 = factory.createUnit('river', name='riv2', head_data=head_data, row_data=row_data) # The path we'll save our new model to. new_path = "C:/path/to/fmp/model.dat" ''' Then create a new DatCollection and give it units river1 and river2. Note that you can provide kwargs to be used when adding the units under the keyword 'unit_kwargs'. An example is given with the unit_kw setup below. When this is supplied you must provide either some kwargs, or an empty dict as a placeholder for each entry in units. The kwargs at unit_kwargs index i will be used for the unit at units index i. ''' unit_kw = [{}, { 'ics': {rdt.FLOW: 3.0, rdt.STAGE: 5.0, rdt.ELEVATION: 4.5} } ] dat = DatCollection.initialisedDat(new_path, units=[river1, river2], unit_kwargs=unit_kw) ''' A different approach. You can also creat a unit with it's constructor and populate the rows after if you prefer. It's then added to the DatCollection ''' # You'll need to import the unit specific module from ship.fmp.datunits import riverunit as riv # Instantiate the unit (if name is not given it will get a default) river3 = riv.RiverUnit(name='riv3') # Set some head_data river3.head_data['distance'].value = 15.0 # Create some row_data and add it to the unit rows = [ {rdt.CHAINAGE: 0.0, rdt.ELEVATION: 8.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 2.0, rdt.ELEVATION: 5.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 4.0, rdt.ELEVATION: 2.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 6.0, rdt.ELEVATION: 2.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 8.0, rdt.ELEVATION: 5.0, rdt.ROUGHNESS: 0.035}, {rdt.CHAINAGE: 10.0, rdt.ELEVATION: 8.0, rdt.ROUGHNESS: 0.035}, ] for r in rows: river3.addRow(r) ''' If you call addUnit without an index it will be appended to the end of the units. Here we find the index of river2 and put river3 there. This will push river2 back up by one (i.e. order is now river1, river3, river2). Note that we can hand initial conditions in as a kwarg here like before. ''' riv2_index = dat.index(river2) dat.addUnit(river3, index=riv2_index, ics={rdt.FLOW: 3.0, rdt.STAGE: 5.0, rdt.ELEVATION: 4.5}) # Write the new fmp .dat file to disk dat.write() ''' It's worth noting that if you're not worried about populating the units with data from the outset it can be a very simple operation. ''' # Just get a blank DatCollection with no units (except header and ics) new_path2 = "C:/path/to/fmp/model2.dat" dat2 = DatCollection.initialisedDat(new_path2) dat2.write() ''' Final go. Create a new DatCollection but add a few empty units to it The units below will be added to the DatCollection in the order of the list. ''' units = [ factory.createUnit('refh', name='riv1'), factory.createUnit('river', name='riv2'), factory.createUnit('river', name='riv3'), factory.createUnit('arch', name='brg1'), factory.createUnit('river', name='riv4'), factory.createUnit('river', name='riv5'), factory.createUnit('htbdy', name='htbdy'), ] new_path3 = "C:/path/to/fmp/model3.dat" dat3 = DatCollection.initialisedDat(new_path3, units=units) dat3.write()
def buildDat(self, contents, arg_dict={}): """ """ self.contents = contents # Counter for the number of rows that have been read from the # file contents list. i = 0 # Get an instance of the unit factory with the number of nodes in the file. unit_factory = FmpUnitFactory() # Dictionary containing the keys to identify units in the dat file unit_vars = unit_factory.getUnitIdentifiers() # Create a unit from the header data in the first few lines of the dat file. if not self.is_ied: i, self.temp_unit = unit_factory.createUnitFromFile( self.contents, 0, 'HEADER', 0) in_unknown_section = False # Now we can update the HeaderUnit subContents self.updateSubContents() in_unknown_section = False while i < len(self.contents): # Get the line and then split it to retrieve the first word. # Check this word against the # unit_type keys we set above to see line = self.contents[i] temp_line = line.strip() if temp_line: first_word = line.split()[0].strip() else: first_word = 'Nothing' if first_word in unit_vars: # If building an UnknownUnit then create and reset if (in_unknown_section == True): self.createUnknownSection() self.updateSubContents() # Reset the reach for the UnknownUnit unit_factory.same_reach = False '''Call the unit creator function and get back the unit and the updated contents list index. Most of these variables are self explanatory, but unit_vars[first_word] is the key for the unit type to make. ''' # i, self.temp_unit = unit_factory.createUnit(self.contents, i, # unit_vars[first_word], self.cur_no_of_units) i, self.temp_unit = unit_factory.createUnitFromFile( self.contents, i, first_word, self.cur_no_of_units) '''In case we got in but found something wasn't supported. it's i-1 because we can't return onto the same line that was read or it will loop forever, so store it here and move on ''' if self.temp_unit == False: self.unknown_data.append(self.contents[i].rstrip('\n')) i += 1 self.unknown_data.append(self.contents[i].rstrip('\n')) in_unknown_section = True else: self.updateSubContents() in_unknown_section = False else: in_unknown_section = True self.unknown_data.append(self.contents[i].rstrip('\n')) i += 1 line = None del self.unknown_data return self.units