jsongrapher 3.9__py3-none-any.whl → 4.2__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 {
@@ -753,12 +755,13 @@ class JSONGrapherRecord:
753
755
  self.fig_dict["data"].append(data_series_dict) #implied return.
754
756
  return data_series_dict
755
757
 
756
- def add_data_series_as_equation(self, series_name, x_values=None, y_values=None, equation_dict=None, evaluate_equations_as_added=True, comments="", trace_style="", uid="", line="", extra_fields=None):
758
+ def add_data_series_as_equation(self, series_name, graphical_dimensionality, x_values=None, y_values=None, equation_dict=None, evaluate_equations_as_added=True, comments="", trace_style="", uid="", line="", extra_fields=None):
757
759
  """
758
760
  This is a way to add an equation that would be used to fill an x,y data series.
759
761
  The equation will be a equation_dict of the json_equationer type
760
762
  """
761
763
  # series_name: Name of the data series.
764
+ # graphical_dimensionality is the number of geometric dimensions, so should be either 2 or 3.
762
765
  # x: List of x-axis values. Or similar structure.
763
766
  # y: List of y-axis values. Or similar structure.
764
767
  # equation_dict: This is the field for the equation_dict of json_equationer type
@@ -775,6 +778,7 @@ class JSONGrapherRecord:
775
778
  y_values = []
776
779
  if equation_dict is None:
777
780
  equation_dict = {}
781
+ equation_dict["graphical_dimensionality"] = int(graphical_dimensionality)
778
782
 
779
783
  x_values = list(x_values)
780
784
  y_values = list(y_values)
@@ -832,7 +836,7 @@ class JSONGrapherRecord:
832
836
  if equation_dict != None:
833
837
  self.fig_dict["data"][series_index]["equation"] = equation_dict
834
838
  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.
839
+ 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
840
  return data_series_dict #Extra regular return
837
841
 
838
842
  #this function returns the current record.
@@ -901,8 +905,35 @@ class JSONGrapherRecord:
901
905
  def import_from_dict(self, fig_dict):
902
906
  self.fig_dict = fig_dict
903
907
 
904
- def import_from_file(self, json_filename_or_object):
905
- self.import_from_json(json_filename_or_object)
908
+ def import_from_file(self, record_filename_or_object):
909
+ """
910
+ Determine the type of file or data and call the appropriate import function.
911
+
912
+ Args:
913
+ record_filename_or_object (str or dict): Filename of the CSV/TSV/JSON file or a dictionary object.
914
+
915
+ Returns:
916
+ dict: Processed JSON data.
917
+ """
918
+ import os # Moved inside the function
919
+
920
+ # If the input is a dictionary, process it as JSON
921
+ if isinstance(record_filename_or_object, dict):
922
+ result = self.import_from_json(record_filename_or_object)
923
+ else:
924
+ # Determine file extension
925
+ file_extension = os.path.splitext(record_filename_or_object)[1].lower()
926
+
927
+ if file_extension == ".csv":
928
+ result = self.import_from_csv(record_filename_or_object, delimiter=",")
929
+ elif file_extension == ".tsv":
930
+ result = self.import_from_csv(record_filename_or_object, delimiter="\t")
931
+ elif file_extension == ".json":
932
+ result = self.import_from_json(record_filename_or_object)
933
+ else:
934
+ raise ValueError("Unsupported file type. Please provide a CSV, TSV, or JSON file.")
935
+
936
+ return result
906
937
 
907
938
  #the json object can be a filename string or can be json object which is actually a dictionary.
908
939
  def import_from_json(self, json_filename_or_object):
@@ -928,6 +959,63 @@ class JSONGrapherRecord:
928
959
  self.fig_dict = json_filename_or_object
929
960
  return self.fig_dict
930
961
 
962
+ def import_from_csv(self, filename, delimiter=","):
963
+ """
964
+ Convert CSV file content into a JSON structure for Plotly.
965
+
966
+ Args:
967
+ filename (str): Path to the CSV file.
968
+ delimiter (str, optional): Delimiter used in CSV. Default is ",".
969
+ Use "\\t" for a tab-delimited file.
970
+
971
+ Returns:
972
+ dict: JSON representation of the CSV data.
973
+ """
974
+ import os
975
+ # Modify the filename based on the delimiter and existing extension
976
+ file_extension = os.path.splitext(filename)[1]
977
+ if delimiter == "," and not file_extension: # No extension present
978
+ filename += ".csv"
979
+ elif delimiter == "\t" and not file_extension: # No extension present
980
+ filename += ".tsv"
981
+ with open(filename, "r", encoding="utf-8") as file:
982
+ file_content = file.read().strip()
983
+ # Separate rows
984
+ arr = file_content.split("\n")
985
+ # Count number of columns
986
+ number_of_columns = len(arr[5].split(delimiter))
987
+ # Extract config information
988
+ comments = arr[0].split(delimiter)[0].split(":")[1].strip()
989
+ datatype = arr[1].split(delimiter)[0].split(":")[1].strip()
990
+ chart_label = arr[2].split(delimiter)[0].split(":")[1].strip()
991
+ x_label = arr[3].split(delimiter)[0].split(":")[1].strip()
992
+ y_label = arr[4].split(delimiter)[0].split(":")[1].strip()
993
+ # Extract series names
994
+ series_names_array = [
995
+ n.strip()
996
+ for n in arr[5].split(":")[1].split('"')[0].split(delimiter)
997
+ if n.strip()
998
+ ]
999
+ # Extract data
1000
+ data = [[float(str_val) for str_val in row.split(delimiter)] for row in arr[8:]]
1001
+ self.fig_dict["comments"] = comments
1002
+ self.fig_dict["datatype"] = datatype
1003
+ self.fig_dict["layout"]["title"] = {"text": chart_label}
1004
+ self.fig_dict["layout"]["xaxis"]["title"] = {"text": x_label}
1005
+ self.fig_dict["layout"]["yaxis"]["title"] = {"text": y_label}
1006
+ # Create series datasets
1007
+ new_data = []
1008
+ for index, series_name in enumerate(series_names_array):
1009
+ data_series_dict = {}
1010
+ data_series_dict["name"] = series_name
1011
+ data_series_dict["x"] = [row[0] for row in data]
1012
+ data_series_dict["y"] = [row[index + 1] for row in data]
1013
+ data_series_dict["uid"] = str(index)
1014
+ new_data.append(data_series_dict)
1015
+ self.fig_dict["data"] = new_data
1016
+ self.fig_dict = self.fig_dict
1017
+ return self.fig_dict
1018
+
931
1019
  def set_datatype(self, datatype):
932
1020
  """
933
1021
  Sets the datatype field used as the experiment type or schema identifier.
@@ -1852,6 +1940,7 @@ def apply_plot_style_to_plotly_dict(fig_dict, plot_style=None):
1852
1940
  if str(plot_style["layout_style"]).lower() != 'none': #take no action if received "None" or NoneType
1853
1941
  if plot_style["layout_style"] == '': #in this case, we're going to use the default.
1854
1942
  plot_style["layout_style"] = 'default'
1943
+ print("Warning: No layout_style provided and 'z' field found in first data series. For 'bubble' plots, it is recommended to set layout_style to 'default'. For 'mesh3d' graphs and 'scatter3d' graphs, it is recommended to set layout_style to 'default3d'. Set layout_style to 'none' or another layout_style to avoid this warning.")
1855
1944
  fig_dict = remove_layout_style_from_plotly_dict(fig_dict=fig_dict)
1856
1945
  fig_dict = apply_layout_style_to_plotly_dict(fig_dict=fig_dict, layout_style_to_apply=plot_style["layout_style"])
1857
1946
  #Code logic for trace_styles_collection style.
@@ -2051,14 +2140,14 @@ def apply_trace_style_to_single_data_series(data_series, trace_styles_collection
2051
2140
  data_series["trace_style"] = trace_style_to_apply
2052
2141
  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
2142
  #first see if there is a trace_style in the data_series.
2054
- trace_style = data_series.get("trace_style", "")
2143
+ trace_style_to_apply = data_series.get("trace_style", "")
2055
2144
  #If it's "none", then we'll return the data series unchanged.
2056
2145
  #We consider it that for every trace_styles_collection, that "none" means to make no change.
2057
- if str(trace_style).lower() == "none":
2146
+ if str(trace_style_to_apply).lower() == "none":
2058
2147
  return data_series
2059
2148
  #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
2149
+ if isinstance(trace_style_to_apply,dict):
2150
+ trace_style_to_apply = trace_style_to_apply
2062
2151
  #if the trace_style_to_apply is a string and we have not received a trace_styles collection, then we have nothing
2063
2152
  #to use, so will return the data_series unchanged.
2064
2153
  if type(trace_style_to_apply) == type("string"):
@@ -2071,6 +2160,16 @@ def apply_trace_style_to_single_data_series(data_series, trace_styles_collection
2071
2160
  if type(trace_style_to_apply) == type("string"):
2072
2161
  if (trace_style_to_apply.lower() == "nature") or (trace_style_to_apply.lower() == "science"):
2073
2162
  trace_style_to_apply = "default"
2163
+ #Because the 3D traces will not plot correctly unless recognized,
2164
+ #we have a hardcoded case for the situation that 3D dataset is received without plot style.
2165
+ if trace_styles_collection == "default":
2166
+ if trace_style_to_apply == "":
2167
+ if data_series.get("z", '') != '':
2168
+ trace_style_to_apply = "scatter3d"
2169
+ uid = data_series.get('uid', '')
2170
+ name = data_series.get("name", '')
2171
+ 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.")
2172
+
2074
2173
 
2075
2174
  #at this stage, should remove any existing formatting before applying new formatting.
2076
2175
  data_series = remove_trace_style_from_single_data_series(data_series)
@@ -2110,12 +2209,12 @@ def apply_trace_style_to_single_data_series(data_series, trace_styles_collection
2110
2209
  trace_style = data_series.get("trace_style", "")
2111
2210
  else:
2112
2211
  trace_style = trace_style_to_apply
2113
-
2114
2212
  if trace_style == "": #if the trace style is an empty string....
2115
2213
  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
2214
 
2117
2215
  #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
2216
  #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
2217
+ #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
2218
  colorscale = "" #initializing variable.
2120
2219
  if isinstance(trace_style, str): #check if it is a string type.
2121
2220
  if "__" in trace_style:
@@ -3389,11 +3488,11 @@ def evaluate_equation_for_data_series_by_index(fig_dict, data_series_index, verb
3389
3488
  data_dict_filled['equation'] = equation_dict_evaluated
3390
3489
  data_dict_filled['x_label'] = data_dict_filled['equation']['x_variable']
3391
3490
  data_dict_filled['y_label'] = data_dict_filled['equation']['y_variable']
3392
- data_dict_filled['x'] = equation_dict_evaluated['x_points']
3393
- data_dict_filled['y'] = equation_dict_evaluated['y_points']
3491
+ data_dict_filled['x'] = list(equation_dict_evaluated['x_points'])
3492
+ data_dict_filled['y'] = list(equation_dict_evaluated['y_points'])
3394
3493
  if graphical_dimensionality == 3:
3395
3494
  data_dict_filled['z_label'] = data_dict_filled['equation']['z_variable']
3396
- data_dict_filled['z'] = equation_dict_evaluated['z_points']
3495
+ data_dict_filled['z'] = list(equation_dict_evaluated['z_points'])
3397
3496
  #data_dict_filled may include "x_label" and/or "y_label". If it does, we'll need to check about scaling units.
3398
3497
  if (("x_label" in data_dict_filled) or ("y_label" in data_dict_filled)) or ("z_label" in data_dict_filled):
3399
3498
  #first, get the units that are in the layout of fig_dict so we know what to convert to.
@@ -3462,10 +3561,10 @@ def update_implicit_data_series_data(target_fig_dict, source_fig_dict, parallel_
3462
3561
  # Use zip() when parallel_structure=True and lengths match
3463
3562
  for target_series, source_series in zip(target_data_series, source_data_series):
3464
3563
  if ("equation" in target_series) or ("simulate" in target_series):
3465
- target_series["x"] = source_series.get("x", []) # Extract and apply "x" values
3466
- target_series["y"] = source_series.get("y", []) # Extract and apply "y" values
3564
+ target_series["x"] = list(source_series.get("x", [])) # Extract and apply "x" values
3565
+ target_series["y"] = list(source_series.get("y", [])) # Extract and apply "y" values
3467
3566
  if "z" in source_series:
3468
- target_series["z"] = source_series.get("z", []) # Extract and apply "z" values
3567
+ target_series["z"] = list(source_series.get("z", [])) # Extract and apply "z" values
3469
3568
  else:
3470
3569
  # Match by name when parallel_structure=False or lengths differ
3471
3570
  source_data_dict = {series["name"]: series for series in source_data_series if "name" in series}
@@ -3476,10 +3575,10 @@ def update_implicit_data_series_data(target_fig_dict, source_fig_dict, parallel_
3476
3575
 
3477
3576
  if target_name in source_data_dict:
3478
3577
  source_series = source_data_dict[target_name]
3479
- target_series["x"] = source_series.get("x", []) # Extract and apply "x" values
3480
- target_series["y"] = source_series.get("y", []) # Extract and apply "y" values
3578
+ target_series["x"] = list(source_series.get("x", [])) # Extract and apply "x" values
3579
+ target_series["y"] = list(source_series.get("y", [])) # Extract and apply "y" values
3481
3580
  if "z" in source_series:
3482
- target_series["z"] = source_series.get("z", []) # Extract and apply "z" values
3581
+ target_series["z"] = list(source_series.get("z", [])) # Extract and apply "z" values
3483
3582
  return updated_fig_dict
3484
3583
 
3485
3584
 
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.2'
@@ -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:
@@ -0,0 +1,118 @@
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
+
3
+ # JSONGrapher (python)
4
+
5
+ Imagine a world where a person can simply drag a data file into a graphing utility and a plot will be made -- including axes with the data's units. Imagine that data from data other sources (with other units) can then be dragged in for comparison, with all data plotted on an interactive graph. Imagine that the units of all of these datasets will be converted automatically, as needed, during the plotting.
6
+
7
+ Create interactive plots just by drag-and-drop of JSON records. Share the json files for easy plotting by others. JSONGrapher will automatically convert units between records to plot the data sets together, to enable comparisons. 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.
8
+
9
+ To use python JSONGrapher, first install it using conda or pip:<br>
10
+ `pip install JSONGrapher[COMPLETE]` or `conda install conda-forge::jsongrapher` <br>
11
+ Alternatively, you can download the directory directly.<br>
12
+
13
+ ## **0\. Plotting a JSON Record**
14
+ To create an interactive plot, you just need one line of code! <br>
15
+ 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! Below are example 2D and 3D plots. <br>
16
+ Further below shows how easy it is to create your own json records.
17
+ <pre>
18
+ import JSONGrapher; JSONGrapher.launch()
19
+ # Then just drag records into the window!
20
+ </pre>
21
+
22
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/JSONGrapherWindowShortened.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/JSONGrapherWindowShortened.gif" width="20%"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
23
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/UAN_DTA_image.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/UAN_DTA_image.gif" width="25%"></a>
24
+ <br>
25
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_mesh3d.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_mesh3d.gif" width="35%"></a>
26
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_Scatter3d_example10.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_Scatter3d_example10.gif" width="35%"></a>
27
+ <br>
28
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_bubble.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_bubble.gif" width="35%"></a>&nbsp;&nbsp;&nbsp;
29
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/SrTiO3_rainbow_image.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/SrTiO3_rainbow_image.gif" width="30%"></a>
30
+ <br><br>
31
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/O_OH_Scaling.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/O_OH_Scaling.gif" width="50%"></a>
32
+
33
+
34
+ ## **1\. Preparing to Create a Record**
35
+
36
+ The remainder of this landing page follows a json record tutorial [example file](https://github.com/AdityaSavara/jsongrapher-py/blob/main/examples/example_2_creating_records_and_using_styles/example_2_json_record_tutorial.py) which shows how to create graphable .json records. The records can then be plotted with python JSONGrapher or with jsongrapher.com<br>
37
+
38
+ Let's create an example where we plot the height of a pear tree over several years.
39
+ <pre>
40
+ Record = JSONRecordCreator.create_new_JSONGrapherRecord()
41
+ x_label_including_units = "Time (years)"
42
+ y_label_including_units = "Height (m)"
43
+ time_in_years = [0, 1, 2, 3, 4]
44
+ tree_heights = [0, 0.42, 0.86, 1.19, 1.45]
45
+ </pre>
46
+
47
+ ## **2\. Populating the New JSONGrapher Record**
48
+
49
+ <pre>
50
+ Record.set_comments("Tree Growth Data collected from the US National Arboretum")
51
+ Record.set_datatype("Tree_Growth_Curve")
52
+ Record.set_x_axis_label_including_units(x_label_including_units)
53
+ Record.set_y_axis_label_including_units(y_label_including_units)
54
+ Record.add_data_series(series_name="pear tree growth", x_values=time_in_years, y_values=tree_heights, plot_type="scatter_spline")
55
+ Record.set_graph_title("Pear Tree Growth Versus Time")
56
+ </pre>
57
+
58
+ ## **3\. Exporting to File**
59
+
60
+ We can export a record to a .json file, which can then be used with JSONGrapher.
61
+ <pre>
62
+ Record.export_to_json_file("ExampleFromTutorial.json")
63
+ Record.print_to_inspect()
64
+ </pre>
65
+
66
+ <p><strong>Expected Output:</strong></p>
67
+ <pre>
68
+ JSONGrapher Record exported to, ./ExampleFromTutorial.json
69
+ {
70
+ "comments": "Tree Growth Data collected from the US National Arboretum",
71
+ "datatype": "Tree_Growth_Curve",
72
+ "data": [
73
+ {
74
+ "name": "pear tree growth",
75
+ "x": [0, 1, 2, 3, 4],
76
+ "y": [0, 0.42, 0.86, 1.19, 1.45],
77
+ "type": "scatter",
78
+ "line": { "shape": "spline" }
79
+ }
80
+ ],
81
+ "layout": {
82
+ "title": "Pear Tree Growth Versus Time",
83
+ "xaxis": { "title": "Time (year)" },
84
+ "yaxis": { "title": "Height (m)" }
85
+ }
86
+ }
87
+ </pre>
88
+
89
+ ## **4\. Plotting to Inspect**
90
+
91
+ We can plot the data with plotly, interact with the graph, and save as a png file.
92
+ <pre>
93
+ Record.plot_with_plotly() #Try hovering your mouse over points after this command!
94
+ </pre>
95
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_2_creating_records_and_using_styles/image_from_tutorial_plotly_fig.png"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_2_creating_records_and_using_styles/image_from_tutorial_plotly_fig.png" width="40%"></a>
96
+
97
+ We can plot the data using Matplotlib and export the plot as a PNG file.
98
+ <pre>
99
+ Record.plot_with_matplotlib()
100
+ Record.export_to_matplotlib_png("image_from_tutorial_matplotlib_fig")
101
+ </pre>
102
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_2_creating_records_and_using_styles/image_from_tutorial_matplotlib_fig.png"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_2_creating_records_and_using_styles/image_from_tutorial_matplotlib_fig.png" width="40%"></a>
103
+
104
+ You can also see more examples: https://github.com/AdityaSavara/jsongrapher-py/tree/main/examples
105
+
106
+ Additionally, json records you send to others can be plotted by them at www.jsongrapher.com
107
+ This 'see the plot using a browser' capability is intended to facilitate including JSONGrapher records in supporting information of scientific publications.
108
+
109
+
110
+ ## **Contributing to JSONGrapher, Feature Suggestions, and Reporting Issues**
111
+
112
+ These interactions should be through github at https://github.com/AdityaSavara/jsongrapher-py
113
+
114
+ 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.
115
+
116
+ To suggest features, create a new issue under the issues tab.
117
+
118
+ 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:
@@ -0,0 +1,145 @@
1
+ Metadata-Version: 2.1
2
+ Name: jsongrapher
3
+ Version: 4.2
4
+ Summary: The python version of JSONGrapher with tools for creating JSONGrapher Records.
5
+ Home-page: https://github.com/AdityaSavara/jsongrapher-py
6
+ Author: Aditya Savara
7
+ Author-email: AdityaSavara2008@u.northwestern.edu
8
+ License: BSD-3-Clause
9
+ Classifier: License :: OSI Approved :: BSD License
10
+ Classifier: Programming Language :: Python
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.6
13
+ Classifier: Programming Language :: Python :: Implementation :: CPython
14
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
15
+ Requires-Python: >=3.0.0
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE.txt
18
+ Requires-Dist: numpy>=1.26
19
+ Provides-Extra: complete
20
+ Requires-Dist: matplotlib; extra == "complete"
21
+ Requires-Dist: plotly; extra == "complete"
22
+ Requires-Dist: unitpy; extra == "complete"
23
+ Requires-Dist: tkinterdnd2; extra == "complete"
24
+ Requires-Dist: urllib; extra == "complete"
25
+ Requires-Dist: json-equationer; extra == "complete"
26
+
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
+
30
+ # JSONGrapher (python)
31
+
32
+ Imagine a world where a person can simply drag a data file into a graphing utility and a plot will be made -- including axes with the data's units. Imagine that data from data other sources (with other units) can then be dragged in for comparison, with all data plotted on an interactive graph. Imagine that the units of all of these datasets will be converted automatically, as needed, during the plotting.
33
+
34
+ Create interactive plots just by drag-and-drop of JSON records. Share the json files for easy plotting by others. JSONGrapher will automatically convert units between records to plot the data sets together, to enable comparisons. 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.
35
+
36
+ To use python JSONGrapher, first install it using conda or pip:<br>
37
+ `pip install JSONGrapher[COMPLETE]` or `conda install conda-forge::jsongrapher` <br>
38
+ Alternatively, you can download the directory directly.<br>
39
+
40
+ ## **0\. Plotting a JSON Record**
41
+ To create an interactive plot, you just need one line of code! <br>
42
+ 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! Below are example 2D and 3D plots. <br>
43
+ Further below shows how easy it is to create your own json records.
44
+ <pre>
45
+ import JSONGrapher; JSONGrapher.launch()
46
+ # Then just drag records into the window!
47
+ </pre>
48
+
49
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/JSONGrapherWindowShortened.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/JSONGrapherWindowShortened.gif" width="20%"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
50
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/UAN_DTA_image.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/UAN_DTA_image.gif" width="25%"></a>
51
+ <br>
52
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_mesh3d.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_mesh3d.gif" width="35%"></a>
53
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_Scatter3d_example10.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_Scatter3d_example10.gif" width="35%"></a>
54
+ <br>
55
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_bubble.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/Rate_Constant_bubble.gif" width="35%"></a>&nbsp;&nbsp;&nbsp;
56
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/SrTiO3_rainbow_image.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/SrTiO3_rainbow_image.gif" width="30%"></a>
57
+ <br><br>
58
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/O_OH_Scaling.gif"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_1_drag_and_drop/images/O_OH_Scaling.gif" width="50%"></a>
59
+
60
+
61
+ ## **1\. Preparing to Create a Record**
62
+
63
+ The remainder of this landing page follows a json record tutorial [example file](https://github.com/AdityaSavara/jsongrapher-py/blob/main/examples/example_2_creating_records_and_using_styles/example_2_json_record_tutorial.py) which shows how to create graphable .json records. The records can then be plotted with python JSONGrapher or with jsongrapher.com<br>
64
+
65
+ Let's create an example where we plot the height of a pear tree over several years.
66
+ <pre>
67
+ Record = JSONRecordCreator.create_new_JSONGrapherRecord()
68
+ x_label_including_units = "Time (years)"
69
+ y_label_including_units = "Height (m)"
70
+ time_in_years = [0, 1, 2, 3, 4]
71
+ tree_heights = [0, 0.42, 0.86, 1.19, 1.45]
72
+ </pre>
73
+
74
+ ## **2\. Populating the New JSONGrapher Record**
75
+
76
+ <pre>
77
+ Record.set_comments("Tree Growth Data collected from the US National Arboretum")
78
+ Record.set_datatype("Tree_Growth_Curve")
79
+ Record.set_x_axis_label_including_units(x_label_including_units)
80
+ Record.set_y_axis_label_including_units(y_label_including_units)
81
+ Record.add_data_series(series_name="pear tree growth", x_values=time_in_years, y_values=tree_heights, plot_type="scatter_spline")
82
+ Record.set_graph_title("Pear Tree Growth Versus Time")
83
+ </pre>
84
+
85
+ ## **3\. Exporting to File**
86
+
87
+ We can export a record to a .json file, which can then be used with JSONGrapher.
88
+ <pre>
89
+ Record.export_to_json_file("ExampleFromTutorial.json")
90
+ Record.print_to_inspect()
91
+ </pre>
92
+
93
+ <p><strong>Expected Output:</strong></p>
94
+ <pre>
95
+ JSONGrapher Record exported to, ./ExampleFromTutorial.json
96
+ {
97
+ "comments": "Tree Growth Data collected from the US National Arboretum",
98
+ "datatype": "Tree_Growth_Curve",
99
+ "data": [
100
+ {
101
+ "name": "pear tree growth",
102
+ "x": [0, 1, 2, 3, 4],
103
+ "y": [0, 0.42, 0.86, 1.19, 1.45],
104
+ "type": "scatter",
105
+ "line": { "shape": "spline" }
106
+ }
107
+ ],
108
+ "layout": {
109
+ "title": "Pear Tree Growth Versus Time",
110
+ "xaxis": { "title": "Time (year)" },
111
+ "yaxis": { "title": "Height (m)" }
112
+ }
113
+ }
114
+ </pre>
115
+
116
+ ## **4\. Plotting to Inspect**
117
+
118
+ We can plot the data with plotly, interact with the graph, and save as a png file.
119
+ <pre>
120
+ Record.plot_with_plotly() #Try hovering your mouse over points after this command!
121
+ </pre>
122
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_2_creating_records_and_using_styles/image_from_tutorial_plotly_fig.png"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_2_creating_records_and_using_styles/image_from_tutorial_plotly_fig.png" width="40%"></a>
123
+
124
+ We can plot the data using Matplotlib and export the plot as a PNG file.
125
+ <pre>
126
+ Record.plot_with_matplotlib()
127
+ Record.export_to_matplotlib_png("image_from_tutorial_matplotlib_fig")
128
+ </pre>
129
+ <a href="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_2_creating_records_and_using_styles/image_from_tutorial_matplotlib_fig.png"><img src="https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_2_creating_records_and_using_styles/image_from_tutorial_matplotlib_fig.png" width="40%"></a>
130
+
131
+ You can also see more examples: https://github.com/AdityaSavara/jsongrapher-py/tree/main/examples
132
+
133
+ Additionally, json records you send to others can be plotted by them at www.jsongrapher.com
134
+ This 'see the plot using a browser' capability is intended to facilitate including JSONGrapher records in supporting information of scientific publications.
135
+
136
+
137
+ ## **Contributing to JSONGrapher, Feature Suggestions, and Reporting Issues**
138
+
139
+ These interactions should be through github at https://github.com/AdityaSavara/jsongrapher-py
140
+
141
+ 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.
142
+
143
+ To suggest features, create a new issue under the issues tab.
144
+
145
+ To report issues, create a new issue under the issues tab.
@@ -0,0 +1,19 @@
1
+ JSONGrapher/JSONRecordCreator.py,sha256=Wu5gCafri9g4bAAcyAJwlAoTLkExx7ssxjnQYcuGPUg,215343
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=bUff73G-qXNfPT8kDpDG9cWR4Adm49E9fp682pqJfbI,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.2.data/data/LICENSE.txt,sha256=7Guw_pmj_H4sApnM7fld2L4HH6CP-3ZYdFoOXtHFx0Y,1489
14
+ jsongrapher-4.2.data/data/README.md,sha256=u9uRPF0T12Pl6M6qjEleXZoB41ye0VTQPCJpEdldwNU,8157
15
+ jsongrapher-4.2.dist-info/LICENSE.txt,sha256=7Guw_pmj_H4sApnM7fld2L4HH6CP-3ZYdFoOXtHFx0Y,1489
16
+ jsongrapher-4.2.dist-info/METADATA,sha256=SmJRCR_Mh6cYNpdGZnB1AsA8C-k-iBD8Cvd_PcFojCo,9231
17
+ jsongrapher-4.2.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
18
+ jsongrapher-4.2.dist-info/top_level.txt,sha256=5f7Ui2hCKCPTQOjD540WKghKNYOvUDNfdpnDbIlAD3Y,12
19
+ jsongrapher-4.2.dist-info/RECORD,,
@@ -1,101 +0,0 @@
1
- # 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
- 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
-
6
- To use python JSONGrapher, first install it using conda or pip:<br>
7
- `pip install JSONGrapher[COMPLETE]` or `conda install conda-forge::jsongrapher` <br>
8
- Alternatively, you can download the directory directly.<br>
9
-
10
- ## **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.
13
- <pre>
14
- import JSONGrapher
15
- JSONGrapher.launch()
16
- </pre>
17
-
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)
19
-
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)
24
-
25
-
26
-
27
-
28
- ## **1\. Preparing to Create a Record**
29
-
30
- The remainder of this landing page follows a json record tutorial [example file](https://github.com/AdityaSavara/jsongrapher-py/blob/main/examples/example_2_creating_records_and_using_styles/example_2_json_record_tutorial.py) which shows how to create graphable .json records. The records can then be plotted with python JSONGrapher or with jsongrapher.com<br>
31
-
32
- Let's create an example where we plot the height of a pear tree over several years.
33
- <pre>
34
- x_label_including_units = "Time (years)"
35
- y_label_including_units = "Height (m)"
36
- time_in_years = [0, 1, 2, 3, 4]
37
- tree_heights = [0, 0.42, 0.86, 1.19, 1.45]
38
- </pre>
39
-
40
- ## **2\. Creating and Populating a New JSONGrapher Record**
41
-
42
- <pre>
43
- Record = JSONRecordCreator.create_new_JSONGrapherRecord()
44
- Record.set_comments("Tree Growth Data collected from the US National Arboretum")
45
- Record.set_datatype("Tree_Growth_Curve")
46
- Record.set_x_axis_label_including_units(x_label_including_units)
47
- Record.set_y_axis_label_including_units(y_label_including_units)
48
- Record.add_data_series(series_name="pear tree growth", x_values=time_in_years, y_values=tree_heights, plot_type="scatter_spline")
49
- Record.set_graph_title("Pear Tree Growth Versus Time")
50
- </pre>
51
-
52
- ## **3\. Exporting to File**
53
-
54
- We can export a record to a .json file, which can then be used with JSONGrapher.
55
- <pre>
56
- Record.export_to_json_file("ExampleFromTutorial.json")
57
- Record.print_to_inspect()
58
- </pre>
59
-
60
- <p><strong>Expected Output:</strong></p>
61
- <pre>
62
- JSONGrapher Record exported to, ./ExampleFromTutorial.json
63
- {
64
- "comments": "Tree Growth Data collected from the US National Arboretum",
65
- "datatype": "Tree_Growth_Curve",
66
- "data": [
67
- {
68
- "name": "pear tree growth",
69
- "x": [0, 1, 2, 3, 4],
70
- "y": [0, 0.42, 0.86, 1.19, 1.45],
71
- "type": "scatter",
72
- "line": { "shape": "spline" }
73
- }
74
- ],
75
- "layout": {
76
- "title": "Pear Tree Growth Versus Time",
77
- "xaxis": { "title": "Time (year)" },
78
- "yaxis": { "title": "Height (m)" }
79
- }
80
- }
81
- </pre>
82
-
83
- ## **4\. Plotting to Inspect**
84
-
85
- We can plot the data using Matplotlib and export the plot as a PNG file.
86
- <pre>
87
- Record.plot_with_matplotlib()
88
- Record.export_to_matplotlib_png("image_from_tutorial_matplotlib_fig")
89
- </pre>
90
-
91
- We can create an interactive graph with python plotly:
92
- <pre>
93
- Record.plot_with_plotly() #Try hovering your mouse over points after this command!
94
- </pre>
95
-
96
- [![JSONGRapher record plotted using matplotlib](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_2_creating_records_and_using_styles/image_from_tutorial_matplotlib_fig.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_2_creating_records_and_using_styles/image_from_tutorial_matplotlib_fig.png)
97
-
98
- You can also see more examples: https://github.com/AdityaSavara/jsongrapher-py/tree/main/examples
99
-
100
- 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.
@@ -1,128 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: jsongrapher
3
- Version: 3.9
4
- Summary: The python version of JSONGrapher with tools for creating JSONGrapher Records.
5
- Home-page: https://github.com/AdityaSavara/jsongrapher-py
6
- Author: Aditya Savara
7
- Author-email: AdityaSavara2008@u.northwestern.edu
8
- License: BSD-3-Clause
9
- Classifier: License :: OSI Approved :: BSD License
10
- Classifier: Programming Language :: Python
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.6
13
- Classifier: Programming Language :: Python :: Implementation :: CPython
14
- Classifier: Programming Language :: Python :: Implementation :: PyPy
15
- Requires-Python: >=3.0.0
16
- Description-Content-Type: text/markdown
17
- License-File: LICENSE
18
- Requires-Dist: numpy>=1.26
19
- Provides-Extra: complete
20
- Requires-Dist: matplotlib; extra == "complete"
21
- Requires-Dist: plotly; extra == "complete"
22
- Requires-Dist: unitpy; extra == "complete"
23
- Requires-Dist: tkinterdnd2; extra == "complete"
24
- Requires-Dist: urllib; extra == "complete"
25
- Requires-Dist: json-equationer; extra == "complete"
26
-
27
-
28
- # 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
- 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
-
33
- To use python JSONGrapher, first install it using conda or pip:<br>
34
- `pip install JSONGrapher[COMPLETE]` or `conda install conda-forge::jsongrapher` <br>
35
- Alternatively, you can download the directory directly.<br>
36
-
37
- ## **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.
40
- <pre>
41
- import JSONGrapher
42
- JSONGrapher.launch()
43
- </pre>
44
-
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)
46
-
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)
51
-
52
-
53
-
54
-
55
- ## **1\. Preparing to Create a Record**
56
-
57
- The remainder of this landing page follows a json record tutorial [example file](https://github.com/AdityaSavara/jsongrapher-py/blob/main/examples/example_2_creating_records_and_using_styles/example_2_json_record_tutorial.py) which shows how to create graphable .json records. The records can then be plotted with python JSONGrapher or with jsongrapher.com<br>
58
-
59
- Let's create an example where we plot the height of a pear tree over several years.
60
- <pre>
61
- x_label_including_units = "Time (years)"
62
- y_label_including_units = "Height (m)"
63
- time_in_years = [0, 1, 2, 3, 4]
64
- tree_heights = [0, 0.42, 0.86, 1.19, 1.45]
65
- </pre>
66
-
67
- ## **2\. Creating and Populating a New JSONGrapher Record**
68
-
69
- <pre>
70
- Record = JSONRecordCreator.create_new_JSONGrapherRecord()
71
- Record.set_comments("Tree Growth Data collected from the US National Arboretum")
72
- Record.set_datatype("Tree_Growth_Curve")
73
- Record.set_x_axis_label_including_units(x_label_including_units)
74
- Record.set_y_axis_label_including_units(y_label_including_units)
75
- Record.add_data_series(series_name="pear tree growth", x_values=time_in_years, y_values=tree_heights, plot_type="scatter_spline")
76
- Record.set_graph_title("Pear Tree Growth Versus Time")
77
- </pre>
78
-
79
- ## **3\. Exporting to File**
80
-
81
- We can export a record to a .json file, which can then be used with JSONGrapher.
82
- <pre>
83
- Record.export_to_json_file("ExampleFromTutorial.json")
84
- Record.print_to_inspect()
85
- </pre>
86
-
87
- <p><strong>Expected Output:</strong></p>
88
- <pre>
89
- JSONGrapher Record exported to, ./ExampleFromTutorial.json
90
- {
91
- "comments": "Tree Growth Data collected from the US National Arboretum",
92
- "datatype": "Tree_Growth_Curve",
93
- "data": [
94
- {
95
- "name": "pear tree growth",
96
- "x": [0, 1, 2, 3, 4],
97
- "y": [0, 0.42, 0.86, 1.19, 1.45],
98
- "type": "scatter",
99
- "line": { "shape": "spline" }
100
- }
101
- ],
102
- "layout": {
103
- "title": "Pear Tree Growth Versus Time",
104
- "xaxis": { "title": "Time (year)" },
105
- "yaxis": { "title": "Height (m)" }
106
- }
107
- }
108
- </pre>
109
-
110
- ## **4\. Plotting to Inspect**
111
-
112
- We can plot the data using Matplotlib and export the plot as a PNG file.
113
- <pre>
114
- Record.plot_with_matplotlib()
115
- Record.export_to_matplotlib_png("image_from_tutorial_matplotlib_fig")
116
- </pre>
117
-
118
- We can create an interactive graph with python plotly:
119
- <pre>
120
- Record.plot_with_plotly() #Try hovering your mouse over points after this command!
121
- </pre>
122
-
123
- [![JSONGRapher record plotted using matplotlib](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_2_creating_records_and_using_styles/image_from_tutorial_matplotlib_fig.png)](https://raw.githubusercontent.com/AdityaSavara/JSONGrapher-py/main/examples/example_2_creating_records_and_using_styles/image_from_tutorial_matplotlib_fig.png)
124
-
125
- You can also see more examples: https://github.com/AdityaSavara/jsongrapher-py/tree/main/examples
126
-
127
- Additionally, json records you send to others can be plotted by them at www.jsongrapher.com
128
- This 'see the plot using a browser' capability is intended to facilitate including JSONGrapher records in supporting information of scientific publications.
@@ -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,,