1- from pydantic import BaseModel , Field , ConfigDict
1+ from pydantic import BaseModel , Field
22from typing import List , Dict , Optional
3- import datetime
3+ from datetime import datetime
44from enum import Enum
55import bibtexparser
6- from elinkapi import Elink , Record
7- from elinkapi .record import RecordResponse , AccessLimitation , JournalType
8- from elinkapi .geolocation import Geolocation
9- from elinkapi .identifier import Identifier
10- from elinkapi .related_identifier import RelatedIdentifier
11- from elinkapi .person import Person
12- from elinkapi .organization import Organization
13-
14- class TestClass (RecordResponse ):
15- ...
16- # stuff
6+
7+
8+ class ConnectionModel (BaseModel ):
9+ endpoint : str = Field (..., title = "URL Endpoint of the connection" )
10+ username : str = Field (..., title = "User Name" )
11+ password : str = Field (..., title = "Password" )
12+
13+
14+ class RoboCrysModel (BaseModel ):
15+ material_id : str
16+ last_updated : datetime
17+ description : Optional [str ] = None
18+ error : Optional [str ] = None
19+
20+ @classmethod
21+ def get_default_description (cls ):
22+ return (
23+ "Computed materials data using density "
24+ "functional theory calculations. These calculations determine "
25+ "the electronic structure of bulk materials by solving "
26+ "approximations to the Schrodinger equation. For more "
27+ "information, see https://materialsproject.org/docs/calculations"
28+ )
29+
30+
31+ class MaterialModel (BaseModel ):
32+ last_updated : datetime = Field (
33+ None , title = "timestamp for the most recent calculation"
34+ )
35+ updated_at : datetime = Field (None , title = "alternative to last_updated" )
36+ created_at : datetime = Field (
37+ None ,
38+ description = "creation time for this material defined by when the first structure "
39+ "optimization calculation was run" ,
40+ )
41+ task_id : str = Field (
42+ "" , title = "task id for this material. Also called the material id"
43+ )
44+ # pretty_formula: str = Field(..., title="clean representation of the formula")
45+ pretty_formula : str = Field (..., title = "clean representation of the formula" )
46+ chemsys : str
47+
1748
1849class ELinkGetResponseModel (BaseModel ):
19- osti_id : Optional [int ] = Field (...)
50+ osti_id : Optional [str ] = Field (...)
2051 dataset_type : str = Field (default = "SM" )
2152 title : str = Field (...)
22- persons : List [ Person ]
53+ creators : str = Field ( default = "Kristin Persson" ) # replace with authors
2354 contributors : List [Dict [str , str ]] = Field (
2455 default = [{"first_name" : "Materials" , "last_name" : "Project" }],
2556 description = "List of Dict of first name, last name mapping" ,
2657 ) # no contributor
27- publication_date : datetime .date
58+ product_nos : str = Field (..., title = "MP id" )
59+ accession_num : str = Field (..., title = "MP id" )
60+ contract_nos : str = Field ("AC02-05CH11231; EDCBEE" )
61+ originating_research_org : str = Field (
62+ default = "Lawrence Berkeley National Laboratory (LBNL), Berkeley, CA (United States)"
63+ )
64+ publication_date : str = Field (...)
65+ language : str = Field (default = "English" )
66+ country : str = Field (default = "US" )
67+ sponsor_org : str = Field (
68+ default = "USDOE Office of Science (SC), Basic Energy Sciences (BES) (SC-22)"
69+ )
2870 site_url : str = Field (...)
71+ contact_name : str = Field (default = "Kristin Persson" )
72+ contact_org : str = Field (default = "LBNL" )
73+ contact_email : str = Field (default = "feedback@materialsproject.org" )
74+ contact_phone : str = Field (default = "+1(510)486-7218" )
75+ related_resource : str = Field ("https://materialsproject.org/citing" )
76+ contributor_organizations : str = Field (default = "MIT; UC Berkeley; Duke; U Louvain" )
77+ subject_categories_code : str = Field (default = "36 MATERIALS SCIENCE" )
78+ keywords : str = Field (...)
79+ description : str = Field (default = "" )
2980 doi : dict = Field (
3081 {}, title = "DOI info" , description = "Mainly used during GET request"
3182 )
32- mp_id : str | None = None
33- keywords : List [str ] = None
3483
3584 @classmethod
36- def from_elinkapi_record (cls , R ):
37- gotResponse = ELinkGetResponseModel (
38- osti_id = R .osti_id ,
39- title = R .title ,
40- persons = R .persons ,
41- # assume default contributors for now, creators vs contributors?
42- publication_date = R .publication_date ,
43- site_url = R .site_url ,
44- doi = {"doi" : R .doi },
45- mp_id = next ((id .value for id in R .identifiers if id .type == 'RN' ), None ),
46- keywords = R .keywords
47- )
48-
49- return gotResponse
50-
51- def get_title (self ):
52- formula = self .keywords [1 ]
85+ def get_title (cls , material : MaterialModel ):
86+ formula = material .pretty_formula
5387 return "Materials Data on %s by Materials Project" % formula
5488
55- def get_site_url (self ):
56- return "https://materialsproject.org/materials/%s" % self .mp_id
89+ @classmethod
90+ def get_site_url (cls , mp_id ):
91+ return "https://materialsproject.org/materials/%s" % mp_id
5792
58- def get_keywords (self ):
59- # keywords = "; ".join(
60- # ["crystal structure", material.pretty_formula, material.chemsys]
61- # )
62- return self .keywords
93+ @classmethod
94+ def get_keywords (cls , material ):
95+ keywords = "; " .join (
96+ ["crystal structure" , material .pretty_formula , material .chemsys ]
97+ )
98+ return keywords
6399
64100 @classmethod
65101 def get_default_description (cls ):
@@ -77,11 +113,11 @@ def custom_to_dict(cls, elink_record) -> dict:
77113 return elink_record .dict (exclude = {"osti_id" , "doi" })
78114 else :
79115 return elink_record .dict (exclude = {"doi" })
80-
116+
81117
82118class ElinkResponseStatusEnum (Enum ):
83- SUCCESS = "SUCCESS"
84- FAILED = "FAILURE"
119+ SUCCESS = "SUCCESS"
120+ FAILED = "FAILURE"
85121
86122
87123class ELinkPostResponseModel (BaseModel ):
@@ -106,4 +142,178 @@ def generate_doi_record(self):
106142 )
107143 doi_collection_record .set_status (status = self .doi ["@status" ])
108144 doi_collection_record .last_validated_on = datetime .now ()
109- return doi_collection_record
145+ return doi_collection_record
146+
147+
148+ class DOIRecordStatusEnum (str , Enum ):
149+ COMPLETED = "COMPLETED"
150+ PENDING = "PENDING"
151+ FAILURE = "FAILURE"
152+ INIT = "INIT"
153+
154+
155+ class DOIRecordModel (BaseModel ):
156+ material_id : str = Field (...)
157+ doi : str = Field (default = "" )
158+ bibtex : Optional [str ] = None
159+ status : DOIRecordStatusEnum
160+ valid : bool = Field (False )
161+ last_updated : datetime = Field (
162+ default = datetime .now (),
163+ title = "DOI last updated time." ,
164+ description = "Last updated is defined as either a Bibtex or status change." ,
165+ )
166+ created_at : datetime = Field (
167+ default = datetime .now (),
168+ title = "DOI Created At" ,
169+ description = "creation time for this DOI record" ,
170+ )
171+ last_validated_on : datetime = Field (
172+ default = datetime .now (),
173+ title = "Date Last Validated" ,
174+ description = "Date that this data is last validated, " "not necessarily updated" ,
175+ )
176+ elsevier_updated_on : datetime = Field (
177+ default = datetime .now (),
178+ title = "Date Elsevier is updated" ,
179+ description = "If None, means never uploaded to elsevier" ,
180+ )
181+ error : Optional [str ] = Field (
182+ default = None , description = "None if no error, else error message"
183+ )
184+
185+ class Config :
186+ use_enum_values = True
187+
188+ def set_status (self , status ):
189+ self .status = status
190+
191+ def get_osti_id (self ):
192+ if self .doi is None or self .doi == "" :
193+ return ""
194+ else :
195+ return self .doi .split ("/" )[- 1 ]
196+
197+ def get_bibtex_abstract (self ):
198+ try :
199+ if self .bibtex is None :
200+ return ""
201+ bib_db : bibtexparser .bibdatabase .BibDatabase = bibtexparser .loads (
202+ self .bibtex
203+ )
204+ if bib_db .entries :
205+ return bib_db .entries [0 ]["abstractnote" ]
206+ except Exception as e :
207+ print (e )
208+ return ""
209+
210+
211+ class OSTIDOIRecordModel (DOIRecordModel ):
212+ material_id : str = Field (...)
213+ doi : str = Field (default = "" )
214+ bibtex : Optional [str ] = None
215+ valid : bool = Field (False )
216+ last_updated : datetime = Field (
217+ default = datetime .now (),
218+ title = "DOI last updated time." ,
219+ description = "Last updated is defined as either a Bibtex or status change." ,
220+ )
221+
222+
223+ class ElsevierPOSTContainerModel (BaseModel ):
224+ identifier : str = Field (default = "" , title = "mp_id" )
225+ source : str = "MATERIALS_PROJECT"
226+ date : str = datetime .now ().date ().isoformat ().__str__ ()
227+ title : str
228+ description : str = ""
229+ doi : str
230+ authors : List [str ] = ["Kristin Persson" ]
231+ url : str
232+ type : str = "dataset"
233+ dateAvailable : str = datetime .now ().date ().isoformat ().__str__ ()
234+ dateCreated : str = datetime .now ().date ().isoformat ().__str__ ()
235+ version : str = "1.0.0"
236+ funding : str = "USDOE Office of Science (SC), Basic Energy Sciences (BES) (SC-22)"
237+ language : str = "en"
238+ method : str = "Materials Project"
239+ accessRights : str = "Public"
240+ contact : str = "Kristin Persson <kapersson@lbl.gov>"
241+ dataStandard : str = "https://materialsproject.org/citing"
242+ howToCite : str = "https://materialsproject.org/citing"
243+ subjectAreas : List [str ] = ["36 MATERIALS SCIENCE" ]
244+ keywords : List [str ]
245+ institutions : List [str ] = ["Lawrence Berkeley National Laboratory" ]
246+ institutionIds : List [str ] = ["AC02-05CH11231; EDCBEE" ]
247+ spatialCoverage : List [str ] = []
248+ temporalCoverage : List [str ] = []
249+ references : List [str ] = ["https://materialsproject.org/citing" ]
250+ relatedResources : List [str ] = ["https://materialsproject.org/citing" ]
251+ location : str = "1 Cyclotron Rd, Berkeley, CA 94720"
252+ childContainerIds : List [str ] = []
253+
254+ @classmethod
255+ def get_url (cls , mp_id ):
256+ return "https://materialsproject.org/materials/%s" % mp_id
257+
258+ @classmethod
259+ def get_keywords (cls , material : MaterialModel ):
260+ return ["crystal structure" , material .pretty_formula , material .chemsys ]
261+
262+ @classmethod
263+ def get_default_description (cls ):
264+ return (
265+ "Computed materials data using density "
266+ "functional theory calculations. These calculations determine "
267+ "the electronic structure of bulk materials by solving "
268+ "approximations to the Schrodinger equation. For more "
269+ "information, see https://materialsproject.org/docs/calculations"
270+ )
271+
272+ @classmethod
273+ def get_date_created (cls , material : MaterialModel ) -> str :
274+ return material .created_at .date ().__str__ ()
275+
276+ @classmethod
277+ def get_date_available (cls , material : MaterialModel ) -> str :
278+ return material .created_at .date ().__str__ ()
279+
280+ @classmethod
281+ def get_title (cls , material : MaterialModel ) -> str :
282+ return material .pretty_formula
283+
284+ @classmethod
285+ def from_material_model (cls , material : MaterialModel , doi : str , description : str ):
286+ model = ElsevierPOSTContainerModel (
287+ identifier = material .task_id ,
288+ title = material .pretty_formula ,
289+ doi = doi ,
290+ url = "https://materialsproject.org/materials/%s" % material .task_id ,
291+ keywords = ["crystal structure" , material .pretty_formula , material .chemsys ],
292+ date = datetime .now ().date ().__str__ (),
293+ dateCreated = material .created_at .date ().__str__ (),
294+ dateAvailable = ElsevierPOSTContainerModel .get_date_available (material ),
295+ description = description ,
296+ )
297+ return model
298+
299+
300+ class ExplorerGetJSONResponseModel (BaseModel ):
301+ osti_id : str
302+ title : str
303+ report_number : str
304+ doi : str
305+ product_type : str
306+ language : str
307+ country_publication : str
308+ description : str
309+ site_ownership_code : str
310+ publication_date : str
311+ entry_date : str
312+ contributing_organizations : str
313+ authors : List [str ]
314+ subjects : List [str ]
315+ contributing_org : str
316+ doe_contract_number : str
317+ sponsor_orgs : List [str ]
318+ research_orgs : List [str ]
319+ links : List [Dict [str , str ]]
0 commit comments