Skip to content

Commit

Permalink
do we still need
Browse files Browse the repository at this point in the history
  • Loading branch information
jbae11 committed Jun 11, 2020
2 parents 5c22c10 + 9561105 commit ec4caf7
Show file tree
Hide file tree
Showing 50 changed files with 3,263 additions and 3,134 deletions.
7 changes: 7 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
before_script:
- pip install -r reqs.txt

run-test:
script:
- python setup.py install
- pytest ./tests/unit_test.py
11 changes: 11 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Copyright 2020 Jin Whan Bae

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 changes: 54 additions & 4 deletions cyclus_gui/gui/arche_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,8 @@ def __init__(self, master, output_path):
messagebox.showinfo('Found', 'Found Cyclus, automatically grabbing archetype libraries :)')
except:
try:
# try to download m.json from gitlab
url = 'https://code.ornl.gov/4ib/cyclus_gui/raw/master/src/m.json'
urllib.request.urlretrieve(url, self.meta_file_path)
self.arche = self.read_metafile(self.meta_file_path)
# try to download m.json from gitlab
self.arche = self.get_metafile_from_git(self.meta_file_path)
messagebox.showinfo('Downloaded', 'Downloaded metadata from https://code.ornl.gov/4ib/cyclus_gui/\nIt seems like you do not have Cyclus.\n So I filled this for you :)')
except:
messagebox.showinfo('No Internet', 'No internet, so we are going to use metadata saved in the package.\n Using all cyclus/cycamore arcehtypes as default.')
Expand All @@ -79,6 +77,51 @@ def __init__(self, master, output_path):

# status window
self.update_loaded_modules_window()
self.check_duplicate()


def get_metafile_from_git(self, meta_file_path):
url = 'https://code.ornl.gov/4ib/cyclus_gui/raw/master/src/m.json'
urllib.request.urlretrieve(url, meta_file_path)
arche = self.read_metafile(meta_file_path)
return arche


def check_duplicate(self):
prev = []
duplicate = []
for a in self.arche:
if a[1] not in prev:
prev.append(a[1])
else:
duplicate.append(a[1])
if duplicate:
self.duplicates = True
self.duplicate_window_dict = {}
for i in duplicate:
self.choose_between_duplicate(i)



def choose_between_duplicate(self, duplicate_name):
self.duplicate_window_dict[duplicate_name] = Toplevel(self.master)
self.duplicate_window_dict[duplicate_name].title('Choice!')
Label(self.duplicate_window_dict[duplicate_name], text='Duplicate archetype name. Pick one to keep:').pack()
j = [i for i in self.arche if i[1] == duplicate_name]
for i in j:
Button(self.duplicate_window_dict[duplicate_name], text='%s:%s' %(i[0],i[1]), command=lambda:self.delete_all_but(i, j)).pack()


def delete_all_but(self, chosen, all_):
for i in all_:
if i != chosen:
self.delete_arche(i)
self.duplicate_window_dict[i[1]].destroy()
self.duplicates = False
self.update_loaded_modules_window()





def import_libraries(self, local):
Expand Down Expand Up @@ -270,12 +313,19 @@ def add(self):


def done(self):

self.check_duplicate()
if self.duplicates:
messagebox.showerror('Check Duplicates', 'See if you have any duplicate archetype names!\nThere should be a window that tells you to choose one.')
return

string = '<archetypes>\n'
for pair in self.arche:
string += '\t<spec>\t<lib>%s</lib>\t<name>%s</name></spec>\n' %(pair[0], pair[1])
string += '</archetypes>\n'
with open(os.path.join(self.output_path, 'archetypes.xml'), 'w') as f:
f.write(string)
messagebox.showinfo('Success', 'Successfully created archetype file!')
self.master.destroy()


Expand Down
11 changes: 5 additions & 6 deletions cyclus_gui/gui/backend_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from tkinter import messagebox
from tkinter import filedialog
from tkinter.scrolledtext import ScrolledText
import xmltodict
import uuid
import os
import shutil
Expand All @@ -19,7 +18,7 @@


class BackendWindow(Frame):
def __init__(self, master, output_path):
def __init__(self, master, output_path, filename='cyclus.sqlite'):
"""
does backend analysis
"""
Expand All @@ -31,7 +30,7 @@ def __init__(self, master, output_path):
self.output_path = output_path
self.master.geometry('+0+%s' %int(self.screen_height/4))
self.configure_window()
self.get_cursor()
self.get_cursor(filename)
self.get_id_proto_dict()
self.get_start_times()

Expand Down Expand Up @@ -129,8 +128,8 @@ def get_id_proto_dict(self):
self.id_proto_dict[agent['agentid']] = agent['prototype']


def get_cursor(self):
con = lite.connect(os.path.join(self.output_path, 'cyclus.sqlite'))
def get_cursor(self, filename='cyclus.sqlite'):
con = lite.connect(os.path.join(self.output_path, filename))
con.row_factory = lite.Row
self.cur = con.cursor()

Expand Down Expand Up @@ -657,7 +656,7 @@ def plot_flow(self):
maxy = 14 * len(flow_clean)
y_coords = np.linspace(0, maxx, len(flow_clean))[::-1]
x_coords = np.linspace(0, maxy, max([len(q) for q in flow_clean]))
xgap = x_coords[1] - x_coords[0]
# xgap = x_coords[1] - x_coords[0]
ygap = y_coords[1] - y_coords[0]

uniq_commods = list(set(df['Commodity']))
Expand Down
104 changes: 53 additions & 51 deletions cyclus_gui/gui/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@

os_ = platform.system()
print('Your OS is:', os_)
if 'windows' in os_.lower():
windows=True
if 'windows' in os_.lower() or 'linux' in os_.lower():
no_hover=True
else:
windows=False
no_hover=False


uniq_id = str(uuid.uuid4())[:3]
Expand Down Expand Up @@ -135,7 +135,7 @@ def init_window(self):
combine_run_button = Button(root, text='Combine and Run', command= lambda: self.check_and_run())
backend_button = Button(root, text='Backend Analysis', command= lambda: self.open_window('backend', output_path))

if not windows:
if not no_hover:
CreateToolTip(saveas_button, text='You can save your current instance with a different three-letter hash.')
CreateToolTip(load_button, text='You can load from a previous instance.\nFor every instance, the GUI automatically creates `output_xxx` directory\nwhere it saves all the files, so that it can be called later on.')
CreateToolTip(load_complete_input, text='You can load from a previously-existing Cyclus input xml file.\nThere are limitations to some input files, if they use special archetypes. You can edit or run cyclus on the file!')
Expand Down Expand Up @@ -213,38 +213,40 @@ def load_prev_window(self):
self.initialized['prev'] = True
self.load_window = Toplevel(self.master)
self.load_window.title('Load previous with hash')
Label(self.load_window, text='Enter id:', bg='yellow').pack()
entry = Entry(self.load_window)
entry.pack()
Button(self.load_window, text='Load!', command=lambda: self.load_prev(entry)).pack()


def load_prev(self, entry):
folders = os.listdir(file_path)
folders = [f for f in folders if os.path.isdir(os.path.join(file_path, f))]
hash_ = str(entry.get())
for i in folders:
if hash_ in i:
files_in = os.listdir(os.path.join(file_path, 'output_%s'%hash_))
info_text = 'Found folder %s.\nLoading input blocks:\n\n' %i
for f_ in files_in:
f_ = f_.replace('.xml', '')
info_text += '\t%s\n' %f_
messagebox.showinfo('Found!', info_text)
global uniq_id
global output_path
uniq_id = hash_
self.hash_var.set(hash_)
print('Changed ID to %s' %hash_)
output_path = os.path.join(file_path, i)
self.load_window.destroy()
shutil.rmtree('output_%s' %self.uniq_id)
self.uniq_id = hash_
self.initialized['prev'] = False
return
# if folder is not found,
messagebox.showerror('Error', 'No folder with that name.\n The folder must exist in: \n %s' %file_path)
folders = [f for f in folders if 'output_' in f]
hashs = [f.replace('output_', '') for f in folders]
hashs = sorted([f for f in hashs if f != self.uniq_id])
Label(self.load_window, text='Current working directory:').pack()
Label(self.load_window, text=os.path.abspath(file_path), bg='yellow').pack()
Label(self.load_window, text='Available instances:').pack()
for h in hashs:
Button(self.load_window, text=h, command=lambda:self.load_prev(h)).pack()
if not hashs:
# if list is empty:
Label(self.load_window, text='NONE', bg='red').pack()


def load_prev(self, h):
files_in = os.listdir(os.path.join(file_path, 'output_%s'%h))
info_text = 'Found folder output_%s.\nLoading input blocks:\n\n' %h
for f_ in files_in:
f_ = f_.replace('.xml', '')
info_text += '\t%s\n' %f_
messagebox.showinfo('Found!', info_text)
global uniq_id
global output_path
uniq_id = h
self.hash_var.set(h)
print('Changed ID to %s' %h)
output_path = os.path.join(file_path, 'output_%s' %h)
self.load_window.destroy()
shutil.rmtree('output_%s' %self.uniq_id)
self.uniq_id = h
self.initialized['prev'] = False
return


def askopenfile(self):
file = filedialog.askopenfile(parent=self.master, mode='r', title='Choose an xml file')
Expand Down Expand Up @@ -273,24 +275,24 @@ def load_xml_file(self, file):

def load_from_pris(self):
guide_text = """
You can `initialize' your simulation as a real-life nation!
This method loads from the PRIS database and deploys reactors in your
desired country, in a desired initial time. The reactor lifetimes
are calculated as a remaining lifetime.
Assumptions:
1. Timestep is assumed to be a month
2. Reactors below 100 MWe are filtered out (assumed to be research reactors)
3. Core size is linearly scaled with power capacity
4. Reactor lifetimes are all assumed to be 60 years from their first criticality date
5. Fuel Cycle facilities are deployed with infinite capacity.
Simulation defaults:
1. Reactors are cycamore::Reactor (recipe reactors)
2. By default deploys a `RandLand' region with `Fuel_Cycle_Facilities' institution with facilities:
a. `nat_u_source' -> [natl_u]
b. [natl_u] -> `enrichment' -> [uox]
d. [uox_waste, used_candu, mox_waste, tailings, reprocess_waste] -> `SomeSink'
You can `initialize' your simulation as a real-life nation!
This method loads from the PRIS database and deploys reactors in your
desired country, in a desired initial time. The reactor lifetimes
are calculated as a remaining lifetime.
Assumptions:
1. Timestep is assumed to be a month
2. Reactors below 100 MWe are filtered out (assumed to be research reactors)
3. Core size is linearly scaled with power capacity
4. Reactor lifetimes are all assumed to be 60 years from their first criticality date
5. Fuel Cycle facilities are deployed with infinite capacity.
Simulation defaults:
1. Reactors are cycamore::Reactor (recipe reactors)
2. By default deploys a `RandLand' region with `Fuel_Cycle_Facilities' institution with facilities:
a. `nat_u_source' -> [natl_u]
b. [natl_u] -> `enrichment' -> [uox]
d. [uox_waste, used_candu, mox_waste, tailings, reprocess_waste] -> `SomeSink'
"""
self.guide(guide_text)
try:
Expand Down
2 changes: 1 addition & 1 deletion cyclus_gui/gui/proto_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ def submit(self):
facility_dict['name'] = name
facility_dict['config'] = config['config']
new_dict['root']['facility'].append(facility_dict)
f.write(xmltodict.unparse(new_dict, pretty=True))
f.write('\n'.join(xmltodict.unparse(new_dict, pretty=True).split('\n')[1:]))
messagebox.showinfo('Sucess', 'Successfully rendered %i facility prototypes!' %len(new_dict['root']['facility']))
self.master.destroy()
self
Expand Down
21 changes: 10 additions & 11 deletions cyclus_gui/gui/sim_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ def on_leave(self, event):
self.new_window.destroy()



def is_it_pos_integer(self, num):
if float(num) % 1.0 != 0.0:
return False
Expand All @@ -84,25 +83,25 @@ def read_xml(self):


def done(self):
self.entry_dict = {key: val.get() for key, val in self.entry_dict.items()}

val_dict = {key:val.get() for key,val in self.entry_dict.items()}
# check input:
if '' in self.entry_dict.values():
if '' in val_dict.values():
messagebox.showerror('Error', 'You omitted some parameters')
elif not self.is_it_pos_integer(self.entry_dict['startmonth']):
elif not self.is_it_pos_integer(val_dict['startmonth']):
messagebox.showeeror('Error', 'Start Month must be a positive integer')
elif not self.is_it_pos_integer(self.entry_dict['startyear']):
elif not self.is_it_pos_integer(val_dict['startyear']):
messagebox.showerror('Error', 'Start Year must be a positive integer')
elif int(self.entry_dict['startmonth']) not in list(range(1,13)):
messagebox.showeror('Error', 'Month has to be number from 1 to 12')
elif self.entry_dict['decay'] not in ['never', 'lazy', 'manual']:
elif int(val_dict['startmonth']) not in list(range(1,13)):
messagebox.showerror('Error', 'Month has to be number from 1 to 12')
return
elif val_dict['decay'] not in ['never', 'lazy', 'manual']:
messagebox.showerror('Error', 'Decay must be either never, lazy, or manual')
elif not self.is_it_pos_integer(self.entry_dict['dt']):
elif not self.is_it_pos_integer(val_dict['dt']):
messagebox.showerror('Error', 'dt must be a positive integer')
else:
messagebox.showinfo('Success', 'Rendered Simulation definition into xml! :)')
xml_string = '<control>\n'
for key, val in self.entry_dict.items():
for key, val in val_dict.items():
if key=='dt' and int(val)==2629846:
continue
if (key=='explicit_inventory' or key=='explicit_inventory_compact') and int(val)==0:
Expand Down
Loading

0 comments on commit ec4caf7

Please sign in to comment.