Skip to content

Analysis

plot_symmetry(json_file='cect/cache/symmetry_measures.json', synclass='Chemical', datasets_line1=None, datasets_line2=None)

Plot symmetry for specified synclass across selected datasets. Produces 3 subplots for SensorySomaticH, MotorSomaticH, InterneuronsSomaticH.

Parameters:

Name Type Description Default
json_file str

Path to the cached JSON file.

'cect/cache/symmetry_measures.json'
synclass str

Synapse class to plot, e.g., "Chemical".

'Chemical'
datasets_to_plot list

List of datasets to include. Defaults to all.

required
Source code in cect/Analysis.py
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
def plot_symmetry(
    json_file="cect/cache/symmetry_measures.json",
    synclass: str = "Chemical",
    datasets_line1=None,
    datasets_line2=None,
):
    """
    Plot symmetry for specified synclass across selected datasets.
    Produces 3 subplots for SensorySomaticH, MotorSomaticH, InterneuronsSomaticH.

    Parameters:
        json_file (str): Path to the cached JSON file.
        synclass (str): Synapse class to plot, e.g., "Chemical".
        datasets_to_plot (list, optional): List of datasets to include. Defaults to all.
    """
    # Load JSON data
    with open(json_file, "r") as f:
        data = json.load(f)

    views = [
        "SensorySomaticH",
        "MotorSomaticH",
        "InterneuronsSomaticH",
        "NonpharyngealH",
    ]

    if datasets_line1 is None:
        datasets_line1 = list(data.keys())
    if datasets_line2 is None:
        datasets_line2 = list(data.keys())

    x_labels = list(datasets_line2)
    x_full = np.arange(len(x_labels))

    fig, axes = plt.subplots(1, 3, figsize=(18, 5))
    fig.suptitle(f"Symmetry Across SomaticH Views ({synclass})", fontsize=16)

    def get_val(view, dataset):
        val = data.get(dataset, {}).get(view, {}).get(synclass)
        if val is None:
            return None
        try:
            return float(val)
        except (ValueError, TypeError):
            return None

    for i, view in enumerate(views):
        ax = axes[0]

        # --- Line 1 (baseline): use only its own x positions; this keeps the line continuous across Yim2024 ---
        x1 = []
        y1 = []
        for idx, lbl in enumerate(x_labels):
            if lbl in datasets_line1:
                v = get_val(view, lbl)
                if v is not None:
                    x1.append(idx)
                    y1.append(v)
        # --- Line 2 (with Yim2024): aligned to every x tick in datasets_line2 ---
        y2 = [get_val(view, lbl) if lbl in datasets_line2 else None for lbl in x_labels]
        # Convert None to np.nan for plotting
        y2 = [np.nan if v is None else v for v in y2]

        ax.plot(x1, y1, marker="o", linestyle="-", label="Normal")
        ax.plot(x_full, y2, marker="s", linestyle="--", label="Dauer")

        ax.set_xticks(x_full)
        ax.set_xticklabels(x_labels, rotation=45, ha="right")
        ax.set_title(view, fontsize=14)
        ax.set_xlabel("Dataset", fontsize=12)
        ax.set_ylabel("Symmetry (%)", fontsize=12)
        ax.set_ylim(0, 105)
        ax.grid(True, linestyle="--", alpha=0.5)
        ax.legend()

    plt.tight_layout(rect=[0, 0, 1, 0.95])
    plt.show()