jsongrapher 3.9__py3-none-any.whl → 4.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import JSONGrapher.styles.layout_styles_library
3
3
  import JSONGrapher.styles.trace_styles_collection_library
4
+ import JSONGrapher.version
4
5
  #TODO: put an option to suppress warnings from JSONRecordCreator
5
6
 
6
7
 
@@ -607,6 +608,7 @@ class JSONGrapherRecord:
607
608
 
608
609
  self.fig_dict.update( {
609
610
  "comments": comments, # Top-level comments
611
+ "jsongrapher": "To plot this file, go to www.jsongrapher.com and drag this file into your browser, or use the python version of JSONGrapher. File created with python Version " + JSONGrapher.version.__version__,
610
612
  "datatype": datatype, # Top-level datatype (datatype)
611
613
  "data": data_objects_list if data_objects_list else [], # Data series list
612
614
  "layout": layout if layout else {
@@ -832,7 +834,7 @@ class JSONGrapherRecord:
832
834
  if equation_dict != None:
833
835
  self.fig_dict["data"][series_index]["equation"] = equation_dict
834
836
  data_series_dict = self.fig_dict["data"][series_index]
835
- self.fig_dict = evaluate_equation_for_data_series_by_index(data_series_index=data_series_dict, verbose=verbose) #implied return.
837
+ self.fig_dict = evaluate_equation_for_data_series_by_index(fig_dict=self.fig_dict, data_series_index=data_series_dict, verbose=verbose) #implied return.
836
838
  return data_series_dict #Extra regular return
837
839
 
838
840
  #this function returns the current record.
@@ -901,8 +903,35 @@ class JSONGrapherRecord:
901
903
  def import_from_dict(self, fig_dict):
902
904
  self.fig_dict = fig_dict
903
905
 
904
- def import_from_file(self, json_filename_or_object):
905
- self.import_from_json(json_filename_or_object)
906
+ def import_from_file(self, record_filename_or_object):
907
+ """
908
+ Determine the type of file or data and call the appropriate import function.
909
+
910
+ Args:
911
+ record_filename_or_object (str or dict): Filename of the CSV/TSV/JSON file or a dictionary object.
912
+
913
+ Returns:
914
+ dict: Processed JSON data.
915
+ """
916
+ import os # Moved inside the function
917
+
918
+ # If the input is a dictionary, process it as JSON
919
+ if isinstance(record_filename_or_object, dict):
920
+ result = self.import_from_json(record_filename_or_object)
921
+ else:
922
+ # Determine file extension
923
+ file_extension = os.path.splitext(record_filename_or_object)[1].lower()
924
+
925
+ if file_extension == ".csv":
926
+ result = self.import_from_csv(record_filename_or_object, delimiter=",")
927
+ elif file_extension == ".tsv":
928
+ result = self.import_from_csv(record_filename_or_object, delimiter="\t")
929
+ elif file_extension == ".json":
930
+ result = self.import_from_json(record_filename_or_object)
931
+ else:
932
+ raise ValueError("Unsupported file type. Please provide a CSV, TSV, or JSON file.")
933
+
934
+ return result
906
935
 
907
936
  #the json object can be a filename string or can be json object which is actually a dictionary.
908
937
  def import_from_json(self, json_filename_or_object):
@@ -928,6 +957,63 @@ class JSONGrapherRecord:
928
957
  self.fig_dict = json_filename_or_object
929
958
  return self.fig_dict
930
959
 
960
+ def import_from_csv(self, filename, delimiter=","):
961
+ """
962
+ Convert CSV file content into a JSON structure for Plotly.
963
+
964
+ Args:
965
+ filename (str): Path to the CSV file.
966
+ delimiter (str, optional): Delimiter used in CSV. Default is ",".
967
+ Use "\\t" for a tab-delimited file.
968
+
969
+ Returns:
970
+ dict: JSON representation of the CSV data.
971
+ """
972
+ import os
973
+ # Modify the filename based on the delimiter and existing extension
974
+ file_extension = os.path.splitext(filename)[1]
975
+ if delimiter == "," and not file_extension: # No extension present
976
+ filename += ".csv"
977
+ elif delimiter == "\t" and not file_extension: # No extension present
978
+ filename += ".tsv"
979
+ with open(filename, "r", encoding="utf-8") as file:
980
+ file_content = file.read().strip()
981
+ # Separate rows
982
+ arr = file_content.split("\n")
983
+ # Count number of columns
984
+ number_of_columns = len(arr[5].split(delimiter))
985
+ # Extract config information
986
+ comments = arr[0].split(delimiter)[0].split(":")[1].strip()
987
+ datatype = arr[1].split(delimiter)[0].split(":")[1].strip()
988
+ chart_label = arr[2].split(delimiter)[0].split(":")[1].strip()
989
+ x_label = arr[3].split(delimiter)[0].split(":")[1].strip()
990
+ y_label = arr[4].split(delimiter)[0].split(":")[1].strip()
991
+ # Extract series names
992
+ series_names_array = [
993
+ n.strip()
994
+ for n in arr[5].split(":")[1].split('"')[0].split(delimiter)
995
+ if n.strip()
996
+ ]
997
+ # Extract data
998
+ data = [[float(str_val) for str_val in row.split(delimiter)] for row in arr[8:]]
999
+ self.fig_dict["comments"] = comments
1000
+ self.fig_dict["datatype"] = datatype
1001
+ self.fig_dict["layout"]["title"] = {"text": chart_label}
1002
+ self.fig_dict["layout"]["xaxis"]["title"] = {"text": x_label}
1003
+ self.fig_dict["layout"]["yaxis"]["title"] = {"text": y_label}
1004
+ # Create series datasets
1005
+ new_data = []
1006
+ for index, series_name in enumerate(series_names_array):
1007
+ data_series_dict = {}
1008
+ data_series_dict["name"] = series_name
1009
+ data_series_dict["x"] = [row[0] for row in data]
1010
+ data_series_dict["y"] = [row[index + 1] for row in data]
1011
+ data_series_dict["uid"] = str(index)
1012
+ new_data.append(data_series_dict)
1013
+ self.fig_dict["data"] = new_data
1014
+ self.fig_dict = self.fig_dict
1015
+ return self.fig_dict
1016
+
931
1017
  def set_datatype(self, datatype):
932
1018
  """
933
1019
  Sets the datatype field used as the experiment type or schema identifier.
@@ -2051,14 +2137,14 @@ def apply_trace_style_to_single_data_series(data_series, trace_styles_collection
2051
2137
  data_series["trace_style"] = trace_style_to_apply
2052
2138
  elif str(trace_style_to_apply) == str(''): #If we received an empty string for the trace_style_to apply (default JSONGrapher flow), we'll check in the data_series object.
2053
2139
  #first see if there is a trace_style in the data_series.
2054
- trace_style = data_series.get("trace_style", "")
2140
+ trace_style_to_apply = data_series.get("trace_style", "")
2055
2141
  #If it's "none", then we'll return the data series unchanged.
2056
2142
  #We consider it that for every trace_styles_collection, that "none" means to make no change.
2057
- if str(trace_style).lower() == "none":
2143
+ if str(trace_style_to_apply).lower() == "none":
2058
2144
  return data_series
2059
2145
  #if we find a dictionary, we will set the trace_style_to_apply to that, to ensure we skip other string checks to use the dictionary.
2060
- if isinstance(trace_style,dict):
2061
- trace_style_to_apply = trace_style
2146
+ if isinstance(trace_style_to_apply,dict):
2147
+ trace_style_to_apply = trace_style_to_apply
2062
2148
  #if the trace_style_to_apply is a string and we have not received a trace_styles collection, then we have nothing
2063
2149
  #to use, so will return the data_series unchanged.
2064
2150
  if type(trace_style_to_apply) == type("string"):
@@ -2071,6 +2157,16 @@ def apply_trace_style_to_single_data_series(data_series, trace_styles_collection
2071
2157
  if type(trace_style_to_apply) == type("string"):
2072
2158
  if (trace_style_to_apply.lower() == "nature") or (trace_style_to_apply.lower() == "science"):
2073
2159
  trace_style_to_apply = "default"
2160
+ #Because the 3D traces will not plot correctly unless recognized,
2161
+ #we have a hardcoded case for the situation that 3D dataset is received without plot style.
2162
+ if trace_styles_collection == "default":
2163
+ if trace_style_to_apply == "":
2164
+ if data_series.get("z", '') != '':
2165
+ trace_style_to_apply = "scatter3d"
2166
+ uid = data_series.get('uid', '')
2167
+ name = data_series.get("name", '')
2168
+ print("Warning: A dataseries was found with no trace_style but with a 'z' field. " , "uid: " , uid , " . " + "name:", name , " . The trace style for this dataseries is being set to scatter3d.")
2169
+
2074
2170
 
2075
2171
  #at this stage, should remove any existing formatting before applying new formatting.
2076
2172
  data_series = remove_trace_style_from_single_data_series(data_series)
@@ -2110,12 +2206,12 @@ def apply_trace_style_to_single_data_series(data_series, trace_styles_collection
2110
2206
  trace_style = data_series.get("trace_style", "")
2111
2207
  else:
2112
2208
  trace_style = trace_style_to_apply
2113
-
2114
2209
  if trace_style == "": #if the trace style is an empty string....
2115
2210
  trace_style = list(styles_collection_dict.keys())[0] #take the first trace_style name in the style_dict. In python 3.7 and later dictionary keys preserve ordering.
2116
2211
 
2117
2212
  #If a person adds "__colorscale" to the end of a trace_style, like "scatter_spline__rainbow" we will extract the colorscale and apply it to the plot.
2118
2213
  #This should be done before extracting the trace_style from the styles_available, because we need to split the string to break out the trace_style
2214
+ #Also should be initialized before determining the second half of colorscale_structure checks (which occurs after the trace_style application), since it affects that logic.
2119
2215
  colorscale = "" #initializing variable.
2120
2216
  if isinstance(trace_style, str): #check if it is a string type.
2121
2217
  if "__" in trace_style:
JSONGrapher/__init__.py CHANGED
@@ -1,3 +1,4 @@
1
1
  #Try to do things a bit like https://github.com/python/cpython/blob/master/Lib/collections/__init__.py
2
2
  #Except instead of putting things here directly in __init__, we'll import them so they are accessible by importing the module.
3
3
  from JSONGrapher.JSONRecordCreator import *
4
+ from JSONGrapher.version import *
@@ -446,6 +446,8 @@ def split_at_first_delimiter(string, delimter=" "):
446
446
  #I would still expect the optimzed code to be an order of magnitude faster. So it may be worth finding the slow steps.
447
447
  #One possibility might be to use "re.compile()"
448
448
  def evaluate_equation_dict(equation_dict, verbose=False):
449
+ import copy
450
+ equation_dict = copy.deepcopy(equation_dict) # Create a deep copy to prevent unintended modifications
449
451
  #First a block of code to extract the x_points needed
450
452
  # Extract each dictionary key as a local variable
451
453
  equation_string = equation_dict['equation_string']
@@ -479,21 +481,28 @@ def evaluate_equation_dict(equation_dict, verbose=False):
479
481
 
480
482
  #Start of block to check for any custom units and add them to the ureg if necessary.
481
483
  custom_units_list = []
484
+ #helper function to clean custom units brackets. In future, could be made more general rather than hardcoded as angle brackets.
485
+ def clean_brackets(string):
486
+ return string.replace("<", "").replace(">", "")
487
+
482
488
  for constant_entry_key in independent_variables_dict.keys():
483
489
  independent_variables_string = independent_variables_dict[constant_entry_key]
484
490
  custom_units_extracted = extract_tagged_strings(independent_variables_string)
491
+ independent_variables_dict[constant_entry_key] = clean_brackets(independent_variables_dict[constant_entry_key])
485
492
  for custom_unit in custom_units_extracted: #this will be skipped if the list is empty.
486
493
  ureg.define(f"{custom_unit} = [custom]") #use "[custom]" to create a custom unit in the pint module.
487
494
  custom_units_list.extend(custom_units_extracted)
488
495
 
489
496
  #now also check for the x_variable_extracted_dict
490
497
  custom_units_extracted = extract_tagged_strings(x_variable_extracted_dict["units"])
498
+ x_variable_extracted_dict["units"] = clean_brackets(x_variable_extracted_dict["units"])
491
499
  for custom_unit in custom_units_extracted: #this will be skipped if the list is empty.
492
500
  ureg.define(f"{custom_unit} = [custom]") #use "[custom]" to create a custom unit in the pint module.
493
501
  custom_units_list.extend(custom_units_extracted)
494
502
 
495
503
  #now also check for the y_variable_extracted_dict (technically not needed)
496
504
  custom_units_extracted = extract_tagged_strings(y_variable_extracted_dict["units"])
505
+ y_variable_extracted_dict["units"] = clean_brackets(y_variable_extracted_dict["units"])
497
506
  for custom_unit in custom_units_extracted: #this will be skipped if the list is empty.
498
507
  ureg.define(f"{custom_unit} = [custom]") #use "[custom]" to create a custom unit in the pint module.
499
508
  custom_units_list.extend(custom_units_extracted)
@@ -501,18 +510,24 @@ def evaluate_equation_dict(equation_dict, verbose=False):
501
510
  if graphical_dimensionality == 3:
502
511
  #now also check for the z_variable_extracted_dict (technically not needed)
503
512
  custom_units_extracted = extract_tagged_strings(z_variable_extracted_dict["units"])
513
+ z_variable_extracted_dict["units"] = clean_brackets(z_variable_extracted_dict["units"])
504
514
  for custom_unit in custom_units_extracted: #this will be skipped if the list is empty.
505
515
  ureg.define(f"{custom_unit} = [custom]") #use "[custom]" to create a custom unit in the pint module.
506
516
  custom_units_list.extend(custom_units_extracted)
507
517
 
508
518
  #now also check for the equation_string
509
519
  custom_units_extracted = extract_tagged_strings(equation_string)
520
+ equation_string = clean_brackets(equation_string)
510
521
  for custom_unit in custom_units_extracted: #this will be skipped if the list is empty.
511
522
  ureg.define(f"{custom_unit} = [custom]") #use "[custom]" to create a custom unit in the pint module.
512
523
  custom_units_list.extend(custom_units_extracted)
513
524
 
525
+ # Remove duplicates by converting to a set and back to a list.
526
+ custom_units_list = list(set(custom_units_list))
514
527
  #now sort from longest to shortest, since we will have to put them back in that way later.
528
+ # Sort the unique units by length in descending order
515
529
  custom_units_list = sorted(custom_units_list, key=len, reverse=True)
530
+
516
531
  #End of block to check for any custom units and add them to the ureg if necessary.
517
532
 
518
533
  #For graphical_dimensionality of 2, The full list of independent variables includes the x_variable and the independent_variables.
JSONGrapher/version.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = '4.1'
@@ -1,3 +1,5 @@
1
+ BSD 3-Clause License
2
+
1
3
  Copyright 2025 Aditya Savara
2
4
 
3
5
  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
@@ -1,26 +1,28 @@
1
+ [![Anaconda-Server Badge](https://anaconda.org/conda-forge/jsongrapher/badges/version.svg)](https://anaconda.org/conda-forge/jsongrapher) [![Anaconda-Server Badge](https://badge.fury.io/py/jsongrapher.svg)](https://badge.fury.io/py/jsongrapher)
2
+
1
3
  # JSONGrapher (python)
2
- This is the python version of JSONGrapher with JSONRecordCreator. This package is for plotting JSON records with drag and drop and has tools for creating the JSON records.
3
4
 
4
- The software will automatically plot multiple records together, for comparison, and will automaticlaly converting units between records as needed to plot them for comparison (like kg/s and g/s).
5
+ Imagine a world where a person can simply drag a datafile into a graphing utility and a plot will be made, including scientific units, and more plots can be dragged in from data from other sources (and other units) to compare all of the data together, in an interactive graph.
6
+
7
+ Create interactive plots just by drag-and-drop of JSON records. Share the json files for easy plotting by others. JSONGrapher automatically plots multiple records together, for comparison, and will automaticlaly convert units between records to plot the data sets together. For example, if one record is in kg/s and another in g/s, JSONGrapher will do the conversion automatically to plot both records together for comparison. Tools and examples are included for how to create JSON records.
5
8
 
6
9
  To use python JSONGrapher, first install it using conda or pip:<br>
7
10
  `pip install JSONGrapher[COMPLETE]` or `conda install conda-forge::jsongrapher` <br>
8
11
  Alternatively, you can download the directory directly.<br>
9
12
 
10
13
  ## **0\. Plotting a JSON Record**
11
- It's as simple as one line! Then drag an [example](https://github.com/AdityaSavara/jsongrapher-py/tree/main/examples/example_1_drag_and_drop) JSONGrapher record into the window to plot!
12
- Below shows several plot types for 2D and 3D plots, followed by a simple example of how to use python JSONGrapher to create your own records.
14
+ To create an interactive plot, you just need one line of code! Then drag an [example](https://github.com/AdityaSavara/jsongrapher-py/tree/main/examples/example_1_drag_and_drop) JSONGrapher record into the window to plot!
15
+ Below are example 2D and 3D plots. Further below shows how easy it is to create your own json records.
13
16
  <pre>
14
- import JSONGrapher
15
- JSONGrapher.launch()
17
+ import JSONGrapher; JSONGrapher.launch()
16
18
  </pre>
17
19
 
18
- [![JSONGRapher window](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/JSONGrapher/JSONGrapherWindowShortened.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/JSONGrapher/JSONGrapherWindowShortened.png) [![JSONGRapher plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/UAN_DTA_image.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/UAN_DTA_image.png)
20
+ [![JSONGRapher window](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/JSONGrapher/JSONGrapherWindowShortened.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/JSONGrapher/JSONGrapherWindowShortened.png) [![JSONGRapher plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/UAN_DTA_image.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/UAN_DTA_image.png)
19
21
 
20
- [![rainbow plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/SrTiO3_rainbow_image.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/SrTiO3_rainbow_image.png)
21
- [![mesh3d plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/Rate_Constant_mesh3d.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/Rate_Constant_mesh3d.png)
22
- [![scatter3d plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/Rate_Constant_Scatter3d_example10.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/Rate_Constant_Scatter3d_example10.png)
23
- [![bubble plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/Rate_Constant_bubble.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/Rate_Constant_bubble.png)
22
+ [![rainbow plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/SrTiO3_rainbow_image.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/SrTiO3_rainbow_image.png)
23
+ [![mesh3d plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_mesh3d.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_mesh3d.png)
24
+ [![scatter3d plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_Scatter3d_example10.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_Scatter3d_example10.png)
25
+ [![bubble plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_bubble.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_bubble.png)
24
26
 
25
27
 
26
28
 
@@ -98,4 +100,15 @@ Record.plot_with_plotly() #Try hovering your mouse over points after this comman
98
100
  You can also see more examples: https://github.com/AdityaSavara/jsongrapher-py/tree/main/examples
99
101
 
100
102
  Additionally, json records you send to others can be plotted by them at www.jsongrapher.com
101
- This 'see the plot using a browser' capability is intended to facilitate including JSONGrapher records in supporting information of scientific publications.
103
+ This 'see the plot using a browser' capability is intended to facilitate including JSONGrapher records in supporting information of scientific publications.
104
+
105
+
106
+ ## **Contributing to JSONGrapher, Feature Suggestions, and Reporting Issues**
107
+
108
+ These interactions should be through github at https://github.com/AdityaSavara/jsongrapher-py
109
+
110
+ To contribute to JSONGrapher, make a pull request with sufficient details about what issue you are trying to solve, and adequate commenting in your code to follow the logic. After that, be prepared for further communication if needed.
111
+
112
+ To suggest features, create a new issue under the issues tab.
113
+
114
+ To report issues, create a new issue under the issues tab.
@@ -1,3 +1,5 @@
1
+ BSD 3-Clause License
2
+
1
3
  Copyright 2025 Aditya Savara
2
4
 
3
5
  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jsongrapher
3
- Version: 3.9
3
+ Version: 4.1
4
4
  Summary: The python version of JSONGrapher with tools for creating JSONGrapher Records.
5
5
  Home-page: https://github.com/AdityaSavara/jsongrapher-py
6
6
  Author: Aditya Savara
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: Implementation :: CPython
14
14
  Classifier: Programming Language :: Python :: Implementation :: PyPy
15
15
  Requires-Python: >=3.0.0
16
16
  Description-Content-Type: text/markdown
17
- License-File: LICENSE
17
+ License-File: LICENSE.txt
18
18
  Requires-Dist: numpy>=1.26
19
19
  Provides-Extra: complete
20
20
  Requires-Dist: matplotlib; extra == "complete"
@@ -25,29 +25,31 @@ Requires-Dist: urllib; extra == "complete"
25
25
  Requires-Dist: json-equationer; extra == "complete"
26
26
 
27
27
 
28
+ [![Anaconda-Server Badge](https://anaconda.org/conda-forge/jsongrapher/badges/version.svg)](https://anaconda.org/conda-forge/jsongrapher) [![Anaconda-Server Badge](https://badge.fury.io/py/jsongrapher.svg)](https://badge.fury.io/py/jsongrapher)
29
+
28
30
  # JSONGrapher (python)
29
- This is the python version of JSONGrapher with JSONRecordCreator. This package is for plotting JSON records with drag and drop and has tools for creating the JSON records.
30
31
 
31
- The software will automatically plot multiple records together, for comparison, and will automaticlaly converting units between records as needed to plot them for comparison (like kg/s and g/s).
32
+ Imagine a world where a person can simply drag a datafile into a graphing utility and a plot will be made, including scientific units, and more plots can be dragged in from data from other sources (and other units) to compare all of the data together, in an interactive graph.
33
+
34
+ Create interactive plots just by drag-and-drop of JSON records. Share the json files for easy plotting by others. JSONGrapher automatically plots multiple records together, for comparison, and will automaticlaly convert units between records to plot the data sets together. For example, if one record is in kg/s and another in g/s, JSONGrapher will do the conversion automatically to plot both records together for comparison. Tools and examples are included for how to create JSON records.
32
35
 
33
36
  To use python JSONGrapher, first install it using conda or pip:<br>
34
37
  `pip install JSONGrapher[COMPLETE]` or `conda install conda-forge::jsongrapher` <br>
35
38
  Alternatively, you can download the directory directly.<br>
36
39
 
37
40
  ## **0\. Plotting a JSON Record**
38
- It's as simple as one line! Then drag an [example](https://github.com/AdityaSavara/jsongrapher-py/tree/main/examples/example_1_drag_and_drop) JSONGrapher record into the window to plot!
39
- Below shows several plot types for 2D and 3D plots, followed by a simple example of how to use python JSONGrapher to create your own records.
41
+ To create an interactive plot, you just need one line of code! Then drag an [example](https://github.com/AdityaSavara/jsongrapher-py/tree/main/examples/example_1_drag_and_drop) JSONGrapher record into the window to plot!
42
+ Below are example 2D and 3D plots. Further below shows how easy it is to create your own json records.
40
43
  <pre>
41
- import JSONGrapher
42
- JSONGrapher.launch()
44
+ import JSONGrapher; JSONGrapher.launch()
43
45
  </pre>
44
46
 
45
- [![JSONGRapher window](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/JSONGrapher/JSONGrapherWindowShortened.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/JSONGrapher/JSONGrapherWindowShortened.png) [![JSONGRapher plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/UAN_DTA_image.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/UAN_DTA_image.png)
47
+ [![JSONGRapher window](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/JSONGrapher/JSONGrapherWindowShortened.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/JSONGrapher/JSONGrapherWindowShortened.png) [![JSONGRapher plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/UAN_DTA_image.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/UAN_DTA_image.png)
46
48
 
47
- [![rainbow plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/SrTiO3_rainbow_image.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/SrTiO3_rainbow_image.png)
48
- [![mesh3d plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/Rate_Constant_mesh3d.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/Rate_Constant_mesh3d.png)
49
- [![scatter3d plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/Rate_Constant_Scatter3d_example10.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/Rate_Constant_Scatter3d_example10.png)
50
- [![bubble plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/Rate_Constant_bubble.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/Rate_Constant_bubble.png)
49
+ [![rainbow plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/SrTiO3_rainbow_image.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/SrTiO3_rainbow_image.png)
50
+ [![mesh3d plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_mesh3d.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_mesh3d.png)
51
+ [![scatter3d plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_Scatter3d_example10.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_Scatter3d_example10.png)
52
+ [![bubble plot](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_bubble.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_bubble.png)
51
53
 
52
54
 
53
55
 
@@ -126,3 +128,14 @@ You can also see more examples: https://github.com/AdityaSavara/jsongrapher-py/t
126
128
 
127
129
  Additionally, json records you send to others can be plotted by them at www.jsongrapher.com
128
130
  This 'see the plot using a browser' capability is intended to facilitate including JSONGrapher records in supporting information of scientific publications.
131
+
132
+
133
+ ## **Contributing to JSONGrapher, Feature Suggestions, and Reporting Issues**
134
+
135
+ These interactions should be through github at https://github.com/AdityaSavara/jsongrapher-py
136
+
137
+ To contribute to JSONGrapher, make a pull request with sufficient details about what issue you are trying to solve, and adequate commenting in your code to follow the logic. After that, be prepared for further communication if needed.
138
+
139
+ To suggest features, create a new issue under the issues tab.
140
+
141
+ To report issues, create a new issue under the issues tab.
@@ -0,0 +1,19 @@
1
+ JSONGrapher/JSONRecordCreator.py,sha256=46saEYWpy3Oiai2lCAGEfayIs6ZLNBjcH7nC2Yi87G8,214735
2
+ JSONGrapher/UnitPytesting.py,sha256=xizJ-2fg9C5oNMFJyfavbBLMusayE9KWQiYIRrQQd4A,4363
3
+ JSONGrapher/UnitpyCustomUnitsTesting.py,sha256=Rwq5p8HXN0FP54lRFgLTV0kgJ9TpcFaD3_C0MEOoEzw,1297
4
+ JSONGrapher/__init__.py,sha256=fA3R6paWq3uskiLe3OglQZY_uJOejZHMFKdyX0dXWjo,310
5
+ JSONGrapher/drag_and_drop_gui.py,sha256=-7QJHLhzadHotWhONH4inerMaZ_xuwoTQSMRF_MPVe0,5632
6
+ JSONGrapher/equation_creator.py,sha256=VFu6dFo-C0wDf1N3e0CyCBI-53cCUrp3oe0umdMLofs,17968
7
+ JSONGrapher/equation_evaluator.py,sha256=Cm7UK5vWa6fT0OylD9f22_eR8zUvxY_Sy_W6n6N9bew,37012
8
+ JSONGrapher/units_list.py,sha256=ROrlAsD66oPozZmOaE65xjNUEg3CxkSmA8iPE2_ihYI,34438
9
+ JSONGrapher/version.py,sha256=plmUxJqz8GZ6qgO0GmMnNftP7opuGp9bxRvdx2Lbgco,19
10
+ JSONGrapher/styles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ JSONGrapher/styles/layout_styles_library.py,sha256=vGb1tE_ETY-Blj2frt8ddHA976ADFSCoabjzKn2ZNYU,3051
12
+ JSONGrapher/styles/trace_styles_collection_library.py,sha256=DUbbO8jTlhn2q-lOY1XYGkHV1RbJX-P5Z1SUCM0qo6M,5952
13
+ jsongrapher-4.1.data/data/LICENSE.txt,sha256=7Guw_pmj_H4sApnM7fld2L4HH6CP-3ZYdFoOXtHFx0Y,1489
14
+ jsongrapher-4.1.data/data/README.md,sha256=stbbH5GC2URwaG41OepUSmtH1_2t6CGw-nAxhYy_UJI,7151
15
+ jsongrapher-4.1.dist-info/LICENSE.txt,sha256=7Guw_pmj_H4sApnM7fld2L4HH6CP-3ZYdFoOXtHFx0Y,1489
16
+ jsongrapher-4.1.dist-info/METADATA,sha256=wYThzsgr77C_0dn1oIUN5kmb9C9KKooVlvC0ldbn2Kk,8225
17
+ jsongrapher-4.1.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
18
+ jsongrapher-4.1.dist-info/top_level.txt,sha256=5f7Ui2hCKCPTQOjD540WKghKNYOvUDNfdpnDbIlAD3Y,12
19
+ jsongrapher-4.1.dist-info/RECORD,,
@@ -1,18 +0,0 @@
1
- JSONGrapher/JSONRecordCreator.py,sha256=nENtRcr0hlysqhRIc-BhYRE8VN9Q8TaB0IC74jiKUzw,209780
2
- JSONGrapher/UnitPytesting.py,sha256=xizJ-2fg9C5oNMFJyfavbBLMusayE9KWQiYIRrQQd4A,4363
3
- JSONGrapher/UnitpyCustomUnitsTesting.py,sha256=Rwq5p8HXN0FP54lRFgLTV0kgJ9TpcFaD3_C0MEOoEzw,1297
4
- JSONGrapher/__init__.py,sha256=cc5qXQidP_ABPXdnXy_DTdgPanHuR7ya45LV-BdWVh8,277
5
- JSONGrapher/drag_and_drop_gui.py,sha256=-7QJHLhzadHotWhONH4inerMaZ_xuwoTQSMRF_MPVe0,5632
6
- JSONGrapher/equation_creator.py,sha256=VFu6dFo-C0wDf1N3e0CyCBI-53cCUrp3oe0umdMLofs,17968
7
- JSONGrapher/equation_evaluator.py,sha256=coNVkZDRmEti3wYOc9NBY2Z1fRz3ei9ZxFd-ST-bOWc,36020
8
- JSONGrapher/units_list.py,sha256=ROrlAsD66oPozZmOaE65xjNUEg3CxkSmA8iPE2_ihYI,34438
9
- JSONGrapher/styles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- JSONGrapher/styles/layout_styles_library.py,sha256=vGb1tE_ETY-Blj2frt8ddHA976ADFSCoabjzKn2ZNYU,3051
11
- JSONGrapher/styles/trace_styles_collection_library.py,sha256=DUbbO8jTlhn2q-lOY1XYGkHV1RbJX-P5Z1SUCM0qo6M,5952
12
- jsongrapher-3.9.data/data/LICENSE,sha256=MroL1bQKoAHrMJv2KvABMmZX5j-DZ2EP_zaQacLUtj0,1465
13
- jsongrapher-3.9.data/data/README.md,sha256=OntfAICB_uwfjoq8tMDYc_W7eXSC2N22X0udPIGb2Nw,5888
14
- jsongrapher-3.9.dist-info/LICENSE,sha256=MroL1bQKoAHrMJv2KvABMmZX5j-DZ2EP_zaQacLUtj0,1465
15
- jsongrapher-3.9.dist-info/METADATA,sha256=q1LGWAVZNTTawUuuWZzy8WypNwQv7tdYWNIt1xWSbsE,6960
16
- jsongrapher-3.9.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
17
- jsongrapher-3.9.dist-info/top_level.txt,sha256=5f7Ui2hCKCPTQOjD540WKghKNYOvUDNfdpnDbIlAD3Y,12
18
- jsongrapher-3.9.dist-info/RECORD,,