Skip to content

Commit 87b84e8

Browse files
v1.3.0
1 parent 247a3bd commit 87b84e8

7 files changed

Lines changed: 83 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
8+
## [1.3.0] - 2025-09-25
9+
10+
### Added
11+
- ability to pass any plotly keyword arguments e.g. 'font' and or 'legend' via `update_layout_kwargs`
12+
13+
### Changed
14+
- useability improvement: space characters are stripped from x_id, y_id and also from the loaded dataframe column headers therefore leading and trailing spaces no longer create errors
15+
716
## [1.2.0] - 2025-09-05
817

918
### Added

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Plotme takes tabular data (e.g. excel) and outputs interactive scatter plots. It
1717
* error bars
1818
* axes kwargs
1919
* [pio.templates](https://plotly.com/python/templates/)
20+
* pass any plotly keyword arguments e.g. 'font' and or 'legend' `update_layout_kwargs`
2021
* auto-detect data files (xls, xlsx, csv only)
2122
* supported data files: xls, xlsx, csv, txt
2223
* filter data files (include and exclude) `folder_include_filter`, `folder_exclude_filter`,
@@ -45,6 +46,42 @@ Plotme takes tabular data (e.g. excel) and outputs interactive scatter plots. It
4546
3. modify the template as needed
4647
4. run again to generate plot(s)
4748

49+
50+
### example JSON plot_info.json file
51+
in this example
52+
* the x value is extracted from the file name via regular expression
53+
* each point on the scatter plot is the maximum value from a column called `Force(N)-data` where the header is located at the 4th row of a data file
54+
* the legend is inside the plot in the right top corner, by default the legend is outside the plot on the right side
55+
```json
56+
{
57+
"title_text": "Force over temperature",
58+
"x_id": "_(\\d+)C",
59+
"x_title": "Temperature (C)",
60+
"y_id": "Force(N)-data",
61+
"y_title": "Max Force (N)",
62+
"showlegend": true,
63+
"update_layout_args": {
64+
"legend": {"xanchor": "right", "yanchor": "top"},
65+
"font": {"size": 17}
66+
},
67+
"x_axes_kwargs": {
68+
"type": "-"
69+
},
70+
"y_axes_kwargs": {
71+
"type": "log"
72+
},
73+
"xaxes_visible": true,
74+
"yaxes_visible": true,
75+
"schema": {
76+
"header": 3,
77+
"x_id_is_reg_exp": true
78+
},
79+
"post": "max",
80+
"pio.template": "plotly_white",
81+
"trace_mode": "markers"
82+
}
83+
```
84+
4885
## Contribute
4986

5087
### unimplemented ideas, in order of priority

plotme/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os
22

3-
__version__ = '1.2.0'
3+
__version__ = '1.3.0'
44

55
os.environ['PLOTME_VERSION'] = __version__

plotme/helper.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,29 @@ def start_logging(log_folder='', log_level=logging.INFO, file_name='',
5353
logging.info('info logging active')
5454
logging.warning('warning logging active')
5555
logging.error('error logging active')
56+
57+
58+
def strip_white_space(string_or_strings):
59+
"""
60+
Strips leading and trailing white space from a string or any iterable of strings
61+
62+
Parameters
63+
----------
64+
string_or_strings: str or iterable
65+
string or iterable of strings to be stripped
66+
67+
Returns
68+
-------
69+
str or same type as input
70+
stripped string or iterable of stripped strings
71+
"""
72+
if isinstance(string_or_strings, str):
73+
return string_or_strings.strip()
74+
else:
75+
try:
76+
# Try to iterate over the input
77+
stripped_items = [s.strip() for s in string_or_strings]
78+
# Return the same type as input (list, tuple, etc.)
79+
return type(string_or_strings)(stripped_items)
80+
except TypeError:
81+
raise ValueError(f"Unexpected type: {type(string_or_strings)}, expected str or iterable")

plotme/load_data.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@ def __init__(self, directory, x_id='', y_id='', args_dict={}):
153153
file_info = {'file_stem' : file_path.stem,
154154
'file_path': str(file_path)}
155155
df = read(file, index_col=index_col, header=header)
156+
157+
# strip only beginning and ending white space from column headers
158+
df.columns = df.columns.str.strip()
156159

157160
# if x_id or y_id not a columns header, try to fuzzy match it
158161
# if matching doesn't work then skip the file

plotme/plotting.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from jsonschema import validate
1111
from plotly.subplots import make_subplots
1212

13+
from plotme.helper import strip_white_space
1314
from plotme.load_data import Folder, check_filter_match
1415
from plotme.schema import schema, template
1516

@@ -88,12 +89,15 @@ def single_plot(args_dict={}):
8889

8990
title = args_dict.get('title_text', 'plotme plot')
9091
x_id = args_dict.get('x_id', 'index')
92+
x_id = strip_white_space(x_id)
9193
x_title = args_dict.get('x_title', x_id) # use x_id if no label is given
9294
y_id = args_dict.get('y_id', 'headers')
95+
y_id = strip_white_space(y_id)
9396
y_title = args_dict.get('y_title', y_id) # use y_id if no label is given
9497
trace_mode = args_dict.get('trace_mode', 'markers')
9598
marker_symbols = args_dict.get('marker_symbols')
9699
show_legend = args_dict.get('showlegend', True)
100+
update_layout_kwargs = args_dict.get('update_layout_args', {})
97101
x_axes_kwargs = args_dict.get('x_axes_kwargs', {})
98102
y_axes_kwargs = args_dict.get('y_axes_kwargs', {})
99103
x_axes_visible = args_dict.get('xaxes_visible', True)
@@ -203,6 +207,7 @@ def single_plot(args_dict={}):
203207

204208
fig.update_layout(height=height, width=width, title_text=title)
205209
fig.update_layout(showlegend=show_legend)
210+
fig.update_layout(**update_layout_kwargs)
206211
fig.update_xaxes(visible=x_axes_visible, **x_axes_kwargs)
207212
fig.update_yaxes(visible=y_axes_visible, **y_axes_kwargs)
208213

plotme/schema.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"y_title": {"type": "string"},
99
"y_id": {"type": ["array", "string"], "items": {"type": "string"}},
1010
"showlegend": {"type": "boolean"},
11+
"update_layout_kwargs": {"type": "object"},
1112
"xaxes_visible": {"type": "boolean"},
1213
"yaxes_visible": {"type": "boolean"},
1314
"folder_include_filter": {"type": "string"},
@@ -75,6 +76,7 @@
7576
"y_title": "label in plot, y_id used if unspecified",
7677
"y_id": ["array of column headers, single column header or column letter"],
7778
"showlegend": True,
79+
"update_layout_kwargs": "pass through any fig.update_layout key word arguments to plotly",
7880
"xaxes_visible": True,
7981
"yaxes_visible": True,
8082
"folder_include_filter": "must be in the folder name, string or array of strings",

0 commit comments

Comments
 (0)