Project structure for a reactor model built in Python











up vote
4
down vote

favorite
2












I use Python for various computational reactor modeling activities. While there are many components to the models I develop, the basic structure of the project folder tends to be similar to the following:



pyreactor/
├── gas_properties.py
├── geometry.py
├── main.py
├── parameters.py
├── results
│   ├── fig1.pdf
│   └── output.txt
└── velocity.py


The parameters.py file contains dictionaries with various model parameters for different components of the model. Each parameter has an associated value and description.



# parameters.py

reactor = {
'd_inner': (0.2, 'Inner diameter [m]'),
'height': (1.5, 'Height of reactor [m]')
}

gas = {
'mu': ([300, 350, 400, 450, 500], 'Gas viscosities [uP]'),
'p': (115_000, 'Gas pressure [Pa]'),
'species': 'CO2',
'temp': (500, 'Temperature of gas [Celsius]'),
}

solid = {
'cd': (0.25, 'Drag coefficient [-]'),
'dp': (0.03, 'Particle diameter [m]'),
'phi': (0.86, 'Particle sphericity [-]'),
'rho': (2500, 'Density of sand particle [kg/m^3]')
}


The Python files labeled gas_properties.py, geometry.py, and velocity.py represent different components of the reactor model. The gas_properties.py file calculates various properties of the gas using parameters defined in parameters.py. If the script is run as __main__ then it prints some results to the console and displays a plot figure:



# gas_properties.py

import matplotlib.pyplot as plt
import parameters as pm


def rhog(mw, p, tk):
mw = mw / 1000
r = 8.3145
rho = (p * mw) / (r * tk)
return rho


# Parameters
# ----------------------------------------------------------------------------

mu = pm.gas['mu'][0]
p = pm.gas['p'][0]
sp = pm.gas['species']
tk = pm.gas['temp'][0]

# Calculate density and plot viscosities
# ----------------------------------------------------------------------------

if sp is 'CO2':
mw = 44
elif sp is 'CO':
mw = 28

rho = rhog(mw, p, tk)

fig1, ax = plt.subplots()
ax.plot(mu)
ax.set_xlabel('Items [-]')
ax.set_ylabel('Gas viscosity [uP]')

if __name__ == "__main__":
print('--- Gas properties ---')
print(f'mw = {mw} g/mol')
print(f'rho = {rho:.2f} kg/m^3')
plt.show()


The geometry.py file calculates dimensions of the reactor. It prints results to the console if run as __main__:



# geometry.py

import numpy as np
import parameters as pm

# Parameters
# ----------------------------------------------------------------------------

d = pm.reactor['d_inner'][0]
h = pm.reactor['height'][0]

# Calculate cross section area and volume
# ----------------------------------------------------------------------------

a_cross = (np.pi / 4) * (d**2)
vol = a_cross * h

if __name__ == "__main__":
print('--- Geometry calculations ---')
print(f'a_cross = {a_cross:.4f} m^2')
print(f'volume = {vol:.4f} m^3')


The velocity.py file estimates velocity of the particles in the system. It imports gas_properties for the gas density that is used in the velocity function ut(). If the script is run as __main__ then results are printed to the console:



# velocity.py

import parameters as pm
from gas_properties import rho as rhog


def ut(cd, dp, rhog, rhos):
g = 9.81
tm1 = 4 * dp * (rhos - rhog) * g
tm2 = 3 * rhog * cd
ut = (tm1 / tm2)**(1 / 2)
return ut


# Parameters
# ----------------------------------------------------------------------------

cd = pm.solid['cd'][0]
d = pm.solid['dp'][0]
rhos = pm.solid['rho'][0]

# Calculate terminal velocity
# ----------------------------------------------------------------------------

ut = ut(cd, d, rhog, rhos)

if __name__ == "__main__":
print('--- Velocity of particle ---')
print(f'ut = {ut:.2f} m/s')


Finally, the main.py file imports all the components gas_properties.py, geometry.py, and velocity.py of the reactor model. This file prints the parameters and results to a text file named output.txt in the results/ folder. The main file also saves plot figures to the results/ folder:



# main.py

import datetime
import parameters as pm
import gas_properties as gp
import geometry as gm
import velocity as ve

# Parameters and results saved to text file in results/ folder
# ----------------------------------------------------------------------------

with open('results/output.txt', 'w') as txt_file:
date = datetime.datetime.now().strftime('%m/%d/%Y')
print(f'Generated on {date} by G.W.', file=txt_file)

print('n--- Reactor Parameters ---n', file=txt_file)
for key, value in pm.reactor.items():
print(f'{key:8} {value[0]:10} t {value[1]}', file=txt_file)

print('n--- Gas Parameters ---n', file=txt_file)
for key, value in pm.gas.items():
if type(value[0]) is list:
print(f'{key:8} {value[0]} t {value[1]}', file=txt_file)
elif key is 'species':
print(f'{key:27} {value}', file=txt_file)
else:
print(f'{key:20} {value[0]:10} t {value[1]}', file=txt_file)

print('n--- Solid Parameters ---n', file=txt_file)
for key, value in pm.solid.items():
print(f'{key:8} {value[0]:10} t {value[1]}', file=txt_file)

print('n--- Gas Properties Results ---n', file=txt_file)
print(f"{'rho':8} {gp.rho:10.2f} t Density of gas [kg/m^3]", file=txt_file)

print('n--- Geometry Results ---n', file=txt_file)
print(f"{'a_cross':10} {gm.a_cross:.4f} t Cross section area of reactor [m^2]", file=txt_file)
print(f"{'volume':10} {gm.vol:.4f} t Volume of reactor [m^3]", file=txt_file)

print('n--- Velocity Results ---n', file=txt_file)
print(f"{'ut':10} {ve.ut:.2f} t Terminal velocity [m/s]", file=txt_file)

# Plots saved to file in results/ folder
# ----------------------------------------------------------------------------

gp.fig1.savefig('results/fig1.pdf', bbox_inches='tight')


While this approach works fine, I feel like there may be a better way of organizing the code and folder structure. Some specific questions that come to mind are:




  1. Is using a parameters file that contains dictionaries a good practice? I find that having all model parameters in one file is more maintainable and makes it easy to find what parameters are used for the model.

  2. Each component of the reactor model is treated as an individual file (or module) which is imported into the main script. Is this an efficient way to handle model components or is there another feature of the Python programming language that I should consider?

  3. All results and figures are saved to the results folder. Is this a reasonable approach or should save results elsewhere on the computer?


Please let me know if there are ways to improve my code and project structure. Regarding the parameters file, I'm aware of YAML, JSON, and INI files but for this example I would like to use standard Python 3 features such as a dictionary, list, tuple, set, etc.










share|improve this question




























    up vote
    4
    down vote

    favorite
    2












    I use Python for various computational reactor modeling activities. While there are many components to the models I develop, the basic structure of the project folder tends to be similar to the following:



    pyreactor/
    ├── gas_properties.py
    ├── geometry.py
    ├── main.py
    ├── parameters.py
    ├── results
    │   ├── fig1.pdf
    │   └── output.txt
    └── velocity.py


    The parameters.py file contains dictionaries with various model parameters for different components of the model. Each parameter has an associated value and description.



    # parameters.py

    reactor = {
    'd_inner': (0.2, 'Inner diameter [m]'),
    'height': (1.5, 'Height of reactor [m]')
    }

    gas = {
    'mu': ([300, 350, 400, 450, 500], 'Gas viscosities [uP]'),
    'p': (115_000, 'Gas pressure [Pa]'),
    'species': 'CO2',
    'temp': (500, 'Temperature of gas [Celsius]'),
    }

    solid = {
    'cd': (0.25, 'Drag coefficient [-]'),
    'dp': (0.03, 'Particle diameter [m]'),
    'phi': (0.86, 'Particle sphericity [-]'),
    'rho': (2500, 'Density of sand particle [kg/m^3]')
    }


    The Python files labeled gas_properties.py, geometry.py, and velocity.py represent different components of the reactor model. The gas_properties.py file calculates various properties of the gas using parameters defined in parameters.py. If the script is run as __main__ then it prints some results to the console and displays a plot figure:



    # gas_properties.py

    import matplotlib.pyplot as plt
    import parameters as pm


    def rhog(mw, p, tk):
    mw = mw / 1000
    r = 8.3145
    rho = (p * mw) / (r * tk)
    return rho


    # Parameters
    # ----------------------------------------------------------------------------

    mu = pm.gas['mu'][0]
    p = pm.gas['p'][0]
    sp = pm.gas['species']
    tk = pm.gas['temp'][0]

    # Calculate density and plot viscosities
    # ----------------------------------------------------------------------------

    if sp is 'CO2':
    mw = 44
    elif sp is 'CO':
    mw = 28

    rho = rhog(mw, p, tk)

    fig1, ax = plt.subplots()
    ax.plot(mu)
    ax.set_xlabel('Items [-]')
    ax.set_ylabel('Gas viscosity [uP]')

    if __name__ == "__main__":
    print('--- Gas properties ---')
    print(f'mw = {mw} g/mol')
    print(f'rho = {rho:.2f} kg/m^3')
    plt.show()


    The geometry.py file calculates dimensions of the reactor. It prints results to the console if run as __main__:



    # geometry.py

    import numpy as np
    import parameters as pm

    # Parameters
    # ----------------------------------------------------------------------------

    d = pm.reactor['d_inner'][0]
    h = pm.reactor['height'][0]

    # Calculate cross section area and volume
    # ----------------------------------------------------------------------------

    a_cross = (np.pi / 4) * (d**2)
    vol = a_cross * h

    if __name__ == "__main__":
    print('--- Geometry calculations ---')
    print(f'a_cross = {a_cross:.4f} m^2')
    print(f'volume = {vol:.4f} m^3')


    The velocity.py file estimates velocity of the particles in the system. It imports gas_properties for the gas density that is used in the velocity function ut(). If the script is run as __main__ then results are printed to the console:



    # velocity.py

    import parameters as pm
    from gas_properties import rho as rhog


    def ut(cd, dp, rhog, rhos):
    g = 9.81
    tm1 = 4 * dp * (rhos - rhog) * g
    tm2 = 3 * rhog * cd
    ut = (tm1 / tm2)**(1 / 2)
    return ut


    # Parameters
    # ----------------------------------------------------------------------------

    cd = pm.solid['cd'][0]
    d = pm.solid['dp'][0]
    rhos = pm.solid['rho'][0]

    # Calculate terminal velocity
    # ----------------------------------------------------------------------------

    ut = ut(cd, d, rhog, rhos)

    if __name__ == "__main__":
    print('--- Velocity of particle ---')
    print(f'ut = {ut:.2f} m/s')


    Finally, the main.py file imports all the components gas_properties.py, geometry.py, and velocity.py of the reactor model. This file prints the parameters and results to a text file named output.txt in the results/ folder. The main file also saves plot figures to the results/ folder:



    # main.py

    import datetime
    import parameters as pm
    import gas_properties as gp
    import geometry as gm
    import velocity as ve

    # Parameters and results saved to text file in results/ folder
    # ----------------------------------------------------------------------------

    with open('results/output.txt', 'w') as txt_file:
    date = datetime.datetime.now().strftime('%m/%d/%Y')
    print(f'Generated on {date} by G.W.', file=txt_file)

    print('n--- Reactor Parameters ---n', file=txt_file)
    for key, value in pm.reactor.items():
    print(f'{key:8} {value[0]:10} t {value[1]}', file=txt_file)

    print('n--- Gas Parameters ---n', file=txt_file)
    for key, value in pm.gas.items():
    if type(value[0]) is list:
    print(f'{key:8} {value[0]} t {value[1]}', file=txt_file)
    elif key is 'species':
    print(f'{key:27} {value}', file=txt_file)
    else:
    print(f'{key:20} {value[0]:10} t {value[1]}', file=txt_file)

    print('n--- Solid Parameters ---n', file=txt_file)
    for key, value in pm.solid.items():
    print(f'{key:8} {value[0]:10} t {value[1]}', file=txt_file)

    print('n--- Gas Properties Results ---n', file=txt_file)
    print(f"{'rho':8} {gp.rho:10.2f} t Density of gas [kg/m^3]", file=txt_file)

    print('n--- Geometry Results ---n', file=txt_file)
    print(f"{'a_cross':10} {gm.a_cross:.4f} t Cross section area of reactor [m^2]", file=txt_file)
    print(f"{'volume':10} {gm.vol:.4f} t Volume of reactor [m^3]", file=txt_file)

    print('n--- Velocity Results ---n', file=txt_file)
    print(f"{'ut':10} {ve.ut:.2f} t Terminal velocity [m/s]", file=txt_file)

    # Plots saved to file in results/ folder
    # ----------------------------------------------------------------------------

    gp.fig1.savefig('results/fig1.pdf', bbox_inches='tight')


    While this approach works fine, I feel like there may be a better way of organizing the code and folder structure. Some specific questions that come to mind are:




    1. Is using a parameters file that contains dictionaries a good practice? I find that having all model parameters in one file is more maintainable and makes it easy to find what parameters are used for the model.

    2. Each component of the reactor model is treated as an individual file (or module) which is imported into the main script. Is this an efficient way to handle model components or is there another feature of the Python programming language that I should consider?

    3. All results and figures are saved to the results folder. Is this a reasonable approach or should save results elsewhere on the computer?


    Please let me know if there are ways to improve my code and project structure. Regarding the parameters file, I'm aware of YAML, JSON, and INI files but for this example I would like to use standard Python 3 features such as a dictionary, list, tuple, set, etc.










    share|improve this question


























      up vote
      4
      down vote

      favorite
      2









      up vote
      4
      down vote

      favorite
      2






      2





      I use Python for various computational reactor modeling activities. While there are many components to the models I develop, the basic structure of the project folder tends to be similar to the following:



      pyreactor/
      ├── gas_properties.py
      ├── geometry.py
      ├── main.py
      ├── parameters.py
      ├── results
      │   ├── fig1.pdf
      │   └── output.txt
      └── velocity.py


      The parameters.py file contains dictionaries with various model parameters for different components of the model. Each parameter has an associated value and description.



      # parameters.py

      reactor = {
      'd_inner': (0.2, 'Inner diameter [m]'),
      'height': (1.5, 'Height of reactor [m]')
      }

      gas = {
      'mu': ([300, 350, 400, 450, 500], 'Gas viscosities [uP]'),
      'p': (115_000, 'Gas pressure [Pa]'),
      'species': 'CO2',
      'temp': (500, 'Temperature of gas [Celsius]'),
      }

      solid = {
      'cd': (0.25, 'Drag coefficient [-]'),
      'dp': (0.03, 'Particle diameter [m]'),
      'phi': (0.86, 'Particle sphericity [-]'),
      'rho': (2500, 'Density of sand particle [kg/m^3]')
      }


      The Python files labeled gas_properties.py, geometry.py, and velocity.py represent different components of the reactor model. The gas_properties.py file calculates various properties of the gas using parameters defined in parameters.py. If the script is run as __main__ then it prints some results to the console and displays a plot figure:



      # gas_properties.py

      import matplotlib.pyplot as plt
      import parameters as pm


      def rhog(mw, p, tk):
      mw = mw / 1000
      r = 8.3145
      rho = (p * mw) / (r * tk)
      return rho


      # Parameters
      # ----------------------------------------------------------------------------

      mu = pm.gas['mu'][0]
      p = pm.gas['p'][0]
      sp = pm.gas['species']
      tk = pm.gas['temp'][0]

      # Calculate density and plot viscosities
      # ----------------------------------------------------------------------------

      if sp is 'CO2':
      mw = 44
      elif sp is 'CO':
      mw = 28

      rho = rhog(mw, p, tk)

      fig1, ax = plt.subplots()
      ax.plot(mu)
      ax.set_xlabel('Items [-]')
      ax.set_ylabel('Gas viscosity [uP]')

      if __name__ == "__main__":
      print('--- Gas properties ---')
      print(f'mw = {mw} g/mol')
      print(f'rho = {rho:.2f} kg/m^3')
      plt.show()


      The geometry.py file calculates dimensions of the reactor. It prints results to the console if run as __main__:



      # geometry.py

      import numpy as np
      import parameters as pm

      # Parameters
      # ----------------------------------------------------------------------------

      d = pm.reactor['d_inner'][0]
      h = pm.reactor['height'][0]

      # Calculate cross section area and volume
      # ----------------------------------------------------------------------------

      a_cross = (np.pi / 4) * (d**2)
      vol = a_cross * h

      if __name__ == "__main__":
      print('--- Geometry calculations ---')
      print(f'a_cross = {a_cross:.4f} m^2')
      print(f'volume = {vol:.4f} m^3')


      The velocity.py file estimates velocity of the particles in the system. It imports gas_properties for the gas density that is used in the velocity function ut(). If the script is run as __main__ then results are printed to the console:



      # velocity.py

      import parameters as pm
      from gas_properties import rho as rhog


      def ut(cd, dp, rhog, rhos):
      g = 9.81
      tm1 = 4 * dp * (rhos - rhog) * g
      tm2 = 3 * rhog * cd
      ut = (tm1 / tm2)**(1 / 2)
      return ut


      # Parameters
      # ----------------------------------------------------------------------------

      cd = pm.solid['cd'][0]
      d = pm.solid['dp'][0]
      rhos = pm.solid['rho'][0]

      # Calculate terminal velocity
      # ----------------------------------------------------------------------------

      ut = ut(cd, d, rhog, rhos)

      if __name__ == "__main__":
      print('--- Velocity of particle ---')
      print(f'ut = {ut:.2f} m/s')


      Finally, the main.py file imports all the components gas_properties.py, geometry.py, and velocity.py of the reactor model. This file prints the parameters and results to a text file named output.txt in the results/ folder. The main file also saves plot figures to the results/ folder:



      # main.py

      import datetime
      import parameters as pm
      import gas_properties as gp
      import geometry as gm
      import velocity as ve

      # Parameters and results saved to text file in results/ folder
      # ----------------------------------------------------------------------------

      with open('results/output.txt', 'w') as txt_file:
      date = datetime.datetime.now().strftime('%m/%d/%Y')
      print(f'Generated on {date} by G.W.', file=txt_file)

      print('n--- Reactor Parameters ---n', file=txt_file)
      for key, value in pm.reactor.items():
      print(f'{key:8} {value[0]:10} t {value[1]}', file=txt_file)

      print('n--- Gas Parameters ---n', file=txt_file)
      for key, value in pm.gas.items():
      if type(value[0]) is list:
      print(f'{key:8} {value[0]} t {value[1]}', file=txt_file)
      elif key is 'species':
      print(f'{key:27} {value}', file=txt_file)
      else:
      print(f'{key:20} {value[0]:10} t {value[1]}', file=txt_file)

      print('n--- Solid Parameters ---n', file=txt_file)
      for key, value in pm.solid.items():
      print(f'{key:8} {value[0]:10} t {value[1]}', file=txt_file)

      print('n--- Gas Properties Results ---n', file=txt_file)
      print(f"{'rho':8} {gp.rho:10.2f} t Density of gas [kg/m^3]", file=txt_file)

      print('n--- Geometry Results ---n', file=txt_file)
      print(f"{'a_cross':10} {gm.a_cross:.4f} t Cross section area of reactor [m^2]", file=txt_file)
      print(f"{'volume':10} {gm.vol:.4f} t Volume of reactor [m^3]", file=txt_file)

      print('n--- Velocity Results ---n', file=txt_file)
      print(f"{'ut':10} {ve.ut:.2f} t Terminal velocity [m/s]", file=txt_file)

      # Plots saved to file in results/ folder
      # ----------------------------------------------------------------------------

      gp.fig1.savefig('results/fig1.pdf', bbox_inches='tight')


      While this approach works fine, I feel like there may be a better way of organizing the code and folder structure. Some specific questions that come to mind are:




      1. Is using a parameters file that contains dictionaries a good practice? I find that having all model parameters in one file is more maintainable and makes it easy to find what parameters are used for the model.

      2. Each component of the reactor model is treated as an individual file (or module) which is imported into the main script. Is this an efficient way to handle model components or is there another feature of the Python programming language that I should consider?

      3. All results and figures are saved to the results folder. Is this a reasonable approach or should save results elsewhere on the computer?


      Please let me know if there are ways to improve my code and project structure. Regarding the parameters file, I'm aware of YAML, JSON, and INI files but for this example I would like to use standard Python 3 features such as a dictionary, list, tuple, set, etc.










      share|improve this question















      I use Python for various computational reactor modeling activities. While there are many components to the models I develop, the basic structure of the project folder tends to be similar to the following:



      pyreactor/
      ├── gas_properties.py
      ├── geometry.py
      ├── main.py
      ├── parameters.py
      ├── results
      │   ├── fig1.pdf
      │   └── output.txt
      └── velocity.py


      The parameters.py file contains dictionaries with various model parameters for different components of the model. Each parameter has an associated value and description.



      # parameters.py

      reactor = {
      'd_inner': (0.2, 'Inner diameter [m]'),
      'height': (1.5, 'Height of reactor [m]')
      }

      gas = {
      'mu': ([300, 350, 400, 450, 500], 'Gas viscosities [uP]'),
      'p': (115_000, 'Gas pressure [Pa]'),
      'species': 'CO2',
      'temp': (500, 'Temperature of gas [Celsius]'),
      }

      solid = {
      'cd': (0.25, 'Drag coefficient [-]'),
      'dp': (0.03, 'Particle diameter [m]'),
      'phi': (0.86, 'Particle sphericity [-]'),
      'rho': (2500, 'Density of sand particle [kg/m^3]')
      }


      The Python files labeled gas_properties.py, geometry.py, and velocity.py represent different components of the reactor model. The gas_properties.py file calculates various properties of the gas using parameters defined in parameters.py. If the script is run as __main__ then it prints some results to the console and displays a plot figure:



      # gas_properties.py

      import matplotlib.pyplot as plt
      import parameters as pm


      def rhog(mw, p, tk):
      mw = mw / 1000
      r = 8.3145
      rho = (p * mw) / (r * tk)
      return rho


      # Parameters
      # ----------------------------------------------------------------------------

      mu = pm.gas['mu'][0]
      p = pm.gas['p'][0]
      sp = pm.gas['species']
      tk = pm.gas['temp'][0]

      # Calculate density and plot viscosities
      # ----------------------------------------------------------------------------

      if sp is 'CO2':
      mw = 44
      elif sp is 'CO':
      mw = 28

      rho = rhog(mw, p, tk)

      fig1, ax = plt.subplots()
      ax.plot(mu)
      ax.set_xlabel('Items [-]')
      ax.set_ylabel('Gas viscosity [uP]')

      if __name__ == "__main__":
      print('--- Gas properties ---')
      print(f'mw = {mw} g/mol')
      print(f'rho = {rho:.2f} kg/m^3')
      plt.show()


      The geometry.py file calculates dimensions of the reactor. It prints results to the console if run as __main__:



      # geometry.py

      import numpy as np
      import parameters as pm

      # Parameters
      # ----------------------------------------------------------------------------

      d = pm.reactor['d_inner'][0]
      h = pm.reactor['height'][0]

      # Calculate cross section area and volume
      # ----------------------------------------------------------------------------

      a_cross = (np.pi / 4) * (d**2)
      vol = a_cross * h

      if __name__ == "__main__":
      print('--- Geometry calculations ---')
      print(f'a_cross = {a_cross:.4f} m^2')
      print(f'volume = {vol:.4f} m^3')


      The velocity.py file estimates velocity of the particles in the system. It imports gas_properties for the gas density that is used in the velocity function ut(). If the script is run as __main__ then results are printed to the console:



      # velocity.py

      import parameters as pm
      from gas_properties import rho as rhog


      def ut(cd, dp, rhog, rhos):
      g = 9.81
      tm1 = 4 * dp * (rhos - rhog) * g
      tm2 = 3 * rhog * cd
      ut = (tm1 / tm2)**(1 / 2)
      return ut


      # Parameters
      # ----------------------------------------------------------------------------

      cd = pm.solid['cd'][0]
      d = pm.solid['dp'][0]
      rhos = pm.solid['rho'][0]

      # Calculate terminal velocity
      # ----------------------------------------------------------------------------

      ut = ut(cd, d, rhog, rhos)

      if __name__ == "__main__":
      print('--- Velocity of particle ---')
      print(f'ut = {ut:.2f} m/s')


      Finally, the main.py file imports all the components gas_properties.py, geometry.py, and velocity.py of the reactor model. This file prints the parameters and results to a text file named output.txt in the results/ folder. The main file also saves plot figures to the results/ folder:



      # main.py

      import datetime
      import parameters as pm
      import gas_properties as gp
      import geometry as gm
      import velocity as ve

      # Parameters and results saved to text file in results/ folder
      # ----------------------------------------------------------------------------

      with open('results/output.txt', 'w') as txt_file:
      date = datetime.datetime.now().strftime('%m/%d/%Y')
      print(f'Generated on {date} by G.W.', file=txt_file)

      print('n--- Reactor Parameters ---n', file=txt_file)
      for key, value in pm.reactor.items():
      print(f'{key:8} {value[0]:10} t {value[1]}', file=txt_file)

      print('n--- Gas Parameters ---n', file=txt_file)
      for key, value in pm.gas.items():
      if type(value[0]) is list:
      print(f'{key:8} {value[0]} t {value[1]}', file=txt_file)
      elif key is 'species':
      print(f'{key:27} {value}', file=txt_file)
      else:
      print(f'{key:20} {value[0]:10} t {value[1]}', file=txt_file)

      print('n--- Solid Parameters ---n', file=txt_file)
      for key, value in pm.solid.items():
      print(f'{key:8} {value[0]:10} t {value[1]}', file=txt_file)

      print('n--- Gas Properties Results ---n', file=txt_file)
      print(f"{'rho':8} {gp.rho:10.2f} t Density of gas [kg/m^3]", file=txt_file)

      print('n--- Geometry Results ---n', file=txt_file)
      print(f"{'a_cross':10} {gm.a_cross:.4f} t Cross section area of reactor [m^2]", file=txt_file)
      print(f"{'volume':10} {gm.vol:.4f} t Volume of reactor [m^3]", file=txt_file)

      print('n--- Velocity Results ---n', file=txt_file)
      print(f"{'ut':10} {ve.ut:.2f} t Terminal velocity [m/s]", file=txt_file)

      # Plots saved to file in results/ folder
      # ----------------------------------------------------------------------------

      gp.fig1.savefig('results/fig1.pdf', bbox_inches='tight')


      While this approach works fine, I feel like there may be a better way of organizing the code and folder structure. Some specific questions that come to mind are:




      1. Is using a parameters file that contains dictionaries a good practice? I find that having all model parameters in one file is more maintainable and makes it easy to find what parameters are used for the model.

      2. Each component of the reactor model is treated as an individual file (or module) which is imported into the main script. Is this an efficient way to handle model components or is there another feature of the Python programming language that I should consider?

      3. All results and figures are saved to the results folder. Is this a reasonable approach or should save results elsewhere on the computer?


      Please let me know if there are ways to improve my code and project structure. Regarding the parameters file, I'm aware of YAML, JSON, and INI files but for this example I would like to use standard Python 3 features such as a dictionary, list, tuple, set, etc.







      python python-3.x numpy matplotlib






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Dec 5 at 20:13

























      asked Dec 4 at 19:40









      wigging

      13816




      13816






















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          0
          down vote














          Is using a parameters file that contains dictionaries a good practice?




          No. It doesn't look like you're actually using the dictionaries for anything other than static lookup (and an iteration); as such, those parameters should simply be in a tuple, copied to locals.



          Also, I suggest that you make your parameters uniform (insofar as name, value and unit); something like



          from collections import namedtuple

          Param = namedtuple('Param', ('name', 'value', 'unit', 'desc'))

          params = (
          Param('d_inner', 0.2, 'm', 'Inner diameter'),
          Param('height', 1.5, 'm', 'Height of reactor'),
          # ...
          )
          locals().update({p.name: p for p in params})

          # ...

          print('--- Reactor Parameters ---')
          print('{:8} {:6} {:4} {:20}'.format('Name', 'Value', 'Unit', 'Description'))
          for p in params:
          print('{:8} {:<6.2f} {:4} {:20}'.format(p.name, p.value, p.unit, p.desc))





          share|improve this answer





















          • What is locals? Is it like a collection of global variables?
            – wigging
            Dec 4 at 20:22










          • It's a dictionary of all of the variables in the current scope.
            – Reinderien
            Dec 4 at 20:45










          • I’d even go further and recommend a config module. That’s usually where you want to store parameters.
            – яүυк
            Dec 4 at 21:26










          • Other than the parameters, do you have any comments on using a main script to run everything and where to put results?
            – wigging
            Dec 4 at 21:59










          • Not really, that's all fairly sane
            – Reinderien
            Dec 4 at 22:14











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209022%2fproject-structure-for-a-reactor-model-built-in-python%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          0
          down vote














          Is using a parameters file that contains dictionaries a good practice?




          No. It doesn't look like you're actually using the dictionaries for anything other than static lookup (and an iteration); as such, those parameters should simply be in a tuple, copied to locals.



          Also, I suggest that you make your parameters uniform (insofar as name, value and unit); something like



          from collections import namedtuple

          Param = namedtuple('Param', ('name', 'value', 'unit', 'desc'))

          params = (
          Param('d_inner', 0.2, 'm', 'Inner diameter'),
          Param('height', 1.5, 'm', 'Height of reactor'),
          # ...
          )
          locals().update({p.name: p for p in params})

          # ...

          print('--- Reactor Parameters ---')
          print('{:8} {:6} {:4} {:20}'.format('Name', 'Value', 'Unit', 'Description'))
          for p in params:
          print('{:8} {:<6.2f} {:4} {:20}'.format(p.name, p.value, p.unit, p.desc))





          share|improve this answer





















          • What is locals? Is it like a collection of global variables?
            – wigging
            Dec 4 at 20:22










          • It's a dictionary of all of the variables in the current scope.
            – Reinderien
            Dec 4 at 20:45










          • I’d even go further and recommend a config module. That’s usually where you want to store parameters.
            – яүυк
            Dec 4 at 21:26










          • Other than the parameters, do you have any comments on using a main script to run everything and where to put results?
            – wigging
            Dec 4 at 21:59










          • Not really, that's all fairly sane
            – Reinderien
            Dec 4 at 22:14















          up vote
          0
          down vote














          Is using a parameters file that contains dictionaries a good practice?




          No. It doesn't look like you're actually using the dictionaries for anything other than static lookup (and an iteration); as such, those parameters should simply be in a tuple, copied to locals.



          Also, I suggest that you make your parameters uniform (insofar as name, value and unit); something like



          from collections import namedtuple

          Param = namedtuple('Param', ('name', 'value', 'unit', 'desc'))

          params = (
          Param('d_inner', 0.2, 'm', 'Inner diameter'),
          Param('height', 1.5, 'm', 'Height of reactor'),
          # ...
          )
          locals().update({p.name: p for p in params})

          # ...

          print('--- Reactor Parameters ---')
          print('{:8} {:6} {:4} {:20}'.format('Name', 'Value', 'Unit', 'Description'))
          for p in params:
          print('{:8} {:<6.2f} {:4} {:20}'.format(p.name, p.value, p.unit, p.desc))





          share|improve this answer





















          • What is locals? Is it like a collection of global variables?
            – wigging
            Dec 4 at 20:22










          • It's a dictionary of all of the variables in the current scope.
            – Reinderien
            Dec 4 at 20:45










          • I’d even go further and recommend a config module. That’s usually where you want to store parameters.
            – яүυк
            Dec 4 at 21:26










          • Other than the parameters, do you have any comments on using a main script to run everything and where to put results?
            – wigging
            Dec 4 at 21:59










          • Not really, that's all fairly sane
            – Reinderien
            Dec 4 at 22:14













          up vote
          0
          down vote










          up vote
          0
          down vote










          Is using a parameters file that contains dictionaries a good practice?




          No. It doesn't look like you're actually using the dictionaries for anything other than static lookup (and an iteration); as such, those parameters should simply be in a tuple, copied to locals.



          Also, I suggest that you make your parameters uniform (insofar as name, value and unit); something like



          from collections import namedtuple

          Param = namedtuple('Param', ('name', 'value', 'unit', 'desc'))

          params = (
          Param('d_inner', 0.2, 'm', 'Inner diameter'),
          Param('height', 1.5, 'm', 'Height of reactor'),
          # ...
          )
          locals().update({p.name: p for p in params})

          # ...

          print('--- Reactor Parameters ---')
          print('{:8} {:6} {:4} {:20}'.format('Name', 'Value', 'Unit', 'Description'))
          for p in params:
          print('{:8} {:<6.2f} {:4} {:20}'.format(p.name, p.value, p.unit, p.desc))





          share|improve this answer













          Is using a parameters file that contains dictionaries a good practice?




          No. It doesn't look like you're actually using the dictionaries for anything other than static lookup (and an iteration); as such, those parameters should simply be in a tuple, copied to locals.



          Also, I suggest that you make your parameters uniform (insofar as name, value and unit); something like



          from collections import namedtuple

          Param = namedtuple('Param', ('name', 'value', 'unit', 'desc'))

          params = (
          Param('d_inner', 0.2, 'm', 'Inner diameter'),
          Param('height', 1.5, 'm', 'Height of reactor'),
          # ...
          )
          locals().update({p.name: p for p in params})

          # ...

          print('--- Reactor Parameters ---')
          print('{:8} {:6} {:4} {:20}'.format('Name', 'Value', 'Unit', 'Description'))
          for p in params:
          print('{:8} {:<6.2f} {:4} {:20}'.format(p.name, p.value, p.unit, p.desc))






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Dec 4 at 20:07









          Reinderien

          1,889616




          1,889616












          • What is locals? Is it like a collection of global variables?
            – wigging
            Dec 4 at 20:22










          • It's a dictionary of all of the variables in the current scope.
            – Reinderien
            Dec 4 at 20:45










          • I’d even go further and recommend a config module. That’s usually where you want to store parameters.
            – яүυк
            Dec 4 at 21:26










          • Other than the parameters, do you have any comments on using a main script to run everything and where to put results?
            – wigging
            Dec 4 at 21:59










          • Not really, that's all fairly sane
            – Reinderien
            Dec 4 at 22:14


















          • What is locals? Is it like a collection of global variables?
            – wigging
            Dec 4 at 20:22










          • It's a dictionary of all of the variables in the current scope.
            – Reinderien
            Dec 4 at 20:45










          • I’d even go further and recommend a config module. That’s usually where you want to store parameters.
            – яүυк
            Dec 4 at 21:26










          • Other than the parameters, do you have any comments on using a main script to run everything and where to put results?
            – wigging
            Dec 4 at 21:59










          • Not really, that's all fairly sane
            – Reinderien
            Dec 4 at 22:14
















          What is locals? Is it like a collection of global variables?
          – wigging
          Dec 4 at 20:22




          What is locals? Is it like a collection of global variables?
          – wigging
          Dec 4 at 20:22












          It's a dictionary of all of the variables in the current scope.
          – Reinderien
          Dec 4 at 20:45




          It's a dictionary of all of the variables in the current scope.
          – Reinderien
          Dec 4 at 20:45












          I’d even go further and recommend a config module. That’s usually where you want to store parameters.
          – яүυк
          Dec 4 at 21:26




          I’d even go further and recommend a config module. That’s usually where you want to store parameters.
          – яүυк
          Dec 4 at 21:26












          Other than the parameters, do you have any comments on using a main script to run everything and where to put results?
          – wigging
          Dec 4 at 21:59




          Other than the parameters, do you have any comments on using a main script to run everything and where to put results?
          – wigging
          Dec 4 at 21:59












          Not really, that's all fairly sane
          – Reinderien
          Dec 4 at 22:14




          Not really, that's all fairly sane
          – Reinderien
          Dec 4 at 22:14


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209022%2fproject-structure-for-a-reactor-model-built-in-python%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Список кардиналов, возведённых папой римским Каликстом III

          Deduzione

          Mysql.sock missing - “Can't connect to local MySQL server through socket”