jsongrapher 4.2__py3-none-any.whl → 4.4__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.
@@ -610,13 +610,13 @@ class JSONGrapherRecord:
610
610
  "comments": comments, # Top-level comments
611
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__,
612
612
  "datatype": datatype, # Top-level datatype (datatype)
613
- "data": data_objects_list if data_objects_list else [], # Data series list
614
613
  "layout": layout if layout else {
615
614
  "title": {"text": graph_title},
616
615
  "xaxis": {"title": {"text": x_axis_label_including_units}},
617
616
  "yaxis": {"title": {"text": y_axis_label_including_units}}
618
- }
619
- }
617
+ },
618
+ "data": data_objects_list if data_objects_list else [] # Data series list
619
+ }
620
620
  )
621
621
 
622
622
  if plot_style !="":
@@ -1940,7 +1940,8 @@ def apply_plot_style_to_plotly_dict(fig_dict, plot_style=None):
1940
1940
  if str(plot_style["layout_style"]).lower() != 'none': #take no action if received "None" or NoneType
1941
1941
  if plot_style["layout_style"] == '': #in this case, we're going to use the default.
1942
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.")
1943
+ if "z" in fig_dict["data"][0]:
1944
+ print("Warning: No layout_style provided and 'z' field found in first data series. For 'bubble2d' 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.")
1944
1945
  fig_dict = remove_layout_style_from_plotly_dict(fig_dict=fig_dict)
1945
1946
  fig_dict = apply_layout_style_to_plotly_dict(fig_dict=fig_dict, layout_style_to_apply=plot_style["layout_style"])
1946
1947
  #Code logic for trace_styles_collection style.
@@ -2219,16 +2220,19 @@ def apply_trace_style_to_single_data_series(data_series, trace_styles_collection
2219
2220
  if isinstance(trace_style, str): #check if it is a string type.
2220
2221
  if "__" in trace_style:
2221
2222
  trace_style, colorscale = trace_style.split("__")
2223
+ if ("bubble" in trace_style) and ("bubble3d" not in trace_style) and ("bubble2d" not in trace_style):
2224
+ trace_style = trace_style.replace("bubble", "bubble2d")
2222
2225
 
2223
2226
  colorscale_structure = "" #initialize this variable for use later. It tells us which fields to put the colorscale related values in. This should be done before regular trace_style fields are applied.
2224
2227
  #3D and bubble plots will have a colorscale by default.
2225
- if trace_style == "bubble": #for bubble trace styles, we need to move the z values into the marker size. We also need to do this before the styles_dict collection is accessed, since then the trace_style becomes a dictionary.
2226
- data_series = prepare_bubble_sizes(data_series)
2227
- colorscale_structure = "bubble"
2228
- elif trace_style == "mesh3d": #for bubble trace styles, we need to move the z values into the marker size. We also need to do this before the styles_dict collection is accessed, since then the trace_style becomes a dictionary.
2229
- colorscale_structure = "mesh3d"
2230
- elif trace_style == "scatter3d": #for bubble trace styles, we need to move the z values into the marker size. We also need to do this before the styles_dict collection is accessed, since then the trace_style becomes a dictionary.
2231
- colorscale_structure = "scatter3d"
2228
+ if isinstance(trace_style,str):
2229
+ if "bubble" in trace_style.lower(): #for bubble trace styles (both 2D and 3D), we need to prepare the bubble sizes. We also need to do this before the styles_dict collection is accessed, since then the trace_style becomes a dictionary.
2230
+ data_series = prepare_bubble_sizes(data_series)
2231
+ colorscale_structure = "bubble"
2232
+ elif "mesh3d" in trace_style.lower():
2233
+ colorscale_structure = "mesh3d"
2234
+ elif "scatter3d" in trace_style.lower():
2235
+ colorscale_structure = "scatter3d"
2232
2236
 
2233
2237
  if trace_style in styles_collection_dict:
2234
2238
  trace_style = styles_collection_dict.get(trace_style)
@@ -2248,7 +2252,7 @@ def apply_trace_style_to_single_data_series(data_series, trace_styles_collection
2248
2252
  data_series[key] = value # Direct assignment for non-dictionary values
2249
2253
 
2250
2254
  #Before applying colorscales, we check if we have recieved a colorscale from the user. If so, we'll need to parse the trace_type to assign the colorscale structure.
2251
- if colorscale != "":
2255
+ if ((colorscale_structure == "") and (colorscale != "")):
2252
2256
  #If it is a scatter plot with markers, then the colorscale_structure will be marker. Need to check for this before the lines alone case.
2253
2257
  if ("markers" in data_series["mode"]) or ("markers+lines" in data_series["mode"]) or ("lines+markers" in data_series["mode"]):
2254
2258
  colorscale_structure = "marker"
@@ -2260,7 +2264,7 @@ def apply_trace_style_to_single_data_series(data_series, trace_styles_collection
2260
2264
  #Block of code to clean color values for 3D plots and 2D plots. It can't be just from the style dictionary because we need to point to data.
2261
2265
  def clean_color_values(list_of_values, variable_string_for_warning):
2262
2266
  if None in list_of_values:
2263
- print("Warning: A colorscale based on" + variable_string_for_warning + "was requested. None values were found. They are being replaced with 0 values. It is recommended to provide data without None values.")
2267
+ print("Warning: A colorscale based on " + variable_string_for_warning + " was requested. None values were found. They are being replaced with 0 values. It is recommended to provide data without None values.")
2264
2268
  color_values = [0 if value is None else value for value in list_of_values]
2265
2269
  else:
2266
2270
  color_values = list_of_values
@@ -2268,6 +2272,8 @@ def apply_trace_style_to_single_data_series(data_series, trace_styles_collection
2268
2272
 
2269
2273
  if colorscale_structure == "bubble":
2270
2274
  #data_series["marker"]["colorscale"] = "viridis_r" #https://plotly.com/python/builtin-colorscales/
2275
+ if colorscale != "": #this means there is a user specified colorscale.
2276
+ data_series["marker"]["colorscale"] = colorscale
2271
2277
  data_series["marker"]["showscale"] = True
2272
2278
  if "z" in data_series:
2273
2279
  color_values = clean_color_values(list_of_values= data_series["z"], variable_string_for_warning="z")
@@ -2277,6 +2283,8 @@ def apply_trace_style_to_single_data_series(data_series, trace_styles_collection
2277
2283
  data_series["marker"]["color"] = color_values
2278
2284
  elif colorscale_structure == "scatter3d":
2279
2285
  #data_series["marker"]["colorscale"] = "viridis_r" #https://plotly.com/python/builtin-colorscales/
2286
+ if colorscale != "": #this means there is a user specified colorscale.
2287
+ data_series["marker"]["colorscale"] = colorscale
2280
2288
  data_series["marker"]["showscale"] = True
2281
2289
  if "z" in data_series:
2282
2290
  color_values = clean_color_values(list_of_values= data_series["z"], variable_string_for_warning="z")
@@ -2286,6 +2294,8 @@ def apply_trace_style_to_single_data_series(data_series, trace_styles_collection
2286
2294
  data_series["marker"]["color"] = color_values
2287
2295
  elif colorscale_structure == "mesh3d":
2288
2296
  #data_series["colorscale"] = "viridis_r" #https://plotly.com/python/builtin-colorscales/
2297
+ if colorscale != "": #this means there is a user specified colorscale.
2298
+ data_series["colorscale"] = colorscale
2289
2299
  data_series["showscale"] = True
2290
2300
  if "z" in data_series:
2291
2301
  color_values = clean_color_values(list_of_values= data_series["z"], variable_string_for_warning="z")
@@ -2313,10 +2323,18 @@ def prepare_bubble_sizes(data_series):
2313
2323
  #We also will scale them to some maximum bubble size that is specifed.
2314
2324
  if "marker" not in data_series:
2315
2325
  data_series["marker"] = {}
2316
- if "z_points" in data_series:
2326
+ if "bubble_sizes" in data_series:
2327
+ if isinstance(data_series["bubble_sizes"], str): #if bubble sizes is a string, it must be a variable name to use for the bubble sizes.
2328
+ bubble_sizes_variable_name = data_series["bubble_sizes"]
2329
+ data_series["marker"]["size"] = data_series[bubble_sizes_variable_name]
2330
+ else:
2331
+ data_series["marker"]["size"] = data_series["bubble_sizes"]
2332
+ elif "z_points" in data_series:
2317
2333
  data_series["marker"]["size"] = data_series["z_points"]
2318
2334
  elif "z" in data_series:
2319
2335
  data_series["marker"]["size"] = data_series["z"]
2336
+ elif "y" in data_series:
2337
+ data_series["marker"]["size"] = data_series["y"]
2320
2338
 
2321
2339
  #now need to normalize to the max value in the list.
2322
2340
  def normalize_to_max(starting_list):
@@ -2338,7 +2356,7 @@ def prepare_bubble_sizes(data_series):
2338
2356
  if "max_bubble_size" in data_series:
2339
2357
  max_bubble_size = data_series["max_bubble_size"]
2340
2358
  else:
2341
- max_bubble_size = 10
2359
+ max_bubble_size = 100
2342
2360
  scaled_sizes = normalized_sizes*max_bubble_size
2343
2361
  data_series["marker"]["size"] = scaled_sizes.tolist() #from numpy array back to list.
2344
2362
 
@@ -2441,7 +2459,11 @@ def extract_trace_style_from_data_series_dict(data_series_dict, new_trace_style_
2441
2459
  additional_attributes_to_extract = []
2442
2460
 
2443
2461
  if new_trace_style_name=='':
2444
- new_trace_style_name = data_series_dict.get("trace_style", "") #keep blank if not present.
2462
+ #Check if there is a current trace style that is a string, and use that for the name if present.
2463
+ current_trace_style = data_series_dict.get("trace_style", "")
2464
+ if isinstance(current_trace_style, str):
2465
+ new_trace_style_name = current_trace_style
2466
+ #if there is still no new_trace_style_name, we will name it 'custom'
2445
2467
  if new_trace_style_name=='':
2446
2468
  new_trace_style_name = "custom"
2447
2469
 
@@ -3101,11 +3123,10 @@ def convert_to_3d_layout(layout):
3101
3123
  new_layout = copy.deepcopy(layout)
3102
3124
 
3103
3125
  # Add the axis fields inside `scene` first
3104
- new_layout["scene"] = {
3105
- "xaxis": layout.get("xaxis", {}),
3106
- "yaxis": layout.get("yaxis", {}),
3107
- "zaxis": layout.get("zaxis", {})
3108
- }
3126
+ scene = new_layout.setdefault("scene", {}) #Create a new dict if not present, otherwise use existing one.
3127
+ scene["xaxis"] = layout.get("xaxis", {})
3128
+ scene["yaxis"] = layout.get("yaxis", {})
3129
+ scene["zaxis"] = layout.get("zaxis", {})
3109
3130
 
3110
3131
  # Remove the original axis fields from the top-level layout
3111
3132
  new_layout.pop("xaxis", None)
@@ -3120,19 +3141,40 @@ def remove_bubble_fields(fig_dict):
3120
3141
  #This code will modify the data_series inside the fig_dict, directly.
3121
3142
  bubble_found = False #initialize with false case.
3122
3143
  for data_series in fig_dict["data"]:
3123
- if "trace_style" in data_series:
3124
- if (data_series["trace_style"] == "bubble") or ("max_bubble_size" in data_series):
3144
+ trace_style = data_series.get("trace_style") #trace_style will be None of the key is not present.
3145
+
3146
+ if isinstance(trace_style, str):
3147
+ #If the style is just "bubble" (not explicitly 2D or 3D), default to bubble2d for backward compatibility
3148
+ if ("bubble" in trace_style) and ("bubble3d" not in trace_style) and ("bubble2d" not in trace_style):
3149
+ trace_style = trace_style.replace("bubble", "bubble2d")
3150
+ if ("bubble" in trace_style.lower()) or ("max_bubble_size" in data_series):
3125
3151
  bubble_found = True
3126
- if bubble_found == True:
3127
- if "z" in data_series:
3128
- data_series.pop("z")
3129
- if "z_points" in data_series:
3130
- data_series.pop("z_points")
3152
+ if bubble_found is True:
3153
+ if "bubble2d" in trace_style.lower(): #pop the z variable if it's a bubble2d.
3154
+ if "z" in data_series:
3155
+ data_series.pop("z")
3156
+ if "z_points" in data_series:
3157
+ data_series.pop("z_points")
3131
3158
  if "max_bubble_size" in data_series:
3132
3159
  data_series.pop("max_bubble_size")
3133
- if bubble_found == True:
3134
- if "zaxis" in fig_dict["layout"]:
3135
- fig_dict["layout"].pop("zaxis")
3160
+ if "bubble_sizes" in data_series:
3161
+ # Now, need to check if the bubble_size is a variable that should be deleted.
3162
+ # That will be if it is a string, and also not a standard variable.
3163
+ if isinstance(data_series["bubble_sizes"], str):
3164
+ bubble_sizes_variable_name = data_series["bubble_sizes"]
3165
+ # For bubble2d case, will remove anything that is not x or y.
3166
+ if "bubble2d" in trace_style.lower():
3167
+ if bubble_sizes_variable_name not in ("x", "y"):
3168
+ data_series.pop(bubble_sizes_variable_name, None)
3169
+ if "bubble3d" in trace_style.lower():
3170
+ if bubble_sizes_variable_name not in ("x", "y", "z"):
3171
+ data_series.pop(bubble_sizes_variable_name, None)
3172
+ # next, remove bubble_sizes since it's not needed anymore and should be removed.
3173
+ data_series.pop("bubble_sizes")
3174
+ # need to remove "zaxis" if making a bubble2d.
3175
+ if "bubble2d" in trace_style.lower():
3176
+ if "zaxis" in fig_dict["layout"]:
3177
+ fig_dict["layout"].pop("zaxis")
3136
3178
  return fig_dict
3137
3179
 
3138
3180
  def update_3d_axes(fig_dict):
@@ -17,6 +17,7 @@ styles_library = {
17
17
  },
18
18
  "default3d": {
19
19
  "layout": {
20
+ "scene": {"aspectmode":"cube"},
20
21
  "title": {"font": {"size": 32}, "x": 0.5},
21
22
  "xaxis": {"title": {"font": {"size": 12}}, "tickfont": {"size": 12}},
22
23
  "yaxis": {"title": {"font": {"size": 12}}, "tickfont": {"size": 12}},
@@ -42,6 +42,15 @@ styles_library = {
42
42
  "showscale": True
43
43
  }
44
44
  },
45
+ "bubble2d": {
46
+ "type": "scatter",
47
+ "mode": "markers",
48
+ "marker": {
49
+ "color": "auto",
50
+ "colorscale": "viridis_r",
51
+ "showscale": True
52
+ }
53
+ },
45
54
  "spline": {
46
55
  "type": "scatter",
47
56
  "mode": "lines",
@@ -76,6 +85,11 @@ styles_library = {
76
85
  "colorscale":"rainbow",
77
86
  "showscale":True
78
87
  },
88
+ "bubble3d": {
89
+ "mode": "markers",
90
+ "type": "scatter3d",
91
+ "marker": {"color" : "","colorscale":"rainbow", "showscale":True}
92
+ },
79
93
  "heatmap": {
80
94
  "type": "heatmap",
81
95
  "colorscale": "Viridis",
JSONGrapher/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = '4.2'
1
+ __version__ = '4.4'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jsongrapher
3
- Version: 4.2
3
+ Version: 4.4
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
@@ -1,4 +1,4 @@
1
- JSONGrapher/JSONRecordCreator.py,sha256=Wu5gCafri9g4bAAcyAJwlAoTLkExx7ssxjnQYcuGPUg,215343
1
+ JSONGrapher/JSONRecordCreator.py,sha256=7AlusrLNjMkqOZd3A_Kb_tyhqF-QOvRn7uQQGaXybFY,218318
2
2
  JSONGrapher/UnitPytesting.py,sha256=xizJ-2fg9C5oNMFJyfavbBLMusayE9KWQiYIRrQQd4A,4363
3
3
  JSONGrapher/UnitpyCustomUnitsTesting.py,sha256=Rwq5p8HXN0FP54lRFgLTV0kgJ9TpcFaD3_C0MEOoEzw,1297
4
4
  JSONGrapher/__init__.py,sha256=fA3R6paWq3uskiLe3OglQZY_uJOejZHMFKdyX0dXWjo,310
@@ -6,14 +6,14 @@ JSONGrapher/drag_and_drop_gui.py,sha256=-7QJHLhzadHotWhONH4inerMaZ_xuwoTQSMRF_MP
6
6
  JSONGrapher/equation_creator.py,sha256=VFu6dFo-C0wDf1N3e0CyCBI-53cCUrp3oe0umdMLofs,17968
7
7
  JSONGrapher/equation_evaluator.py,sha256=Cm7UK5vWa6fT0OylD9f22_eR8zUvxY_Sy_W6n6N9bew,37012
8
8
  JSONGrapher/units_list.py,sha256=ROrlAsD66oPozZmOaE65xjNUEg3CxkSmA8iPE2_ihYI,34438
9
- JSONGrapher/version.py,sha256=bUff73G-qXNfPT8kDpDG9cWR4Adm49E9fp682pqJfbI,19
9
+ JSONGrapher/version.py,sha256=qBnDha-1O1-zjh3MFXQsOlQrB1ykLZIoeKE5jHBMh-k,19
10
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,,
11
+ JSONGrapher/styles/layout_styles_library.py,sha256=adGZNVAj_VysYX-9x1NqxDnhIQFtKsMW8swGaY30ocs,3100
12
+ JSONGrapher/styles/trace_styles_collection_library.py,sha256=4WhrmsSotPGRwFplGPoRjTiyFd3PMneg5mUewjZMK88,6437
13
+ jsongrapher-4.4.data/data/LICENSE.txt,sha256=7Guw_pmj_H4sApnM7fld2L4HH6CP-3ZYdFoOXtHFx0Y,1489
14
+ jsongrapher-4.4.data/data/README.md,sha256=u9uRPF0T12Pl6M6qjEleXZoB41ye0VTQPCJpEdldwNU,8157
15
+ jsongrapher-4.4.dist-info/LICENSE.txt,sha256=7Guw_pmj_H4sApnM7fld2L4HH6CP-3ZYdFoOXtHFx0Y,1489
16
+ jsongrapher-4.4.dist-info/METADATA,sha256=XwDZLT51CId5nJG7-Mu-885q8NmVDvt168xza0qEuvc,9231
17
+ jsongrapher-4.4.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
18
+ jsongrapher-4.4.dist-info/top_level.txt,sha256=5f7Ui2hCKCPTQOjD540WKghKNYOvUDNfdpnDbIlAD3Y,12
19
+ jsongrapher-4.4.dist-info/RECORD,,