Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved output file names #610

Open
wants to merge 11 commits into
base: protos
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,11 @@ def configure(self, value):
self._original_input = value

InputFileConfigurator.configure(self, value)

inputTraj = IInputData.create("HDFTrajectoryInputData", self["value"])
try:
inputTraj = IInputData.create("HDFTrajectoryInputData", self["value"])
except KeyError:
self.error_status = f"Could not use {value} as input trajectory"
return

self["hdf_trajectory"] = inputTraj

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def __init__(self, name, formats=None, **kwargs):
self._formats = (
formats if formats is not None else OutputFilesConfigurator._default[-1]
)
self._forbidden_files = []

def configure(self, value):
"""
Expand Down Expand Up @@ -98,7 +99,16 @@ def configure(self, value):

self["root"] = root
self["formats"] = formats
self["files"] = ["%s%s" % (root, IFormat.create(f).extension) for f in formats]
self["files"] = []
for extension in [IFormat.create(f).extension for f in formats]:
if extension in root[-len(extension) :]:
self["files"].append(root)
else:
self["files"].append(root + extension)
for file in self["files"]:
if os.path.abspath(file) in self._forbidden_files:
self.error_status = f"File {file} is either open or being written into. Please pick another name."
return

self["value"] = self["files"]
self["log_level"] = logs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def __init__(self, name, formats=None, **kwargs):
IConfigurator.__init__(self, name, **kwargs)

self._formats = [fmt for fmt in ioformats if ioformats[fmt].can_write]
self._forbidden_files = []

def configure(self, value):
"""
Expand Down Expand Up @@ -87,6 +88,9 @@ def configure(self, value):
self["root"] = root
self["format"] = format
self["file"] = root
if os.path.abspath(self["file"]) in self._forbidden_files:
self.error_status = f"File {self['file']} is either open or being written into. Please pick another name."
return
self["log_level"] = logs
if logs == "no logs":
self["write_logs"] = False
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def __init__(self, name, format=None, **kwargs):
self._format = "MDTFormat"
self._dtype = np.float64
self._compression = "none"
self._forbidden_files = []

def configure(self, value: tuple):
self._original_input = value
Expand Down Expand Up @@ -95,6 +96,9 @@ def configure(self, value: tuple):
if not self["extension"] in temp_name[-5:]: # capture most extension lengths
temp_name += self["extension"]
self["file"] = temp_name
if os.path.abspath(self["file"]) in self._forbidden_files:
self.error_status = f"File {self['file']} is either open or being written into. Please pick another name."
return
self["dtype"] = self._dtype
self["compression"] = self._compression
self["log_level"] = logs
Expand Down
2 changes: 2 additions & 0 deletions MDANSE/Src/MDANSE/Framework/Converters/DCD.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ class DCD(Converter):
Converts a DCD trajectory to a HDF trajectory.
"""

label = "DCD"

settings = collections.OrderedDict()
settings["pdb_file"] = (
"InputFileConfigurator",
Expand Down
2 changes: 1 addition & 1 deletion MDANSE/Src/MDANSE/Framework/Converters/VASP.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class VASP(Converter):
Converts a VASP trajectory to a HDF trajectory.
"""

label = "VASP (>=5)"
label = "VASP v5"

settings = collections.OrderedDict()
settings["xdatcar_file"] = (
Expand Down
2 changes: 1 addition & 1 deletion MDANSE/Src/MDANSE/Framework/Jobs/Infrared.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Infrared(IJob):

enabled = True

label = "Dipole AutoCorrelation Function"
label = "Infrared Spectrum"

category = (
"Analysis",
Expand Down
2 changes: 1 addition & 1 deletion MDANSE/Src/MDANSE/Framework/Session/CurrentSession.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def load_session(self, fname: str):
class SessionSettings(AbstractSession):
def __init__(self):
super().__init__()
self.main_path = "."
self.main_path = os.path.abspath(".")

def create_structured_project(self):
self.relative_paths = {
Expand Down
6 changes: 4 additions & 2 deletions MDANSE_GUI/Src/MDANSE_GUI/InputWidgets/AseInputFileWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
import os

from qtpy.QtWidgets import QLineEdit, QPushButton, QFileDialog, QComboBox
from qtpy.QtCore import Slot
from ase.io.formats import filetype
Expand All @@ -37,10 +39,10 @@ def __init__(self, *args, **kwargs):
parent = kwargs.get("parent", None)
self.default_path = parent.default_path
except KeyError:
self.default_path = "."
self.default_path = os.path.abspath(".")
LOG.error("KeyError in InputFileWidget - can't get default path.")
except AttributeError:
self.default_path = "."
self.default_path = os.path.abspath(".")
LOG.error("AttributeError in InputFileWidget - can't get default path.")
default_value = kwargs.get("default", "")
if self._tooltip:
Expand Down
36 changes: 11 additions & 25 deletions MDANSE_GUI/Src/MDANSE_GUI/InputWidgets/InputFileWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,29 +33,19 @@ def __init__(self, *args, file_dialog=QFileDialog.getOpenFileName, **kwargs):
else:
default_value = ""
parent = kwargs.get("parent", None)
self._parent = parent
if parent is not None:
self._job_name = parent._job_name
self._settings = parent._settings
try:
paths_group = self._settings.group("paths")
try:
self.default_path = paths_group.get(self._job_name)
except KeyError:
paths_group.add(
self._job_name,
".",
f"The filesystem path recently used by {self._job_name}",
)
self.default_path = "."
parent = kwargs.get("parent", None)
self.default_path = parent._default_path
except KeyError:
self.default_path = os.path.abspath(".")
LOG.error("KeyError in OutputFilesWidget - can't get default path.")
except AttributeError:
try:
self.default_path = parent.default_path
except KeyError:
self.default_path = "."
LOG.error("KeyError in InputFileWidget - can't get default path.")
except AttributeError:
self.default_path = "."
LOG.error("AttributeError in InputFileWidget - can't get default path.")
self.default_path = os.path.abspath(".")
LOG.error("AttributeError in OutputFilesWidget - can't get default path.")
default_value = kwargs.get("default", "")
if self._tooltip:
self._tooltip_text = self._tooltip
Expand Down Expand Up @@ -95,15 +85,10 @@ def valueFromDialog(self):
This will start a FileDialog, take the resulting path,
and emit a signal to update the value show by the GUI.
"""
paths_group = self._settings.group("paths")
try:
self.default_path = paths_group.get(self._job_name)
except:
LOG.warning(f"session.get_path failed for {self._job_name}")
new_value = self._file_dialog(
self.parent(), # the parent of the dialog
"Load file", # the label of the window
self.default_path, # the initial search path
self._parent._default_path, # the initial search path
self._qt_file_association, # text string specifying the file name filter.
)
if new_value is not None and new_value[0]:
Expand All @@ -113,7 +98,8 @@ def valueFromDialog(self):
LOG.info(
f"Settings path of {self._job_name} to {os.path.split(new_value[0])[0]}"
)
paths_group.set(self._job_name, os.path.split(new_value[0])[0])
if self._parent is not None:
self._parent._default_path = os.path.split(new_value[0])[0]
except:
LOG.error(
f"session.set_path failed for {self._job_name}, {os.path.split(new_value[0])[0]}"
Expand Down
65 changes: 24 additions & 41 deletions MDANSE_GUI/Src/MDANSE_GUI/InputWidgets/OutputFilesWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
import glob
import itertools
import os
import os.path

Expand All @@ -35,18 +33,30 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, layout_type="QGridLayout", **kwargs)
default_value = self._configurator.default
try:
parent = kwargs.get("parent", None)
self.default_path = parent.default_path
self._parent = kwargs.get("parent", None)
self.default_path = self._parent._default_path
except KeyError:
self.default_path = "."
self.default_path = os.path.abspath(".")
LOG.error("KeyError in OutputFilesWidget - can't get default path.")
except AttributeError:
self.default_path = "."
self.default_path = os.path.abspath(".")
LOG.error("AttributeError in OutputFilesWidget - can't get default path.")
else:
self._session = self._parent._parent_tab._session
try:
self._parent = kwargs.get("parent", None)
jobname = str(self._parent._job_instance.label).replace(" ", "")
guess_name = os.path.join(self.default_path, jobname + "_result1")
except:
guess_name = default_value[0]
LOG.error("It was not possible to get the job name from the parent")
while os.path.exists(guess_name + ".mda"):
prefix, number = guess_name.split("_result")
guess_name = prefix + "_result" + str(1 + int(number))
self.file_association = "Output file name (*)"
self._value = default_value
self._field = QLineEdit(default_value[0], self._base)
self._field.setPlaceholderText(default_value[0])
self._field = QLineEdit(guess_name, self._base)
self._field.setPlaceholderText(guess_name)
self.type_box = CheckableComboBox(self._base)
self.type_box.addItems(self._configurator.formats)
self.type_box.set_default("MDAFormat")
Expand Down Expand Up @@ -92,6 +102,10 @@ def file_dialog(self):
This will start a FileDialog, take the resulting path,
and emit a signal to update the value show by the GUI.
"""
try:
self.default_path = self._parent._default_path
except AttributeError:
self.default_path = os.path.abspath(".")
new_value = QFileDialog.getSaveFileName(
self._base, # the parent of the dialog
"Save files", # the label of the window
Expand All @@ -102,44 +116,13 @@ def file_dialog(self):
self._field.setText(new_value[0])
self.updateValue()

@staticmethod
def _get_unique_filename(directory, basename):
filesInDirectory = [
os.path.join(directory, e)
for e in itertools.chain(
glob.iglob(os.path.join(directory, "*")),
glob.iglob(os.path.join(directory, ".*")),
)
if os.path.isfile(os.path.join(directory, e))
]
basenames = [os.path.splitext(f)[0] for f in filesInDirectory]

initialPath = path = os.path.join(directory, basename)
comp = 1
while True:
if path in basenames:
path = "%s(%d)" % (initialPath, comp)
comp += 1
continue
return path

def get_widget_value(self):
self._configurator._forbidden_files = self._session.reserved_filenames()
filename = self._field.text()
if len(filename) < 1:
filename = self._default_value[0]

formats = self.type_box.checked_values()
log_level = self.logs_combo.currentText()

return (filename, formats, log_level)

def set_data(self, datakey):
basename = "%s_%s" % (
os.path.splitext(os.path.basename(datakey))[0],
self._parent.type,
)
trajectoryDir = os.path.dirname(datakey)

path = OutputFilesWidget._get_unique_filename(trajectoryDir, basename)

self._filename.SetValue(path)
return (os.path.abspath(filename), formats, log_level)
40 changes: 12 additions & 28 deletions MDANSE_GUI/Src/MDANSE_GUI/InputWidgets/OutputStructureWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
import glob
import itertools
import os
import os.path

Expand All @@ -37,17 +35,24 @@ def __init__(self, *args, **kwargs):
parent = kwargs.get("parent", None)
self.default_path = parent.default_path
except KeyError:
self.default_path = "."
self.default_path = os.path.abspath(".")
LOG.error("KeyError in OutputTrajectoryWidget - can't get default path.")
except AttributeError:
self.default_path = "."
self.default_path = os.path.abspath(".")
LOG.error(
"AttributeError in OutputTrajectoryWidget - can't get default path."
)
try:
parent = kwargs.get("parent", None)
jobname = str(parent._job_instance.label).replace(" ", "")
guess_name = os.path.join(self.default_path, "POSCAR")
except:
guess_name = default_value[0]
LOG.error("It was not possible to get the job name from the parent")
self.file_association = "Output file name (*)"
self._value = default_value
self._field = QLineEdit(default_value[0], self._base)
self._field.setPlaceholderText(default_value[0])
self._field = QLineEdit(guess_name, self._base)
self._field.setPlaceholderText(guess_name)
self.format_box = QComboBox(self._base)
self.format_box.addItems(self._configurator._formats)
self.format_box.setCurrentText(default_value[1])
Expand Down Expand Up @@ -108,31 +113,10 @@ def file_dialog(self):
self._field.setText(new_value[0])
self.updateValue()

@staticmethod
def _get_unique_filename(directory, basename):
filesInDirectory = [
os.path.join(directory, e)
for e in itertools.chain(
glob.iglob(os.path.join(directory, "*")),
glob.iglob(os.path.join(directory, ".*")),
)
if os.path.isfile(os.path.join(directory, e))
]
basenames = [os.path.splitext(f)[0] for f in filesInDirectory]

initialPath = path = os.path.join(directory, basename)
comp = 1
while True:
if path in basenames:
path = "%s(%d)" % (initialPath, comp)
comp += 1
continue
return path

def get_widget_value(self):
filename = self._field.text()
if len(filename) < 1:
filename = self._default_value[0]
format = self.format_box.currentText()
log_level = self.logs_combo.currentText()
return (filename, format, log_level)
return (os.path.abspath(filename), format, log_level)
Loading