OSCR

Medial prefrontal cortex neurons integrate amygdala and hypothalamic oxytocin signals to mediate stress-induced social alterations.

Code ↔ Paper

1 match between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 1 match
  1. [1] § Material and methods › In vivo microendoscopic calcium imaging › Principal component analysis ↔ Functions_PCA.py, lines 549–585 · score 0.61 · Explained variance ratioes, PCs, component, PCA, behaviours

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Python · 662 lines · 20 KB · no license · 1 match

  1. # Functions.py
  2. #
  3. # Author: Xiaoqian Sun, Apr 2023
  4. #
  5. # Functions for projection project
  6. from IPython.core.debugger import set_trace
  7. # Import Packages
  8. #========================================================================================
  9. import os
  10. import cv2
  11. import math
  12. import itertools
  13. import scipy as sp
  14. import numpy as np
  15. import pandas as pd
  16. from PIL import Image
  17. import seaborn as sns
  18. import tifffile as tiff
  19. import matplotlib as mpl
  20. from itertools import groupby
  21. from operator import itemgetter
  22. import matplotlib.pyplot as plt
  23. from scipy.stats import pearsonr
  24. import matplotlib.colors as mcolors
  25. from sklearn.decomposition import PCA
  26. # from oasis.functions import deconvolve
  27. from sklearn.preprocessing import MinMaxScaler
  28. from scipy.ndimage.filters import gaussian_filter
  29. from sklearn.ensemble import RandomForestClassifier
  30. from sklearn.model_selection import train_test_split
  31. from scipy.signal import chirp, find_peaks, peak_widths
  32. import warnings
  33. warnings.filterwarnings('ignore')
  34. # Functions
  35. #========================================================================================
  36. def process_frame(df):
  37. '''
  38. Aim:
  39. frame 0 at trace file may not sart from time 0
  40. called in function `add_event_label()`
  41. '''
  42. # get frame list
  43. frame_list = df.index.values.tolist()
  44. # get starting value
  45. a = frame_list[0]
  46. new_frame_list = [(i-a) for i in frame_list]
  47. return(new_frame_list)
  48. def process_event_interval(df):
  49. '''
  50. Aim:
  51. time in event file doesn't always start from 0s, fix that
  52. called in function `add_event_label()`
  53. '''
  54. new_col = []
  55. for col in df.columns.tolist():
  56. new_col.append(col.strip())
  57. df.columns = new_col
  58. event_list = df[['From Second','To Second']].values.tolist()
  59. startTime = df['From Second'].values.tolist()[0]
  60. new_event_list = []
  61. for event in event_list:
  62. new_event = [x -startTime for x in event]
  63. new_event_list.append(new_event)
  64. return(new_event_list)
  65. # +
  66. def get_event_label(event_df):
  67. '''
  68. Aim:
  69. for OFT
  70. translate 'event' in eventFile to integer label
  71. each row (corresponding to each time interval) of event is assigned a label
  72. called in function `add_event_label()`
  73. '''
  74. # get event status list
  75. Event_status = event_df['Event'].values.tolist()
  76. # compact event label list for three sessions
  77. event_label = []
  78. # ['In_all',
  79. # 'In_right',
  80. # 'Investigating_RIGHT_SNIFF',
  81. # 'In_left',
  82. # 'Investigating_LEFT_SNIFF']
  83. # if which_status_to_check_frame == 'Investigating_RIGHT_SNIFF':
  84. # which_status_to_check_frame = str(11)
  85. # elif which_status_to_check_frame == 'Investigating_LEFT_SNIFF':
  86. # which_status_to_check_frame = str(12)
  87. # elif which_status_to_check_frame == 'In_right':
  88. # which_status_to_check_frame = str(21)
  89. # elif which_status_to_check_frame == 'In_all':
  90. # which_status_to_check_frame = str(22)
  91. # elif which_status_to_check_frame == 'In_left':
  92. # which_status_to_check_frame = str(23)
  93. # else:
  94. for i in Event_status:
  95. if i.strip() == 'In_right':
  96. event_label.append(21)
  97. elif i.strip() == 'Investigating_RIGHT_SNIFF' :
  98. event_label.append(11)
  99. elif i.strip() == 'In_left':
  100. event_label.append(23)
  101. elif i.strip() == 'Investigating_LEFT_SNIFF':
  102. event_label.append(12)
  103. else:
  104. event_label.append(22)
  105. # for i in Event_status:
  106. # if i.strip() == 'Area:Mouse 1 Center In floor':
  107. # event_label.append(10)
  108. # elif i.strip() == 'Area:Mouse 1 Center In All ' :
  109. # event_label.append(10)
  110. # elif i.strip() == 'Area:Mouse 1 Center In central area':
  111. # event_label.append(11)
  112. # elif i.strip() == 'Area:Mouse 1 Center In corner':
  113. # event_label.append(12)
  114. # elif i.strip() == 'Mouse 1 sniffing On wall':
  115. # event_label.append(30)
  116. # elif i.strip() == 'Mouse 1 Grooming in Area All':
  117. # event_label.append(31)
  118. # elif i.strip() == 'Mouse 1 Grooming in Area floor':
  119. # event_label.append(31)
  120. # elif i.strip() == 'Mouse 1 Locomotion in Area All':
  121. # event_label.append(32)
  122. # else:
  123. # event_label.append(90)
  124. return(event_label)
  125. # -
  126. def add_event_label(trace_df, event_path):
  127. '''
  128. Aim:
  129. add event_label to each frame
  130. one frame can have several label (since mouse can in a location and do something)
  131. Retrun:
  132. trace dataframe with one label column
  133. '''
  134. frame_list = process_frame(trace_df)
  135. #get event dataframe/eventIntervals/eventLabel
  136. # event_df = pd.read_csv(event_path)
  137. event_df = pd.read_excel(event_path)
  138. interval_list = process_event_interval(event_df)
  139. event_label = get_event_label(event_df)
  140. # add label to each frame
  141. frame_label_list = []
  142. for frame in frame_list:
  143. frame_label = str()
  144. for i in range(len(interval_list)): # one frame can be in several interval
  145. if min(interval_list[i]) <= frame <= max(interval_list[i]) :
  146. frame_label = frame_label+ str(event_label[i])
  147. # convert str to int
  148. if len(frame_label) == 0:
  149. frame_label = np.nan
  150. else:
  151. frame_label = int(frame_label)
  152. # append frame label to list
  153. frame_label_list.append(frame_label)
  154. # add label list to trace df
  155. new_df = trace_df.copy()
  156. new_df['Frame_Label'] = frame_label_list
  157. new_df = new_df.dropna()
  158. return(new_df)
  159. def find_compositeIntervals(df,
  160. which_status_to_check,
  161. intervalLength=20,
  162. if_CombineAdjacentChunks=True,
  163. gapMax=10):
  164. '''
  165. Aim:
  166. a mouse might get into a location/behavior several time during a whole session. this function is to
  167. find all intervals that the mouse gets into certain state.
  168. Arguments:
  169. - df: neuron activity df with status label for each frame (1-in state)
  170. - which_status_to_check: behavior/location (choose from center/corner/sniffing/grooming)
  171. - intervalLength: minimum size of state-interval, that is the interval must longer than #_frames, otherwise, this interval will be dumped
  172. - if_CombineAdjacentChunks: if merge 2 neighbours
  173. - gapMax: if gap between two chunks less than gapMax, merge the two
  174. Return:
  175. - kept chunks, sublists in list
  176. '''
  177. df_status = check_frame_interval(df, which_status_to_check, ifKeep=True)
  178. # get status list
  179. status_list = df_status['status'].values.tolist()
  180. # get 1 index
  181. index_1_list = [i for i, x in enumerate(status_list) if x == 1]
  182. # pick all consecutive chunks
  183. chunks = []
  184. try:
  185. for k, g in groupby(enumerate(index_1_list), lambda ix:ix[0]-ix[1]):
  186. chunk = list((map(itemgetter(1), g)))
  187. chunks.append([chunk[0], chunk[-1]])
  188. # combine small chunks
  189. if if_CombineAdjacentChunks:
  190. combinedchunks = []
  191. combinedchunks.append(chunks[0]) # initialize with first chunk
  192. #print('starting point', combinedchunks)
  193. combinedIndex = 0
  194. for chunkIndex in range(1, len(chunks)):
  195. chunkPre = combinedchunks[combinedIndex]
  196. chunkLat = chunks[chunkIndex]
  197. #print('1st round, pre:',chunkPre, ' lat:',chunkLat, ', diff=', chunkLat[0]-chunkPre[1] )
  198. if chunkLat[0]-chunkPre[1] <= gapMax:
  199. del combinedchunks[combinedIndex]
  200. #print('after del 0,', combinedchunks)
  201. combinedchunk = chunkPre+chunkLat
  202. #print('combined chunk is', combinedchunk)
  203. combinedchunks.append([combinedchunk[0], combinedchunk[-1]])
  204. else:
  205. combinedchunks.append(chunkLat)
  206. combinedIndex = combinedIndex + 1
  207. else:
  208. combinedchunks = chunks
  209. # remove small chunks
  210. keep_combinedchunks = []
  211. for chunk in combinedchunks:
  212. if chunk[1]-chunk[0] >= intervalLength:
  213. keep_combinedchunks.append(chunk)
  214. except Exception as e:
  215. keep_combinedchunks = chunks
  216. print(' ', e)
  217. return (keep_combinedchunks)
  218. def normBA(df,df_B_list,df_A_list,beforeB=False,baseSecond=2):
  219. '''
  220. Aim:
  221. normalize trace based on some frames before/start of the trace
  222. Arguments:
  223. - df: trace df
  224. - df_B_list: dataframe list BEFORE behavior/location onset
  225. - df_A_list: dataframe list AFTER behavior/location onset
  226. - beforeB: if use a period before df_B to calculate baseline.
  227. If True, than use baseSecond before de_B to calculate baselinse, otherwise use the entire df_B as baseline
  228. - baseSecond: how long before df_B are used to calculate baseline
  229. Return:
  230. - normalized df_B_list and df_A_list
  231. '''
  232. df_BN_list = []; df_AN_list = []
  233. if len(df_B_list)!=0 and len(df_A_list) !=0:
  234. for dfIndex in range(len(df_B_list)):
  235. dfB = df_B_list[dfIndex]
  236. dfA = df_A_list[dfIndex]
  237. # find baseline
  238. if beforeB:
  239. dfBM = df.loc[(dfB.index[0]-baseSecond):dfB.index[0]]
  240. else:
  241. dfBM = dfB.copy()
  242. dfBM.loc['mean'] = dfBM.mean(axis=0)
  243. # norm first/second half based on baseline
  244. dfBN = dfB-dfBM.loc['mean']
  245. dfAN = dfA-dfBM.loc['mean']
  246. df_BN_list.append(dfBN)
  247. df_AN_list.append(dfAN)
  248. return (df_BN_list, df_AN_list)
  249. def get_BonsetA(df,
  250. which_status_to_check,
  251. fps,
  252. secForward=10,
  253. secBackward=10,
  254. beforeB=False,baseSecond=2,intervalLength=20,if_CombineAdjacentChunks=True,gapMax=10,ifNorm=True):
  255. '''
  256. Aim:
  257. Through function find_compositeIntervals() we locate interval that mouse was in certain state.
  258. By calling this function, we enlarge each interval forward #secForward seconds and make it last #secBackward seconds
  259. For example (1 interval C), C=[second_10, second_25] or C=[second_10, second_15].
  260. By calling this function, we make C=[second_8, second_20]
  261. Arguments:
  262. df: dff
  263. which_status_to_check: the behavior of onset
  264. secForward: seconds to enlarge forward from onset
  265. secBackward: seconds to include backward from onset
  266. other arguments are either from function find_compositeIntervals() or normBA(), check there for more details
  267. '''
  268. df_status = check_frame_interval(df, which_status_to_check, ifKeep=True)
  269. combinedchunks = find_compositeIntervals(df,which_status_to_check,intervalLength=intervalLength,
  270. if_CombineAdjacentChunks=if_CombineAdjacentChunks,gapMax=gapMax)
  271. df_Bonset_list = []
  272. df_onsetA_list = []
  273. if len(combinedchunks) > 0:
  274. # enlargy each interval 100 frames (50 forward, 50 afterward)
  275. for interval in combinedchunks:
  276. if interval[0] >= secForward*fps:
  277. Bonset_start = interval[0] - secForward*fps
  278. Bonset_end = interval[0]
  279. onsetA_start = interval[0]
  280. if interval[0] + secBackward*fps < len(df):
  281. onsetA_end = interval[0] + secBackward*fps
  282. #----------------locate----------------#
  283. Bonset_df = df_status.iloc[Bonset_start:Bonset_end]
  284. Bonset_df = Bonset_df.drop('status', axis = 1)
  285. df_Bonset_list.append(Bonset_df)
  286. onsetA_df = df_status.iloc[onsetA_start:onsetA_end]
  287. onsetA_df = onsetA_df.drop('status', axis = 1)
  288. df_onsetA_list.append(onsetA_df)
  289. # norm
  290. if ifNorm:
  291. df_Bonset_listN, df_onsetA_listN = normBA(df_status,df_Bonset_list,df_onsetA_list,beforeB=beforeB,baseSecond=baseSecond)
  292. else:
  293. df_Bonset_listN, df_onsetA_listN = df_Bonset_list,df_onsetA_list
  294. return (df_Bonset_listN, df_onsetA_listN)
  295. def check_frame_interval(df, which_status_to_check_frame, ifKeep=True):
  296. # set_trace()
  297. # set up which_status_to_check_frame
  298. if which_status_to_check_frame == 'Investigating_RIGHT_SNIFF':
  299. which_status_to_check_frame = str(11)
  300. elif which_status_to_check_frame == 'Investigating_LEFT_SNIFF':
  301. which_status_to_check_frame = str(12)
  302. elif which_status_to_check_frame == 'In_right':
  303. which_status_to_check_frame = str(21)
  304. elif which_status_to_check_frame == 'In_all':
  305. which_status_to_check_frame = str(22)
  306. elif which_status_to_check_frame == 'In_left':
  307. which_status_to_check_frame = str(23)
  308. else:
  309. raise ValueError('Not approved status. choose from: Investigating_RIGHT_SNIFF, Investigating_LEFT_SNIFF, In_right, In_all, In_left')
  310. #df = add_event_label(df, event_1_path, event_2_path, event_3_path, mice_path)[which_session]
  311. frame_label_list = df['Frame_Label'].values.tolist()
  312. # to separate status label, eg:20214111
  313. n = 2
  314. check_frame_label_list = []
  315. for line in frame_label_list:
  316. line = str(line)
  317. line_list= [line[i:i+n] for i in range(0, len(line), n)]
  318. if which_status_to_check_frame in line_list:
  319. check_frame_label_list.append(1)
  320. else:
  321. check_frame_label_list.append(0)
  322. df['status'] = check_frame_label_list
  323. df_keep = df[ (df['status'] == 1)]
  324. # df_keep = df_keep.drop('status', axis = 1)
  325. # df_keep = df_keep.drop('Frame_Label', axis = 1)
  326. print('the shape of the dataframe in the status is:', df_keep.shape)
  327. return(df_keep)
  328. # +
  329. def average_nActEntries(df_list,neuron_list,fps,seconds):
  330. '''
  331. Aim:
  332. get average activity around onset for each neuron across entries
  333. Return:
  334. a dataframe with all mean activity of each neuron [num_frames, num_neurons]
  335. '''
  336. frames = seconds*fps
  337. avgNeuron_actEntries = pd.DataFrame()
  338. if len(df_list) > 0:
  339. for nCol in neuron_list:
  340. # get mean activity of this neuron across entries]
  341. nAct_entries = []
  342. for i in range(len(df_list)):
  343. if df_list[i].shape[0] == frames:
  344. # nAct_entries.append(df_list[i][nCol])
  345. nAct_entries.append(df_list[i][nCol].astype(float))
  346. # set_trace()
  347. nAct_mean = np.mean(np.array(nAct_entries), axis=0)
  348. avgNeuron_actEntries[nCol] = nAct_mean
  349. return(avgNeuron_actEntries)
  350. # -
  351. def filterOut_nonceONce(df, fps, secF):
  352. '''
  353. remove neurons that not showing ceON neurons around center
  354. specificly designed for 3-AverageTrace_4ONs_heatmap
  355. '''
  356. df_keep = df.copy()
  357. f, n = df.shape
  358. for i in range(n):
  359. act = df.iloc[:, i]
  360. Bavg = np.mean(act[:fps*secF])
  361. avgA = np.mean(act[fps*secF:fps*secF*3])
  362. if avgA<Bavg:
  363. df_keep = df_keep.drop(df.columns[i], axis=1)
  364. return(df_keep)
  365. def filterOut_nonceONco(df, fps, secF):
  366. '''
  367. remove neurons that not showing ceON neurons around corner (drop onset)
  368. specificly designed for 3-AverageTrace_4ONs_heatmap
  369. '''
  370. df_keep = df.copy()
  371. f, n = df.shape
  372. for i in range(n):
  373. act = df.iloc[:, i]
  374. Bavg = np.mean(act[:fps*secF])
  375. avgA = np.mean(act[fps*secF:fps*secF*3])
  376. if avgA>Bavg:
  377. df_keep = df_keep.drop(df.columns[i], axis=1)
  378. return(df_keep)
  379. def get_overlap(lists):
  380. ls=[set(l) for l in lists]
  381. fst=ls[0]
  382. for l in ls[1:]:
  383. fst.intersection_update(l)
  384. return (len(fst), fst)
  385. def fit_apply_PCA(input_df_Std, ifPrint=True):
  386. '''
  387. Aim:
  388. apply PCA
  389. '''
  390. pcaModel = PCA(n_components=4)
  391. input_Reduced_Std = pcaModel.fit_transform(input_df_Std)
  392. if ifPrint:
  393. print('first 3PCs explain', round(sum((pcaModel.explained_variance_ratio_[0:3])),3), \
  394. 'PC1='+str(round(pcaModel.explained_variance_ratio_[0],3))+\
  395. ' PC2='+str(round(pcaModel.explained_variance_ratio_[1],3))+\
  396. ' PC3='+str(round(pcaModel.explained_variance_ratio_[2],3)))
  397. #print('explained_variance_ratio_', pcaModel.explained_variance_ratio_)
  398. # reduced df
  399. input_Reduced_df = pd.DataFrame(input_Reduced_Std)
  400. input_Reduced_df.columns = ['PC1', 'PC2', 'PC3', 'PC4']
  401. return(input_Reduced_df, pcaModel)
  402. def generate_PCA_summaryDF(reduced_df, pcaModel, behaviorList, mouseName):
  403. '''
  404. Aim:
  405. generate PCA summary, 4 PCs
  406. eigenvector=features, eigenvalues=coefficient, mean=X.mean
  407. also generate df for running log, just explained variance ratio
  408. '''
  409. # PC summary
  410. #----------------------------------------------------
  411. dic_eigen = {'Eigenvector 1':pcaModel.components_[0],
  412. 'Eigenvector 2':pcaModel.components_[1],
  413. 'Eigenvector 3':pcaModel.components_[2],
  414. 'Eigenvector 4':pcaModel.components_[3],
  415. 'Sample Mean':pcaModel.mean_,
  416. 'Eigenvalues':pcaModel.explained_variance_,
  417. 'Explained Ratio':pcaModel.explained_variance_ratio_,
  418. 'singular Values':pcaModel.singular_values_,
  419. 'behavior':behaviorList}
  420. dic_eigen = dict([(k,pd.Series(v)) for k,v in dic_eigen.items() ])
  421. df_eigen = pd.DataFrame(dic_eigen)
  422. # concat PCs
  423. PCA_summary = pd.concat([df_eigen, reduced_df], axis=1)
  424. # running Log
  425. #----------------------------------------------------
  426. runningLog = pcaModel.explained_variance_ratio_
  427. runningLog_dic = {'mouseName':mouseName,
  428. 'first_3PCs': sum(runningLog),
  429. 'PC1':runningLog[0],
  430. 'PC2': runningLog[1],
  431. 'PC3':runningLog[2]}
  432. runningLog_dic = dict([(k,pd.Series(v)) for k,v in runningLog_dic.items() ])
  433. runningLog_df = pd.DataFrame(runningLog_dic)
  434. return(PCA_summary, runningLog_df)
  435. # Plot
  436. # ========================================================================================
  437. def plot_3D_4Behaviors(PCA_df,behaviors=['center', 'corner', 'sniffing', 'grooming'],cs=['r','g','b','black'],
  438. alphas=[0.6, 0.1, 0.8, 1], ifSave=True,savePath=None,filename=None):
  439. '''
  440. Aim:
  441. plot single 3D line plot and save
  442. different behavior, differetn scatter plot
  443. '''
  444. fig = plt.figure(figsize=(10,10))
  445. ax = fig.add_subplot(111, projection='3d')
  446. for bIndex in range(len(behaviors)):
  447. b = behaviors[bIndex]
  448. x = PCA_df[PCA_df['behavior']==b]['PC1']
  449. y = PCA_df[PCA_df['behavior']==b]['PC2']
  450. z = PCA_df[PCA_df['behavior']==b]['PC3']
  451. ax.scatter(x, y, z, c=cs[bIndex], marker='o', alpha=alphas[bIndex], label=b)
  452. plt.legend()
  453. if ifSave:
  454. if not os.path.exists(savePath):
  455. os.makedirs(savePath)
  456. plt.savefig(os.path.join(savePath, filename), dpi=300)
  457. plt.close()
  458. else:
  459. plt.show()
  460. def plot_2D_4Behaviors(PCA_df,
  461. behaviors=['center', 'corner', 'sniffing', 'grooming'],
  462. cs=['r','g','b','black'],
  463. alphas=[0.6, 0.1, 0.8, 1],
  464. ifSave=True,savePath=None,filename=None):
  465. '''
  466. Aim:
  467. plot single 3D line plot and save
  468. different behavior, differetn scatter plot
  469. '''
  470. fig = plt.figure(figsize=(10, 10))
  471. for bIndex in range(len(behaviors)):
  472. b = behaviors[bIndex]
  473. x = PCA_df[PCA_df['behavior']==b]['PC1']
  474. y = PCA_df[PCA_df['behavior']==b]['PC2']
  475. plt.scatter(x, y, marker='o', color=cs[bIndex], alpha=alphas[bIndex], label=b)
  476. plt.legend()
  477. if ifSave:
  478. if not os.path.exists(savePath):
  479. os.makedirs(savePath)
  480. plt.savefig(os.path.join(savePath, filename), dpi=300)
  481. plt.close()
  482. else:
  483. plt.show()

Functions_PCA.py at commit 4e3dd13, no license · at the source

Overview

Authors: Yujing Zhang1,2, Zi-Qi Zhang1, Zi-Jie Zhai3, Xuchao Ren1, Siyi Zuo1, Zheng Ma1, Min Liu1,4, Dong Li2,5, Yue Wang1,4, Pan Xu1
ORCID iDs: Dong Li, Yue Wang, Pan Xu
  1. School of Clinical and Basic Medical Sciences, Shandong First Medical University,Jinan, China
  2. School of Public Health, Shandong First Medical University,Jinan, China
  3. College of Dentistry, Shandong First Medical University,Jinan, China
  4. Jinan Maternity and Child Care Hospital Affiliated to Shandong First Medical University,Jinan, China
  5. School of Public Health, Jining Medical University,Jining, China
Journal: Communications biology, volume 9, issue 1, article 870
Dates: received 14 August 2025; accepted 9 April 2026; published online 23 April 2026
Type: Research article · Language: English
License: CC BY-NC-ND
Identifiers: DOI 10.1038/s42003-026-10089-z · PMID 42026195 · PMCID PMC13316100 · OpenAlex W7155419020
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: mouse (organism), systems (subfield)
Methods: Connectivity, Statistics, Smoothing, state filtering, decompositions, fMRI & imaging, Single-unit activity, calcium imaging
Keywords: Social behaviour, Neural circuits, Stress and resilience
MeSH: Amygdala*, Hypothalamus*, Neurons*, Oxytocin*, Prefrontal Cortex*, Social Behavior*, Stress, Psychological*, Animals, Male, Mice, Mice, Inbred C57BL, Paraventricular Hypothalamic Nucleus, Signal Transduction (* major topic)
Topic: Neuroendocrine regulation and behavior (Social Psychology, Psychology), according to OpenAlex
Citations: cited by 1 paper (Europe PMC); 60 references in the paper

Abstract

The abstract is not reproduced here: the paper's license (CC BY-NC-ND) does not allow it. Read it in the paper, at the publisher or on Europe PMC.

Repository

Its files are read in the Code ↔ Paper reader above, with 1 match between paragraphs and lines of code.

Xulab-SDFMU/mPFC_circuits_Stress_Social

License: none: the authors keep all their rights
State: the link answers, verified on 29 September 2026
Evidence: files inventoried
Commit: 4e3dd1392abb925ec135fc911b8f023680e37e40, 1 August 2025
Languages: Jupyter (6), Python (1)
Size: 8 files, 7 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, 6 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: pandas (6 files), Matplotlib (4 files), NumPy (4 files), SciPy (3 files), scikit-learn (2 files), seaborn (2 files), OpenCV (1 file), Pillow (1 file), tifffile (1 file)
Availability: 1 check, the latest on 29 September 2026: the link answers
  • 29 September 2026: the link answers
8 files

Code availability statement

The paper has a code availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

Read it in the paper: doi.org/10.1038/s42003-026-10089-z.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 7 scripts, each with its path and the digest of its content;
  • 1 match between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

Datasets cited

Data availability statement

The paper has a data availability statement. Its license (CC BY-NC-ND) does not allow reproducing it here; in short, from what the harvester recognized in it:

  • it points to a dataset: figshare 30084418
  • it says that the data are available on request

Read it in the paper: doi.org/10.1038/s42003-026-10089-z.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 29 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 10 authors, 3 keywords, 13 MeSH terms, 2 funders, 60 references.

Cite

This paper

Zhang, Y., Zhang, Z.-Q., Zhai, Z.-J., Ren, X., Zuo, S., Ma, Z., Liu, M., Li, D., Wang, Y., & Xu, P. (2026). Medial prefrontal cortex neurons integrate amygdala and hypothalamic oxytocin signals to mediate stress-induced social alterations. Communications biology, 9(1), 870. https://doi.org/10.1038/s42003-026-10089-z

BibTeX

@article{zhang2026medial,
author = {Zhang, Yujing and Zhang, Zi-Qi and Zhai, Zi-Jie and Ren, Xuchao and Zuo, Siyi and Ma, Zheng and Liu, Min and Li, Dong and Wang, Yue and Xu, Pan},
title = {{Medial prefrontal cortex neurons integrate amygdala and hypothalamic oxytocin signals to mediate stress-induced social alterations}},
journal = {Communications biology},
year = {2026},
month = apr,
volume = {9},
number = {1},
pages = {870},
publisher = {Nature Publishing Group},
issn = {2399-3642},
doi = {10.1038/s42003-026-10089-z},
url = {https://doi.org/10.1038/s42003-026-10089-z},
pmid = {42026195},
pmcid = {PMC13316100}
}

RIS

TY - JOUR
AU - Zhang, Yujing
AU - Zhang, Zi-Qi
AU - Zhai, Zi-Jie
AU - Ren, Xuchao
AU - Zuo, Siyi
AU - Ma, Zheng
AU - Liu, Min
AU - Li, Dong
AU - Wang, Yue
AU - Xu, Pan
TI - Medial prefrontal cortex neurons integrate amygdala and hypothalamic oxytocin signals to mediate stress-induced social alterations
T2 - Communications biology
J2 - Commun Biol
PY - 2026
DA - 2026/04/23
VL - 9
IS - 1
SP - 870
SN - 2399-3642
PB - Nature Publishing Group
DO - 10.1038/s42003-026-10089-z
UR - https://doi.org/10.1038/s42003-026-10089-z
LA - en
ER -

CSL-JSON

{
"id": "10.1038/s42003-026-10089-z",
"type": "article-journal",
"title": "Medial prefrontal cortex neurons integrate amygdala and hypothalamic oxytocin signals to mediate stress-induced social alterations",
"container-title": "Communications biology",
"author": [
{
"family": "Zhang",
"given": "Yujing"
},
{
"family": "Zhang",
"given": "Zi-Qi"
},
{
"family": "Zhai",
"given": "Zi-Jie"
},
{
"family": "Ren",
"given": "Xuchao"
},
{
"family": "Zuo",
"given": "Siyi"
},
{
"family": "Ma",
"given": "Zheng"
},
{
"family": "Liu",
"given": "Min"
},
{
"family": "Li",
"given": "Dong"
},
{
"family": "Wang",
"given": "Yue"
},
{
"family": "Xu",
"given": "Pan"
}
],
"container-title-short": "Commun Biol",
"volume": "9",
"issue": "1",
"page": "870",
"DOI": "10.1038/s42003-026-10089-z",
"PMID": "42026195",
"PMCID": "PMC13316100",
"ISSN": "2399-3642",
"publisher": "Nature Publishing Group",
"URL": "https://doi.org/10.1038/s42003-026-10089-z",
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
23
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.7554/elife.105528 [code]
Functional specialization of mPFC-BLA and mPFC-NAc pathways in affective state representation.
Journal: eLife
In common: OpenCV, pandas, SciPy, 2 other tools, mouse, 3 references, author Pan Xu
[2] doi:10.7554/elife.109717 [code]
Retrosplenial cortex enables context-dependent goal-directed sensorimotor transformation.
Journal: eLife
In common: tifffile, OpenCV, Pillow, 6 other tools, systems, mouse
[3] doi:10.1038/s41467-026-72454-0 [code]
Dynamic neuronal ensembles encode burst-suppression revealed by cortex-wide optical-electrical interfaces.
Journal: Nature communications
In common: tifffile, OpenCV, Pillow, 6 other tools, systems, mouse
[4] doi:10.1016/j.isci.2026.116206 [code]
Gut distension evokes rapid neural dynamics in vagal and hindbrain populations of larval zebrafish.
Journal: iScience
In common: tifffile, OpenCV, Pillow, 6 other tools, systems
[5] doi:10.1126/sciadv.adv3770 [code]
Evolution of a central dopamine circuit underlies adaptation of a light-evoked sensorimotor response in the blind cavefish.
Journal: Science advances
In common: tifffile, OpenCV, Pillow, 6 other tools, systems
[6] doi: [code]
Real-time closed-loop feedback system for mouse mesoscale cortical signal and movement control
Journal: eLife
In common: tifffile, OpenCV, Pillow, 6 other tools, mouse
[7] doi:10.1364/boe.605322 [code]
Generalized plaque digitization framework for multi-dimensional mesoscopic images.
Journal: Biomedical optics express
In common: tifffile, OpenCV, Pillow, 6 other tools, mouse
[8] doi:10.1038/s41586-026-10323-y [code]
Genetically encoded assembly recorder temporally resolves cellular history.
Journal: Nature
In common: tifffile, OpenCV, Pillow, 6 other tools, mouse
[9] doi:10.1371/journal.pcbi.1014571 [code]
SynAPSeg: A novel dataset and image analysis framework for deep learning-based synapse detection and quantification.
Journal: PLoS computational biology
In common: tifffile, OpenCV, Pillow, 6 other tools
[10] doi:10.1016/j.xcrm.2026.102766 [code]
A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.
Journal: Cell reports. Medicine
In common: tifffile, OpenCV, Pillow, 6 other tools

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.