From 645c99a9b6d7ad58f450d3010c1a286ee54596de Mon Sep 17 00:00:00 2001 From: BHT Date: Wed, 20 Aug 2025 17:09:58 -0500 Subject: [PATCH 01/12] Create stub routines for export to Cinema: Debye-Scherrer plotting routine --- GSASII/GSASIIdataGUI.py | 6 ++++ GSASII/GSASIIseqGUI.py | 65 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/GSASII/GSASIIdataGUI.py b/GSASII/GSASIIdataGUI.py index 55ad846d6..7c45fefa3 100644 --- a/GSASII/GSASIIdataGUI.py +++ b/GSASII/GSASIIdataGUI.py @@ -6637,6 +6637,9 @@ def _makemenu(): # routine to create menu when first used if lbl == 'Project': submenu.Append(G2G.wxID_XPORTSEQFCIF,'... as full CIF', 'Save all sequential refinement results as a CIF file') + G2G.Define_wxId('wxID_XPORTCINEMA') + submenu.Append(G2G.wxID_XPORTCINEMA,'... to CINEMA: DS', + 'Pass sequential refinement results for plotting in CINEMA: Debye-Scherrer') for obj in objlist: item = submenu.Append(wx.ID_ANY,obj.formatName,obj.longFormatName) self.SeqExportLookup[item.GetId()] = (obj,lbl) # lookup table for submenu item @@ -6644,6 +6647,9 @@ def _makemenu(): # routine to create menu when first used self.SequentialEx.Append(G2G.wxID_XPORTSEQCSV,'Save table as CSV', 'Save all sequential refinement results as a CSV spreadsheet file') + G2G.Define_wxId('wxID_XPORTSEQIMG') + self.SequentialEx.Append(G2G.wxID_XPORTSEQIMG,'Save histogram images', + 'Save all sequential refinements as a series of images') self.PostfillDataMenu() SetDataMenuBar(G2frame,self.SequentialMenu) self.SequentialMenu = _makemenu diff --git a/GSASII/GSASIIseqGUI.py b/GSASII/GSASIIseqGUI.py index bbe1abb6e..71248efd5 100644 --- a/GSASII/GSASIIseqGUI.py +++ b/GSASII/GSASIIseqGUI.py @@ -256,6 +256,37 @@ def OnSaveSelSeqCSV(event): 'export the selected columns to a .csv file from menu command' OnSaveSelSeq(event,csv=True) + def OnSaveCinema(event): + '''This is a placeholder routine for exporting file(s) to + run Cinema: Debye-Scherrer + https://github.com/cinemascience/cinema_debye_scherrer + (https://journals.iucr.org/j/issues/2018/03/00/ks5597/ks5597.pdf) + ''' + breakpoint() + pass + + def OnSaveSeqImg(event): + 'export plots from all rows, called from menu command' + # save currently selected row, if any + prevSelected = G2frame.dataDisplay.GetSelectedRows() + # location for output files + import tempfile + tmpdir = tempfile.mkdtemp() + def cleanup(): + '''cleanup is a routine to be called to delete the directory + with the files created here. Call this to clean up + after using or copying the files created here.''' + import shutil + shutil.rmtree(tmpdir) + res = ExportSequentialImages(G2frame,histNames,tmpdir,100) + # reset the selection and replot + for row in prevSelected: # expect this to be length 0 or 1 + G2frame.dataDisplay.SelectRow(row) + PlotSelectedColRow('left') + break + #breakpoint() + cleanup() + def OnSaveSeqCSV(event): 'export all columns to a .csv file from menu command' OnSaveSelSeq(event,csv=True,allcols=True) @@ -1124,6 +1155,8 @@ def OnEditSelectPhaseVars(event): G2frame.Bind(wx.EVT_MENU, DoSequentialExport, id=id) G2frame.Bind(wx.EVT_MENU, OnSaveSeqCSV, id=G2G.wxID_XPORTSEQCSV) G2frame.Bind(wx.EVT_MENU, DoSequentialExport, id=G2G.wxID_XPORTSEQFCIF) + G2frame.Bind(wx.EVT_MENU, OnSaveSeqImg, id=G2G.wxID_XPORTSEQIMG) + G2frame.Bind(wx.EVT_MENU, OnSaveCinema, id=G2G.wxID_XPORTCINEMA) EnablePseudoVarMenus() EnableParFitEqMenus() @@ -2106,3 +2139,35 @@ def OnSelection(event): G2frame.dataWindow.SetSizer(bigSizer) G2frame.dataWindow.SetDataSize() G2frame.SendSizeEvent() + +def ExportSequentialImages(G2frame,histNames,outdir,dpi='figure'): + '''Used to create plot images as PNG for each fit in the sequential results + table in images are created in a temporary directory. + For PWDR entries only. + + :param wx.Frame G2frame: reference to main GSAS-II frame + :param list histNames: a list of the tree name entries + corresponding to each row in the table + :param str outdir: Name of a directory (path). Files created by + this routine are placed here. + :param int dpi: dots per inch for the output. Defaults to the + screen resolution + :returns: a list of the files created by this routine + ''' + import os + files = [] + for i in range(G2frame.dataDisplay.GetNumberRows()): + G2frame.dataDisplay.SelectRow(i) + name = histNames[i] #only does 1st one selected + if name.startswith('PWDR'): + # plot a powder pattern and reset tree selection + pickId = G2frame.PickId + G2frame.PickId = G2frame.PatternId = G2gd.GetGPXtreeItemId(G2frame, G2frame.root, name) + G2pwpl.PlotPatterns(G2frame,newPlot=False,plotType='PWDR') + G2frame.PickId = pickId + wx.GetApp().Yield() + new,plotNum,Page,Plot,limits = G2frame.G2plotNB.FindPlotTab('Powder Patterns','mpl',False) + f = os.path.join(outdir,f'{i}.png') + files.append(f) + Plot.figure.savefig(f,dpi=dpi) + return files From 103bc309b7826c62c0ab27cacb1b4437b38f331d Mon Sep 17 00:00:00 2001 From: Andrew Kuncevich Date: Wed, 27 Aug 2025 14:09:22 +0300 Subject: [PATCH 02/12] issue-11 MVP Cinema integration version --- GSASII/GSASIIseqGUI.py | 155 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 3 deletions(-) diff --git a/GSASII/GSASIIseqGUI.py b/GSASII/GSASIIseqGUI.py index 71248efd5..1242182a3 100644 --- a/GSASII/GSASIIseqGUI.py +++ b/GSASII/GSASIIseqGUI.py @@ -7,6 +7,7 @@ import platform import copy import re +import os import numpy as np import numpy.ma as ma import numpy.linalg as nl @@ -262,8 +263,155 @@ def OnSaveCinema(event): https://github.com/cinemascience/cinema_debye_scherrer (https://journals.iucr.org/j/issues/2018/03/00/ks5597/ks5597.pdf) ''' - breakpoint() - pass + + def show_project_dialog(): + dialog = wx.MessageDialog( + None, + "Continue with current Cinema project or create a new one?", + "Project Selection", + wx.OK | wx.CANCEL | wx.ICON_QUESTION + ) + dialog.SetOKCancelLabels("Continue", "New Project") + + result = dialog.ShowModal() + dialog.Destroy() + + if result == wx.ID_OK: + return True + else: + return False + + colLabels = G2frame.seqResults_colLabels + table_data = G2frame.SeqTable.GetData() + nRows=len(table_data) + + dialogDir = wx.DirDialog( + None, + message="Select Cinema directory containing index.html", # Dialog title + defaultPath="", # Initial directory (empty = current) + style=wx.DD_DEFAULT_STYLE # Dialog style + ) + + if dialogDir.ShowModal() == wx.ID_OK: + selected_dir = dialogDir.GetPath() # Get selected directory + dialogDir.Destroy() + + # Work with Cinema json file + import json + db_directory = None + if show_project_dialog(): + # Actions when continuing work with the current project + dialogDirOfProjectDB = wx.DirDialog( + None, + message="Select directory containing project data - data.csv", # Dialog title + defaultPath="", # Initial directory (empty = current) + style=wx.DD_DEFAULT_STYLE # Dialog style + ) + if dialogDirOfProjectDB.ShowModal() == wx.ID_OK: + db_directory = dialogDirOfProjectDB.GetPath() + + dialogDirOfProjectDB.Destroy() + file_path = os.path.join(db_directory, "data.csv") + + else: + # Actions when creating a new project + json_path = os.path.join(selected_dir, 'databases.json') + + dlg = wx.Dialog(None, title="New Project Parameters", size=(400, 200)) + panel = wx.Panel(dlg) + main_sizer = wx.BoxSizer(wx.VERTICAL) + + # Flexible grid layout (2 columns, 2 rows, 5px spacing) + grid_sizer = wx.FlexGridSizer(2, 2, 5, 5) + grid_sizer.AddGrowableCol(1) + + # Project name field + name_label = wx.StaticText(panel, label="Project Name:") + name_ctrl = wx.TextCtrl(panel, value="New Project Cinema") + grid_sizer.Add(name_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + grid_sizer.Add(name_ctrl, 1, wx.EXPAND|wx.ALIGN_LEFT) + + # Database directory field + dir_label = wx.StaticText(panel, label="DB Directory: data/...") + dir_ctrl = wx.TextCtrl(panel, value="exampledb.cdb") + grid_sizer.Add(dir_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + grid_sizer.Add(dir_ctrl, 1, wx.EXPAND|wx.ALIGN_LEFT) + + main_sizer.Add(grid_sizer, 0, wx.EXPAND|wx.ALL, 10) + + # Buttons + btn_sizer = wx.BoxSizer(wx.HORIZONTAL) + btn_sizer.AddStretchSpacer(1) + btn_ok = wx.Button(panel, wx.ID_OK, "OK") + btn_cancel = wx.Button(panel, wx.ID_CANCEL, "Cancel") + btn_sizer.Add(btn_ok, 0, wx.RIGHT, 10) + btn_sizer.Add(btn_cancel, 0) + btn_sizer.AddStretchSpacer(1) + main_sizer.Add(btn_sizer, 0, wx.EXPAND|wx.ALL, 10) + + panel.SetSizer(main_sizer) + + dlg.Layout() + dlg.Centre() + + + if dlg.ShowModal() == wx.ID_OK: + project_name = name_ctrl.GetValue() + db_directory = os.path.join("data", dir_ctrl.GetValue()) + + try: + os.makedirs(os.path.join(selected_dir,db_directory), exist_ok=True) + except OSError as e: + print(f"Directory creation failed: {e}") + wx.MessageBox(f"Failed to create directory: {e}", "Error", wx.OK|wx.ICON_ERROR) + return # Terminate execution if directory creation failed + + try: + with open(json_path, 'r', encoding='utf-8') as file: + data = json.load(file) + new_entry = { + "name": project_name, + "directory": db_directory, + "smoothLines": True, + "lineOpacity": 1.0 + } + data.append(new_entry) + # rewrite data to json file + with open(json_path, 'w', encoding='utf-8') as file: + json.dump(data, file, indent=8, ensure_ascii=False) + except FileNotFoundError: + print(f"File {json_file_path} not found") + except json.JSONDecodeError: + print(f"Error reading JSON file {json_path}") + except Exception as e: + print(f"An error occurred: {e}") + + file_path = os.path.join(selected_dir, db_directory, "data.csv") + + with open(file_path, 'w', encoding='utf-8') as file: + file.write(", ".join(colLabels)) + file.write(",FILE ") + file.write("\n") + + for r in range(nRows): + file.write(", ".join(str(item) for item in table_data[r])) + file.write(",images/"+"PWDR_"+G2frame.SeqTable.rowLabels[r].replace('.', '_').replace(' ', '_')+".png") + file.write("\n") + print(f"Cinema data.csv saved at: {file_path}") + + output_dir = os.path.join(selected_dir, db_directory, "images") + try: + os.makedirs(output_dir, exist_ok=True) + except OSError as e: + print(f"images directory creation failed: {e}") + wx.MessageBox(f"Failed to create directory images: {e}", "Error", wx.OK|wx.ICON_ERROR) + return # Terminate execution if directory creation failed + + + ExportSequentialImages(G2frame,histNames,output_dir,100) + + print('Export to the Cinema completed successfully') + def OnSaveSeqImg(event): 'export plots from all rows, called from menu command' @@ -1564,6 +1712,7 @@ def OnEditSelectPhaseVars(event): G2frame.SeqTable = G2G.Table([list(cl) for cl in zip(*G2frame.colList)], # convert from columns to rows colLabels=displayLabels,rowLabels=rowLabels,types=Types) G2frame.dataDisplay.SetTable(G2frame.SeqTable, True) + G2frame.seqResults_colLabels = colLabels #need for Cinema export in OnSaveCinema() # make all Use editable all others ReadOnly for c in range(len(colLabels)): for r in range(nRows): @@ -2167,7 +2316,7 @@ def ExportSequentialImages(G2frame,histNames,outdir,dpi='figure'): G2frame.PickId = pickId wx.GetApp().Yield() new,plotNum,Page,Plot,limits = G2frame.G2plotNB.FindPlotTab('Powder Patterns','mpl',False) - f = os.path.join(outdir,f'{i}.png') + f = os.path.join(outdir,f"{histNames[i].replace('.', '_').replace(' ', '_')}.png") files.append(f) Plot.figure.savefig(f,dpi=dpi) return files From ad6deeaaa1582ec67369dd7785145474dec69e85 Mon Sep 17 00:00:00 2001 From: Andrew Kuncevich Date: Wed, 27 Aug 2025 14:51:33 +0300 Subject: [PATCH 03/12] issue-11 MVP Cinema integration version (2) --- GSASII/GSASIIseqGUI.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/GSASII/GSASIIseqGUI.py b/GSASII/GSASIIseqGUI.py index 1242182a3..20717a592 100644 --- a/GSASII/GSASIIseqGUI.py +++ b/GSASII/GSASIIseqGUI.py @@ -264,6 +264,9 @@ def OnSaveCinema(event): (https://journals.iucr.org/j/issues/2018/03/00/ks5597/ks5597.pdf) ''' + IMAGES_SUBDIR = "images" + DB_JSON_FILENAME = "databases.json" + DATA_CSV_FILENAME = "data.csv" def show_project_dialog(): dialog = wx.MessageDialog( None, @@ -285,16 +288,15 @@ def show_project_dialog(): table_data = G2frame.SeqTable.GetData() nRows=len(table_data) - dialogDir = wx.DirDialog( + with wx.DirDialog( None, message="Select Cinema directory containing index.html", # Dialog title defaultPath="", # Initial directory (empty = current) style=wx.DD_DEFAULT_STYLE # Dialog style - ) + ) as dialogDir: + if dialogDir.ShowModal() == wx.ID_OK: + selected_dir = dialogDir.GetPath() # Get selected directory - if dialogDir.ShowModal() == wx.ID_OK: - selected_dir = dialogDir.GetPath() # Get selected directory - dialogDir.Destroy() # Work with Cinema json file import json @@ -303,7 +305,7 @@ def show_project_dialog(): # Actions when continuing work with the current project dialogDirOfProjectDB = wx.DirDialog( None, - message="Select directory containing project data - data.csv", # Dialog title + message="Select directory containing project data - {DATA_CSV_FILENAME}", # Dialog title defaultPath="", # Initial directory (empty = current) style=wx.DD_DEFAULT_STYLE # Dialog style ) @@ -311,11 +313,11 @@ def show_project_dialog(): db_directory = dialogDirOfProjectDB.GetPath() dialogDirOfProjectDB.Destroy() - file_path = os.path.join(db_directory, "data.csv") + file_path = os.path.join(db_directory, DATA_CSV_FILENAME) else: # Actions when creating a new project - json_path = os.path.join(selected_dir, 'databases.json') + json_path = os.path.join(selected_dir, DB_JSON_FILENAME) dlg = wx.Dialog(None, title="New Project Parameters", size=(400, 200)) panel = wx.Panel(dlg) @@ -380,13 +382,13 @@ def show_project_dialog(): with open(json_path, 'w', encoding='utf-8') as file: json.dump(data, file, indent=8, ensure_ascii=False) except FileNotFoundError: - print(f"File {json_file_path} not found") + print(f"File {json_path} not found") except json.JSONDecodeError: print(f"Error reading JSON file {json_path}") except Exception as e: print(f"An error occurred: {e}") - file_path = os.path.join(selected_dir, db_directory, "data.csv") + file_path = os.path.join(selected_dir, db_directory, DATA_CSV_FILENAME) with open(file_path, 'w', encoding='utf-8') as file: file.write(", ".join(colLabels)) @@ -395,11 +397,11 @@ def show_project_dialog(): for r in range(nRows): file.write(", ".join(str(item) for item in table_data[r])) - file.write(",images/"+"PWDR_"+G2frame.SeqTable.rowLabels[r].replace('.', '_').replace(' ', '_')+".png") + file.write("," + IMAGES_SUBDIR + "/PWDR_" + G2frame.SeqTable.rowLabels[r].replace('.', '_').replace(' ', '_') + ".png") file.write("\n") - print(f"Cinema data.csv saved at: {file_path}") + print(f"Cinema {DATA_CSV_FILENAME} saved at: {file_path}") - output_dir = os.path.join(selected_dir, db_directory, "images") + output_dir = os.path.join(selected_dir, db_directory, IMAGES_SUBDIR) try: os.makedirs(output_dir, exist_ok=True) except OSError as e: From 6916f3cc33257233c73e13b76d30ed24f0e2ace9 Mon Sep 17 00:00:00 2001 From: BHT Date: Sun, 31 Aug 2025 16:50:18 -0500 Subject: [PATCH 04/12] make sure dialogs are destroyed; exit when Cancel is pressed; don't use keyword 'file' --- GSASII/GSASIIseqGUI.py | 54 +++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/GSASII/GSASIIseqGUI.py b/GSASII/GSASIIseqGUI.py index 20717a592..bb50c64fd 100644 --- a/GSASII/GSASIIseqGUI.py +++ b/GSASII/GSASIIseqGUI.py @@ -258,8 +258,7 @@ def OnSaveSelSeqCSV(event): OnSaveSelSeq(event,csv=True) def OnSaveCinema(event): - '''This is a placeholder routine for exporting file(s) to - run Cinema: Debye-Scherrer + '''This routine exports file(s) to run Cinema: Debye-Scherrer https://github.com/cinemascience/cinema_debye_scherrer (https://journals.iucr.org/j/issues/2018/03/00/ks5597/ks5597.pdf) ''' @@ -294,9 +293,12 @@ def show_project_dialog(): defaultPath="", # Initial directory (empty = current) style=wx.DD_DEFAULT_STYLE # Dialog style ) as dialogDir: - if dialogDir.ShowModal() == wx.ID_OK: + res = dialogDir.ShowModal() + dialogDir.Destroy() + if res == wx.ID_OK: selected_dir = dialogDir.GetPath() # Get selected directory - + else: + return # Work with Cinema json file import json @@ -305,14 +307,16 @@ def show_project_dialog(): # Actions when continuing work with the current project dialogDirOfProjectDB = wx.DirDialog( None, - message="Select directory containing project data - {DATA_CSV_FILENAME}", # Dialog title + message=f"Select directory containing project data - {DATA_CSV_FILENAME}", # Dialog title defaultPath="", # Initial directory (empty = current) style=wx.DD_DEFAULT_STYLE # Dialog style ) - if dialogDirOfProjectDB.ShowModal() == wx.ID_OK: - db_directory = dialogDirOfProjectDB.GetPath() - + res = dialogDirOfProjectDB.ShowModal() dialogDirOfProjectDB.Destroy() + if res == wx.ID_OK: + db_directory = dialogDirOfProjectDB.GetPath() + else: + return file_path = os.path.join(db_directory, DATA_CSV_FILENAME) else: @@ -355,22 +359,25 @@ def show_project_dialog(): dlg.Layout() dlg.Centre() + res = dlg.ShowModal() + dlg.Destroy() - - if dlg.ShowModal() == wx.ID_OK: + if res == wx.ID_OK: project_name = name_ctrl.GetValue() db_directory = os.path.join("data", dir_ctrl.GetValue()) try: os.makedirs(os.path.join(selected_dir,db_directory), exist_ok=True) except OSError as e: - print(f"Directory creation failed: {e}") + print(f"Directory creation failed: {e}") wx.MessageBox(f"Failed to create directory: {e}", "Error", wx.OK|wx.ICON_ERROR) return # Terminate execution if directory creation failed + else: + return try: - with open(json_path, 'r', encoding='utf-8') as file: - data = json.load(file) + with open(json_path, 'r', encoding='utf-8') as fil: + data = json.load(fil) new_entry = { "name": project_name, "directory": db_directory, @@ -390,30 +397,27 @@ def show_project_dialog(): file_path = os.path.join(selected_dir, db_directory, DATA_CSV_FILENAME) - with open(file_path, 'w', encoding='utf-8') as file: - file.write(", ".join(colLabels)) - file.write(",FILE ") - file.write("\n") + with open(file_path, 'w', encoding='utf-8') as fil: + fil.write(", ".join(colLabels)) + fil.write(",FILE ") + fil.write("\n") for r in range(nRows): - file.write(", ".join(str(item) for item in table_data[r])) - file.write("," + IMAGES_SUBDIR + "/PWDR_" + G2frame.SeqTable.rowLabels[r].replace('.', '_').replace(' ', '_') + ".png") - file.write("\n") + fil.write(", ".join(str(item) for item in table_data[r])) + fil.write("," + IMAGES_SUBDIR + "/PWDR_" + G2frame.SeqTable.rowLabels[r].replace('.', '_').replace(' ', '_') + ".png") + fil.write("\n") print(f"Cinema {DATA_CSV_FILENAME} saved at: {file_path}") output_dir = os.path.join(selected_dir, db_directory, IMAGES_SUBDIR) try: os.makedirs(output_dir, exist_ok=True) except OSError as e: - print(f"images directory creation failed: {e}") + print(f"images directory creation failed: {e}") wx.MessageBox(f"Failed to create directory images: {e}", "Error", wx.OK|wx.ICON_ERROR) return # Terminate execution if directory creation failed - ExportSequentialImages(G2frame,histNames,output_dir,100) - - print('Export to the Cinema completed successfully') - + print('Export to Cinema: Debye-Scherrer completed successfully') def OnSaveSeqImg(event): 'export plots from all rows, called from menu command' From d2518b67636932023d1c445f2fabd7251d61bae3 Mon Sep 17 00:00:00 2001 From: BHT Date: Sun, 31 Aug 2025 20:48:36 -0500 Subject: [PATCH 05/12] CINEMA: export table with same # of digits as SeqTable; save install location --- GSASII/GSASIIseqGUI.py | 76 +++++++++++++++++++++++++++------------- GSASII/config_example.py | 6 ++++ 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/GSASII/GSASIIseqGUI.py b/GSASII/GSASIIseqGUI.py index bb50c64fd..7816ad0e5 100644 --- a/GSASII/GSASIIseqGUI.py +++ b/GSASII/GSASIIseqGUI.py @@ -258,7 +258,7 @@ def OnSaveSelSeqCSV(event): OnSaveSelSeq(event,csv=True) def OnSaveCinema(event): - '''This routine exports file(s) to run Cinema: Debye-Scherrer + '''This routine creates/modifies files to run Cinema: Debye-Scherrer https://github.com/cinemascience/cinema_debye_scherrer (https://journals.iucr.org/j/issues/2018/03/00/ks5597/ks5597.pdf) ''' @@ -283,22 +283,49 @@ def show_project_dialog(): else: return False - colLabels = G2frame.seqResults_colLabels - table_data = G2frame.SeqTable.GetData() - nRows=len(table_data) - - with wx.DirDialog( - None, - message="Select Cinema directory containing index.html", # Dialog title - defaultPath="", # Initial directory (empty = current) - style=wx.DD_DEFAULT_STYLE # Dialog style - ) as dialogDir: - res = dialogDir.ShowModal() - dialogDir.Destroy() - if res == wx.ID_OK: - selected_dir = dialogDir.GetPath() # Get selected directory + #colLabels = G2frame.seqResults_colLabels + #table_data = G2frame.SeqTable.GetData() + nRows=len(G2frame.SeqTable.GetData()) + colLabels = [] + colDecimals = [] + useCol = [] + for i,lbl in enumerate(G2frame.seqResults_colLabels): + typ = G2frame.SeqTable.GetTypeName(0,i) + if typ in ['long','bool']: + colDecimals.append(None) + useCol.append(False) + continue + colLabels.append(lbl) + useCol.append(True) + if ',' in typ: + colDecimals.append(typ.split(',')[1]) else: - return + colDecimals.append('6') + table_data = [] + for r in range(nRows): + row = [] + for i,val in enumerate(G2frame.SeqTable.GetData()[r]): + if not useCol[i]: continue + row.append(f"{val:.{colDecimals[i]}f}") + table_data.append(row) + # Get location where software is installed + selected_dir = GSASIIpath.GetConfigValue('CINEMA_DS_directory') + if not (selected_dir and os.path.exists(selected_dir)): + with wx.DirDialog( + None, + message="Select Cinema directory containing index.html", # Dialog title + defaultPath="", # Initial directory (empty = current) + style=wx.DD_DEFAULT_STYLE # Dialog style + ) as dialogDir: + if dialogDir.ShowModal() == wx.ID_OK: + selected_dir = dialogDir.GetPath() # Get selected directory + dialogDir.Destroy() + else: + dialogDir.Destroy() + return + GSASIIpath.SetConfigValue({'CINEMA_DS_directory':[None,selected_dir]}) + config = G2G.GetConfigValsDocs() + G2G.SaveConfigVars(config) # Work with Cinema json file import json @@ -311,11 +338,11 @@ def show_project_dialog(): defaultPath="", # Initial directory (empty = current) style=wx.DD_DEFAULT_STYLE # Dialog style ) - res = dialogDirOfProjectDB.ShowModal() - dialogDirOfProjectDB.Destroy() - if res == wx.ID_OK: + if dialogDirOfProjectDB.ShowModal() == wx.ID_OK: db_directory = dialogDirOfProjectDB.GetPath() + dialogDirOfProjectDB.Destroy() else: + dialogDirOfProjectDB.Destroy() return file_path = os.path.join(db_directory, DATA_CSV_FILENAME) @@ -323,7 +350,7 @@ def show_project_dialog(): # Actions when creating a new project json_path = os.path.join(selected_dir, DB_JSON_FILENAME) - dlg = wx.Dialog(None, title="New Project Parameters", size=(400, 200)) + dlg = wx.Dialog(None, title="New CINEMA Project Parameters", size=(400, 200)) panel = wx.Panel(dlg) main_sizer = wx.BoxSizer(wx.VERTICAL) @@ -359,12 +386,12 @@ def show_project_dialog(): dlg.Layout() dlg.Centre() - res = dlg.ShowModal() - dlg.Destroy() + dlg.CenterOnParent() - if res == wx.ID_OK: + if dlg.ShowModal() == wx.ID_OK: project_name = name_ctrl.GetValue() db_directory = os.path.join("data", dir_ctrl.GetValue()) + dlg.Destroy() try: os.makedirs(os.path.join(selected_dir,db_directory), exist_ok=True) @@ -373,6 +400,7 @@ def show_project_dialog(): wx.MessageBox(f"Failed to create directory: {e}", "Error", wx.OK|wx.ICON_ERROR) return # Terminate execution if directory creation failed else: + dlg.Destroy() return try: @@ -403,7 +431,7 @@ def show_project_dialog(): fil.write("\n") for r in range(nRows): - fil.write(", ".join(str(item) for item in table_data[r])) + fil.write(", ".join(table_data[r])) fil.write("," + IMAGES_SUBDIR + "/PWDR_" + G2frame.SeqTable.rowLabels[r].replace('.', '_').replace(' ', '_') + ".png") fil.write("\n") print(f"Cinema {DATA_CSV_FILENAME} saved at: {file_path}") diff --git a/GSASII/config_example.py b/GSASII/config_example.py index 3e7ddeb76..3f79cb2b6 100644 --- a/GSASII/config_example.py +++ b/GSASII/config_example.py @@ -337,3 +337,9 @@ is stored in a Bruker BRML file. With the default value (-1), the columns 8, 6, and 5 are tried, in that order. ''' + +CINEMA_DS_directory=None +'''Location where CINEMA: Debye-Scherrer is installed. This is the location +where the index.html file is located. If not set, if the export for this +is used, you will be asked to supply the directory, which will be saved here. +''' From bb4d2ff6be2a27b0e378ce9ccf7ba0174c9b63fc Mon Sep 17 00:00:00 2001 From: BHT Date: Sun, 31 Aug 2025 21:24:14 -0500 Subject: [PATCH 06/12] CINEMA: put file into table --- GSASII/GSASIIseqGUI.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/GSASII/GSASIIseqGUI.py b/GSASII/GSASIIseqGUI.py index 7816ad0e5..d599ebc96 100644 --- a/GSASII/GSASIIseqGUI.py +++ b/GSASII/GSASIIseqGUI.py @@ -268,25 +268,24 @@ def OnSaveCinema(event): DATA_CSV_FILENAME = "data.csv" def show_project_dialog(): dialog = wx.MessageDialog( - None, - "Continue with current Cinema project or create a new one?", + G2frame, + "Reuse previous Cinema project or create a new one?", "Project Selection", wx.OK | wx.CANCEL | wx.ICON_QUESTION ) - dialog.SetOKCancelLabels("Continue", "New Project") - + dialog.SetOKCancelLabels("Reuse", "New Project") + dialog.CenterOnParent() result = dialog.ShowModal() dialog.Destroy() - if result == wx.ID_OK: return True else: return False - #colLabels = G2frame.seqResults_colLabels - #table_data = G2frame.SeqTable.GetData() + # create a table of values from sequential table, copying + # the number of displayed digits and removing unneeded entries nRows=len(G2frame.SeqTable.GetData()) - colLabels = [] + colLabels = ['File'] colDecimals = [] useCol = [] for i,lbl in enumerate(G2frame.seqResults_colLabels): @@ -303,7 +302,7 @@ def show_project_dialog(): colDecimals.append('6') table_data = [] for r in range(nRows): - row = [] + row = [G2frame.SeqTable.GetRowLabelValue(r)] for i,val in enumerate(G2frame.SeqTable.GetData()[r]): if not useCol[i]: continue row.append(f"{val:.{colDecimals[i]}f}") @@ -350,7 +349,7 @@ def show_project_dialog(): # Actions when creating a new project json_path = os.path.join(selected_dir, DB_JSON_FILENAME) - dlg = wx.Dialog(None, title="New CINEMA Project Parameters", size=(400, 200)) + dlg = wx.Dialog(G2frame, title="New Cinema:D-S Project Parameters", size=(400, 200)) panel = wx.Panel(dlg) main_sizer = wx.BoxSizer(wx.VERTICAL) @@ -360,13 +359,13 @@ def show_project_dialog(): # Project name field name_label = wx.StaticText(panel, label="Project Name:") - name_ctrl = wx.TextCtrl(panel, value="New Project Cinema") + name_ctrl = wx.TextCtrl(panel, value="GSAS-II Cinema Export") grid_sizer.Add(name_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) grid_sizer.Add(name_ctrl, 1, wx.EXPAND|wx.ALIGN_LEFT) # Database directory field dir_label = wx.StaticText(panel, label="DB Directory: data/...") - dir_ctrl = wx.TextCtrl(panel, value="exampledb.cdb") + dir_ctrl = wx.TextCtrl(panel, value="g2db.cdb") grid_sizer.Add(dir_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) grid_sizer.Add(dir_ctrl, 1, wx.EXPAND|wx.ALIGN_LEFT) @@ -427,8 +426,7 @@ def show_project_dialog(): with open(file_path, 'w', encoding='utf-8') as fil: fil.write(", ".join(colLabels)) - fil.write(",FILE ") - fil.write("\n") + fil.write(", FILE\n") for r in range(nRows): fil.write(", ".join(table_data[r])) From 868f19b8960b9d4a8bb7ba0bc57beb0e78f20665 Mon Sep 17 00:00:00 2001 From: BHT Date: Sun, 31 Aug 2025 22:05:46 -0500 Subject: [PATCH 07/12] CINEMA: don't allow new entry when DB exists, or force selection of existing DB --- GSASII/GSASIIdataGUI.py | 2 +- GSASII/GSASIIseqGUI.py | 150 +++++++++++++++++++++------------------- 2 files changed, 81 insertions(+), 71 deletions(-) diff --git a/GSASII/GSASIIdataGUI.py b/GSASII/GSASIIdataGUI.py index 7c45fefa3..19bd3da4e 100644 --- a/GSASII/GSASIIdataGUI.py +++ b/GSASII/GSASIIdataGUI.py @@ -6638,7 +6638,7 @@ def _makemenu(): # routine to create menu when first used submenu.Append(G2G.wxID_XPORTSEQFCIF,'... as full CIF', 'Save all sequential refinement results as a CIF file') G2G.Define_wxId('wxID_XPORTCINEMA') - submenu.Append(G2G.wxID_XPORTCINEMA,'... to CINEMA: DS', + submenu.Append(G2G.wxID_XPORTCINEMA,'... to CINEMA: Debye-Scherrer', 'Pass sequential refinement results for plotting in CINEMA: Debye-Scherrer') for obj in objlist: item = submenu.Append(wx.ID_ANY,obj.formatName,obj.longFormatName) diff --git a/GSASII/GSASIIseqGUI.py b/GSASII/GSASIIseqGUI.py index d599ebc96..39bb688c5 100644 --- a/GSASII/GSASIIseqGUI.py +++ b/GSASII/GSASIIseqGUI.py @@ -329,78 +329,88 @@ def show_project_dialog(): # Work with Cinema json file import json db_directory = None - if show_project_dialog(): - # Actions when continuing work with the current project - dialogDirOfProjectDB = wx.DirDialog( - None, - message=f"Select directory containing project data - {DATA_CSV_FILENAME}", # Dialog title - defaultPath="", # Initial directory (empty = current) - style=wx.DD_DEFAULT_STYLE # Dialog style - ) - if dialogDirOfProjectDB.ShowModal() == wx.ID_OK: - db_directory = dialogDirOfProjectDB.GetPath() - dialogDirOfProjectDB.Destroy() - else: - dialogDirOfProjectDB.Destroy() - return - file_path = os.path.join(db_directory, DATA_CSV_FILENAME) - - else: - # Actions when creating a new project - json_path = os.path.join(selected_dir, DB_JSON_FILENAME) - - dlg = wx.Dialog(G2frame, title="New Cinema:D-S Project Parameters", size=(400, 200)) - panel = wx.Panel(dlg) - main_sizer = wx.BoxSizer(wx.VERTICAL) - - # Flexible grid layout (2 columns, 2 rows, 5px spacing) - grid_sizer = wx.FlexGridSizer(2, 2, 5, 5) - grid_sizer.AddGrowableCol(1) - - # Project name field - name_label = wx.StaticText(panel, label="Project Name:") - name_ctrl = wx.TextCtrl(panel, value="GSAS-II Cinema Export") - grid_sizer.Add(name_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) - grid_sizer.Add(name_ctrl, 1, wx.EXPAND|wx.ALIGN_LEFT) - - # Database directory field - dir_label = wx.StaticText(panel, label="DB Directory: data/...") - dir_ctrl = wx.TextCtrl(panel, value="g2db.cdb") - grid_sizer.Add(dir_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) - grid_sizer.Add(dir_ctrl, 1, wx.EXPAND|wx.ALIGN_LEFT) - - main_sizer.Add(grid_sizer, 0, wx.EXPAND|wx.ALL, 10) - - # Buttons - btn_sizer = wx.BoxSizer(wx.HORIZONTAL) - btn_sizer.AddStretchSpacer(1) - btn_ok = wx.Button(panel, wx.ID_OK, "OK") - btn_cancel = wx.Button(panel, wx.ID_CANCEL, "Cancel") - btn_sizer.Add(btn_ok, 0, wx.RIGHT, 10) - btn_sizer.Add(btn_cancel, 0) - btn_sizer.AddStretchSpacer(1) - main_sizer.Add(btn_sizer, 0, wx.EXPAND|wx.ALL, 10) - - panel.SetSizer(main_sizer) - - dlg.Layout() - dlg.Centre() - dlg.CenterOnParent() - - if dlg.ShowModal() == wx.ID_OK: - project_name = name_ctrl.GetValue() - db_directory = os.path.join("data", dir_ctrl.GetValue()) - dlg.Destroy() + Repeat = True + while Repeat: + Repeat = False + if show_project_dialog(): + # Actions when continuing work with a previous project + import glob + f1 = os.path.join('data','*',DATA_CSV_FILENAME) + choices = [os.path.split(i)[0] for i in glob.glob(f1,root_dir=selected_dir)] + dlg = G2G.G2SingleChoiceDialog(G2frame, + 'Select previously used location', + 'Select directory',choices) + dlg.CenterOnParent() + if dlg.ShowModal() == wx.ID_OK: + val = choices[dlg.GetSelection()] + db_directory = os.path.join(selected_dir,val) + dlg.Destroy() + else: + dlg.Destroy() + return + file_path = os.path.join(db_directory, DATA_CSV_FILENAME) - try: - os.makedirs(os.path.join(selected_dir,db_directory), exist_ok=True) - except OSError as e: - print(f"Directory creation failed: {e}") - wx.MessageBox(f"Failed to create directory: {e}", "Error", wx.OK|wx.ICON_ERROR) - return # Terminate execution if directory creation failed else: - dlg.Destroy() - return + # Actions when creating a new project + json_path = os.path.join(selected_dir, DB_JSON_FILENAME) + + dlg = wx.Dialog(G2frame, title="New Cinema:D-S Project", size=(400, 200)) + panel = wx.Panel(dlg) + main_sizer = wx.BoxSizer(wx.VERTICAL) + + # Flexible grid layout (2 columns, 2 rows, 5px spacing) + grid_sizer = wx.FlexGridSizer(2, 2, 5, 5) + grid_sizer.AddGrowableCol(1) + + # Project name field + name_label = wx.StaticText(panel, label="Project Name:") + name_ctrl = wx.TextCtrl(panel, value="GSAS-II Cinema Export") + grid_sizer.Add(name_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + grid_sizer.Add(name_ctrl, 1, wx.EXPAND|wx.ALIGN_LEFT) + + # Database directory field + dir_label = wx.StaticText(panel, label="DB Directory: data/...") + dir_ctrl = wx.TextCtrl(panel, value="g2db.cdb") + grid_sizer.Add(dir_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + grid_sizer.Add(dir_ctrl, 1, wx.EXPAND|wx.ALIGN_LEFT) + + main_sizer.Add(grid_sizer, 0, wx.EXPAND|wx.ALL, 10) + + # Buttons + btn_sizer = wx.BoxSizer(wx.HORIZONTAL) + btn_sizer.AddStretchSpacer(1) + btn_ok = wx.Button(panel, wx.ID_OK, "OK") + btn_ok.SetDefault() + btn_cancel = wx.Button(panel, wx.ID_CANCEL, "Cancel") + btn_sizer.Add(btn_ok, 0, wx.RIGHT, 10) + btn_sizer.Add(btn_cancel, 0) + btn_sizer.AddStretchSpacer(1) + main_sizer.Add(btn_sizer, 0, wx.EXPAND|wx.ALL, 10) + + panel.SetSizer(main_sizer) + main_sizer.Fit(dlg) + dlg.CenterOnParent() + + if dlg.ShowModal() == wx.ID_OK: + project_name = name_ctrl.GetValue() + db_directory = os.path.join("data", dir_ctrl.GetValue()) + dlg.Destroy() + new_loc = os.path.join(selected_dir,db_directory) + if os.path.exists(new_loc): + G2G.G2MessageBox(G2frame, + f'This file has already been created, specify a new DB directory or reuse {dir_ctrl.GetValue()}', + 'In use') + Repeat = True + continue + try: + os.makedirs(new_loc, exist_ok=True) + except OSError as e: + print(f"Directory creation failed: {e}") + wx.MessageBox(f"Failed to create directory: {e}", "Error", wx.OK|wx.ICON_ERROR) + return # Terminate execution if directory creation failed + else: + dlg.Destroy() + return try: with open(json_path, 'r', encoding='utf-8') as fil: From eda27d1d5d7dc9b2b45ac96bb54a7ef48f0be6ac Mon Sep 17 00:00:00 2001 From: BHT Date: Mon, 1 Sep 2025 08:05:10 -0500 Subject: [PATCH 08/12] add check to see that index.html is in required location --- GSASII/GSASIIseqGUI.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/GSASII/GSASIIseqGUI.py b/GSASII/GSASIIseqGUI.py index 39bb688c5..990edb740 100644 --- a/GSASII/GSASIIseqGUI.py +++ b/GSASII/GSASIIseqGUI.py @@ -307,22 +307,36 @@ def show_project_dialog(): if not useCol[i]: continue row.append(f"{val:.{colDecimals[i]}f}") table_data.append(row) - # Get location where software is installed + + # Get location where Cinema software is installed + # must have the index.html file selected_dir = GSASIIpath.GetConfigValue('CINEMA_DS_directory') - if not (selected_dir and os.path.exists(selected_dir)): + while ((selected_dir is None) or (not os.path.exists(selected_dir)) + or (not os.path.exists(os.path.join(selected_dir,'index.html'))) + ): with wx.DirDialog( - None, + G2frame, message="Select Cinema directory containing index.html", # Dialog title defaultPath="", # Initial directory (empty = current) style=wx.DD_DEFAULT_STYLE # Dialog style ) as dialogDir: + dialogDir.CenterOnParent() if dialogDir.ShowModal() == wx.ID_OK: - selected_dir = dialogDir.GetPath() # Get selected directory + selected_dir = dialogDir.GetPath() dialogDir.Destroy() else: dialogDir.Destroy() + print('Cancelling Cinema export') return - GSASIIpath.SetConfigValue({'CINEMA_DS_directory':[None,selected_dir]}) + if not (os.path.exists(selected_dir) and + os.path.exists(os.path.join(selected_dir,'index.html'))): + G2G.G2MessageBox(G2frame, + f'Directory {selected_dir!r} does not exist or '+ + 'does not contain an index.html file. Try again', + 'Invalid location') + continue # don't save if not valid + GSASIIpath.SetConfigValue({'CINEMA_DS_directory': + [None,selected_dir]}) config = G2G.GetConfigValsDocs() G2G.SaveConfigVars(config) @@ -347,6 +361,7 @@ def show_project_dialog(): dlg.Destroy() else: dlg.Destroy() + print('Cancelling Cinema export') return file_path = os.path.join(db_directory, DATA_CSV_FILENAME) @@ -410,6 +425,7 @@ def show_project_dialog(): return # Terminate execution if directory creation failed else: dlg.Destroy() + print('Cancelling Cinema export') return try: @@ -2333,8 +2349,9 @@ def OnSelection(event): def ExportSequentialImages(G2frame,histNames,outdir,dpi='figure'): '''Used to create plot images as PNG for each fit in the sequential results - table in images are created in a temporary directory. + table. For PWDR entries only. + Used in Cinema: D-S to create refinement thumbnails. :param wx.Frame G2frame: reference to main GSAS-II frame :param list histNames: a list of the tree name entries From 6d8e2b47c5aed06844bb06b989db8879099d4e8e Mon Sep 17 00:00:00 2001 From: BHT Date: Mon, 1 Sep 2025 08:13:04 -0500 Subject: [PATCH 09/12] restrict cinema to PWDR seq fits --- GSASII/GSASIIseqGUI.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/GSASII/GSASIIseqGUI.py b/GSASII/GSASIIseqGUI.py index 990edb740..20d24ad1c 100644 --- a/GSASII/GSASIIseqGUI.py +++ b/GSASII/GSASIIseqGUI.py @@ -281,6 +281,12 @@ def show_project_dialog(): return True else: return False + # at present this only has been tested with PWDR sequential fits + if not histNames[0].startswith('PWDR'): + G2G.G2MessageBox(G2frame, + 'Cinema export is only available at present for PWDR fits', + 'Sorry') + return # create a table of values from sequential table, copying # the number of displayed digits and removing unneeded entries From 28762392c4534d0eb16d85b0f3e0119faae177bd Mon Sep 17 00:00:00 2001 From: BHT Date: Mon, 1 Sep 2025 08:29:40 -0500 Subject: [PATCH 10/12] add some more notes on cinema --- GSASII/GSASIIseqGUI.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/GSASII/GSASIIseqGUI.py b/GSASII/GSASIIseqGUI.py index 20d24ad1c..2913c5e48 100644 --- a/GSASII/GSASIIseqGUI.py +++ b/GSASII/GSASIIseqGUI.py @@ -260,7 +260,15 @@ def OnSaveSelSeqCSV(event): def OnSaveCinema(event): '''This routine creates/modifies files to run Cinema: Debye-Scherrer https://github.com/cinemascience/cinema_debye_scherrer + https://cinemascience.github.io/publications.html (https://journals.iucr.org/j/issues/2018/03/00/ks5597/ks5597.pdf) + + Note that cinema is installed and run with: + git clone https://github.com/cinemascience/cinema_debye_scherrer.git + cd cinema_debye_scherrer + python -m http.server + + open http://localhost:8000/ in browser ''' IMAGES_SUBDIR = "images" From fc1239963e7cb7acaf1b2b431212654e11e74ae5 Mon Sep 17 00:00:00 2001 From: Andrew Kuncevich Date: Tue, 2 Sep 2025 12:05:03 +0300 Subject: [PATCH 11/12] issue-11 refactoring --- GSASII/GSASIIseqGUI.py | 44 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/GSASII/GSASIIseqGUI.py b/GSASII/GSASIIseqGUI.py index 2913c5e48..6f8d7adab 100644 --- a/GSASII/GSASIIseqGUI.py +++ b/GSASII/GSASIIseqGUI.py @@ -337,9 +337,7 @@ def show_project_dialog(): dialogDir.CenterOnParent() if dialogDir.ShowModal() == wx.ID_OK: selected_dir = dialogDir.GetPath() - dialogDir.Destroy() else: - dialogDir.Destroy() print('Cancelling Cinema export') return if not (os.path.exists(selected_dir) and @@ -394,6 +392,7 @@ def show_project_dialog(): # Project name field name_label = wx.StaticText(panel, label="Project Name:") name_ctrl = wx.TextCtrl(panel, value="GSAS-II Cinema Export") + name_ctrl.SetMinSize((200, -1)) grid_sizer.Add(name_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) grid_sizer.Add(name_ctrl, 1, wx.EXPAND|wx.ALIGN_LEFT) @@ -437,31 +436,32 @@ def show_project_dialog(): print(f"Directory creation failed: {e}") wx.MessageBox(f"Failed to create directory: {e}", "Error", wx.OK|wx.ICON_ERROR) return # Terminate execution if directory creation failed + + try: + print('Open and reuse json') + with open(json_path, 'r', encoding='utf-8') as fil: + data = json.load(fil) + new_entry = { + "name": project_name, + "directory": db_directory, + "smoothLines": True, + "lineOpacity": 1.0 + } + data.append(new_entry) + # rewrite data to json file + with open(json_path, 'w', encoding='utf-8') as file: + json.dump(data, file, indent=8, ensure_ascii=False) + except FileNotFoundError: + print(f"File {json_path} not found") + except json.JSONDecodeError: + print(f"Error reading JSON file {json_path}") + except Exception as e: + print(f"An error occurred: {e}") else: dlg.Destroy() print('Cancelling Cinema export') return - try: - with open(json_path, 'r', encoding='utf-8') as fil: - data = json.load(fil) - new_entry = { - "name": project_name, - "directory": db_directory, - "smoothLines": True, - "lineOpacity": 1.0 - } - data.append(new_entry) - # rewrite data to json file - with open(json_path, 'w', encoding='utf-8') as file: - json.dump(data, file, indent=8, ensure_ascii=False) - except FileNotFoundError: - print(f"File {json_path} not found") - except json.JSONDecodeError: - print(f"Error reading JSON file {json_path}") - except Exception as e: - print(f"An error occurred: {e}") - file_path = os.path.join(selected_dir, db_directory, DATA_CSV_FILENAME) with open(file_path, 'w', encoding='utf-8') as fil: From 880549323a0a9daf1b2e510d08c100250833fd02 Mon Sep 17 00:00:00 2001 From: BHT Date: Tue, 2 Sep 2025 17:48:39 -0500 Subject: [PATCH 12/12] update comments and remove one line of code that is wrong, but never used (file_path is redefined prior to use --- GSASII/GSASIIseqGUI.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/GSASII/GSASIIseqGUI.py b/GSASII/GSASIIseqGUI.py index 6f8d7adab..9e525104b 100644 --- a/GSASII/GSASIIseqGUI.py +++ b/GSASII/GSASIIseqGUI.py @@ -263,12 +263,16 @@ def OnSaveCinema(event): https://cinemascience.github.io/publications.html (https://journals.iucr.org/j/issues/2018/03/00/ks5597/ks5597.pdf) - Note that cinema is installed and run with: + Routine developed by Andrew Kuncevich (see https://github.com/AdvancedPhotonSource/GSAS-II/issues/11) + + Note that cinema is installed and run with commands like: git clone https://github.com/cinemascience/cinema_debye_scherrer.git cd cinema_debye_scherrer python -m http.server - open http://localhost:8000/ in browser + Perhaps if there is demand, we could have GSAS-II install and launch + Cinema: Debye-Scherrer, but for now let's leave this for users to + do. ''' IMAGES_SUBDIR = "images" @@ -375,7 +379,7 @@ def show_project_dialog(): dlg.Destroy() print('Cancelling Cinema export') return - file_path = os.path.join(db_directory, DATA_CSV_FILENAME) + #file_path = os.path.join(db_directory, DATA_CSV_FILENAME) else: # Actions when creating a new project