def setUpSeries(self): """When the series is given, make it ready for evaluation by updating fields for the axes""" if self.Param_Dict["isValidSeries"]: self.Param_Dict["SignalHandler"].changeEvalMode() self.Status_Dict["Status"].setText("Series ready to evaluate.") self.Button_Dict["MakeLinePlot"].hide() GUILogger.info("Scanning the first file for relevant fields...") # Update Geometry and hide the widgets that would cause errors self.Param_Dict["CurrentDataSet"] = self.Param_Dict["DataSeries"][0] sut.updateGeometry(self.Param_Dict, self.CheckBox_Dict, self.RadioDict_Dict, self.Edit_Dict, self.Label_Dict) # Update the comboBoxes according to entries in field lists try: sut.updateFields(self.Param_Dict, self.ComboBox_Dict) except Exception: return sut.resetExtrema(self.Param_Dict, self.Edit_Dict, self.Button_Dict, self.Label_Dict, self.ComboBox_Dict, self) self.Param_Dict["SignalHandler"].getOtherUnitInput("Grid") fillDataSetDict(self.Param_Dict, self.Status_Dict, self.Wid_Dict["TopLayout"], self._main) setUpWidgets(self.Param_Dict, self.CheckBox_Dict, self.Misc_Dict) updateLabels(self.Param_Dict, self.Label_Dict) self.Param_Dict["SignalHandler"].setPlotOptions() sut.refreshWidgets(self.Edit_Dict, self.ComboBox_Dict)
def testValidFile(self): """Promts the user to enter a file name. If yt can't load it, display an error message and try again. returns: True if load was successful False if user cancels before successful load """ filename = QW.QFileDialog.getOpenFileName(self, "Select a simulation file", self.Param_Dict["Directory"], "All files (*)")[0] if filename != '': try: # SingleDataSet is there so we can go back to a single dataset # if the user loaded one. self.Param_Dict["SingleDataSet"] = self.loadFile(filename) self.Param_Dict["CurrentDataSet"] = self.Param_Dict["SingleDataSet"] self.Param_Dict["Seriesname"] = "" self.Param_Dict["Filename"] = filename self.Status_Dict["Series"].setText(self.Param_Dict["Seriesname"]) self.Param_Dict["isValidFile"] = True self.Param_Dict["isValidSeries"] = False self.setUpFile() return except YTOutputNotIdentified: sut.alertUser("Couldn't load this file. Please try again") # Ask the user to enter another series name. # If he cancels, pass. self.testValidFile() else: GUILogger.warning("Couldn't load file. Click 'Open File' to start over.") return
def testValidSeries(self): """Promts the user to enter a directory name. After one has been chosen, prompt for a series name. If yt can't load it, display an error message and try again. """ directory = QW.QFileDialog.getExistingDirectory(self, "Select a directory with your series in it", self.Param_Dict["Directory"]) if directory != '': # Information on DataSetSeries object: # http://yt-project.org/doc/reference/api/yt.data_objects.time_series.html#yt.data_objects.time_series.DataSetSeries ts = self.loadSeries(directory) if ts is None: return try: GUILogger.info(f"This series includes {len(ts)} files.") # ts = [yt.load(filename) for filename in ts._pre_outputs] self.Param_Dict["DataSeries"] = ts self.setUpSeries() except TypeError: self.RadioDict_Dict["EvalMode"]["Single file"].setChecked(True) self.Param_Dict["SingleDataSet"] = ts GUILogger.warning("Only a single file has been selected. Changing to single file mode.") self.Param_Dict["Filename"] = self.Param_Dict["Seriesname"] self.Param_Dict["Seriesname"] = "" self.Status_Dict["Series"].setText(self.Param_Dict["Seriesname"]) self.Status_Dict["File"].setText(self.Param_Dict["Seriesname"]) self.Param_Dict["isValidFile"] = True self.Param_Dict["isValidSeries"] = False self.setUpFile()
def shuffleCoords(Param_Dict): """The coordinates may need to be shuffled if the user doesn't have the z-axis as normal vector. """ starts = ["XLStart", "YLStart", "ZLStart"] ends = ["XLEnd", "YLEnd", "ZLEnd"] # save the values for shuffling svalues = [Param_Dict[key] for key in starts] evalues = [Param_Dict[key] for key in ends] if Param_Dict["NAxis"] == "x": # This shuffles the list in a cyclic way: [1, 2, 3] -> [2, 3, 1] svalues.append(svalues.pop(0)) evalues.append(evalues.pop(0)) # and once more svalues.append(svalues.pop(0)) evalues.append(evalues.pop(0)) elif Param_Dict["NAxis"] == "y": svalues.append(svalues.pop(0)) evalues.append(evalues.pop(0)) elif Param_Dict["NAxis"] == "z": # no shuffling needed pass else: GUILogger.error( "Something went wrong when transferring the coordinates to LinePlot" ) for i in range(3): Param_Dict[starts[i]] = svalues[i] Param_Dict[ends[i]] = evalues[i]
def PhasePlot(Param_Dict, worker): """Takes a DataSet object loaded with yt and performs a phasePlot on it. Parameters: Param_Dict: to access the relevant parameters """ if Param_Dict["WeightField"] is None: GUILogger.warning('Having <font color="DarkViolet">None</font> as the ' "weight field just accumulates, " "so the extrema might be inaccurate.") ds = Param_Dict["CurrentDataSet"] XField, YField, ZField = Param_Dict["XAxis"], Param_Dict["YAxis"], \ Param_Dict["ZAxis"] ad = ds.all_data() if Param_Dict["ParticlePlot"]: plot = yt.ParticlePhasePlot(ad, XField, YField, ZField, weight_field=Param_Dict["WeightField"], fontsize=14) else: plot = yt.PhasePlot(ad, XField, YField, ZField, weight_field=Param_Dict["WeightField"], fontsize=14) emitStatus(worker, "Setting phase plot modifications") # Set min, max, unit log and color scheme: setAxisSettings(plot, Param_Dict, "X") setAxisSettings(plot, Param_Dict, "Y") setAxisSettings(plot, Param_Dict, "Z") emitStatus(worker, "Annotating the phase plot") plot.annotate_title(Param_Dict["PlotTitle"]) finallyDrawPlot(plot, Param_Dict, worker)
def openPlotAllDialog(self): """Handles the plotting for several files in a series at once.""" if not self.Param_Dict["isValidSeries"]: GUILogger.error("Evaluation stopped. Please open valid directory " "first and enter valid series name.") return self.CheckBox_Dict["TimeSeriesProf"].setChecked(False) self.plotAllDialog = PlotAllDialog(self.Param_Dict) self.plotAllDialog.accepted.connect(lambda: self.evaluateMultiple(self.plotAllDialog.Request_Dict))
def giveMultipleFeedback(self, success, directory): """Gives feedback on wether multiple plots were successful.""" mode = self.Param_Dict["PlotMode"] if success: GUILogger.log(29, f"{mode} plots successful.") if directory != "": GUILogger.log(29, f"The pictures have been saved to <b>{directory}</b>.") cart = self.Param_Dict["Geometry"] == "cartesian" aligned = self.Param_Dict["NormVecMode"] == "Axis-Aligned" slcproj = mode in ["Slice", "Projection"] if cart and slcproj and aligned: self.Button_Dict["MakeLinePlot"].show()
def giveSingleFeedback(self, success): """Gives feedback on wether the plot was successful. Shows the MakeLinePlot button upon successful plotting if the conditions are met""" mode = self.Param_Dict["PlotMode"] if success: GUILogger.log(29, f"{mode} plot successful.") cart = self.Param_Dict["Geometry"] == "cartesian" aligned = self.Param_Dict["NormVecMode"] == "Axis-Aligned" slcproj = mode in ["Slice", "Projection"] if cart and slcproj and aligned: self.Button_Dict["MakeLinePlot"].show()
def emitStatus(worker, message): """Emits a status message on the current worker or raises an exception which needs to be caught above.""" if worker is None: return if worker._isRunning: GUILogger.debug(message) worker.progressUpdate.emit(message) worker.oldMessage = message else: raise WorkingException(f"You cancelled the plotting process \ while <b>{worker.oldMessage.lower()}.</b>")
def issueAnnoWarning(plot, anno): """Unfortunately, grids are not annotated if the center is 0, 0 for a plot. Issue an error to the GUILogger if that is the case. Parameters: plot: yt slice/projection plot instance anno: String denoting the kind of annotation""" center = plot.center if not all(center): # non-zero values are interpreted as True GUILogger.error( f"{anno} could not properly be drawn. This bug occurs if" " one of the center coordinates is 0. Try setting them " "to 1e-100 au or another very low value.")
def calcExtrema(Param_Dict, ds, field, projCond): """Tries to calculate the extrema.""" if projCond: # For a projection plot, we need to get the projected min and max # We also need to create new entries in the fieldMins minMaxArray = calcProjectionExtrema(Param_Dict, ds, field) else: try: minMaxArray = ds.all_data().quantities.extrema(field) except yt.utilities.exceptions.YTFieldNotFound: GUILogger.warning(f"Couldn't find {field} in the available fields") raise WorkingException return minMaxArray
def openFile(self): """Opens a file dialogue and promts the user to add a file or directory, depending on the mode selected in Param_Dict["EvalMode"]. Also tries to load the file using yt. """ if self.Param_Dict["EvalMode"] == "Single": # Create a window that contains dialogue for opening file GUILogger.info("Opening file in single file mode") self.testValidFile() else: # Create a window that contains dialogue for opening directory GUILogger.info("Opening file in time series mode") self.testValidSeries()
def evaluateMultiple(self, Request_Dict): """Passes the evaluation of multiple plots to a ProgressDialog.""" self.Param_Dict["OnlyEvery"] = Request_Dict["OnlyEvery"] if Request_Dict["MakeMovie"]: Request_Dict["Directory"] = sut.setUpMovieFolder(self.Param_Dict) if not Request_Dict["Directory"]: return GUILogger.info("Evaluation started. Checking for missing extrema...") sut.checkExtremaForPlot(self.Param_Dict) self.progressDialog = ProgressDialog(self.Param_Dict, self, mode="PlotAll", Request_Dict=Request_Dict, slider=self.Misc_Dict["SeriesSlider"]) self.progressWorker.finished.connect(self.giveMultipleFeedback)
def loadSeries(self, directory): """Handles loading a given series in a directory. Also changes the current working directory self.Param_Dict["Directory"] Parameters: directory: path of the series returns: ts: yt DataSetSeries object """ GUILogger.info(f"{directory} is directory for series mode") self.Status_Dict["Dir"].setText(directory) self.Param_Dict["Directory"] = directory ok = self.askSeriesName() if ok: try: GUILogger.info(f"Loading series '{self.Param_Dict['Seriesname']}'...") ts = yt.load(directory + '/' + self.Param_Dict["Seriesname"]) self.Param_Dict["Filename"] = "" self.Status_Dict["File"].setText(self.Param_Dict["Filename"]) self.Param_Dict["isValidSeries"] = True self.Param_Dict["isValidFile"] = True return ts except YTOutputNotIdentified: sut.alertUser("Couldn't load this series. Please try again") # Ask the user to enter another series name. # If he cancels, pass. return self.loadSeries(directory) else: GUILogger.warning("Couldn't load series.") GUILogger.log(29, "Try replacing the last digits of your series with " "questionmarks or import all files of the directory " "by using *") return None
def makeProfilePlot(self, Param_Dict, arr, labels, worker=None): """Plots the data of the array to the axes.""" self.arr = arr self.labels = labels emitStatus(worker, "Starting the plot") if Param_Dict["AddProfile"]: self.ax.tick_params(axis='y',) self.twinax = self.ax.twinx() x_values = arr[0].to_value(Param_Dict["XUnit"]) for i in range(len(arr)-1): y_values = arr[i+1].to_value(Param_Dict["YUnit"]) label = labels[i] self.twinax.plot(x_values, y_values, ":", linewidth=3, label=label) emitStatus(worker, "Setting plot modifications") setProfileAxisSettings(Param_Dict, "Y", self.twinax) self.twinax.tick_params(axis='y') # ask matplotlib for the plotted objects and their labels lines, labels = self.ax.get_legend_handles_labels() lines2, labels2 = self.twinax.get_legend_handles_labels() self.ax.legend(lines + lines2, labels + labels2) self.hasProfile = False # We only want the user to be able to add a plot if there is only one profile Param_Dict["SignalHandler"].changeToProfile() else: self.prepareFigure() # Clear everything before plotting # get x- and y-values and plot them: x_values = arr[0].to_value(Param_Dict["XUnit"]) for i in range(len(arr)-1): y_values = arr[i+1].to_value(Param_Dict["YUnit"]) label = labels[i] self.ax.plot(x_values, y_values, "-", linewidth=3, label=label) emitStatus(worker, "Setting plot modifications") setProfileAxisSettings(Param_Dict, "Y", self.ax) self.hasProfile = True Param_Dict["SignalHandler"].changeToProfile() if Param_Dict["Timestamp"] and Param_Dict["XAxis"] != "time": if len(arr) > 2: # This can probably be done more elegantly GUILogger.warning("Timestamp is not annotated for multiple" " profiles. Sorry for leaving the CheckBox there.") else: drawTimestampBox(Param_Dict, self.ax) self.ax.legend() self.ax.grid() setProfileAxisSettings(Param_Dict, "X", self.ax) self.ax.set_title(r"{}".format(Param_Dict["PlotTitle"])) emitStatus(worker, "Drawing plot onto the canvas") self.canvas.draw() # called twice because somehow it isn't fully sized self.canvas.draw() # at first... I don't know why. self.copyParamDict(Param_Dict)
def setUpMovieFolder(Param_Dict): """Creates a folder for the movie pictures to be saved in.""" directory = QW.QFileDialog.getExistingDirectory( None, "Select a directory " "to save the pictures in", Param_Dict["Directory"]) if directory == "": GUILogger.warning( "Evaluation stopped. Please select a valid directory.") return False date = datetime.now().strftime("%d_%m_%Y_%H_%M_%S") plotMode = Param_Dict["PlotMode"] # for the fstring directory = f"{directory}/{plotMode}plots_{date}" mkdir(directory) GUILogger.log(29, f"The pictures are being saved to <b>{directory}</b>.") return directory
def calcProjectionExtrema(Param_Dict, ds, field): """Creates dummy projection plots to then calculate the extrema in those. Returns a ytArray of these extrema""" try: if Param_Dict["ParticlePlot"]: projPlot = yt.ParticleProjectionPlot(ds, Param_Dict["NAxis"], field) else: projPlot = yt.ProjectionPlot(ds, Param_Dict["NAxis"], field) except yt.utilities.exceptions.YTFieldNotFound: GUILogger.warning(f"Couldn't find {field} in the available fields") return ZMin = projPlot.frb[field].min() ZMax = projPlot.frb[field].max() return yt.YTArray([ZMin, ZMax])
def setUpWidgets(Param_Dict, CheckBox_Dict, Misc_Dict): """Formats the slider and spinner so it fits the time series given.""" slider = Misc_Dict["SeriesSlider"] length = len(Param_Dict["DataSeries"]) slider.setRange(0, length - 1) GUILogger.log( 29, f"Loaded all {length} datasets of '{str(Param_Dict['Seriesname'])}'.") GUILogger.info("They are now ready for plotting.") slider.valueChanged.emit(0) slider.show() spinner = Misc_Dict["ProfileSpinner"] spinner.setMaximum(length) spinner.setValue(1) spinner.setDisabled(False)
def annotatePlot(Param_Dict, plot): """Annotates the plot according to the selection of the user. Tutorial: https://yt-project.org/doc/visualizing/callbacks.html""" plot.annotate_title(Param_Dict["PlotTitle"]) if Param_Dict["Timestamp"]: plot.annotate_timestamp(corner='upper_left', draw_inset_box=True) if Param_Dict["Geometry"] == "cartesian": if Param_Dict["Scale"]: plot.annotate_scale(corner='upper_right') if Param_Dict["Contour"]: plot.annotate_contour(Param_Dict["ZAxis"]) if Param_Dict["VelVectors"]: plot.annotate_velocity(normalize=True) if Param_Dict["NormVecMode"] == "Axis-Aligned": if Param_Dict["Grid"]: plot.annotate_grids() issueAnnoWarning(plot, "Grids") if Param_Dict["VelStreamlines"]: issueAnnoWarning(plot, "Velocity streamlines") if Param_Dict["NAxis"] == "x": plot.annotate_streamlines("velocity_y", "velocity_z") elif Param_Dict["NAxis"] == "y": plot.annotate_streamlines("velocity_x", "velocity_z") elif Param_Dict["NAxis"] == "z": plot.annotate_streamlines("velocity_x", "velocity_y") if Param_Dict["MagVectors"]: plot.annotate_magnetic_field(normalize=True) if Param_Dict["MagStreamlines"]: issueAnnoWarning(plot, "Magnetic field streamlines") if Param_Dict["NAxis"] == "x": plot.annotate_streamlines("magy", "magz") elif Param_Dict["NAxis"] == "y": plot.annotate_streamlines("magx", "magz") elif Param_Dict["NAxis"] == "z": plot.annotate_streamlines("magx", "magy") if Param_Dict["ParticleAnno"] and not Param_Dict["ParticlePlot"]: if Param_Dict["PSlabWidth"] == "" or float(Param_Dict["PSlabWidth"]) == 0: Param_Dict["PSlabWidth"] = 1 height = abs(Param_Dict["FieldMins"]["DomainHeight"] - Param_Dict["FieldMaxs"]["DomainHeight"]) if Param_Dict["Zoom"] == 1: GUILogger.warning("When annotating particles, you may need a " "zoom above 1 for proper annotations") plot.annotate_particles(float(Param_Dict["PSlabWidth"])*height, p_size=3.0) elif Param_Dict["Geometry"] == "cylindrical": if Param_Dict["Grid"]: plot.annotate_grids()
def loadFile(self, filename): """Handles loading a given file filename. Also changes the current working directory self.Param_Dict["Directory"]. Parameters: filename: path of the file to load returns: ds: yt DataSet object """ # Perform a reverse split to receive the directory and name separately directory, name = filename.rsplit('/', 1) self.Status_Dict["Dir"].setText(directory) self.Status_Dict["File"].setText('File: ' + name) self.Param_Dict["Directory"] = directory ds = yt.load(filename) GUILogger.info(f"Loading file '{name}'...") return ds
def startLine(self): """Initiates LineDrawing in Canvas""" # Enables the information receival from plot GUILogger.info("Ready to draw a line on the plot.") GUILogger.log(29, "Just <b>press and release left click</b> on top of the plot.") toolbar = self.Param_Dict["CurrentPlotWindow"].toolbar toolbar._active = "ZOOM" # This will set the cross toolbar._actions["pan"].setChecked(False) toolbar._actions["zoom"].setChecked(False) if toolbar._idPress is not None: toolbar._idPress = toolbar.canvas.mpl_disconnect(toolbar._idPress) if toolbar._idRelease is not None: toolbar._idRelease = toolbar.canvas.mpl_disconnect(toolbar._idRelease) toolbar.mode = '' self.Edit_Dict["LineUnit"].setText(self.Param_Dict["oldGridUnit"]) self.Starter = self.Param_Dict["CurrentPlotWindow"].canvas.mpl_connect('button_press_event', self.lStartInput) self.Ender = self.Param_Dict["CurrentPlotWindow"].canvas.mpl_connect('button_release_event', self.lEndInput)
def __init__(self, Param_Dict, axis, parent): super().__init__(parent=parent) GUILogger.info("Do you want to calculate the global extrema?") self.length = len(Param_Dict["DataSeries"]) self.axis = axis self.Param_Dict = Param_Dict self.setWindowFlags(QC.Qt.Window | QC.Qt.CustomizeWindowHint | QC.Qt.WindowTitleHint | QC.Qt.WindowMinimizeButtonHint | QC.Qt.WindowMaximizeButtonHint | QC.Qt.WindowCloseButtonHint) self.setModal(True) # This way, the user can't interact with the rest self.initUi() self.signalsConnection() self.resize(200, 100) self.setWindowIcon(QG.QIcon('simgui_registry/CoverIcon.png')) self.setWindowTitle("Options for extrema calculation") self.show()
def lEndInput(self, event): """Handles the mouseButtonReleases and passes them to simul_utils""" sut.getCoordInput(self.Param_Dict, event, "end") self.Param_Dict["CurrentPlotWindow"].canvas.mpl_disconnect(self.cid) sut.shuffleCoords(self.Param_Dict) sut.changeToLinePlot(self.Param_Dict, self.Edit_Dict) self.RadioDict_Dict["1DOptions"]["Line"].setChecked(True) self.RadioDict_Dict["DimMode"]["1D"].setChecked(True) self.ComboBox_Dict["YAxis"].setCurrentText(self.Param_Dict["ZAxis"]) self.Edit_Dict["YUnit"].setText(self.Param_Dict["ZUnit"]) self.Edit_Dict["YMin"].setText(f"{self.Param_Dict['ZMin']:.3g}") self.Edit_Dict["YMax"].setText(f"{self.Param_Dict['ZMax']:.3g}") self.CheckBox_Dict["YLog"].setChecked(self.Param_Dict["ZLog"]) self.Param_Dict["YLog"] = self.Param_Dict["ZLog"] self.Param_Dict["CurrentPlotWindow"].canvas.mpl_disconnect(self.Ender) GUILogger.log(29, "Line inputs have been updated. Press 'Create Plot' to make the line plot.") toolbar = self.Param_Dict["CurrentPlotWindow"].toolbar toolbar._active = None
def ProfilePlot(Param_Dict, worker): """Takes a DataSet object loaded with yt and performs a ProfilePlot with fields on it. Parameters: Param_Dict: Dict with Parameters """ if Param_Dict["XAxis"] == "time": arr, labels = createProfWithTimeForX(Param_Dict, worker) elif Param_Dict["TimeSeriesProf"]: arr, labels = createMultipleProfiles(Param_Dict, worker) else: arr, labels = createNormalProfile(Param_Dict) if Param_Dict["WeightField"] is None and Param_Dict["XAxis"] != "time": GUILogger.warning('Having <b><font color="DarkViolet">None</font></b> ' "as the weight field just accumulates, " "so the extrema might be inaccurate.") Canvas = Param_Dict["CurrentPlotWindow"] Canvas.makeProfilePlot(Param_Dict, arr, labels, worker)
def __init__(self, Param_Dict): super().__init__() GUILogger.warn( "Do you really want to plot the files with these settings?") self.length = len(Param_Dict["DataSeries"]) self.setWindowFlags(QC.Qt.Window | QC.Qt.CustomizeWindowHint | QC.Qt.WindowTitleHint | QC.Qt.WindowMinimizeButtonHint | QC.Qt.WindowMaximizeButtonHint | QC.Qt.WindowCloseButtonHint) self.plotNumber = self.length self.onlyEvery = 1 self.makeMovie = False self.setModal(True) # This way, the user can't interact with the rest self.initUi() self.signalsConnection() self.resize(400, 300) self.setWindowIcon(QG.QIcon('simgui_registry/CoverIcon.png')) self.setWindowTitle("Options for plotting every file") self.show()
def setUpFile(self, testmode=""): """When the file is given, make it ready for evaluation by updating the fields for the axes and calculating their min and maxes. Parameters: testmode: argument given when called through the buttons to test """ if self.Param_Dict["isValidFile"]: self.Param_Dict["SignalHandler"].changeEvalMode() self.Button_Dict["MakeLinePlot"].hide() GUILogger.info("Scanning file for relevant fields...") # Update Geometry and hide the widgets that would cause errors sut.updateGeometry(self.Param_Dict, self.CheckBox_Dict, self.RadioDict_Dict, self.Edit_Dict, self.Label_Dict) # Update the comboBoxes according to entries in field lists try: sut.updateFields(self.Param_Dict, self.ComboBox_Dict) except Exception: return sut.resetExtrema(self.Param_Dict, self.Edit_Dict, self.Button_Dict, self.Label_Dict, self.ComboBox_Dict, self) self.Param_Dict["SignalHandler"].getOtherUnitInput("Grid") self.Param_Dict["SignalHandler"].setPlotOptions() updateLabels(self.Param_Dict, self.Label_Dict) GUILogger.log(29, f"Loaded '{self.Param_Dict['Filename'].split('/')[-1]}'.") GUILogger.info("It is now ready for plotting.") sut.refreshWidgets(self.Edit_Dict, self.ComboBox_Dict)
def updateFields(Param_Dict, ComboBox_Dict): """Updates ComboBoxes with the current fields used Parameters: Param_Dict: For the current field lists Box_Dict: Dictionary for ComboBoxes """ QW.QApplication.setOverrideCursor(QC.Qt.WaitCursor) ds = Param_Dict["CurrentDataSet"] Param_Dict["WeightFields"] = ["None", "cell_mass", "dens", "temp"] try: point = ds.point([0, 0, 0]) # sampling point for i in sorted(ds.derived_field_list): # in derived field lists, all of the entries are sorted in separate # lists: [['gas', 'dens'], ['gas', 'dens']] etc. if i[0] == 'gas': for axis in ["X", "Y", "Z", "Weight"]: Param_Dict[axis + "Fields"].append(i[1]) if i[0] == 'io': shape = point[i].shape if not (len(shape) > 1 and shape[1] > 1): Param_Dict["ParticleFields"].append(i[1]) except Exception as e: GUILogger.critical("An error occured while trying to load in " f"the fields: <b>{e}</b>.") GUILogger.critical("The reason may be a derived field with " "unknown dependencies. You may need to " "restart the application. If you're running" " python from an iPython console, you even " " need to restart this. Sorry.") raise Exception try: Param_Dict["ParticleFields"].remove("mesh_id") except ValueError: pass updateNormalAxis(Param_Dict, ComboBox_Dict) updateComboBoxes(Param_Dict, ComboBox_Dict) QW.QApplication.restoreOverrideCursor()
def readOutExtrema(self): """Reads out the current constraints of x- and y-axis and stores them before restoring them to the gui""" mode = self.Param_Dict["PlotMode"] xmin, xmax = self.ax.get_xlim() ymin, ymax = self.ax.get_ylim() if mode in ["Profile", "Phase"]: self.Param_Dict["XMin"] = xmin self.Param_Dict["XMax"] = xmax if mode in ["Profile", "Phase", "Line"]: self.Param_Dict["YMin"] = ymin self.Param_Dict["YMax"] = ymax if mode in ["Slice", "Projection"]: self.Param_Dict["HorWidth"] = abs(xmin-xmax) self.Param_Dict["VerWidth"] = abs(ymin-ymax) self.Param_Dict["Zoom"] = 1.0 aligned = self.Param_Dict["NormVecMode"] == "Axis-Aligned" cart = self.Param_Dict["Geometry"] == "cartesian" if cart or self.Param_Dict["NAxis"] == "theta" and aligned: horCen = mean([xmin, xmax]) verCen = mean([ymin, ymax]) if self.Param_Dict["NAxis"] == "theta": n = 2 else: n = ["x", "y", "z"].index(self.Param_Dict["NAxis"]) horAxis = ["X", "Y", "Z"][convertToLessThanThree(n+1)] verAxis = ["X", "Y", "Z"][convertToLessThanThree(n+2)] self.Param_Dict[horAxis + "Center"] = horCen self.Param_Dict[verAxis + "Center"] = verCen elif not aligned: GUILogger.warning("For off-axis plots, setting the center " "coordinates is not supported.") else: GUILogger.warning("Reading out the center coordinates is not " "supported for having " f"{self.Param_Dict['NAxis']} as normal axis." "This may produce weird behaviour.")
def evaluateSingle(self): """Passes the evaluation of data to a ProgressDialog""" if self.Param_Dict["EvalMode"] == "Single" and not self.Param_Dict["isValidFile"]: GUILogger.error("Evaluation stopped. Please open valid file first.") return if self.Param_Dict["EvalMode"] == "Series" and not self.Param_Dict["isValidSeries"]: GUILogger.error("Evaluation stopped. Please open valid directory " "first and enter valid series name.") return GUILogger.info("Evaluation started. Checking for missing extrema...") sut.checkExtremaForPlot(self.Param_Dict) self.progressDialog = ProgressDialog(self.Param_Dict, self, mode="PlotSingle") self.progressWorker.finished.connect(self.giveSingleFeedback)
def createProfWithTimeForX(Param_Dict, worker): """Make a profile plot having the time as the x-Axis. Parameters: Param_Dict: For the fields and DataSets to be plotted. Returns: arr: list containing two YTArrays having the time as the first and the y-field as second entry """ GUILogger.info("This may take some...time...") ts = Param_Dict["DataSeries"] timeMin = Param_Dict["XMin"] # they should already be converted to xunit. timeMax = Param_Dict["XMax"] times = [] datasets = [] emitStatus(worker, "Gathering time data") for ds in ts: # use the times we have already calculated for each dataset time = Param_Dict["DataSetDict"][str(ds) + "Time"].to_value(Param_Dict["XUnit"]) timecompare = float("{:.3g}".format(time)) if timeMin <= timecompare <= timeMax: times.append(time) datasets.append(str(ds)) GUILogger.log(29, "Iterating over the whole series from {:.3g} to {:.3g} {}..." .format(timeMin, timeMax, Param_Dict["XUnit"])) calcQuan = getCalcQuanName(Param_Dict) field = Param_Dict["YAxis"] calcQuanString = getCalcQuanString(Param_Dict) storage = {} i = 0 length = len(times) if Param_Dict["YAxis"] in Param_Dict["NewDerFieldDict"].keys(): for ds in ts: if str(ds) in datasets: try: yResult = Param_Dict["DataSetDict"][str(ds) + field + calcQuan] except KeyError: ad = ds.all_data() yResult = eval(calcQuanString) # save the plotpoints for later use value = yt.YTQuantity(yResult, Param_Dict["YUnit"]).to_value(Param_Dict["FieldUnits"][field]) Param_Dict["DataSetDict"][str(ds) + field + calcQuan] = value storage[str(i)] = yResult # this is kind of clunky, but this way we don't run into problems later i += 1 progString = f"{i}/{length} data points calculated" emitStatus(worker, progString) if i % ceil(length/10) == 0: # maximum of 10 updates GUILogger.info(f"Progress: {progString}.") else: # We want to use parallel iteration if possible yt.enable_parallelism(suppress_logging=True) newTS = yt.load(Param_Dict["Directory"] + "/" + Param_Dict["Seriesname"]) for store, ds in newTS.piter(storage=storage): try: yResult = Param_Dict["DataSetDict"][str(ds) + field + calcQuan] except KeyError: ad = ds.all_data() # This is needed for the following command yResult = eval(calcQuanString) # save the plotpoints for later use value = yt.YTQuantity(yResult, Param_Dict["YUnit"]).to_value(Param_Dict["FieldUnits"][field]) Param_Dict["DataSetDict"][str(ds) + field + calcQuan] = value store.result = yResult i += 1 progString = f"{i}/{length} data points calculated" emitStatus(worker, progString) if i % ceil(length/10) == 0: # maximum of 10 updates GUILogger.info(f"Progress: {progString}.") labels = [field] # Convert the storage dictionary values to an array, so they can be # easily plotted arr_x = yt.YTArray(times, Param_Dict["XUnit"]) arr_y = yt.YTArray(list(storage.values()), Param_Dict["YUnit"]) arr = [arr_x, arr_y] # print(arr) return arr, labels